/*
- * 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 MontaVista Software, Inc.
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
  */
 
 #include <linux/module.h>
 
 
 /* REVISIT when these symbols vanish elsewhere, remove them here too */
-#undef TWL4030_GPIO_IRQ_BASE
-#undef TWL4030_GPIO_IRQ_END
+/* #undef TWL4030_GPIO_IRQ_BASE */
+/* #undef TWL4030_GPIO_IRQ_END */
 #undef TWL4030_MODIRQ_GPIO
 
 static struct gpio_chip twl_gpiochip;
 static int twl4030_gpio_irq_base;
 static int twl4030_gpio_irq_end;
 
+#ifdef MODULE
+#define is_module()    true
+#else
+#define is_module()    false
+#endif
 
 /* BitField Definitions */
 
        twl4030_gpio_irq_base = pdata->irq_base;
        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) {
                /*
                 * Create a kernel thread to handle deferred unmasking of gpio
                        twl4030_gpio_irq_base, twl4030_gpio_irq_end - 1);
        }
 
+no_irqs:
        if (!ret) {
                twl_gpiochip.base = pdata->gpio_base;
                twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
        if (status < 0)
                return status;
 
+       if (is_module() || (twl4030_gpio_irq_end - twl4030_gpio_irq_base) <= 0)
+               return 0;
+
        /* uninstall the gpio demultiplexing interrupt handler */
        irq = platform_get_irq(pdev, 0);
        set_irq_handler(irq, NULL);
 {
        return platform_driver_register(&gpio_twl4030_driver);
 }
-module_init(gpio_twl4030_init);
+subsys_initcall(gpio_twl4030_init);
 
 static void __exit gpio_twl4030_exit(void)
 {
 
 #define twl_has_keypad()       false
 #endif
 
-#ifdef CONFIG_TWL4030_GPIO
+#if defined(CONFIG_GPIO_TWL4030) || defined(CONFIG_GPIO_TWL4030_MODULE)
 #define twl_has_gpio() true
 #else
 #define twl_has_gpio() false
                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
         * the T2 Interrupt subsystem
                                client->irq, pdata->irq_base, pdata->irq_end - 1);
        }
 
-       return 0;
-
+       status = add_children(pdata);
 fail:
-       twl4030_remove(client);
+       if (status < 0)
+               twl4030_remove(client);
        return status;
 }