Commit 5dc1edce authored by David Brownell's avatar David Brownell Committed by Tony Lindgren

move twl4030-gpio to drivers/gpio

Move the twl4030 GPIO support from drivers/i2c/chips to drivers/gpio,
which is a more appropriate home for this code.

The Kconfig symbol name is changed to match the GPIO_* convention for
such symbols, so config files must change in the obvious ways (Kconfig
will prompt you).  There's now some helptext.

It can now be compiled as a module, should anyone really want to
do that; that'll be mostly useful for test builds.  Sanity check the
IRQ range we're given.

Initialization order needed a bit of work too:  core add_children()
called only after IRQs get set up, gpio uses subsys_initcall.  This
depends on a patch making i2c driver model init use postcore_initcall.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@nokia.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent ce04a6fe
...@@ -369,7 +369,7 @@ ...@@ -369,7 +369,7 @@
/* External TWL4030 gpio interrupts are optional */ /* External TWL4030 gpio interrupts are optional */
#define TWL4030_GPIO_IRQ_BASE TWL4030_PWR_IRQ_END #define TWL4030_GPIO_IRQ_BASE TWL4030_PWR_IRQ_END
#ifdef CONFIG_TWL4030_GPIO #ifdef CONFIG_GPIO_TWL4030
#define TWL4030_GPIO_NR_IRQS 18 #define TWL4030_GPIO_NR_IRQS 18
#else #else
#define TWL4030_GPIO_NR_IRQS 0 #define TWL4030_GPIO_NR_IRQS 0
......
...@@ -127,6 +127,13 @@ config GPIO_PCF857X ...@@ -127,6 +127,13 @@ config GPIO_PCF857X
This driver provides an in-kernel interface to those GPIOs using This driver provides an in-kernel interface to those GPIOs using
platform-neutral GPIO calls. platform-neutral GPIO calls.
config GPIO_TWL4030
tristate "TWL4030/TPS659x0 GPIO Driver"
depends on TWL4030_CORE && GPIOLIB
help
Say yes here to access the GPIO signals of various multi-function
power management chips from Texas Instruments.
comment "PCI GPIO expanders:" comment "PCI GPIO expanders:"
config GPIO_BT8XX config GPIO_BT8XX
......
...@@ -9,4 +9,5 @@ obj-$(CONFIG_GPIO_MAX732X) += max732x.o ...@@ -9,4 +9,5 @@ obj-$(CONFIG_GPIO_MAX732X) += max732x.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_PCA953X) += pca953x.o obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
/* /*
* linux/drivers/i2c/chips/twl4030_gpio.c * twl4030_gpio.c -- access to GPIOs on TWL4030/TPS659x0 chips
* *
* Copyright (C) 2006-2007 Texas Instruments, Inc. * Copyright (C) 2006-2007 Texas Instruments, Inc.
* Copyright (C) 2006 MontaVista Software, Inc. * Copyright (C) 2006 MontaVista Software, Inc.
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -48,14 +47,19 @@ ...@@ -48,14 +47,19 @@
/* REVISIT when these symbols vanish elsewhere, remove them here too */ /* REVISIT when these symbols vanish elsewhere, remove them here too */
#undef TWL4030_GPIO_IRQ_BASE /* #undef TWL4030_GPIO_IRQ_BASE */
#undef TWL4030_GPIO_IRQ_END /* #undef TWL4030_GPIO_IRQ_END */
#undef TWL4030_MODIRQ_GPIO #undef TWL4030_MODIRQ_GPIO
static struct gpio_chip twl_gpiochip; static struct gpio_chip twl_gpiochip;
static int twl4030_gpio_irq_base; static int twl4030_gpio_irq_base;
static int twl4030_gpio_irq_end; static int twl4030_gpio_irq_end;
#ifdef MODULE
#define is_module() true
#else
#define is_module() false
#endif
/* BitField Definitions */ /* BitField Definitions */
...@@ -765,7 +769,24 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev) ...@@ -765,7 +769,24 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
twl4030_gpio_irq_base = pdata->irq_base; twl4030_gpio_irq_base = pdata->irq_base;
twl4030_gpio_irq_end = pdata->irq_end; twl4030_gpio_irq_end = pdata->irq_end;
/* REVISIT skip most of this if the irq range is empty... */ if ((twl4030_gpio_irq_end - twl4030_gpio_irq_base) > 0) {
if (is_module()) {
dev_err(&pdev->dev,
"can't dispatch IRQs from modules\n");
goto no_irqs;
}
if (twl4030_gpio_irq_end > NR_IRQS) {
dev_err(&pdev->dev,
"last IRQ is too large: %d\n",
twl4030_gpio_irq_end);
return -EINVAL;
}
} else {
dev_notice(&pdev->dev,
"no IRQs being dispatched\n");
goto no_irqs;
}
if (!ret) { if (!ret) {
/* /*
* Create a kernel thread to handle deferred unmasking of gpio * Create a kernel thread to handle deferred unmasking of gpio
...@@ -805,6 +826,7 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev) ...@@ -805,6 +826,7 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
twl4030_gpio_irq_base, twl4030_gpio_irq_end - 1); twl4030_gpio_irq_base, twl4030_gpio_irq_end - 1);
} }
no_irqs:
if (!ret) { if (!ret) {
twl_gpiochip.base = pdata->gpio_base; twl_gpiochip.base = pdata->gpio_base;
twl_gpiochip.ngpio = TWL4030_GPIO_MAX; twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
...@@ -849,6 +871,9 @@ static int __devexit gpio_twl4030_remove(struct platform_device *pdev) ...@@ -849,6 +871,9 @@ static int __devexit gpio_twl4030_remove(struct platform_device *pdev)
if (status < 0) if (status < 0)
return status; return status;
if (is_module() || (twl4030_gpio_irq_end - twl4030_gpio_irq_base) <= 0)
return 0;
/* uninstall the gpio demultiplexing interrupt handler */ /* uninstall the gpio demultiplexing interrupt handler */
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
set_irq_handler(irq, NULL); set_irq_handler(irq, NULL);
...@@ -883,7 +908,7 @@ static int __init gpio_twl4030_init(void) ...@@ -883,7 +908,7 @@ static int __init gpio_twl4030_init(void)
{ {
return platform_driver_register(&gpio_twl4030_driver); return platform_driver_register(&gpio_twl4030_driver);
} }
module_init(gpio_twl4030_init); subsys_initcall(gpio_twl4030_init);
static void __exit gpio_twl4030_exit(void) static void __exit gpio_twl4030_exit(void)
{ {
......
...@@ -157,10 +157,6 @@ config TWL4030_CORE ...@@ -157,10 +157,6 @@ config TWL4030_CORE
help help
Say yes here if you have TWL4030 chip on your board Say yes here if you have TWL4030 chip on your board
config TWL4030_GPIO
bool "TWL4030 GPIO Driver"
depends on TWL4030_CORE && GPIOLIB
config TWL4030_MADC config TWL4030_MADC
tristate "TWL4030 MADC Driver" tristate "TWL4030 MADC Driver"
depends on TWL4030_CORE depends on TWL4030_CORE
......
...@@ -25,7 +25,6 @@ obj-$(CONFIG_MENELAUS) += menelaus.o ...@@ -25,7 +25,6 @@ obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-pwrirq.o twl4030-power.o obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-pwrirq.o twl4030-power.o
obj-$(CONFIG_TWL4030_GPIO) += twl4030-gpio.o
obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
obj-$(CONFIG_TWL4030_POWEROFF) += twl4030-poweroff.o obj-$(CONFIG_TWL4030_POWEROFF) += twl4030-poweroff.o
obj-$(CONFIG_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o obj-$(CONFIG_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
#define twl_has_keypad() false #define twl_has_keypad() false
#endif #endif
#ifdef CONFIG_TWL4030_GPIO #if defined(CONFIG_GPIO_TWL4030) || defined(CONFIG_GPIO_TWL4030_MODULE)
#define twl_has_gpio() true #define twl_has_gpio() true
#else #else
#define twl_has_gpio() false #define twl_has_gpio() false
...@@ -1110,10 +1110,6 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -1110,10 +1110,6 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
mutex_init(&twl->xfer_lock); mutex_init(&twl->xfer_lock);
} }
status = add_children(pdata);
if (status < 0)
goto fail;
/* /*
* Check if the PIH module is initialized, if yes, then init * Check if the PIH module is initialized, if yes, then init
* the T2 Interrupt subsystem * the T2 Interrupt subsystem
...@@ -1128,10 +1124,10 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -1128,10 +1124,10 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
client->irq, pdata->irq_base, pdata->irq_end - 1); client->irq, pdata->irq_base, pdata->irq_end - 1);
} }
return 0; status = add_children(pdata);
fail: fail:
twl4030_remove(client); if (status < 0)
twl4030_remove(client);
return status; return status;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment