|
22 | 22 | #include <linux/err.h> |
23 | 23 | #include <linux/i2c.h> |
24 | 24 | #include <linux/platform_device.h> |
| 25 | +#include <linux/reboot.h> |
25 | 26 | #include <linux/regmap.h> |
26 | 27 | #include <linux/of.h> |
27 | 28 |
|
28 | 29 | #include <linux/mfd/core.h> |
29 | 30 | #include <linux/mfd/tps6586x.h> |
30 | 31 |
|
31 | 32 | #define TPS6586X_SUPPLYENE 0x14 |
| 33 | +#define SOFT_RST_BIT BIT(0) |
32 | 34 | #define EXITSLREQ_BIT BIT(1) |
33 | 35 | #define SLEEP_MODE_BIT BIT(3) |
34 | 36 |
|
@@ -457,13 +459,34 @@ static const struct regmap_config tps6586x_regmap_config = { |
457 | 459 | .cache_type = REGCACHE_RBTREE, |
458 | 460 | }; |
459 | 461 |
|
460 | | -static struct device *tps6586x_dev; |
461 | | -static void tps6586x_power_off(void) |
| 462 | +static int tps6586x_power_off_handler(struct sys_off_data *data) |
462 | 463 | { |
463 | | - if (tps6586x_clr_bits(tps6586x_dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT)) |
464 | | - return; |
| 464 | + int ret; |
| 465 | + |
| 466 | + /* Put the PMIC into sleep state. This takes at least 20ms. */ |
| 467 | + ret = tps6586x_clr_bits(data->dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT); |
| 468 | + if (ret) |
| 469 | + return notifier_from_errno(ret); |
| 470 | + |
| 471 | + ret = tps6586x_set_bits(data->dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT); |
| 472 | + if (ret) |
| 473 | + return notifier_from_errno(ret); |
| 474 | + |
| 475 | + mdelay(50); |
| 476 | + return notifier_from_errno(-ETIME); |
| 477 | +} |
| 478 | + |
| 479 | +static int tps6586x_restart_handler(struct sys_off_data *data) |
| 480 | +{ |
| 481 | + int ret; |
| 482 | + |
| 483 | + /* Put the PMIC into hard reboot state. This takes at least 20ms. */ |
| 484 | + ret = tps6586x_set_bits(data->dev, TPS6586X_SUPPLYENE, SOFT_RST_BIT); |
| 485 | + if (ret) |
| 486 | + return notifier_from_errno(ret); |
465 | 487 |
|
466 | | - tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT); |
| 488 | + mdelay(50); |
| 489 | + return notifier_from_errno(-ETIME); |
467 | 490 | } |
468 | 491 |
|
469 | 492 | static void tps6586x_print_version(struct i2c_client *client, int version) |
@@ -559,9 +582,20 @@ static int tps6586x_i2c_probe(struct i2c_client *client) |
559 | 582 | goto err_add_devs; |
560 | 583 | } |
561 | 584 |
|
562 | | - if (pdata->pm_off && !pm_power_off) { |
563 | | - tps6586x_dev = &client->dev; |
564 | | - pm_power_off = tps6586x_power_off; |
| 585 | + if (pdata->pm_off) { |
| 586 | + ret = devm_register_power_off_handler(&client->dev, &tps6586x_power_off_handler, |
| 587 | + NULL); |
| 588 | + if (ret) { |
| 589 | + dev_err(&client->dev, "register power off handler failed: %d\n", ret); |
| 590 | + goto err_add_devs; |
| 591 | + } |
| 592 | + |
| 593 | + ret = devm_register_restart_handler(&client->dev, &tps6586x_restart_handler, |
| 594 | + NULL); |
| 595 | + if (ret) { |
| 596 | + dev_err(&client->dev, "register restart handler failed: %d\n", ret); |
| 597 | + goto err_add_devs; |
| 598 | + } |
565 | 599 | } |
566 | 600 |
|
567 | 601 | return 0; |
|
0 commit comments