diff options
author | Linus Torvalds | 2013-05-01 00:15:24 +0200 |
---|---|---|
committer | Linus Torvalds | 2013-05-01 00:15:24 +0200 |
commit | 151173e8ce9b95bbbbd7eedb9035cfaffbdb7cb2 (patch) | |
tree | bca02f40bdd054fa2e30f4923e1513d40873c4d9 /drivers/mfd/ab8500-sysctrl.c | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jik... (diff) | |
parent | pm2301-charger: Fix suspend/resume (diff) | |
download | kernel-qcow2-linux-151173e8ce9b95bbbbd7eedb9035cfaffbdb7cb2.tar.gz kernel-qcow2-linux-151173e8ce9b95bbbbd7eedb9035cfaffbdb7cb2.tar.xz kernel-qcow2-linux-151173e8ce9b95bbbbd7eedb9035cfaffbdb7cb2.zip |
Merge tag 'for-v3.10' of git://git.infradead.org/battery-2.6
Pull battery updates from Anton Vorontsov:
"Highlights:
- OpenFirmware/DeviceTree support for the Power Supply core: the core
now automatically populates supplied_from hierarchy from the device
tree. With these patches chargers and batteries can now lookup
each other without the board files support shim. Rhyland Klein at
NVIDIA did the work
- New ST-Ericsson ABX500 hwmon driver. The driver is heavily using
the AB85xx core and depends on some recent changes to it, so that
is why the driver comes through the battery tree. It has an
appropriate ack from the hwmon maintainer (i.e. Guenter Roeck).
Martin Persson at ST-Ericsson and Hongbo Zhang at Linaro authored
the driver
- Final bits to sync AB85xx ST-Ericsson changes into mainline. The
changes touch mfd parts, but these were acked by the appropriate
MFD maintainer (ie Samuel Ortiz). Lee Jones at Linaro did most of
the work and lead the submission process.
Minor changes, but still worth mentioning:
- Battery temperature reporting fix for Nokia N900 phones
- Versatile Express poweroff driver moved into drivers/power/reset/
- Tree-wide: use devm_kzalloc() where appropriate
- Tree-wide: dev_pm_ops cleanups/fixes"
* tag 'for-v3.10' of git://git.infradead.org/battery-2.6: (112 commits)
pm2301-charger: Fix suspend/resume
charger-manager: Use kmemdup instead of kzalloc + memcpy
power_supply: Populate supplied_from hierarchy from the device tree
power_supply: Add core support for supplied_from
power_supply: Define Binding for power-supplies
rx51_battery: Fix reporting temperature
hwmon: Add ST-Ericsson ABX500 hwmon driver
ab8500_bmdata: Export abx500_res_to_temp tables for hwmon
ab8500_{bmdata,fg}: Add const attributes to some data arrays
ab8500_bmdata: Eliminate CamelCase warning of some variables
ab8500_btemp: Make ab8500_btemp_get* interfaces public
goldfish_battery: Use resource_size()
lp8788-charger: Use PAGE_SIZE for the sysfs read operation
max8925_power: Use devm_kzalloc()
da9030_battery: Use devm_kzalloc()
da9052-battery: Use devm_kzalloc()
ds2760_battery: Use devm_kzalloc()
ds2780_battery: Use devm_kzalloc()
gpio-charger: Use devm_kzalloc()
isp1704_charger: Use devm_kzalloc()
...
Diffstat (limited to 'drivers/mfd/ab8500-sysctrl.c')
-rw-r--r-- | drivers/mfd/ab8500-sysctrl.c | 98 |
1 files changed, 87 insertions, 11 deletions
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 108fd86552f0..272479cdb107 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -15,19 +15,30 @@ #include <linux/mfd/abx500/ab8500.h> #include <linux/mfd/abx500/ab8500-sysctrl.h> +/* RtcCtrl bits */ +#define AB8500_ALARM_MIN_LOW 0x08 +#define AB8500_ALARM_MIN_MID 0x09 +#define RTC_CTRL 0x0B +#define RTC_ALARM_ENABLE 0x4 + static struct device *sysctrl_dev; void ab8500_power_off(void) { sigset_t old; sigset_t all; - static char *pss[] = {"ab8500_ac", "ab8500_usb"}; + static char *pss[] = {"ab8500_ac", "pm2301", "ab8500_usb"}; int i; bool charger_present = false; union power_supply_propval val; struct power_supply *psy; int ret; + if (sysctrl_dev == NULL) { + pr_err("%s: sysctrl not initialized\n", __func__); + return; + } + /* * If we have a charger connected and we're powering off, * reboot into charge-only mode. @@ -74,6 +85,63 @@ shutdown: } } +/* + * Use the AB WD to reset the platform. It will perform a hard + * reset instead of a soft reset. Write the reset reason to + * the AB before reset, which can be read upon restart. + */ +void ab8500_restart(char mode, const char *cmd) +{ + struct ab8500_platform_data *plat; + struct ab8500_sysctrl_platform_data *pdata; + u16 reason = 0; + u8 val; + + if (sysctrl_dev == NULL) { + pr_err("%s: sysctrl not initialized\n", __func__); + return; + } + + plat = dev_get_platdata(sysctrl_dev->parent); + pdata = plat->sysctrl; + if (pdata->reboot_reason_code) + reason = pdata->reboot_reason_code(cmd); + else + pr_warn("[%s] No reboot reason set. Default reason %d\n", + __func__, reason); + + /* + * Disable RTC alarm, just a precaution so that no alarm + * is running when WD reset is executed. + */ + abx500_get_register_interruptible(sysctrl_dev, AB8500_RTC, + RTC_CTRL , &val); + abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC, + RTC_CTRL , (val & ~RTC_ALARM_ENABLE)); + + /* + * Android is not using the RTC alarm registers during reboot + * so we borrow them for writing the reason of reset + */ + + /* reason[8 LSB] */ + val = reason & 0xFF; + abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC, + AB8500_ALARM_MIN_LOW , val); + + /* reason[8 MSB] */ + val = (reason>>8) & 0xFF; + abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC, + AB8500_ALARM_MIN_MID , val); + + /* Setting WD timeout to 0 */ + ab8500_sysctrl_write(AB8500_MAINWDOGTIMER, 0xFF, 0x0); + + /* Setting the parameters to AB8500 WD*/ + ab8500_sysctrl_write(AB8500_MAINWDOGCTRL, 0xFF, (AB8500_ENABLE_WD | + AB8500_WD_RESTART_ON_EXPIRE | AB8500_KICK_WD)); +} + static inline bool valid_bank(u8 bank) { return ((bank == AB8500_SYS_CTRL1_BLOCK) || @@ -85,7 +153,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value) u8 bank; if (sysctrl_dev == NULL) - return -EAGAIN; + return -EINVAL; bank = (reg >> 8); if (!valid_bank(bank)) @@ -101,7 +169,7 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) u8 bank; if (sysctrl_dev == NULL) - return -EAGAIN; + return -EINVAL; bank = (reg >> 8); if (!valid_bank(bank)) @@ -114,28 +182,36 @@ EXPORT_SYMBOL(ab8500_sysctrl_write); static int ab8500_sysctrl_probe(struct platform_device *pdev) { + struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500_platform_data *plat; struct ab8500_sysctrl_platform_data *pdata; - sysctrl_dev = &pdev->dev; plat = dev_get_platdata(pdev->dev.parent); + + if (!(plat && plat->sysctrl)) + return -EINVAL; + if (plat->pm_power_off) pm_power_off = ab8500_power_off; pdata = plat->sysctrl; if (pdata) { - int ret, i, j; + int last, ret, i, j; + + if (is_ab8505(ab8500)) + last = AB8500_SYSCLKREQ4RFCLKBUF; + else + last = AB8500_SYSCLKREQ8RFCLKBUF; - for (i = AB8500_SYSCLKREQ1RFCLKBUF; - i <= AB8500_SYSCLKREQ8RFCLKBUF; i++) { + for (i = AB8500_SYSCLKREQ1RFCLKBUF; i <= last; i++) { j = i - AB8500_SYSCLKREQ1RFCLKBUF; ret = ab8500_sysctrl_write(i, 0xff, - pdata->initial_req_buf_config[j]); + pdata->initial_req_buf_config[j]); dev_dbg(&pdev->dev, - "Setting SysClkReq%dRfClkBuf 0x%X\n", - j + 1, - pdata->initial_req_buf_config[j]); + "Setting SysClkReq%dRfClkBuf 0x%X\n", + j + 1, + pdata->initial_req_buf_config[j]); if (ret < 0) { dev_err(&pdev->dev, "unable to set sysClkReq%dRfClkBuf: " |