diff options
author | Romain Perier <romain.perier@gmail.com> | 2014-10-14 02:31:10 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-10-22 11:59:52 -0400 |
commit | 2b17fa2825fe6b7bf0848b4343833d7612edbccb (patch) | |
tree | 9e196302b6a4235ee2e6e51cc1611811db1919bd /drivers/regulator | |
parent | a4b4e0461ec5532ad498f0dd0e68993ad79bec2b (diff) |
regulator: act8865: Add support to turn off all outputs
When the property "poweroff-source" is found in the
devicetree, the function pm_power_off is defined. This function sends the
rights bit fields to the global off control register. shutdown/poweroff
commands are now supported for hardware components which use these PMU.
Signed-off-by: Romain Perier <romain.perier@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/act8865-regulator.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index afd06f92dfdf..76301ed0f8d4 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c | |||
@@ -61,6 +61,8 @@ | |||
61 | #define ACT8846_REG12_VSET 0xa0 | 61 | #define ACT8846_REG12_VSET 0xa0 |
62 | #define ACT8846_REG12_CTRL 0xa1 | 62 | #define ACT8846_REG12_CTRL 0xa1 |
63 | #define ACT8846_REG13_CTRL 0xb1 | 63 | #define ACT8846_REG13_CTRL 0xb1 |
64 | #define ACT8846_GLB_OFF_CTRL 0xc3 | ||
65 | #define ACT8846_OFF_SYSMASK 0x18 | ||
64 | 66 | ||
65 | /* | 67 | /* |
66 | * ACT8865 Global Register Map. | 68 | * ACT8865 Global Register Map. |
@@ -84,6 +86,7 @@ | |||
84 | #define ACT8865_LDO3_CTRL 0x61 | 86 | #define ACT8865_LDO3_CTRL 0x61 |
85 | #define ACT8865_LDO4_VSET 0x64 | 87 | #define ACT8865_LDO4_VSET 0x64 |
86 | #define ACT8865_LDO4_CTRL 0x65 | 88 | #define ACT8865_LDO4_CTRL 0x65 |
89 | #define ACT8865_MSTROFF 0x20 | ||
87 | 90 | ||
88 | /* | 91 | /* |
89 | * Field Definitions. | 92 | * Field Definitions. |
@@ -98,6 +101,8 @@ | |||
98 | 101 | ||
99 | struct act8865 { | 102 | struct act8865 { |
100 | struct regmap *regmap; | 103 | struct regmap *regmap; |
104 | int off_reg; | ||
105 | int off_mask; | ||
101 | }; | 106 | }; |
102 | 107 | ||
103 | static const struct regmap_config act8865_regmap_config = { | 108 | static const struct regmap_config act8865_regmap_config = { |
@@ -275,6 +280,16 @@ static struct regulator_init_data | |||
275 | return NULL; | 280 | return NULL; |
276 | } | 281 | } |
277 | 282 | ||
283 | static struct i2c_client *act8865_i2c_client; | ||
284 | static void act8865_power_off(void) | ||
285 | { | ||
286 | struct act8865 *act8865; | ||
287 | |||
288 | act8865 = i2c_get_clientdata(act8865_i2c_client); | ||
289 | regmap_write(act8865->regmap, act8865->off_reg, act8865->off_mask); | ||
290 | while (1); | ||
291 | } | ||
292 | |||
278 | static int act8865_pmic_probe(struct i2c_client *client, | 293 | static int act8865_pmic_probe(struct i2c_client *client, |
279 | const struct i2c_device_id *i2c_id) | 294 | const struct i2c_device_id *i2c_id) |
280 | { | 295 | { |
@@ -285,6 +300,7 @@ static int act8865_pmic_probe(struct i2c_client *client, | |||
285 | int i, ret, num_regulators; | 300 | int i, ret, num_regulators; |
286 | struct act8865 *act8865; | 301 | struct act8865 *act8865; |
287 | unsigned long type; | 302 | unsigned long type; |
303 | int off_reg, off_mask; | ||
288 | 304 | ||
289 | pdata = dev_get_platdata(dev); | 305 | pdata = dev_get_platdata(dev); |
290 | 306 | ||
@@ -304,10 +320,14 @@ static int act8865_pmic_probe(struct i2c_client *client, | |||
304 | case ACT8846: | 320 | case ACT8846: |
305 | regulators = act8846_regulators; | 321 | regulators = act8846_regulators; |
306 | num_regulators = ARRAY_SIZE(act8846_regulators); | 322 | num_regulators = ARRAY_SIZE(act8846_regulators); |
323 | off_reg = ACT8846_GLB_OFF_CTRL; | ||
324 | off_mask = ACT8846_OFF_SYSMASK; | ||
307 | break; | 325 | break; |
308 | case ACT8865: | 326 | case ACT8865: |
309 | regulators = act8865_regulators; | 327 | regulators = act8865_regulators; |
310 | num_regulators = ARRAY_SIZE(act8865_regulators); | 328 | num_regulators = ARRAY_SIZE(act8865_regulators); |
329 | off_reg = ACT8865_SYS_CTRL; | ||
330 | off_mask = ACT8865_MSTROFF; | ||
311 | break; | 331 | break; |
312 | default: | 332 | default: |
313 | dev_err(dev, "invalid device id %lu\n", type); | 333 | dev_err(dev, "invalid device id %lu\n", type); |
@@ -345,6 +365,17 @@ static int act8865_pmic_probe(struct i2c_client *client, | |||
345 | return ret; | 365 | return ret; |
346 | } | 366 | } |
347 | 367 | ||
368 | if (of_system_has_poweroff_source(dev->of_node)) { | ||
369 | if (!pm_power_off) { | ||
370 | act8865_i2c_client = client; | ||
371 | act8865->off_reg = off_reg; | ||
372 | act8865->off_mask = off_mask; | ||
373 | pm_power_off = act8865_power_off; | ||
374 | } else { | ||
375 | dev_err(dev, "Failed to set poweroff capability, already defined\n"); | ||
376 | } | ||
377 | } | ||
378 | |||
348 | /* Finally register devices */ | 379 | /* Finally register devices */ |
349 | for (i = 0; i < num_regulators; i++) { | 380 | for (i = 0; i < num_regulators; i++) { |
350 | const struct regulator_desc *desc = ®ulators[i]; | 381 | const struct regulator_desc *desc = ®ulators[i]; |