diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-24 20:00:58 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-24 20:00:58 -0800 | 
| commit | ab7826595e9ec51a51f622c5fc91e2f59440481a (patch) | |
| tree | 34241b399fa7a12c260e06e6c1c31bc69d46e1e3 /drivers/mfd/ab8500-sysctrl.c | |
| parent | 21fbd5809ad126b949206d78e0a0e07ec872ea11 (diff) | |
| parent | ff7109fa632654eaef657186f2942f5b679023d6 (diff) | |
| download | olio-linux-3.10-ab7826595e9ec51a51f622c5fc91e2f59440481a.tar.xz olio-linux-3.10-ab7826595e9ec51a51f622c5fc91e2f59440481a.zip  | |
Merge tag 'mfd-3.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFS updates from Samuel Ortiz:
 "This is the MFD pull request for the 3.9 merge window.
  No new drivers this time, but a bunch of fairly big cleanups:
   - Roger Quadros worked on a OMAP USBHS and TLL platform data
     consolidation, OMAP5 support and clock management code cleanup.
   - The first step of a major sync for the ab8500 driver from Lee
     Jones.  In particular, the debugfs and the sysct interfaces got
     extended and improved.
   - Peter Ujfalusi sent a nice patchset for cleaning and fixing the
     twl-core driver, with a much needed module id lookup code
     improvement.
   - The regular wm5102 and arizona cleanups and fixes from Mark Brown.
   - Laxman Dewangan extended the palmas APIs in order to implement the
     palmas GPIO and rt drivers.
   - Laxman also added DT support for the tps65090 driver.
   - The Intel SCH and ICH drivers got a couple fixes from Aaron Sierra
     and Darren Hart.
   - Linus Walleij patchset for the ab8500 driver allowed ab8500 and
     ab9540 based devices to switch to the new abx500 pin-ctrl driver.
   - The max8925 now has device tree and irqdomain support thanks to
     Qing Xu.
   - The recently added rtsx driver got a few cleanups and fixes for a
     better card detection code path and now also supports the RTS5227
     chipset, thanks to Wei Wang and Roger Tseng."
* tag 'mfd-3.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (109 commits)
  mfd: lpc_ich: Use devres API to allocate private data
  mfd: lpc_ich: Add Device IDs for Intel Wellsburg PCH
  mfd: lpc_sch: Accomodate partial population of the MFD devices
  mfd: da9052-i2c: Staticize da9052_i2c_fix()
  mfd: syscon: Fix sparse warning
  mfd: twl-core: Fix kernel panic on boot
  mfd: rtsx: Fix issue that booting OS with SD card inserted
  mfd: ab8500: Fix compile error
  mfd: Add missing GENERIC_HARDIRQS dependecies
  Documentation: Add docs for max8925 dt
  mfd: max8925: Add dts
  mfd: max8925: Support dt for backlight
  mfd: max8925: Fix onkey driver irq base
  mfd: max8925: Fix mfd device register failure
  mfd: max8925: Add irqdomain for dt
  mfd: vexpress: Allow vexpress-sysreg to self-initialise
  mfd: rtsx: Support RTS5227
  mfd: rtsx: Implement driving adjustment to device-dependent callbacks
  mfd: vexpress: Add pseudo-GPIO based LEDs
  mfd: ab8500: Rename ab8500 to abx500 for hwmon driver
  ...
Diffstat (limited to 'drivers/mfd/ab8500-sysctrl.c')
| -rw-r--r-- | drivers/mfd/ab8500-sysctrl.c | 92 | 
1 files changed, 92 insertions, 0 deletions
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 8a33b2c7eea..108fd86552f 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -7,12 +7,73 @@  #include <linux/err.h>  #include <linux/module.h>  #include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/reboot.h> +#include <linux/signal.h> +#include <linux/power_supply.h>  #include <linux/mfd/abx500.h>  #include <linux/mfd/abx500/ab8500.h>  #include <linux/mfd/abx500/ab8500-sysctrl.h>  static struct device *sysctrl_dev; +void ab8500_power_off(void) +{ +	sigset_t old; +	sigset_t all; +	static char *pss[] = {"ab8500_ac", "ab8500_usb"}; +	int i; +	bool charger_present = false; +	union power_supply_propval val; +	struct power_supply *psy; +	int ret; + +	/* +	 * If we have a charger connected and we're powering off, +	 * reboot into charge-only mode. +	 */ + +	for (i = 0; i < ARRAY_SIZE(pss); i++) { +		psy = power_supply_get_by_name(pss[i]); +		if (!psy) +			continue; + +		ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); + +		if (!ret && val.intval) { +			charger_present = true; +			break; +		} +	} + +	if (!charger_present) +		goto shutdown; + +	/* Check if battery is known */ +	psy = power_supply_get_by_name("ab8500_btemp"); +	if (psy) { +		ret = psy->get_property(psy, POWER_SUPPLY_PROP_TECHNOLOGY, +					&val); +		if (!ret && val.intval != POWER_SUPPLY_TECHNOLOGY_UNKNOWN) { +			printk(KERN_INFO +			       "Charger \"%s\" is connected with known battery." +			       " Rebooting.\n", +			       pss[i]); +			machine_restart("charging"); +		} +	} + +shutdown: +	sigfillset(&all); + +	if (!sigprocmask(SIG_BLOCK, &all, &old)) { +		(void)ab8500_sysctrl_set(AB8500_STW4500CTRL1, +					 AB8500_STW4500CTRL1_SWOFF | +					 AB8500_STW4500CTRL1_SWRESET4500N); +		(void)sigprocmask(SIG_SETMASK, &old, NULL); +	} +} +  static inline bool valid_bank(u8 bank)  {  	return ((bank == AB8500_SYS_CTRL1_BLOCK) || @@ -33,6 +94,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value)  	return abx500_get_register_interruptible(sysctrl_dev, bank,  		(u8)(reg & 0xFF), value);  } +EXPORT_SYMBOL(ab8500_sysctrl_read);  int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)  { @@ -48,10 +110,40 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)  	return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank,  		(u8)(reg & 0xFF), mask, value);  } +EXPORT_SYMBOL(ab8500_sysctrl_write);  static int ab8500_sysctrl_probe(struct platform_device *pdev)  { +	struct ab8500_platform_data *plat; +	struct ab8500_sysctrl_platform_data *pdata; +  	sysctrl_dev = &pdev->dev; +	plat = dev_get_platdata(pdev->dev.parent); +	if (plat->pm_power_off) +		pm_power_off = ab8500_power_off; + +	pdata = plat->sysctrl; + +	if (pdata) { +		int ret, i, j; + +		for (i = AB8500_SYSCLKREQ1RFCLKBUF; +		     i <= AB8500_SYSCLKREQ8RFCLKBUF; i++) { +			j = i - AB8500_SYSCLKREQ1RFCLKBUF; +			ret = ab8500_sysctrl_write(i, 0xff, +						   pdata->initial_req_buf_config[j]); +			dev_dbg(&pdev->dev, +				"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: " +					"%d\n", j + 1, ret); +			} +		} +	} +  	return 0;  }  |