power supply and reset changes for the v3.19 series
* update power/reset drivers to use kernel restart handler * add power off driver for i.mx6 * add DT support for gpio-charger -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCgAGBQJUjv52AAoJENju1/PIO/qaESIP/3rRE/Gw1fmfX+F1wN+jXQao WXw2JW/IUQG0TQlpTnEqPQQu+H48dX58MbpNVSLy2O7Z4XiMRDG2HkEduyJYGm+P 37pfgiTH9Vj7MJ0EnNK3lLrQmF1l+yNHIjZUGLPEjbKmXSzJYPHwNhtC5U9/QooY igRwKC51bBw6of6pPaIYP6nxQeaNVgI3MaOnJ1+glLc0uQuy5mc4gODL6yCEkvuR WCsyJi226m/dBD+ZgejSet7kJS3JG4dR0GuqZkJ22DS5wKbwKrgXfOiVl+xrgCwR FqbvnZbscr+jt/xFJsAT5zqtvHNgxx37XVwkV3nHsKX8UugYg3rCB5T/mlgNj+m/ Cg5BePP84O1NMJHYXSj7Wo6BYYoFJO8ucT0uIKpcci3UyvtqWcMXzptNjkAtylw1 P+0EtP7HL4jBLJ5Snd0Je47w2mztmaJmqCc9LU8odznlFbaJ25X3chf3zqAoKdpY Lqe1XWxi5HtLNmuX/NsNhw0tdxuSiH5e2r7yM5Bwtm4uh4Yx9Ab9TEtloF3u+en5 ALR88cryxbP0zu0K/HFUeoM3v7mqH3x29NqAsSpY1D6p87308FUa1rkvYMlHwcFD Y2W2iZhmxnE5Bi9OTpfDgGQYNEUiELWmMDi3S3aSwb0QM9UWsi043LGMQfpG5QCn +xKTKJDNJsHAX5jYDuDY =v7l/ -----END PGP SIGNATURE----- Merge tag 'for-v3.19' of git://git.infradead.org/battery-2.6 Pull power supply updates from Sebastian Reichel:: "Power supply and reset changes for the v3.19 series - update power/reset drivers to use kernel restart handler - add power off driver for i.mx6 - add DT support for gpio-charger" * tag 'for-v3.19' of git://git.infradead.org/battery-2.6: power: reset: adjust priority of simple syscon reboot driver power: ds2782_battery: Simplify the PM hooks power/reset: brcmstb: Register with kernel restart handler power/reset: hisi: Register with kernel restart handler power/reset: keystone: Register with kernel restart handler power/reset: axxia: Register with kernel restart handler power/reset: xgene: Register with kernel restart handler power/reset: xgene: Use mdelay instead of jiffies based timeout power/reset: xgene: Use local variable dev instead of pdev->dev power/reset: xgene: Drop devm_kfree power/reset: xgene: Return -ENOMEM if out of memory power/reset: vexpress: Register with kernel restart handler power: reset: imx-snvs-poweroff: add power off driver for i.mx6 power: gpio-charger: add device tree support dt-bindings: document gpio-charger bindings
This commit is contained in:
Коммит
7051d8e630
|
@ -0,0 +1,27 @@
|
|||
gpio-charger
|
||||
|
||||
Required properties :
|
||||
- compatible : "gpio-charger"
|
||||
- gpios : GPIO indicating the charger presence.
|
||||
See GPIO binding in bindings/gpio/gpio.txt .
|
||||
- charger-type : power supply type, one of
|
||||
unknown
|
||||
battery
|
||||
ups
|
||||
mains
|
||||
usb-sdp (USB standard downstream port)
|
||||
usb-dcp (USB dedicated charging port)
|
||||
usb-cdp (USB charging downstream port)
|
||||
usb-aca (USB accessory charger adapter)
|
||||
|
||||
Example:
|
||||
|
||||
usb_charger: charger {
|
||||
compatible = "gpio-charger";
|
||||
charger-type = "usb-sdp";
|
||||
gpios = <&gpf0 2 0 0 0>;
|
||||
}
|
||||
|
||||
battery {
|
||||
power-supplies = <&usb_charger>;
|
||||
};
|
|
@ -351,13 +351,9 @@ static int ds278x_resume(struct device *dev)
|
|||
schedule_delayed_work(&info->bat_work, DS278x_DELAY);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ds278x_battery_pm_ops, ds278x_suspend, ds278x_resume);
|
||||
#define DS278X_BATTERY_PM_OPS (&ds278x_battery_pm_ops)
|
||||
|
||||
#else
|
||||
#define DS278X_BATTERY_PM_OPS NULL
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
enum ds278x_num_id {
|
||||
DS2782 = 0,
|
||||
|
@ -460,7 +456,7 @@ MODULE_DEVICE_TABLE(i2c, ds278x_id);
|
|||
static struct i2c_driver ds278x_battery_driver = {
|
||||
.driver = {
|
||||
.name = "ds2782-battery",
|
||||
.pm = DS278X_BATTERY_PM_OPS,
|
||||
.pm = &ds278x_battery_pm_ops,
|
||||
},
|
||||
.probe = ds278x_battery_probe,
|
||||
.remove = ds278x_battery_remove,
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <linux/power/gpio-charger.h>
|
||||
|
||||
|
@ -69,6 +71,59 @@ static enum power_supply_property gpio_charger_properties[] = {
|
|||
POWER_SUPPLY_PROP_ONLINE,
|
||||
};
|
||||
|
||||
static
|
||||
struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct gpio_charger_platform_data *pdata;
|
||||
const char *chargetype;
|
||||
enum of_gpio_flags flags;
|
||||
int ret;
|
||||
|
||||
if (!np)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pdata->name = np->name;
|
||||
|
||||
pdata->gpio = of_get_gpio_flags(np, 0, &flags);
|
||||
if (pdata->gpio < 0) {
|
||||
if (pdata->gpio != -EPROBE_DEFER)
|
||||
dev_err(dev, "could not get charger gpio\n");
|
||||
return ERR_PTR(pdata->gpio);
|
||||
}
|
||||
|
||||
pdata->gpio_active_low = !!(flags & OF_GPIO_ACTIVE_LOW);
|
||||
|
||||
pdata->type = POWER_SUPPLY_TYPE_UNKNOWN;
|
||||
ret = of_property_read_string(np, "charger-type", &chargetype);
|
||||
if (ret >= 0) {
|
||||
if (!strncmp("unknown", chargetype, 7))
|
||||
pdata->type = POWER_SUPPLY_TYPE_UNKNOWN;
|
||||
else if (!strncmp("battery", chargetype, 7))
|
||||
pdata->type = POWER_SUPPLY_TYPE_BATTERY;
|
||||
else if (!strncmp("ups", chargetype, 3))
|
||||
pdata->type = POWER_SUPPLY_TYPE_UPS;
|
||||
else if (!strncmp("mains", chargetype, 5))
|
||||
pdata->type = POWER_SUPPLY_TYPE_MAINS;
|
||||
else if (!strncmp("usb-sdp", chargetype, 7))
|
||||
pdata->type = POWER_SUPPLY_TYPE_USB;
|
||||
else if (!strncmp("usb-dcp", chargetype, 7))
|
||||
pdata->type = POWER_SUPPLY_TYPE_USB_DCP;
|
||||
else if (!strncmp("usb-cdp", chargetype, 7))
|
||||
pdata->type = POWER_SUPPLY_TYPE_USB_CDP;
|
||||
else if (!strncmp("usb-aca", chargetype, 7))
|
||||
pdata->type = POWER_SUPPLY_TYPE_USB_ACA;
|
||||
else
|
||||
dev_warn(dev, "unknown charger type %s\n", chargetype);
|
||||
}
|
||||
|
||||
return pdata;
|
||||
}
|
||||
|
||||
static int gpio_charger_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
|
||||
|
@ -78,8 +133,13 @@ static int gpio_charger_probe(struct platform_device *pdev)
|
|||
int irq;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "No platform data\n");
|
||||
return -EINVAL;
|
||||
pdata = gpio_charger_parse_dt(&pdev->dev);
|
||||
if (IS_ERR(pdata)) {
|
||||
ret = PTR_ERR(pdata);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "No platform data\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gpio_is_valid(pdata->gpio)) {
|
||||
|
@ -103,6 +163,7 @@ static int gpio_charger_probe(struct platform_device *pdev)
|
|||
charger->get_property = gpio_charger_get_property;
|
||||
charger->supplied_to = pdata->supplied_to;
|
||||
charger->num_supplicants = pdata->num_supplicants;
|
||||
charger->of_node = pdev->dev.of_node;
|
||||
|
||||
ret = gpio_request(pdata->gpio, dev_name(&pdev->dev));
|
||||
if (ret) {
|
||||
|
@ -189,12 +250,19 @@ static int gpio_charger_resume(struct device *dev)
|
|||
static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops,
|
||||
gpio_charger_suspend, gpio_charger_resume);
|
||||
|
||||
static const struct of_device_id gpio_charger_match[] = {
|
||||
{ .compatible = "gpio-charger" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, gpio_charger_match);
|
||||
|
||||
static struct platform_driver gpio_charger_driver = {
|
||||
.probe = gpio_charger_probe,
|
||||
.remove = gpio_charger_remove,
|
||||
.driver = {
|
||||
.name = "gpio-charger",
|
||||
.pm = &gpio_charger_pm_ops,
|
||||
.of_match_table = gpio_charger_match,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -19,14 +19,12 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <asm/system_misc.h>
|
||||
|
||||
|
||||
#define SC_CRIT_WRITE_KEY 0x1000
|
||||
#define SC_LATCH_ON_RESET 0x1004
|
||||
#define SC_RESET_CONTROL 0x1008
|
||||
|
@ -39,7 +37,8 @@
|
|||
|
||||
static struct regmap *syscon;
|
||||
|
||||
static void do_axxia_restart(enum reboot_mode reboot_mode, const char *cmd)
|
||||
static int axxia_restart_handler(struct notifier_block *this,
|
||||
unsigned long mode, void *cmd)
|
||||
{
|
||||
/* Access Key (0xab) */
|
||||
regmap_write(syscon, SC_CRIT_WRITE_KEY, 0xab);
|
||||
|
@ -50,11 +49,19 @@ static void do_axxia_restart(enum reboot_mode reboot_mode, const char *cmd)
|
|||
/* Assert chip reset */
|
||||
regmap_update_bits(syscon, SC_RESET_CONTROL,
|
||||
RSTCTL_RST_CHIP, RSTCTL_RST_CHIP);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block axxia_restart_nb = {
|
||||
.notifier_call = axxia_restart_handler,
|
||||
.priority = 128,
|
||||
};
|
||||
|
||||
static int axxia_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int err;
|
||||
|
||||
syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
|
||||
if (IS_ERR(syscon)) {
|
||||
|
@ -62,9 +69,11 @@ static int axxia_reset_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(syscon);
|
||||
}
|
||||
|
||||
arm_pm_restart = do_axxia_restart;
|
||||
err = register_restart_handler(&axxia_restart_nb);
|
||||
if (err)
|
||||
dev_err(dev, "cannot register restart handler (err=%d)\n", err);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_axxia_reset_match[] = {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
@ -26,8 +27,6 @@
|
|||
#include <linux/smp.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
||||
#include <asm/system_misc.h>
|
||||
|
||||
#define RESET_SOURCE_ENABLE_REG 1
|
||||
#define SW_MASTER_RESET_REG 2
|
||||
|
||||
|
@ -35,7 +34,8 @@ static struct regmap *regmap;
|
|||
static u32 rst_src_en;
|
||||
static u32 sw_mstr_rst;
|
||||
|
||||
static void brcmstb_reboot(enum reboot_mode mode, const char *cmd)
|
||||
static int brcmstb_restart_handler(struct notifier_block *this,
|
||||
unsigned long mode, void *cmd)
|
||||
{
|
||||
int rc;
|
||||
u32 tmp;
|
||||
|
@ -43,31 +43,38 @@ static void brcmstb_reboot(enum reboot_mode mode, const char *cmd)
|
|||
rc = regmap_write(regmap, rst_src_en, 1);
|
||||
if (rc) {
|
||||
pr_err("failed to write rst_src_en (%d)\n", rc);
|
||||
return;
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
rc = regmap_read(regmap, rst_src_en, &tmp);
|
||||
if (rc) {
|
||||
pr_err("failed to read rst_src_en (%d)\n", rc);
|
||||
return;
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
rc = regmap_write(regmap, sw_mstr_rst, 1);
|
||||
if (rc) {
|
||||
pr_err("failed to write sw_mstr_rst (%d)\n", rc);
|
||||
return;
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
rc = regmap_read(regmap, sw_mstr_rst, &tmp);
|
||||
if (rc) {
|
||||
pr_err("failed to read sw_mstr_rst (%d)\n", rc);
|
||||
return;
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
while (1)
|
||||
;
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block brcmstb_restart_nb = {
|
||||
.notifier_call = brcmstb_restart_handler,
|
||||
.priority = 128,
|
||||
};
|
||||
|
||||
static int brcmstb_reboot_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc;
|
||||
|
@ -93,9 +100,12 @@ static int brcmstb_reboot_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
arm_pm_restart = brcmstb_reboot;
|
||||
rc = register_restart_handler(&brcmstb_restart_nb);
|
||||
if (rc)
|
||||
dev_err(&pdev->dev,
|
||||
"cannot register restart handler (err=%d)\n", rc);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match[] = {
|
||||
|
|
|
@ -14,27 +14,36 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/proc-fns.h>
|
||||
#include <asm/system_misc.h>
|
||||
|
||||
static void __iomem *base;
|
||||
static u32 reboot_offset;
|
||||
|
||||
static void hisi_restart(enum reboot_mode mode, const char *cmd)
|
||||
static int hisi_restart_handler(struct notifier_block *this,
|
||||
unsigned long mode, void *cmd)
|
||||
{
|
||||
writel_relaxed(0xdeadbeef, base + reboot_offset);
|
||||
|
||||
while (1)
|
||||
cpu_do_idle();
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block hisi_restart_nb = {
|
||||
.notifier_call = hisi_restart_handler,
|
||||
.priority = 128,
|
||||
};
|
||||
|
||||
static int hisi_reboot_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int err;
|
||||
|
||||
base = of_iomap(np, 0);
|
||||
if (!base) {
|
||||
|
@ -47,9 +56,12 @@ static int hisi_reboot_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
arm_pm_restart = hisi_restart;
|
||||
err = register_restart_handler(&hisi_restart_nb);
|
||||
if (err)
|
||||
dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n",
|
||||
err);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct of_device_id hisi_reboot_of_match[] = {
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <asm/system_misc.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
|
@ -52,7 +52,8 @@ static inline int rsctrl_enable_rspll_write(void)
|
|||
RSCTRL_KEY_MASK, RSCTRL_KEY);
|
||||
}
|
||||
|
||||
static void rsctrl_restart(enum reboot_mode mode, const char *cmd)
|
||||
static int rsctrl_restart_handler(struct notifier_block *this,
|
||||
unsigned long mode, void *cmd)
|
||||
{
|
||||
/* enable write access to RSTCTRL */
|
||||
rsctrl_enable_rspll_write();
|
||||
|
@ -60,8 +61,15 @@ static void rsctrl_restart(enum reboot_mode mode, const char *cmd)
|
|||
/* reset the SOC */
|
||||
regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG,
|
||||
RSCTRL_RESET_MASK, 0);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block rsctrl_restart_nb = {
|
||||
.notifier_call = rsctrl_restart_handler,
|
||||
.priority = 128,
|
||||
};
|
||||
|
||||
static struct of_device_id rsctrl_of_match[] = {
|
||||
{.compatible = "ti,keystone-reset", },
|
||||
{},
|
||||
|
@ -114,8 +122,6 @@ static int rsctrl_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
arm_pm_restart = rsctrl_restart;
|
||||
|
||||
/* disable a reset isolation for all module clocks */
|
||||
ret = regmap_write(pllctrl_regs, rspll_offset + RSISO_RG, 0);
|
||||
if (ret)
|
||||
|
@ -147,7 +153,11 @@ static int rsctrl_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
ret = register_restart_handler(&rsctrl_restart_nb);
|
||||
if (ret)
|
||||
dev_err(dev, "cannot register restart handler (err=%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver rsctrl_driver = {
|
||||
|
|
|
@ -68,7 +68,7 @@ static int syscon_reboot_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
|
||||
ctx->restart_handler.notifier_call = syscon_restart_handle;
|
||||
ctx->restart_handler.priority = 128;
|
||||
ctx->restart_handler.priority = 192;
|
||||
err = register_restart_handler(&ctx->restart_handler);
|
||||
if (err)
|
||||
dev_err(dev, "can't register restart notifier (err=%d)\n", err);
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reboot.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;
|
||||
|
@ -43,11 +43,19 @@ static void vexpress_power_off(void)
|
|||
|
||||
static struct device *vexpress_restart_device;
|
||||
|
||||
static void vexpress_restart(enum reboot_mode reboot_mode, const char *cmd)
|
||||
static int vexpress_restart(struct notifier_block *this, unsigned long mode,
|
||||
void *cmd)
|
||||
{
|
||||
vexpress_reset_do(vexpress_restart_device, "restart");
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block vexpress_restart_nb = {
|
||||
.notifier_call = vexpress_restart,
|
||||
.priority = 128,
|
||||
};
|
||||
|
||||
static ssize_t vexpress_reset_active_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -86,12 +94,28 @@ static struct of_device_id vexpress_reset_of_match[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
static int _vexpress_register_restart_handler(struct device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
vexpress_restart_device = dev;
|
||||
err = register_restart_handler(&vexpress_restart_nb);
|
||||
if (err) {
|
||||
dev_err(dev, "cannot register restart handler (err=%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
device_create_file(dev, &dev_attr_active);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
struct regmap *regmap;
|
||||
int ret = 0;
|
||||
|
||||
if (match)
|
||||
func = (enum vexpress_reset_func)match->data;
|
||||
|
@ -110,18 +134,14 @@ static int vexpress_reset_probe(struct platform_device *pdev)
|
|||
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);
|
||||
ret = _vexpress_register_restart_handler(&pdev->dev);
|
||||
break;
|
||||
case FUNC_REBOOT:
|
||||
vexpress_restart_device = &pdev->dev;
|
||||
arm_pm_restart = vexpress_restart;
|
||||
device_create_file(&pdev->dev, &dev_attr_active);
|
||||
ret = _vexpress_register_restart_handler(&pdev->dev);
|
||||
break;
|
||||
};
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct platform_device_id vexpress_reset_id_table[] = {
|
||||
|
|
|
@ -24,63 +24,67 @@
|
|||
* For system shutdown, this is board specify. If a board designer
|
||||
* implements GPIO shutdown, use the gpio-poweroff.c driver.
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/system_misc.h>
|
||||
|
||||
struct xgene_reboot_context {
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
void *csr;
|
||||
u32 mask;
|
||||
struct notifier_block restart_handler;
|
||||
};
|
||||
|
||||
static struct xgene_reboot_context *xgene_restart_ctx;
|
||||
|
||||
static void xgene_restart(enum reboot_mode mode, const char *cmd)
|
||||
static int xgene_restart_handler(struct notifier_block *this,
|
||||
unsigned long mode, void *cmd)
|
||||
{
|
||||
struct xgene_reboot_context *ctx = xgene_restart_ctx;
|
||||
unsigned long timeout;
|
||||
struct xgene_reboot_context *ctx =
|
||||
container_of(this, struct xgene_reboot_context,
|
||||
restart_handler);
|
||||
|
||||
/* Issue the reboot */
|
||||
if (ctx)
|
||||
writel(ctx->mask, ctx->csr);
|
||||
writel(ctx->mask, ctx->csr);
|
||||
|
||||
timeout = jiffies + HZ;
|
||||
while (time_before(jiffies, timeout))
|
||||
cpu_relax();
|
||||
mdelay(1000);
|
||||
|
||||
dev_emerg(&ctx->pdev->dev, "Unable to restart system\n");
|
||||
dev_emerg(ctx->dev, "Unable to restart system\n");
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int xgene_reboot_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct xgene_reboot_context *ctx;
|
||||
struct device *dev = &pdev->dev;
|
||||
int err;
|
||||
|
||||
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx) {
|
||||
dev_err(&pdev->dev, "out of memory for context\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->csr = of_iomap(pdev->dev.of_node, 0);
|
||||
ctx->csr = of_iomap(dev->of_node, 0);
|
||||
if (!ctx->csr) {
|
||||
devm_kfree(&pdev->dev, ctx);
|
||||
dev_err(&pdev->dev, "can not map resource\n");
|
||||
dev_err(dev, "can not map resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node, "mask", &ctx->mask))
|
||||
if (of_property_read_u32(dev->of_node, "mask", &ctx->mask))
|
||||
ctx->mask = 0xFFFFFFFF;
|
||||
|
||||
ctx->pdev = pdev;
|
||||
arm_pm_restart = xgene_restart;
|
||||
xgene_restart_ctx = ctx;
|
||||
ctx->dev = dev;
|
||||
ctx->restart_handler.notifier_call = xgene_restart_handler;
|
||||
ctx->restart_handler.priority = 128;
|
||||
err = register_restart_handler(&ctx->restart_handler);
|
||||
if (err)
|
||||
dev_err(dev, "cannot register restart handler (err=%d)\n", err);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct of_device_id xgene_reboot_of_match[] = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче