Initial commit; kernel source import

This commit is contained in:
Nathan
2025-04-06 23:50:55 -05:00
commit 25c6d769f4
45093 changed files with 18199410 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
menuconfig POWER_RESET
bool "Board level reset or power off"
help
Provides a number of drivers which either reset a complete board
or shut it down, by manipulating the main power supply on the board.
Say Y here to enable board reset and power off
config POWER_RESET_AS3722
bool "ams AS3722 power-off driver"
depends on MFD_AS3722 && POWER_RESET
help
This driver supports turning off board via a ams AS3722 power-off.
config POWER_RESET_GPIO
bool "GPIO power-off driver"
depends on OF_GPIO && POWER_RESET
help
This driver supports turning off your board via a GPIO line.
If your board needs a GPIO high/low to power down, say Y and
create a binding in your devicetree.
config POWER_RESET_QNAP
bool "QNAP power-off driver"
depends on OF_GPIO && POWER_RESET && PLAT_ORION
help
This driver supports turning off QNAP NAS devices by sending
commands to the microcontroller which controls the main power.
Say Y if you have a QNAP NAS.
config POWER_RESET_RESTART
bool "Restart power-off driver"
depends on ARM
help
Some boards don't actually have the ability to power off.
Instead they restart, and u-boot holds the SoC until the
user presses a key. u-boot then boots into Linux.
config POWER_RESET_VEXPRESS
bool
depends on POWER_RESET
help
Power off and reset support for the ARM Ltd. Versatile
Express boards.

View File

@@ -0,0 +1,5 @@
obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o

View File

@@ -0,0 +1,96 @@
/*
* Power off driver for ams AS3722 device.
*
* Copyright (c) 2013, NVIDIA Corporation.
*
* Author: Laxman Dewangan <ldewangan@nvidia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
* whether express or implied; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/mfd/as3722.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
struct as3722_poweroff {
struct device *dev;
struct as3722 *as3722;
};
static struct as3722_poweroff *as3722_pm_poweroff;
static void as3722_pm_power_off(void)
{
int ret;
if (!as3722_pm_poweroff) {
pr_err("AS3722 poweroff is not initialised\n");
return;
}
ret = as3722_update_bits(as3722_pm_poweroff->as3722,
AS3722_RESET_CONTROL_REG, AS3722_POWER_OFF, AS3722_POWER_OFF);
if (ret < 0)
dev_err(as3722_pm_poweroff->dev,
"RESET_CONTROL_REG update failed, %d\n", ret);
}
static int as3722_poweroff_probe(struct platform_device *pdev)
{
struct as3722_poweroff *as3722_poweroff;
struct device_node *np = pdev->dev.parent->of_node;
if (!np)
return -EINVAL;
if (!of_property_read_bool(np, "ams,system-power-controller"))
return 0;
as3722_poweroff = devm_kzalloc(&pdev->dev, sizeof(*as3722_poweroff),
GFP_KERNEL);
if (!as3722_poweroff)
return -ENOMEM;
as3722_poweroff->as3722 = dev_get_drvdata(pdev->dev.parent);
as3722_poweroff->dev = &pdev->dev;
as3722_pm_poweroff = as3722_poweroff;
if (!pm_power_off)
pm_power_off = as3722_pm_power_off;
return 0;
}
static int as3722_poweroff_remove(struct platform_device *pdev)
{
if (pm_power_off == as3722_pm_power_off)
pm_power_off = NULL;
as3722_pm_poweroff = NULL;
return 0;
}
static struct platform_driver as3722_poweroff_driver = {
.driver = {
.name = "as3722-power-off",
.owner = THIS_MODULE,
},
.probe = as3722_poweroff_probe,
.remove = as3722_poweroff_remove,
};
module_platform_driver(as3722_poweroff_driver);
MODULE_DESCRIPTION("Power off driver for ams AS3722 PMIC Device");
MODULE_ALIAS("platform:as3722-power-off");
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,126 @@
/*
* Toggles a GPIO pin to power down a device
*
* Jamie Lentin <jm@lentin.co.uk>
* Andrew Lunn <andrew@lunn.ch>
*
* Copyright (C) 2012 Jamie Lentin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/module.h>
/*
* Hold configuration here, cannot be more than one instance of the driver
* since pm_power_off itself is global.
*/
static int gpio_num = -1;
static int gpio_active_low;
static void gpio_poweroff_do_poweroff(void)
{
BUG_ON(!gpio_is_valid(gpio_num));
/* drive it active, also inactive->active edge */
gpio_direction_output(gpio_num, !gpio_active_low);
mdelay(100);
/* drive inactive, also active->inactive edge */
gpio_set_value(gpio_num, gpio_active_low);
mdelay(100);
/* drive it active, also inactive->active edge */
gpio_set_value(gpio_num, !gpio_active_low);
/* give it some time */
mdelay(3000);
WARN_ON(1);
}
static int gpio_poweroff_probe(struct platform_device *pdev)
{
enum of_gpio_flags flags;
bool input = false;
int ret;
/* If a pm_power_off function has already been added, leave it alone */
if (pm_power_off != NULL) {
pr_err("%s: pm_power_off function already registered",
__func__);
return -EBUSY;
}
gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
if (!gpio_is_valid(gpio_num))
return gpio_num;
gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
input = of_property_read_bool(pdev->dev.of_node, "input");
ret = gpio_request(gpio_num, "poweroff-gpio");
if (ret) {
pr_err("%s: Could not get GPIO %d", __func__, gpio_num);
return ret;
}
if (input) {
if (gpio_direction_input(gpio_num)) {
pr_err("Could not set direction of GPIO %d to input",
gpio_num);
goto err;
}
} else {
if (gpio_direction_output(gpio_num, gpio_active_low)) {
pr_err("Could not set direction of GPIO %d", gpio_num);
goto err;
}
}
pm_power_off = &gpio_poweroff_do_poweroff;
return 0;
err:
gpio_free(gpio_num);
return -ENODEV;
}
static int gpio_poweroff_remove(struct platform_device *pdev)
{
gpio_free(gpio_num);
if (pm_power_off == &gpio_poweroff_do_poweroff)
pm_power_off = NULL;
return 0;
}
static const struct of_device_id of_gpio_poweroff_match[] = {
{ .compatible = "gpio-poweroff", },
{},
};
static struct platform_driver gpio_poweroff_driver = {
.probe = gpio_poweroff_probe,
.remove = gpio_poweroff_remove,
.driver = {
.name = "poweroff-gpio",
.owner = THIS_MODULE,
.of_match_table = of_gpio_poweroff_match,
},
};
module_platform_driver(gpio_poweroff_driver);
MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
MODULE_DESCRIPTION("GPIO poweroff driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:poweroff-gpio");

