diff options
Diffstat (limited to 'drivers/mfd/tps6586x.c')
| -rw-r--r-- | drivers/mfd/tps6586x.c | 65 |
1 files changed, 49 insertions, 16 deletions
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 2d947f3f606a..8d5fe2b60bfa 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -22,6 +22,7 @@ #include <linux/err.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/reboot.h> #include <linux/regmap.h> #include <linux/of.h> @@ -29,6 +30,7 @@ #include <linux/mfd/tps6586x.h> #define TPS6586X_SUPPLYENE 0x14 +#define SOFT_RST_BIT BIT(0) #define EXITSLREQ_BIT BIT(1) #define SLEEP_MODE_BIT BIT(3) @@ -361,9 +363,9 @@ static int tps6586x_irq_init(struct tps6586x *tps6586x, int irq, new_irq_base = 0; } - tps6586x->irq_domain = irq_domain_add_simple(tps6586x->dev->of_node, - irq_num, new_irq_base, &tps6586x_domain_ops, - tps6586x); + tps6586x->irq_domain = irq_domain_create_simple(dev_fwnode(tps6586x->dev), irq_num, + new_irq_base, &tps6586x_domain_ops, + tps6586x); if (!tps6586x->irq_domain) { dev_err(tps6586x->dev, "Failed to create IRQ domain\n"); return -ENOMEM; @@ -454,16 +456,37 @@ static const struct regmap_config tps6586x_regmap_config = { .val_bits = 8, .max_register = TPS6586X_MAX_REGISTER, .volatile_reg = is_volatile_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; -static struct device *tps6586x_dev; -static void tps6586x_power_off(void) +static int tps6586x_power_off_handler(struct sys_off_data *data) { - if (tps6586x_clr_bits(tps6586x_dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT)) - return; + int ret; + + /* Put the PMIC into sleep state. This takes at least 20ms. */ + ret = tps6586x_clr_bits(data->dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT); + if (ret) + return notifier_from_errno(ret); - tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT); + ret = tps6586x_set_bits(data->dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT); + if (ret) + return notifier_from_errno(ret); + + mdelay(50); + return notifier_from_errno(-ETIME); +} + +static int tps6586x_restart_handler(struct sys_off_data *data) +{ + int ret; + + /* Put the PMIC into hard reboot state. This takes at least 20ms. */ + ret = tps6586x_set_bits(data->dev, TPS6586X_SUPPLYENE, SOFT_RST_BIT); + if (ret) + return notifier_from_errno(ret); + + mdelay(50); + return notifier_from_errno(-ETIME); } static void tps6586x_print_version(struct i2c_client *client, int version) @@ -559,9 +582,20 @@ static int tps6586x_i2c_probe(struct i2c_client *client) goto err_add_devs; } - if (pdata->pm_off && !pm_power_off) { - tps6586x_dev = &client->dev; - pm_power_off = tps6586x_power_off; + if (pdata->pm_off) { + ret = devm_register_power_off_handler(&client->dev, &tps6586x_power_off_handler, + NULL); + if (ret) { + dev_err(&client->dev, "register power off handler failed: %d\n", ret); + goto err_add_devs; + } + + ret = devm_register_restart_handler(&client->dev, &tps6586x_restart_handler, + NULL); + if (ret) { + dev_err(&client->dev, "register restart handler failed: %d\n", ret); + goto err_add_devs; + } } return 0; @@ -608,8 +642,8 @@ static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend, tps6586x_i2c_resume); static const struct i2c_device_id tps6586x_id_table[] = { - { "tps6586x", 0 }, - { }, + { "tps6586x" }, + { } }; MODULE_DEVICE_TABLE(i2c, tps6586x_id_table); @@ -619,7 +653,7 @@ static struct i2c_driver tps6586x_driver = { .of_match_table = of_match_ptr(tps6586x_of_match), .pm = &tps6586x_pm_ops, }, - .probe_new = tps6586x_i2c_probe, + .probe = tps6586x_i2c_probe, .remove = tps6586x_i2c_remove, .id_table = tps6586x_id_table, }; @@ -638,4 +672,3 @@ module_exit(tps6586x_exit); MODULE_DESCRIPTION("TPS6586X core driver"); MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); -MODULE_LICENSE("GPL"); |
