diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-05 12:01:30 +0900 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-05 12:01:30 +0900 | 
| commit | 578f1ef91aa92beb571bfb9af8f4d18f405f3b9e (patch) | |
| tree | 8ff59e772d09180b7e7f952a8c90a1bcf25e1d19 /drivers/gpio/gpio-ich.c | |
| parent | ecefbd94b834fa32559d854646d777c56749ef1c (diff) | |
| parent | 74d8378159de16a0a1d1975d4778120d263d6000 (diff) | |
| download | olio-linux-3.10-578f1ef91aa92beb571bfb9af8f4d18f405f3b9e.tar.xz olio-linux-3.10-578f1ef91aa92beb571bfb9af8f4d18f405f3b9e.zip  | |
Merge tag 'mfd-3.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFD changes from Samuel Ortiz:
 "MFD bits for the 3.7 merge window.
  As usual we have a few new drivers:
   - TI LP8788
   - TI OMAP USB TLL
   - Maxim MAX8907
   - SMSC ECE1099
   - Dialog Semiconductor DA9055
   - A simpler syscon driver that allow us to get rid of the anatop one.
  Drivers are also gradually getting Device Tree and IRQ domain support.
  The following drivers got DT support:
   - palmas, 88pm860x, tc3589x and twl4030-audio
  And those ones now use the IRQ domain APIs:
   - 88pm860x, tc3589x, db8500_prcmu
  Also some other interesting changes:
   - Intel's ICH LPC now supports Lynx Point
   - TI's twl4030-audio added a GPO child
   - tps6527 enabled its backlight subdevice
   - The twl6030 pwm driver moved to the new PWM subsystem
  And finally a bunch of cleanup and casual fixes for mc13xxx, 88pm860x,
  palmas, ab8500, wm8994, wm5110, max8907 and the tps65xxx family."
Fix up various annoying conflicts: the DT and IRQ domain support came in
twice and was already in 3.6. And then it was apparently rebased.
Guys, DON'T REBASE!
* tag 'mfd-3.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (89 commits)
  ARM: dts: Enable 88pm860x pmic
  mfd: 88pm860x: Move gpadc init into touch
  mfd: 88pm860x: Device tree support
  mfd: 88pm860x: Use irqdomain
  mfd: smsc: Add support for smsc gpio io/keypad driver
  backlight: tps65217_bl: Add missing platform_set_drvdata in tps65217_bl_probe
  mfd: DA9055 core driver
  mfd: tps65910: Add alarm interrupt of TPS65910 RTC to mfd device list
  mfd: wm5110: Add register patches for revision B
  mfd: wm5110: Disable control interface error report for WM5110 rev B
  mfd: max8907: Remove regulator-compatible from DT docs
  backlight: Add TPS65217 WLED driver
  mfd: Add backlight as subdevice to the tps65217
  mfd: Provide the PRCMU with its own IRQ domain
  mfd: Fix max8907 sparse warning
  mfd: Add lp8788 mfd driver
  mfd: dbx500: Provide a more accurate smp_twd clock
  mfd: rc5t583: Fix warning messages
  regulator: palmas: Add DT support
  mfd: palmas: Change regulator defns to better suite DT
  ...