View File

@@ -0,0 +1,116 @@
/*
* QNAP Turbo NAS Board power off
*
* Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch>
*
* Based on the code from:
*
* Copyright (C) 2009 Martin Michlmayr <tbm@cyrius.com>
* Copyright (C) 2008 Byron Bradley <byron.bbradley@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/serial_reg.h>
#include <linux/kallsyms.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/clk.h>
#define UART1_REG(x) (base + ((UART_##x) << 2))
static void __iomem *base;
static unsigned long tclk;
static void qnap_power_off(void)
{
/* 19200 baud divisor */
const unsigned divisor = ((tclk + (8 * 19200)) / (16 * 19200));
pr_err("%s: triggering power-off...\n", __func__);
/* hijack UART1 and reset into sane state (19200,8n1) */
writel(0x83, UART1_REG(LCR));
writel(divisor & 0xff, UART1_REG(DLL));
writel((divisor >> 8) & 0xff, UART1_REG(DLM));
writel(0x03, UART1_REG(LCR));
writel(0x00, UART1_REG(IER));
writel(0x00, UART1_REG(FCR));
writel(0x00, UART1_REG(MCR));
/* send the power-off command 'A' to PIC */
writel('A', UART1_REG(TX));
}
static int qnap_power_off_probe(struct platform_device *pdev)
{
struct resource *res;
struct clk *clk;
char symname[KSYM_NAME_LEN];
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Missing resource");
return -EINVAL;
}
base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!base) {
dev_err(&pdev->dev, "Unable to map resource");
return -EINVAL;
}
/* We need to know tclk in order to calculate the UART divisor */
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Clk missing");
return PTR_ERR(clk);
}
tclk = clk_get_rate(clk);
/* Check that nothing else has already setup a handler */
if (pm_power_off) {
lookup_symbol_name((ulong)pm_power_off, symname);
dev_err(&pdev->dev,
"pm_power_off already claimed %p %s",
pm_power_off, symname);
return -EBUSY;
}
pm_power_off = qnap_power_off;
return 0;
}
static int qnap_power_off_remove(struct platform_device *pdev)
{
pm_power_off = NULL;
return 0;
}
static const struct of_device_id qnap_power_off_of_match_table[] = {
{ .compatible = "qnap,power-off", },
{}
};
MODULE_DEVICE_TABLE(of, qnap_power_off_of_match_table);
static struct platform_driver qnap_power_off_driver = {
.probe = qnap_power_off_probe,
.remove = qnap_power_off_remove,
.driver = {
.owner = THIS_MODULE,
.name = "qnap_power_off",
.of_match_table = of_match_ptr(qnap_power_off_of_match_table),
},
};
module_platform_driver(qnap_power_off_driver);
MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
MODULE_DESCRIPTION("QNAP Power off driver");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,65 @@
/*
* Power off by restarting and let u-boot keep hold of the machine
* until the user presses a button for example.
*
* Andrew Lunn <andrew@lunn.ch>
*
* Copyright (C) 2012 Andrew Lunn
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/module.h>
#include <asm/system_misc.h>
static void restart_poweroff_do_poweroff(void)
{
arm_pm_restart('h', NULL);
}
static int restart_poweroff_probe(struct platform_device *pdev)
{
/* If a pm_power_off function has already been added, leave it alone */
if (pm_power_off != NULL) {
dev_err(&pdev->dev,
"pm_power_off function already registered");
return -EBUSY;
}
pm_power_off = &restart_poweroff_do_poweroff;
return 0;
}
static int restart_poweroff_remove(struct platform_device *pdev)
{
if (pm_power_off == &restart_poweroff_do_poweroff)
pm_power_off = NULL;
return 0;
}
static const struct of_device_id of_restart_poweroff_match[] = {
{ .compatible = "restart-poweroff", },
{},
};
static struct platform_driver restart_poweroff_driver = {
.probe = restart_poweroff_probe,
.remove = restart_poweroff_remove,
.driver = {
.name = "poweroff-restart",
.owner = THIS_MODULE,
.of_match_table = of_restart_poweroff_match,
},
};
module_platform_driver(restart_poweroff_driver);
MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch");
MODULE_DESCRIPTION("restart poweroff driver");
MODULE_LICENSE("GPLv2");
MODULE_ALIAS("platform:poweroff-restart");

