summaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ab8500-sysctrl.c
diff options
context:
space:
mode:
authorLinus Torvalds2013-05-01 00:15:24 +0200
committerLinus Torvalds2013-05-01 00:15:24 +0200
commit151173e8ce9b95bbbbd7eedb9035cfaffbdb7cb2 (patch)
treebca02f40bdd054fa2e30f4923e1513d40873c4d9 /drivers/mfd/ab8500-sysctrl.c
parentMerge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jik... (diff)
parentpm2301-charger: Fix suspend/resume (diff)
downloadkernel-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.c98
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: "