Diffstat (limited to 'drivers/gpio/gpio-ich.c')
| -rw-r--r-- | drivers/gpio/gpio-ich.c | 79 | 
1 files changed, 69 insertions, 10 deletions
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index b7c06517403..d4d61796669 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -49,6 +49,10 @@ static const u8 ichx_regs[3][3] = {  	{0x0c, 0x38, 0x48},	/* LVL[1-3] offsets */  }; +static const u8 ichx_reglen[3] = { +	0x30, 0x10, 0x10, +}; +  #define ICHX_WRITE(val, reg, base_res)	outl(val, (reg) + (base_res)->start)  #define ICHX_READ(reg, base_res)	inl((reg) + (base_res)->start) @@ -75,6 +79,7 @@ static struct {  	struct resource *pm_base;	/* Power Mangagment IO base */  	struct ichx_desc *desc;	/* Pointer to chipset-specific description */  	u32 orig_gpio_ctrl;	/* Orig CTRL value, used to restore on exit */ +	u8 use_gpio;		/* Which GPIO groups are usable */  } ichx_priv;  static int modparam_gpiobase = -1;	/* dynamic */ @@ -123,8 +128,16 @@ static int ichx_read_bit(int reg, unsigned nr)  	return data & (1 << bit) ? 1 : 0;  } +static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) +{ +	return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO; +} +  static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)  { +	if (!ichx_gpio_check_available(gpio, nr)) +		return -ENXIO; +  	/*  	 * Try setting pin as an input and verify it worked since many pins  	 * are output-only. @@ -138,6 +151,9 @@ static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)  static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,  					int val)  { +	if (!ichx_gpio_check_available(gpio, nr)) +		return -ENXIO; +  	/* Set GPIO output value. */  	ichx_write_bit(GPIO_LVL, nr, val, 0); @@ -153,6 +169,9 @@ static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,  static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)  { +	if (!ichx_gpio_check_available(chip, nr)) +		return -ENXIO; +  	return ichx_read_bit(GPIO_LVL, nr);  } @@ -161,6 +180,9 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)  	unsigned long flags;  	u32 data; +	if (!ichx_gpio_check_available(chip, nr)) +		return -ENXIO; +  	/*  	 * GPI 0 - 15 need to be read from the power management registers on  	 * a ICH6/3100 bridge. @@ -291,6 +313,46 @@ static struct ichx_desc intel5_desc = {  	.ngpio = 76,  }; +static int __devinit ichx_gpio_request_regions(struct resource *res_base, +						const char *name, u8 use_gpio) +{ +	int i; + +	if (!res_base || !res_base->start || !res_base->end) +		return -ENODEV; + +	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) { +		if (!(use_gpio & (1 << i))) +			continue; +		if (!request_region(res_base->start + ichx_regs[0][i], +				    ichx_reglen[i], name)) +			goto request_err; +	} +	return 0; + +request_err: +	/* Clean up: release already requested regions, if any */ +	for (i--; i >= 0; i--) { +		if (!(use_gpio & (1 << i))) +			continue; +		release_region(res_base->start + ichx_regs[0][i], +			       ichx_reglen[i]); +	} +	return -EBUSY; +} + +static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) { +		if (!(use_gpio & (1 << i))) +			continue; +		release_region(res_base->start + ichx_regs[0][i], +			       ichx_reglen[i]); +	} +} +  static int __devinit ichx_gpio_probe(struct platform_device *pdev)  {  	struct resource *res_base, *res_pm; @@ -329,12 +391,11 @@ static int __devinit ichx_gpio_probe(struct platform_device *pdev)  	}  	res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); -	if (!res_base || !res_base->start || !res_base->end) -		return -ENODEV; - -	if (!request_region(res_base->start, resource_size(res_base), -				pdev->name)) -		return -EBUSY; +	ichx_priv.use_gpio = ich_info->use_gpio; +	err = ichx_gpio_request_regions(res_base, pdev->name, +					ichx_priv.use_gpio); +	if (err) +		return err;  	ichx_priv.gpio_base = res_base; @@ -374,8 +435,7 @@ init:  	return 0;  add_err: -	release_region(ichx_priv.gpio_base->start, -			resource_size(ichx_priv.gpio_base)); +	ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);  	if (ichx_priv.pm_base)  		release_region(ichx_priv.pm_base->start,  				resource_size(ichx_priv.pm_base)); @@ -393,8 +453,7 @@ static int __devexit ichx_gpio_remove(struct platform_device *pdev)  		return err;  	} -	release_region(ichx_priv.gpio_base->start, -				resource_size(ichx_priv.gpio_base)); +	ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);  	if (ichx_priv.pm_base)  		release_region(ichx_priv.pm_base->start,  				resource_size(ichx_priv.pm_base));  |