View File

@@ -0,0 +1,146 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Copyright (C) 2012 ARM Limited
*/
#include <linux/jiffies.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/stat.h>
#include <linux/vexpress.h>
#include <asm/system_misc.h>
static void vexpress_reset_do(struct device *dev, const char *what)
{
int err = -ENOENT;
struct vexpress_config_func *func =
vexpress_config_func_get_by_dev(dev);
if (func) {
unsigned long timeout;
err = vexpress_config_write(func, 0, 0);
timeout = jiffies + HZ;
while (time_before(jiffies, timeout))
cpu_relax();
}
dev_emerg(dev, "Unable to %s (%d)\n", what, err);
}
static struct device *vexpress_power_off_device;
static void vexpress_power_off(void)
{
vexpress_reset_do(vexpress_power_off_device, "power off");
}
static struct device *vexpress_restart_device;
static void vexpress_restart(char str, const char *cmd)
{
vexpress_reset_do(vexpress_restart_device, "restart");
}
static ssize_t vexpress_reset_active_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", vexpress_restart_device == dev);
}
static ssize_t vexpress_reset_active_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
long value;
int err = kstrtol(buf, 0, &value);
if (!err && value)
vexpress_restart_device = dev;
return err ? err : count;
}
DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show,
vexpress_reset_active_store);
enum vexpress_reset_func { FUNC_RESET, FUNC_SHUTDOWN, FUNC_REBOOT };
static struct of_device_id vexpress_reset_of_match[] = {
{
.compatible = "arm,vexpress-reset",
.data = (void *)FUNC_RESET,
}, {
.compatible = "arm,vexpress-shutdown",
.data = (void *)FUNC_SHUTDOWN
}, {
.compatible = "arm,vexpress-reboot",
.data = (void *)FUNC_REBOOT
},
{}
};
static int vexpress_reset_probe(struct platform_device *pdev)
{
enum vexpress_reset_func func;
const struct of_device_id *match =
of_match_device(vexpress_reset_of_match, &pdev->dev);
if (match)
func = (enum vexpress_reset_func)match->data;
else
func = pdev->id_entry->driver_data;
switch (func) {
case FUNC_SHUTDOWN:
vexpress_power_off_device = &pdev->dev;
pm_power_off = vexpress_power_off;
break;
case FUNC_RESET:
if (!vexpress_restart_device)
vexpress_restart_device = &pdev->dev;
arm_pm_restart = vexpress_restart;
device_create_file(&pdev->dev, &dev_attr_active);
break;
case FUNC_REBOOT:
vexpress_restart_device = &pdev->dev;
arm_pm_restart = vexpress_restart;
device_create_file(&pdev->dev, &dev_attr_active);
break;
};
return 0;
}
static const struct platform_device_id vexpress_reset_id_table[] = {
{ .name = "vexpress-reset", .driver_data = FUNC_RESET, },
{ .name = "vexpress-shutdown", .driver_data = FUNC_SHUTDOWN, },
{ .name = "vexpress-reboot", .driver_data = FUNC_REBOOT, },
{}
};
static struct platform_driver vexpress_reset_driver = {
.probe = vexpress_reset_probe,
.driver = {
.name = "vexpress-reset",
.of_match_table = vexpress_reset_of_match,
},
.id_table = vexpress_reset_id_table,
};
static int __init vexpress_reset_init(void)
{
return platform_driver_register(&vexpress_reset_driver);
}
device_initcall(vexpress_reset_init);