RE: [PATCH] mfd/tc35892: rename tc35892 to tc3589x

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi again,

Apart from the function renaming, the things of interest here are the
keypad definitions and the MFD client cell hook for distinguishing the different
clients.

(the register/function renaming may or may not at all be valid; hence I am not
Ccing the MFD maintainer for this patch)

Cheers!

>-----Original Message-----
>From: Sundar R IYER
>Sent: Friday, November 26, 2010 8:42 PM
>To: ken.lierman@xxxxxxxxxxxxx
>Cc: dmitry.torokhov@xxxxxxxxx; alan@xxxxxxxxxxxxxxx; Linus WALLEIJ; Rabin
>VINCENT; linux-input@xxxxxxxxxxxxxxx; Sundar R IYER
>Subject: [PATCH] mfd/tc35892: rename tc35892 to tc3589x
>
>Add support for plugging TC3589x devices into the existing
>TC35892 MFD driver.
>
>Signed-off-by: Sundar Iyer <sundar.iyer@xxxxxxxxxxxxxx>
>---
> drivers/gpio/Kconfig        |    8 +-
> drivers/gpio/Makefile       |    2 +-
> drivers/gpio/tc35892-gpio.c |  389 ------------------------------------
> drivers/gpio/tc3589x-gpio.c |  381 +++++++++++++++++++++++++++++++++++
> drivers/mfd/Kconfig         |    6 +-
> drivers/mfd/Makefile        |    2 +-
> drivers/mfd/tc35892.c       |  345 --------------------------------
> drivers/mfd/tc3589x.c       |  465
>+++++++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/tc35892.h |  136 -------------
> include/linux/mfd/tc3589x.h |  192 ++++++++++++++++++
> 10 files changed, 1047 insertions(+), 879 deletions(-)
> delete mode 100644 drivers/gpio/tc35892-gpio.c
> create mode 100644 drivers/gpio/tc3589x-gpio.c
> delete mode 100644 drivers/mfd/tc35892.c
> create mode 100644 drivers/mfd/tc3589x.c
> delete mode 100644 include/linux/mfd/tc35892.h
> create mode 100644 include/linux/mfd/tc3589x.h
>
>diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
>index 3143ac7..9e32b2b 100644
>--- a/drivers/gpio/Kconfig
>+++ b/drivers/gpio/Kconfig
>@@ -230,11 +230,11 @@ config GPIO_STMPE
>         This enables support for the GPIOs found on the STMPE I/O
>         Expanders.
>
>-config GPIO_TC35892
>-      bool "TC35892 GPIOs"
>-      depends on MFD_TC35892
>+config GPIO_TC3589X
>+      bool "TC3589X GPIOs"
>+      depends on MFD_TC3589X
>       help
>-        This enables support for the GPIOs found on the TC35892
>+        This enables support for the GPIOs found on the TC35892/3
>         I/O Expander.
>
> config GPIO_TWL4030
>diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
>index bdf3dde..39bfd7a 100644
>--- a/drivers/gpio/Makefile
>+++ b/drivers/gpio/Makefile
>@@ -24,7 +24,7 @@ obj-$(CONFIG_GPIO_PCF857X)   += pcf857x.o
> obj-$(CONFIG_GPIO_PCH)                += pch_gpio.o
> obj-$(CONFIG_GPIO_PL061)      += pl061.o
> obj-$(CONFIG_GPIO_STMPE)      += stmpe-gpio.o
>-obj-$(CONFIG_GPIO_TC35892)    += tc35892-gpio.o
>+obj-$(CONFIG_GPIO_TC3589X)    += tc3589x-gpio.o
> obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o
> obj-$(CONFIG_GPIO_TWL4030)    += twl4030-gpio.o
> obj-$(CONFIG_GPIO_UCB1400)    += ucb1400_gpio.o
>diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c
>deleted file mode 100644
>index 7e10c93..0000000
>--- a/drivers/gpio/tc35892-gpio.c
>+++ /dev/null
>@@ -1,389 +0,0 @@
>-/*
>- * Copyright (C) ST-Ericsson SA 2010
>- *
>- * License Terms: GNU General Public License, version 2
>- * Author: Hanumath Prasad <hanumath.prasad@xxxxxxxxxxxxxx> for ST-Ericsson
>- * Author: Rabin Vincent <rabin.vincent@xxxxxxxxxxxxxx> for ST-Ericsson
>- */
>-
>-#include <linux/module.h>
>-#include <linux/init.h>
>-#include <linux/platform_device.h>
>-#include <linux/slab.h>
>-#include <linux/gpio.h>
>-#include <linux/irq.h>
>-#include <linux/interrupt.h>
>-#include <linux/mfd/tc35892.h>
>-
>-/*
>- * These registers are modified under the irq bus lock and cached to avoid
>- * unnecessary writes in bus_sync_unlock.
>- */
>-enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
>-
>-#define CACHE_NR_REGS 4
>-#define CACHE_NR_BANKS        3
>-
>-struct tc35892_gpio {
>-      struct gpio_chip chip;
>-      struct tc35892 *tc35892;
>-      struct device *dev;
>-      struct mutex irq_lock;
>-
>-      int irq_base;
>-
>-      /* Caches of interrupt control registers for bus_lock */
>-      u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
>-      u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
>-};
>-
>-static inline struct tc35892_gpio *to_tc35892_gpio(struct gpio_chip *chip)
>-{
>-      return container_of(chip, struct tc35892_gpio, chip);
>-}
>-
>-static int tc35892_gpio_get(struct gpio_chip *chip, unsigned offset)
>-{
>-      struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
>-      struct tc35892 *tc35892 = tc35892_gpio->tc35892;
>-      u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2;
>-      u8 mask = 1 << (offset % 8);
>-      int ret;
>-
>-      ret = tc35892_reg_read(tc35892, reg);
>-      if (ret < 0)
>-              return ret;
>-
>-      return ret & mask;
>-}
>-
>-static void tc35892_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
>-{
>-      struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
>-      struct tc35892 *tc35892 = tc35892_gpio->tc35892;
>-      u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2;
>-      unsigned pos = offset % 8;
>-      u8 data[] = {!!val << pos, 1 << pos};
>-
>-      tc35892_block_write(tc35892, reg, ARRAY_SIZE(data), data);
>-}
>-
>-static int tc35892_gpio_direction_output(struct gpio_chip *chip,
>-                                       unsigned offset, int val)
>-{
>-      struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
>-      struct tc35892 *tc35892 = tc35892_gpio->tc35892;
>-      u8 reg = TC35892_GPIODIR0 + offset / 8;
>-      unsigned pos = offset % 8;
>-
>-      tc35892_gpio_set(chip, offset, val);
>-
>-      return tc35892_set_bits(tc35892, reg, 1 << pos, 1 << pos);
>-}
>-
>-static int tc35892_gpio_direction_input(struct gpio_chip *chip,
>-                                      unsigned offset)
>-{
>-      struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
>-      struct tc35892 *tc35892 = tc35892_gpio->tc35892;
>-      u8 reg = TC35892_GPIODIR0 + offset / 8;
>-      unsigned pos = offset % 8;
>-
>-      return tc35892_set_bits(tc35892, reg, 1 << pos, 0);
>-}
>-
>-static int tc35892_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
>-{
>-      struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
>-
>-      return tc35892_gpio->irq_base + offset;
>-}
>-
>-static struct gpio_chip template_chip = {
>-      .label                  = "tc35892",
>-      .owner                  = THIS_MODULE,
>-      .direction_input        = tc35892_gpio_direction_input,
>-      .get                    = tc35892_gpio_get,
>-      .direction_output       = tc35892_gpio_direction_output,
>-      .set                    = tc35892_gpio_set,
>-      .to_irq                 = tc35892_gpio_to_irq,
>-      .can_sleep              = 1,
>-};
>-
>-static int tc35892_gpio_irq_set_type(unsigned int irq, unsigned int type)
>-{
>-      struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
>-      int offset = irq - tc35892_gpio->irq_base;
>-      int regoffset = offset / 8;
>-      int mask = 1 << (offset % 8);
>-
>-      if (type == IRQ_TYPE_EDGE_BOTH) {
>-              tc35892_gpio->regs[REG_IBE][regoffset] |= mask;
>-              return 0;
>-      }
>-
>-      tc35892_gpio->regs[REG_IBE][regoffset] &= ~mask;
>-
>-      if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
>-              tc35892_gpio->regs[REG_IS][regoffset] |= mask;
>-      else
>-              tc35892_gpio->regs[REG_IS][regoffset] &= ~mask;
>-
>-      if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
>-              tc35892_gpio->regs[REG_IEV][regoffset] |= mask;
>-      else
>-              tc35892_gpio->regs[REG_IEV][regoffset] &= ~mask;
>-
>-      return 0;
>-}
>-
>-static void tc35892_gpio_irq_lock(unsigned int irq)
>-{
>-      struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
>-
>-      mutex_lock(&tc35892_gpio->irq_lock);
>-}
>-
>-static void tc35892_gpio_irq_sync_unlock(unsigned int irq)
>-{
>-      struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
>-      struct tc35892 *tc35892 = tc35892_gpio->tc35892;
>-      static const u8 regmap[] = {
>-              [REG_IBE]       = TC35892_GPIOIBE0,
>-              [REG_IEV]       = TC35892_GPIOIEV0,
>-              [REG_IS]        = TC35892_GPIOIS0,
>-              [REG_IE]        = TC35892_GPIOIE0,
>-      };
>-      int i, j;
>-
>-      for (i = 0; i < CACHE_NR_REGS; i++) {
>-              for (j = 0; j < CACHE_NR_BANKS; j++) {
>-                      u8 old = tc35892_gpio->oldregs[i][j];
>-                      u8 new = tc35892_gpio->regs[i][j];
>-
>-                      if (new == old)
>-                              continue;
>-
>-                      tc35892_gpio->oldregs[i][j] = new;
>-                      tc35892_reg_write(tc35892, regmap[i] + j * 8, new);
>-              }
>-      }
>-
>-      mutex_unlock(&tc35892_gpio->irq_lock);
>-}
>-
>-static void tc35892_gpio_irq_mask(unsigned int irq)
>-{
>-      struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
>-      int offset = irq - tc35892_gpio->irq_base;
>-      int regoffset = offset / 8;
>-      int mask = 1 << (offset % 8);
>-
>-      tc35892_gpio->regs[REG_IE][regoffset] &= ~mask;
>-}
>-
>-static void tc35892_gpio_irq_unmask(unsigned int irq)
>-{
>-      struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
>-      int offset = irq - tc35892_gpio->irq_base;
>-      int regoffset = offset / 8;
>-      int mask = 1 << (offset % 8);
>-
>-      tc35892_gpio->regs[REG_IE][regoffset] |= mask;
>-}
>-
>-static struct irq_chip tc35892_gpio_irq_chip = {
>-      .name                   = "tc35892-gpio",
>-      .bus_lock               = tc35892_gpio_irq_lock,
>-      .bus_sync_unlock        = tc35892_gpio_irq_sync_unlock,
>-      .mask                   = tc35892_gpio_irq_mask,
>-      .unmask                 = tc35892_gpio_irq_unmask,
>-      .set_type               = tc35892_gpio_irq_set_type,
>-};
>-
>-static irqreturn_t tc35892_gpio_irq(int irq, void *dev)
>-{
>-      struct tc35892_gpio *tc35892_gpio = dev;
>-      struct tc35892 *tc35892 = tc35892_gpio->tc35892;
>-      u8 status[CACHE_NR_BANKS];
>-      int ret;
>-      int i;
>-
>-      ret = tc35892_block_read(tc35892, TC35892_GPIOMIS0,
>-                               ARRAY_SIZE(status), status);
>-      if (ret < 0)
>-              return IRQ_NONE;
>-
>-      for (i = 0; i < ARRAY_SIZE(status); i++) {
>-              unsigned int stat = status[i];
>-              if (!stat)
>-                      continue;
>-
>-              while (stat) {
>-                      int bit = __ffs(stat);
>-                      int line = i * 8 + bit;
>-
>-                      handle_nested_irq(tc35892_gpio->irq_base + line);
>-                      stat &= ~(1 << bit);
>-              }
>-
>-              tc35892_reg_write(tc35892, TC35892_GPIOIC0 + i, status[i]);
>-      }
>-
>-      return IRQ_HANDLED;
>-}
>-
>-static int tc35892_gpio_irq_init(struct tc35892_gpio *tc35892_gpio)
>-{
>-      int base = tc35892_gpio->irq_base;
>-      int irq;
>-
>-      for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) {
>-              set_irq_chip_data(irq, tc35892_gpio);
>-              set_irq_chip_and_handler(irq, &tc35892_gpio_irq_chip,
>-                                       handle_simple_irq);
>-              set_irq_nested_thread(irq, 1);
>-#ifdef CONFIG_ARM
>-              set_irq_flags(irq, IRQF_VALID);
>-#else
>-              set_irq_noprobe(irq);
>-#endif
>-      }
>-
>-      return 0;
>-}
>-
>-static void tc35892_gpio_irq_remove(struct tc35892_gpio *tc35892_gpio)
>-{
>-      int base = tc35892_gpio->irq_base;
>-      int irq;
>-
>-      for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) {
>-#ifdef CONFIG_ARM
>-              set_irq_flags(irq, 0);
>-#endif
>-              set_irq_chip_and_handler(irq, NULL, NULL);
>-              set_irq_chip_data(irq, NULL);
>-      }
>-}
>-
>-static int __devinit tc35892_gpio_probe(struct platform_device *pdev)
>-{
>-      struct tc35892 *tc35892 = dev_get_drvdata(pdev->dev.parent);
>-      struct tc35892_gpio_platform_data *pdata;
>-      struct tc35892_gpio *tc35892_gpio;
>-      int ret;
>-      int irq;
>-
>-      pdata = tc35892->pdata->gpio;
>-      if (!pdata)
>-              return -ENODEV;
>-
>-      irq = platform_get_irq(pdev, 0);
>-      if (irq < 0)
>-              return irq;
>-
>-      tc35892_gpio = kzalloc(sizeof(struct tc35892_gpio), GFP_KERNEL);
>-      if (!tc35892_gpio)
>-              return -ENOMEM;
>-
>-      mutex_init(&tc35892_gpio->irq_lock);
>-
>-      tc35892_gpio->dev = &pdev->dev;
>-      tc35892_gpio->tc35892 = tc35892;
>-
>-      tc35892_gpio->chip = template_chip;
>-      tc35892_gpio->chip.ngpio = tc35892->num_gpio;
>-      tc35892_gpio->chip.dev = &pdev->dev;
>-      tc35892_gpio->chip.base = pdata->gpio_base;
>-
>-      tc35892_gpio->irq_base = tc35892->irq_base + TC35892_INT_GPIO(0);
>-
>-      /* Bring the GPIO module out of reset */
>-      ret = tc35892_set_bits(tc35892, TC35892_RSTCTRL,
>-                             TC35892_RSTCTRL_GPIRST, 0);
>-      if (ret < 0)
>-              goto out_free;
>-
>-      ret = tc35892_gpio_irq_init(tc35892_gpio);
>-      if (ret)
>-              goto out_free;
>-
>-      ret = request_threaded_irq(irq, NULL, tc35892_gpio_irq, IRQF_ONESHOT,
>-                                 "tc35892-gpio", tc35892_gpio);
>-      if (ret) {
>-              dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
>-              goto out_removeirq;
>-      }
>-
>-      ret = gpiochip_add(&tc35892_gpio->chip);
>-      if (ret) {
>-              dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
>-              goto out_freeirq;
>-      }
>-
>-      if (pdata->setup)
>-              pdata->setup(tc35892, tc35892_gpio->chip.base);
>-
>-      platform_set_drvdata(pdev, tc35892_gpio);
>-
>-      return 0;
>-
>-out_freeirq:
>-      free_irq(irq, tc35892_gpio);
>-out_removeirq:
>-      tc35892_gpio_irq_remove(tc35892_gpio);
>-out_free:
>-      kfree(tc35892_gpio);
>-      return ret;
>-}
>-
>-static int __devexit tc35892_gpio_remove(struct platform_device *pdev)
>-{
>-      struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev);
>-      struct tc35892 *tc35892 = tc35892_gpio->tc35892;
>-      struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio;
>-      int irq = platform_get_irq(pdev, 0);
>-      int ret;
>-
>-      if (pdata->remove)
>-              pdata->remove(tc35892, tc35892_gpio->chip.base);
>-
>-      ret = gpiochip_remove(&tc35892_gpio->chip);
>-      if (ret < 0) {
>-              dev_err(tc35892_gpio->dev,
>-                      "unable to remove gpiochip: %d\n", ret);
>-              return ret;
>-      }
>-
>-      free_irq(irq, tc35892_gpio);
>-      tc35892_gpio_irq_remove(tc35892_gpio);
>-
>-      platform_set_drvdata(pdev, NULL);
>-      kfree(tc35892_gpio);
>-
>-      return 0;
>-}
>-
>-static struct platform_driver tc35892_gpio_driver = {
>-      .driver.name    = "tc35892-gpio",
>-      .driver.owner   = THIS_MODULE,
>-      .probe          = tc35892_gpio_probe,
>-      .remove         = __devexit_p(tc35892_gpio_remove),
>-};
>-
>-static int __init tc35892_gpio_init(void)
>-{
>-      return platform_driver_register(&tc35892_gpio_driver);
>-}
>-subsys_initcall(tc35892_gpio_init);
>-
>-static void __exit tc35892_gpio_exit(void)
>-{
>-      platform_driver_unregister(&tc35892_gpio_driver);
>-}
>-module_exit(tc35892_gpio_exit);
>-
>-MODULE_LICENSE("GPL v2");
>-MODULE_DESCRIPTION("TC35892 GPIO driver");
>-MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
>diff --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/tc3589x-gpio.c
>new file mode 100644
>index 0000000..4c75970
>--- /dev/null
>+++ b/drivers/gpio/tc3589x-gpio.c
>@@ -0,0 +1,381 @@
>+/*
>+ * Copyright (C) ST-Ericsson SA 2010
>+ *
>+ * License Terms: GNU General Public License, version 2
>+ * Author: Hanumath Prasad <hanumath.prasad@xxxxxxxxxxxxxx> for ST-Ericsson
>+ * Author: Rabin Vincent <rabin.vincent@xxxxxxxxxxxxxx> for ST-Ericsson
>+ */
>+
>+#include <linux/module.h>
>+#include <linux/init.h>
>+#include <linux/platform_device.h>
>+#include <linux/slab.h>
>+#include <linux/gpio.h>
>+#include <linux/irq.h>
>+#include <linux/interrupt.h>
>+#include <linux/mfd/tc3589x.h>
>+
>+/*
>+ * These registers are modified under the irq bus lock and cached to avoid
>+ * unnecessary writes in bus_sync_unlock.
>+ */
>+enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
>+
>+#define CACHE_NR_REGS 4
>+#define CACHE_NR_BANKS        3
>+
>+struct tc3589x_gpio {
>+      struct gpio_chip chip;
>+      struct tc3589x *tc3589x;
>+      struct device *dev;
>+      struct mutex irq_lock;
>+
>+      int irq_base;
>+
>+      /* Caches of interrupt control registers for bus_lock */
>+      u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
>+      u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
>+};
>+
>+static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip)
>+{
>+      return container_of(chip, struct tc3589x_gpio, chip);
>+}
>+
>+static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
>+      struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
>+      u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
>+      u8 mask = 1 << (offset % 8);
>+      int ret;
>+
>+      ret = tc3589x_reg_read(tc3589x, reg);
>+      if (ret < 0)
>+              return ret;
>+
>+      return ret & mask;
>+}
>+
>+static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
>+      struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
>+      u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
>+      unsigned pos = offset % 8;
>+      u8 data[] = {!!val << pos, 1 << pos};
>+
>+      tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
>+}
>+
>+static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
>+                                       unsigned offset, int val)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
>+      struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
>+      u8 reg = TC3589x_GPIODIR0 + offset / 8;
>+      unsigned pos = offset % 8;
>+
>+      tc3589x_gpio_set(chip, offset, val);
>+
>+      return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos);
>+}
>+
>+static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
>+                                      unsigned offset)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
>+      struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
>+      u8 reg = TC3589x_GPIODIR0 + offset / 8;
>+      unsigned pos = offset % 8;
>+
>+      return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
>+}
>+
>+static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
>+
>+      return tc3589x_gpio->irq_base + offset;
>+}
>+
>+static struct gpio_chip template_chip = {
>+      .label                  = "tc3589x",
>+      .owner                  = THIS_MODULE,
>+      .direction_input        = tc3589x_gpio_direction_input,
>+      .get                    = tc3589x_gpio_get,
>+      .direction_output       = tc3589x_gpio_direction_output,
>+      .set                    = tc3589x_gpio_set,
>+      .to_irq                 = tc3589x_gpio_to_irq,
>+      .can_sleep              = 1,
>+};
>+
>+static int tc3589x_gpio_irq_set_type(unsigned int irq, unsigned int type)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
>+      int offset = irq - tc3589x_gpio->irq_base;
>+      int regoffset = offset / 8;
>+      int mask = 1 << (offset % 8);
>+
>+      if (type == IRQ_TYPE_EDGE_BOTH) {
>+              tc3589x_gpio->regs[REG_IBE][regoffset] |= mask;
>+              return 0;
>+      }
>+
>+      tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask;
>+
>+      if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
>+              tc3589x_gpio->regs[REG_IS][regoffset] |= mask;
>+      else
>+              tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask;
>+
>+      if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
>+              tc3589x_gpio->regs[REG_IEV][regoffset] |= mask;
>+      else
>+              tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask;
>+
>+      return 0;
>+}
>+
>+static void tc3589x_gpio_irq_lock(unsigned int irq)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
>+
>+      mutex_lock(&tc3589x_gpio->irq_lock);
>+}
>+
>+static void tc3589x_gpio_irq_sync_unlock(unsigned int irq)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
>+      struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
>+      static const u8 regmap[] = {
>+              [REG_IBE]       = TC3589x_GPIOIBE0,
>+              [REG_IEV]       = TC3589x_GPIOIEV0,
>+              [REG_IS]        = TC3589x_GPIOIS0,
>+              [REG_IE]        = TC3589x_GPIOIE0,
>+      };
>+      int i, j;
>+
>+      for (i = 0; i < CACHE_NR_REGS; i++) {
>+              for (j = 0; j < CACHE_NR_BANKS; j++) {
>+                      u8 old = tc3589x_gpio->oldregs[i][j];
>+                      u8 new = tc3589x_gpio->regs[i][j];
>+
>+                      if (new == old)
>+                              continue;
>+
>+                      tc3589x_gpio->oldregs[i][j] = new;
>+                      tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
>+              }
>+      }
>+
>+      mutex_unlock(&tc3589x_gpio->irq_lock);
>+}
>+
>+static void tc3589x_gpio_irq_mask(unsigned int irq)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
>+      int offset = irq - tc3589x_gpio->irq_base;
>+      int regoffset = offset / 8;
>+      int mask = 1 << (offset % 8);
>+
>+      tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
>+}
>+
>+static void tc3589x_gpio_irq_unmask(unsigned int irq)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
>+      int offset = irq - tc3589x_gpio->irq_base;
>+      int regoffset = offset / 8;
>+      int mask = 1 << (offset % 8);
>+
>+      tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
>+}
>+
>+static struct irq_chip tc3589x_gpio_irq_chip = {
>+      .name                   = "tc3589x-gpio",
>+      .bus_lock               = tc3589x_gpio_irq_lock,
>+      .bus_sync_unlock        = tc3589x_gpio_irq_sync_unlock,
>+      .mask                   = tc3589x_gpio_irq_mask,
>+      .unmask                 = tc3589x_gpio_irq_unmask,
>+      .set_type               = tc3589x_gpio_irq_set_type,
>+};
>+
>+static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = dev;
>+      struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
>+      u8 status[CACHE_NR_BANKS];
>+      int ret;
>+      int i;
>+
>+      ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0,
>+                               ARRAY_SIZE(status), status);
>+      if (ret < 0)
>+              return IRQ_NONE;
>+
>+      for (i = 0; i < ARRAY_SIZE(status); i++) {
>+              unsigned int stat = status[i];
>+              if (!stat)
>+                      continue;
>+
>+              while (stat) {
>+                      int bit = __ffs(stat);
>+                      int line = i * 8 + bit;
>+
>+                      handle_nested_irq(tc3589x_gpio->irq_base + line);
>+                      stat &= ~(1 << bit);
>+              }
>+
>+              tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]);
>+      }
>+
>+      return IRQ_HANDLED;
>+}
>+
>+static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio)
>+{
>+      int base = tc3589x_gpio->irq_base;
>+      int irq;
>+
>+      for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
>+              set_irq_chip_data(irq, tc3589x_gpio);
>+              set_irq_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
>+                                       handle_simple_irq);
>+              set_irq_nested_thread(irq, 1);
>+#ifdef CONFIG_ARM
>+              set_irq_flags(irq, IRQF_VALID);
>+#else
>+              set_irq_noprobe(irq);
>+#endif
>+      }
>+
>+      return 0;
>+}
>+
>+static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio)
>+{
>+      int base = tc3589x_gpio->irq_base;
>+      int irq;
>+
>+      for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
>+#ifdef CONFIG_ARM
>+              set_irq_flags(irq, 0);
>+#endif
>+              set_irq_chip_and_handler(irq, NULL, NULL);
>+              set_irq_chip_data(irq, NULL);
>+      }
>+}
>+
>+static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
>+{
>+      struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
>+      struct tc3589x_gpio_platform_data *pdata;
>+      struct tc3589x_gpio *tc3589x_gpio;
>+      int ret;
>+      int irq;
>+
>+      pdata = tc3589x->pdata->gpio;
>+      if (!pdata)
>+              return -ENODEV;
>+
>+      irq = platform_get_irq(pdev, 0);
>+      if (irq < 0)
>+              return irq;
>+
>+      tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
>+      if (!tc3589x_gpio)
>+              return -ENOMEM;
>+
>+      mutex_init(&tc3589x_gpio->irq_lock);
>+
>+      tc3589x_gpio->dev = &pdev->dev;
>+      tc3589x_gpio->tc3589x = tc3589x;
>+
>+      tc3589x_gpio->chip = template_chip;
>+      tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
>+      tc3589x_gpio->chip.dev = &pdev->dev;
>+      tc3589x_gpio->chip.base = pdata->gpio_base;
>+
>+      tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0);
>+
>+      /* Bring the GPIO module out of reset */
>+      ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
>+                             TC3589x_RSTCTRL_GPIRST, 0);
>+      if (ret < 0)
>+              goto out_free;
>+
>+      ret = tc3589x_gpio_irq_init(tc3589x_gpio);
>+      if (ret)
>+              goto out_free;
>+
>+      ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
>+                                 "tc3589x-gpio", tc3589x_gpio);
>+      if (ret) {
>+              dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
>+              goto out_removeirq;
>+      }
>+
>+      ret = gpiochip_add(&tc3589x_gpio->chip);
>+      if (ret) {
>+              dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
>+              goto out_freeirq;
>+      }
>+
>+      platform_set_drvdata(pdev, tc3589x_gpio);
>+
>+      return 0;
>+
>+out_freeirq:
>+      free_irq(irq, tc3589x_gpio);
>+out_removeirq:
>+      tc3589x_gpio_irq_remove(tc3589x_gpio);
>+out_free:
>+      kfree(tc3589x_gpio);
>+      return ret;
>+}
>+
>+static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
>+{
>+      struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
>+      int irq = platform_get_irq(pdev, 0);
>+      int ret;
>+
>+      ret = gpiochip_remove(&tc3589x_gpio->chip);
>+      if (ret < 0) {
>+              dev_err(tc3589x_gpio->dev,
>+                      "unable to remove gpiochip: %d\n", ret);
>+              return ret;
>+      }
>+
>+      free_irq(irq, tc3589x_gpio);
>+      tc3589x_gpio_irq_remove(tc3589x_gpio);
>+
>+      platform_set_drvdata(pdev, NULL);
>+      kfree(tc3589x_gpio);
>+
>+      return 0;
>+}
>+
>+static struct platform_driver tc3589x_gpio_driver = {
>+      .driver.name    = "tc3589x-gpio",
>+      .driver.owner   = THIS_MODULE,
>+      .probe          = tc3589x_gpio_probe,
>+      .remove         = __devexit_p(tc3589x_gpio_remove),
>+};
>+
>+static int __init tc3589x_gpio_init(void)
>+{
>+      return platform_driver_register(&tc3589x_gpio_driver);
>+}
>+subsys_initcall(tc3589x_gpio_init);
>+
>+static void __exit tc3589x_gpio_exit(void)
>+{
>+      platform_driver_unregister(&tc3589x_gpio_driver);
>+}
>+module_exit(tc3589x_gpio_exit);
>+
>+MODULE_LICENSE("GPL v2");
>+MODULE_DESCRIPTION("TC3589x GPIO driver");
>+MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
>diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>index 57a8eee..5faeb4e 100644
>--- a/drivers/mfd/Kconfig
>+++ b/drivers/mfd/Kconfig
>@@ -218,12 +218,12 @@ config MFD_STMPE
>               Keypad: stmpe-keypad
>               Touchscreen: stmpe-ts
>
>-config MFD_TC35892
>-      bool "Support Toshiba TC35892"
>+config MFD_TC3589X
>+      bool "Support Toshiba TC35892/3"
>       depends on I2C=y && GENERIC_HARDIRQS
>       select MFD_CORE
>       help
>-        Support for the Toshiba TC35892 I/O Expander.
>+        Support for the Toshiba TC35892/3 I/O Expander.
>
>         This driver provides common support for accessing the device,
>         additional drivers must be enabled in order to use the
>diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
>index 741ccfd..4aacb41 100644
>--- a/drivers/mfd/Makefile
>+++ b/drivers/mfd/Makefile
>@@ -16,7 +16,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) +=
>davinci_voicecodec.o
> obj-$(CONFIG_MFD_DM355EVM_MSP)        += dm355evm_msp.o
>
> obj-$(CONFIG_MFD_STMPE)               += stmpe.o
>-obj-$(CONFIG_MFD_TC35892)     += tc35892.o
>+obj-$(CONFIG_MFD_TC3589X)     += tc3589x.o
> obj-$(CONFIG_MFD_T7L66XB)     += t7l66xb.o tmio_core.o
> obj-$(CONFIG_MFD_TC6387XB)    += tc6387xb.o tmio_core.o
> obj-$(CONFIG_MFD_TC6393XB)    += tc6393xb.o tmio_core.o
>diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c
>deleted file mode 100644
>index e619e2a..0000000
>--- a/drivers/mfd/tc35892.c
>+++ /dev/null
>@@ -1,345 +0,0 @@
>-/*
>- * Copyright (C) ST-Ericsson SA 2010
>- *
>- * License Terms: GNU General Public License, version 2
>- * Author: Hanumath Prasad <hanumath.prasad@xxxxxxxxxxxxxx> for ST-Ericsson
>- * Author: Rabin Vincent <rabin.vincent@xxxxxxxxxxxxxx> for ST-Ericsson
>- */
>-
>-#include <linux/module.h>
>-#include <linux/interrupt.h>
>-#include <linux/irq.h>
>-#include <linux/slab.h>
>-#include <linux/i2c.h>
>-#include <linux/mfd/core.h>
>-#include <linux/mfd/tc35892.h>
>-
>-/**
>- * tc35892_reg_read() - read a single TC35892 register
>- * @tc35892:  Device to read from
>- * @reg:      Register to read
>- */
>-int tc35892_reg_read(struct tc35892 *tc35892, u8 reg)
>-{
>-      int ret;
>-
>-      ret = i2c_smbus_read_byte_data(tc35892->i2c, reg);
>-      if (ret < 0)
>-              dev_err(tc35892->dev, "failed to read reg %#x: %d\n",
>-                      reg, ret);
>-
>-      return ret;
>-}
>-EXPORT_SYMBOL_GPL(tc35892_reg_read);
>-
>-/**
>- * tc35892_reg_read() - write a single TC35892 register
>- * @tc35892:  Device to write to
>- * @reg:      Register to read
>- * @data:     Value to write
>- */
>-int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data)
>-{
>-      int ret;
>-
>-      ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data);
>-      if (ret < 0)
>-              dev_err(tc35892->dev, "failed to write reg %#x: %d\n",
>-                      reg, ret);
>-
>-      return ret;
>-}
>-EXPORT_SYMBOL_GPL(tc35892_reg_write);
>-
>-/**
>- * tc35892_block_read() - read multiple TC35892 registers
>- * @tc35892:  Device to read from
>- * @reg:      First register
>- * @length:   Number of registers
>- * @values:   Buffer to write to
>- */
>-int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values)
>-{
>-      int ret;
>-
>-      ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values);
>-      if (ret < 0)
>-              dev_err(tc35892->dev, "failed to read regs %#x: %d\n",
>-                      reg, ret);
>-
>-      return ret;
>-}
>-EXPORT_SYMBOL_GPL(tc35892_block_read);
>-
>-/**
>- * tc35892_block_write() - write multiple TC35892 registers
>- * @tc35892:  Device to write to
>- * @reg:      First register
>- * @length:   Number of registers
>- * @values:   Values to write
>- */
>-int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length,
>-                      const u8 *values)
>-{
>-      int ret;
>-
>-      ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length,
>-                                           values);
>-      if (ret < 0)
>-              dev_err(tc35892->dev, "failed to write regs %#x: %d\n",
>-                      reg, ret);
>-
>-      return ret;
>-}
>-EXPORT_SYMBOL_GPL(tc35892_block_write);
>-
>-/**
>- * tc35892_set_bits() - set the value of a bitfield in a TC35892 register
>- * @tc35892:  Device to write to
>- * @reg:      Register to write
>- * @mask:     Mask of bits to set
>- * @values:   Value to set
>- */
>-int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val)
>-{
>-      int ret;
>-
>-      mutex_lock(&tc35892->lock);
>-
>-      ret = tc35892_reg_read(tc35892, reg);
>-      if (ret < 0)
>-              goto out;
>-
>-      ret &= ~mask;
>-      ret |= val;
>-
>-      ret = tc35892_reg_write(tc35892, reg, ret);
>-
>-out:
>-      mutex_unlock(&tc35892->lock);
>-      return ret;
>-}
>-EXPORT_SYMBOL_GPL(tc35892_set_bits);
>-
>-static struct resource gpio_resources[] = {
>-      {
>-              .start  = TC35892_INT_GPIIRQ,
>-              .end    = TC35892_INT_GPIIRQ,
>-              .flags  = IORESOURCE_IRQ,
>-      },
>-};
>-
>-static struct mfd_cell tc35892_devs[] = {
>-      {
>-              .name           = "tc35892-gpio",
>-              .num_resources  = ARRAY_SIZE(gpio_resources),
>-              .resources      = &gpio_resources[0],
>-      },
>-};
>-
>-static irqreturn_t tc35892_irq(int irq, void *data)
>-{
>-      struct tc35892 *tc35892 = data;
>-      int status;
>-
>-      status = tc35892_reg_read(tc35892, TC35892_IRQST);
>-      if (status < 0)
>-              return IRQ_NONE;
>-
>-      while (status) {
>-              int bit = __ffs(status);
>-
>-              handle_nested_irq(tc35892->irq_base + bit);
>-              status &= ~(1 << bit);
>-      }
>-
>-      /*
>-       * A dummy read or write (to any register) appears to be necessary to
>-       * have the last interrupt clear (for example, GPIO IC write) take
>-       * effect.
>-       */
>-      tc35892_reg_read(tc35892, TC35892_IRQST);
>-
>-      return IRQ_HANDLED;
>-}
>-
>-static void tc35892_irq_dummy(unsigned int irq)
>-{
>-      /* No mask/unmask at this level */
>-}
>-
>-static struct irq_chip tc35892_irq_chip = {
>-      .name   = "tc35892",
>-      .mask   = tc35892_irq_dummy,
>-      .unmask = tc35892_irq_dummy,
>-};
>-
>-static int tc35892_irq_init(struct tc35892 *tc35892)
>-{
>-      int base = tc35892->irq_base;
>-      int irq;
>-
>-      for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
>-              set_irq_chip_data(irq, tc35892);
>-              set_irq_chip_and_handler(irq, &tc35892_irq_chip,
>-                                       handle_edge_irq);
>-              set_irq_nested_thread(irq, 1);
>-#ifdef CONFIG_ARM
>-              set_irq_flags(irq, IRQF_VALID);
>-#else
>-              set_irq_noprobe(irq);
>-#endif
>-      }
>-
>-      return 0;
>-}
>-
>-static void tc35892_irq_remove(struct tc35892 *tc35892)
>-{
>-      int base = tc35892->irq_base;
>-      int irq;
>-
>-      for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
>-#ifdef CONFIG_ARM
>-              set_irq_flags(irq, 0);
>-#endif
>-              set_irq_chip_and_handler(irq, NULL, NULL);
>-              set_irq_chip_data(irq, NULL);
>-      }
>-}
>-
>-static int tc35892_chip_init(struct tc35892 *tc35892)
>-{
>-      int manf, ver, ret;
>-
>-      manf = tc35892_reg_read(tc35892, TC35892_MANFCODE);
>-      if (manf < 0)
>-              return manf;
>-
>-      ver = tc35892_reg_read(tc35892, TC35892_VERSION);
>-      if (ver < 0)
>-              return ver;
>-
>-      if (manf != TC35892_MANFCODE_MAGIC) {
>-              dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf);
>-              return -EINVAL;
>-      }
>-
>-      dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
>-
>-      /* Put everything except the IRQ module into reset */
>-      ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL,
>-                              TC35892_RSTCTRL_TIMRST
>-                              | TC35892_RSTCTRL_ROTRST
>-                              | TC35892_RSTCTRL_KBDRST
>-                              | TC35892_RSTCTRL_GPIRST);
>-      if (ret < 0)
>-              return ret;
>-
>-      /* Clear the reset interrupt. */
>-      return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1);
>-}
>-
>-static int __devinit tc35892_probe(struct i2c_client *i2c,
>-                                 const struct i2c_device_id *id)
>-{
>-      struct tc35892_platform_data *pdata = i2c->dev.platform_data;
>-      struct tc35892 *tc35892;
>-      int ret;
>-
>-      if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
>-                                   | I2C_FUNC_SMBUS_I2C_BLOCK))
>-              return -EIO;
>-
>-      tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL);
>-      if (!tc35892)
>-              return -ENOMEM;
>-
>-      mutex_init(&tc35892->lock);
>-
>-      tc35892->dev = &i2c->dev;
>-      tc35892->i2c = i2c;
>-      tc35892->pdata = pdata;
>-      tc35892->irq_base = pdata->irq_base;
>-      tc35892->num_gpio = id->driver_data;
>-
>-      i2c_set_clientdata(i2c, tc35892);
>-
>-      ret = tc35892_chip_init(tc35892);
>-      if (ret)
>-              goto out_free;
>-
>-      ret = tc35892_irq_init(tc35892);
>-      if (ret)
>-              goto out_free;
>-
>-      ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq,
>-                                 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
>-                                 "tc35892", tc35892);
>-      if (ret) {
>-              dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret);
>-              goto out_removeirq;
>-      }
>-
>-      ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs,
>-                            ARRAY_SIZE(tc35892_devs), NULL,
>-                            tc35892->irq_base);
>-      if (ret) {
>-              dev_err(tc35892->dev, "failed to add children\n");
>-              goto out_freeirq;
>-      }
>-
>-      return 0;
>-
>-out_freeirq:
>-      free_irq(tc35892->i2c->irq, tc35892);
>-out_removeirq:
>-      tc35892_irq_remove(tc35892);
>-out_free:
>-      kfree(tc35892);
>-      return ret;
>-}
>-
>-static int __devexit tc35892_remove(struct i2c_client *client)
>-{
>-      struct tc35892 *tc35892 = i2c_get_clientdata(client);
>-
>-      mfd_remove_devices(tc35892->dev);
>-
>-      free_irq(tc35892->i2c->irq, tc35892);
>-      tc35892_irq_remove(tc35892);
>-
>-      kfree(tc35892);
>-
>-      return 0;
>-}
>-
>-static const struct i2c_device_id tc35892_id[] = {
>-      { "tc35892", 24 },
>-      { }
>-};
>-MODULE_DEVICE_TABLE(i2c, tc35892_id);
>-
>-static struct i2c_driver tc35892_driver = {
>-      .driver.name    = "tc35892",
>-      .driver.owner   = THIS_MODULE,
>-      .probe          = tc35892_probe,
>-      .remove         = __devexit_p(tc35892_remove),
>-      .id_table       = tc35892_id,
>-};
>-
>-static int __init tc35892_init(void)
>-{
>-      return i2c_add_driver(&tc35892_driver);
>-}
>-subsys_initcall(tc35892_init);
>-
>-static void __exit tc35892_exit(void)
>-{
>-      i2c_del_driver(&tc35892_driver);
>-}
>-module_exit(tc35892_exit);
>-
>-MODULE_LICENSE("GPL v2");
>-MODULE_DESCRIPTION("TC35892 MFD core driver");
>-MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
>diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
>new file mode 100644
>index 0000000..e23e499
>--- /dev/null
>+++ b/drivers/mfd/tc3589x.c
>@@ -0,0 +1,465 @@
>+/*
>+ * Copyright (C) ST-Ericsson SA 2010
>+ *
>+ * License Terms: GNU General Public License, version 2
>+ * Author: Hanumath Prasad <hanumath.prasad@xxxxxxxxxxxxxx> for ST-Ericsson
>+ * Author: Rabin Vincent <rabin.vincent@xxxxxxxxxxxxxx> for ST-Ericsson
>+ */
>+
>+#include <linux/module.h>
>+#include <linux/interrupt.h>
>+#include <linux/irq.h>
>+#include <linux/slab.h>
>+#include <linux/i2c.h>
>+#include <linux/mfd/core.h>
>+#include <linux/mfd/tc3589x.h>
>+
>+#define TC3589x_CLKMODE_MODCTL_SLEEP          0x0
>+#define TC3589x_CLKMODE_MODCTL_OPERATION      (1 << 0)
>+
>+/**
>+ * tc3589x_reg_read() - read a single TC3589x register
>+ * @tc3589x:  Device to read from
>+ * @reg:      Register to read
>+ */
>+int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg)
>+{
>+      int ret;
>+
>+      ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg);
>+      if (ret < 0)
>+              dev_err(tc3589x->dev, "failed to read reg %#x: %d\n",
>+                      reg, ret);
>+
>+      return ret;
>+}
>+EXPORT_SYMBOL_GPL(tc3589x_reg_read);
>+
>+/**
>+ * tc3589x_reg_read() - write a single TC3589x register
>+ * @tc3589x:  Device to write to
>+ * @reg:      Register to read
>+ * @data:     Value to write
>+ */
>+int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data)
>+{
>+      int ret;
>+
>+      ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data);
>+      if (ret < 0)
>+              dev_err(tc3589x->dev, "failed to write reg %#x: %d\n",
>+                      reg, ret);
>+
>+      return ret;
>+}
>+EXPORT_SYMBOL_GPL(tc3589x_reg_write);
>+
>+/**
>+ * tc3589x_block_read() - read multiple TC3589x registers
>+ * @tc3589x:  Device to read from
>+ * @reg:      First register
>+ * @length:   Number of registers
>+ * @values:   Buffer to write to
>+ */
>+int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values)
>+{
>+      int ret;
>+
>+      ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values);
>+      if (ret < 0)
>+              dev_err(tc3589x->dev, "failed to read regs %#x: %d\n",
>+                      reg, ret);
>+
>+      return ret;
>+}
>+EXPORT_SYMBOL_GPL(tc3589x_block_read);
>+
>+/**
>+ * tc3589x_block_write() - write multiple TC3589x registers
>+ * @tc3589x:  Device to write to
>+ * @reg:      First register
>+ * @length:   Number of registers
>+ * @values:   Values to write
>+ */
>+int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
>+                      const u8 *values)
>+{
>+      int ret;
>+
>+      ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length,
>+                                           values);
>+      if (ret < 0)
>+              dev_err(tc3589x->dev, "failed to write regs %#x: %d\n",
>+                      reg, ret);
>+
>+      return ret;
>+}
>+EXPORT_SYMBOL_GPL(tc3589x_block_write);
>+
>+/**
>+ * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register
>+ * @tc3589x:  Device to write to
>+ * @reg:      Register to write
>+ * @mask:     Mask of bits to set
>+ * @values:   Value to set
>+ */
>+int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val)
>+{
>+      int ret;
>+
>+      mutex_lock(&tc3589x->lock);
>+
>+      ret = tc3589x_reg_read(tc3589x, reg);
>+      if (ret < 0)
>+              goto out;
>+
>+      ret &= ~mask;
>+      ret |= val;
>+
>+      ret = tc3589x_reg_write(tc3589x, reg, ret);
>+
>+out:
>+      mutex_unlock(&tc3589x->lock);
>+      return ret;
>+}
>+EXPORT_SYMBOL_GPL(tc3589x_set_bits);
>+
>+static struct resource gpio_resources[] = {
>+      {
>+              .start  = TC3589x_INT_GPIIRQ,
>+              .end    = TC3589x_INT_GPIIRQ,
>+              .flags  = IORESOURCE_IRQ,
>+      },
>+};
>+
>+static struct resource keypad_resources[] = {
>+      {
>+              .start  = TC3589x_INT_KBDIRQ,
>+              .end    = TC3589x_INT_KBDIRQ,
>+              .flags  = IORESOURCE_IRQ,
>+      },
>+};
>+
>+static struct mfd_cell tc3589x_devs_gpio[] = {
>+      {
>+              .name           = "tc3589x-gpio",
>+              .num_resources  = ARRAY_SIZE(gpio_resources),
>+              .resources      = &gpio_resources[0],
>+      },
>+};
>+
>+static struct mfd_cell tc3589x_devs_keypad[] = {
>+      {
>+              .name           = "tc3589x-keypad",
>+              .num_resources  = ARRAY_SIZE(keypad_resources),
>+              .resources      = &keypad_resources[0],
>+      },
>+};
>+
>+static irqreturn_t tc3589x_irq(int irq, void *data)
>+{
>+      struct tc3589x *tc3589x = data;
>+      int status;
>+
>+again:
>+      status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
>+      if (status < 0)
>+              return IRQ_NONE;
>+
>+      while (status) {
>+              int bit = __ffs(status);
>+
>+              handle_nested_irq(tc3589x->irq_base + bit);
>+              status &= ~(1 << bit);
>+      }
>+
>+      /*
>+       * A dummy read or write (to any register) appears to be necessary to
>+       * have the last interrupt clear (for example, GPIO IC write) take
>+       * effect. In such a case, recheck for any interrupt which is still
>+       * pending.
>+       */
>+      status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
>+      if (status)
>+              goto again;
>+
>+      return IRQ_HANDLED;
>+}
>+
>+static void tc3589x_irq_dummy(unsigned int irq)
>+{
>+      /* No mask/unmask at this level */
>+}
>+
>+static struct irq_chip tc3589x_irq_chip = {
>+      .name   = "tc3589x",
>+      .mask   = tc3589x_irq_dummy,
>+      .unmask = tc3589x_irq_dummy,
>+};
>+
>+static int tc3589x_irq_init(struct tc3589x *tc3589x)
>+{
>+      int base = tc3589x->irq_base;
>+      int irq;
>+
>+      for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
>+              set_irq_chip_data(irq, tc3589x);
>+              set_irq_chip_and_handler(irq, &tc3589x_irq_chip,
>+                                       handle_edge_irq);
>+              set_irq_nested_thread(irq, 1);
>+#ifdef CONFIG_ARM
>+              set_irq_flags(irq, IRQF_VALID);
>+#else
>+              set_irq_noprobe(irq);
>+#endif
>+      }
>+
>+      return 0;
>+}
>+
>+static void tc3589x_irq_remove(struct tc3589x *tc3589x)
>+{
>+      int base = tc3589x->irq_base;
>+      int irq;
>+
>+      for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
>+#ifdef CONFIG_ARM
>+              set_irq_flags(irq, 0);
>+#endif
>+              set_irq_chip_and_handler(irq, NULL, NULL);
>+              set_irq_chip_data(irq, NULL);
>+      }
>+}
>+
>+static int tc3589x_chip_init(struct tc3589x *tc3589x)
>+{
>+      int manf, ver, ret;
>+
>+      manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE);
>+      if (manf < 0)
>+              return manf;
>+
>+      ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION);
>+      if (ver < 0)
>+              return ver;
>+
>+      if (manf != TC3589x_MANFCODE_MAGIC) {
>+              dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf);
>+              return -EINVAL;
>+      }
>+
>+      dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
>+
>+      /*
>+       * Put everything except the IRQ module into reset;
>+       * also spare the GPIO module for any pin initialization
>+       * done during pre-kernel boot
>+       */
>+      ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL,
>+                              TC3589x_RSTCTRL_TIMRST
>+                              | TC3589x_RSTCTRL_ROTRST
>+                              | TC3589x_RSTCTRL_KBDRST);
>+      if (ret < 0)
>+              return ret;
>+
>+      /* Clear the reset interrupt. */
>+      return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
>+}
>+
>+static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
>+{
>+      int ret = 0;
>+      unsigned int blocks = tc3589x->pdata->block;
>+
>+      if (blocks & TC3589x_BLOCK_GPIO) {
>+                ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_devs_gpio,
>+                                ARRAY_SIZE(tc3589x_devs_gpio), NULL,
>+                                tc3589x->irq_base);
>+                if (ret) {
>+                        dev_err(tc3589x->dev, "failed to add children\n");
>+                        return ret;
>+                }
>+              dev_info(tc3589x->dev, "added gpio block\n");
>+      }
>+
>+      if (blocks & TC3589x_BLOCK_KEYPAD) {
>+                ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_devs_keypad,
>+                                ARRAY_SIZE(tc3589x_devs_keypad), NULL,
>+                                tc3589x->irq_base);
>+                if (ret) {
>+                        dev_err(tc3589x->dev, "failed to add children\n");
>+                        return ret;
>+                }
>+              dev_info(tc3589x->dev, "added keypad block\n");
>+      }
>+
>+      return ret;
>+
>+}
>+
>+static int __devinit tc3589x_probe(struct i2c_client *i2c,
>+                                 const struct i2c_device_id *id)
>+{
>+      struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
>+      struct tc3589x *tc3589x;
>+      int ret;
>+
>+      if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
>+                                   | I2C_FUNC_SMBUS_I2C_BLOCK))
>+              return -EIO;
>+
>+      tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL);
>+      if (!tc3589x)
>+              return -ENOMEM;
>+
>+      mutex_init(&tc3589x->lock);
>+
>+      tc3589x->dev = &i2c->dev;
>+      tc3589x->i2c = i2c;
>+      tc3589x->pdata = pdata;
>+      tc3589x->irq_base = pdata->irq_base;
>+      tc3589x->num_gpio = id->driver_data;
>+
>+      i2c_set_clientdata(i2c, tc3589x);
>+
>+      ret = tc3589x_chip_init(tc3589x);
>+      if (ret)
>+              goto out_free;
>+
>+      ret = tc3589x_irq_init(tc3589x);
>+      if (ret)
>+              goto out_free;
>+
>+      ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq,
>+                      IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
>+                      "tc3589x", tc3589x);
>+      if (ret) {
>+              dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret);
>+              goto out_removeirq;
>+      }
>+
>+      ret = tc3589x_device_init(tc3589x);
>+      if (ret) {
>+              dev_err(tc3589x->dev, "failed to add mfd cells\n");
>+              goto out_removeirq;
>+      }
>+#if 0
>+      /* if GPIO block */
>+      if (pdata->block == 0)  {
>+              ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_devs_gpio,
>+                              ARRAY_SIZE(tc3589x_devs_gpio), NULL,
>+                              tc3589x->irq_base);
>+              if (ret) {
>+                      dev_err(tc3589x->dev, "failed to add children\n");
>+                      goto out_freeirq;
>+              }
>+              dev_info(tc3589x->dev, "Added GPIO block client\n");
>+      }
>+
>+      /* if keypad block */
>+      if (pdata->block == 1)  {
>+              ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_devs_keypad,
>+                              ARRAY_SIZE(tc3589x_devs_keypad), NULL,
>+                              tc3589x->irq_base);
>+              if (ret) {
>+                      dev_err(tc3589x->dev, "failed to add children\n");
>+                      goto out_freeirq;
>+              }
>+              dev_info(tc3589x->dev, "Added Keypad block client\n");
>+      }
>+#endif
>+      return 0;
>+
>+out_freeirq:
>+      free_irq(tc3589x->i2c->irq, tc3589x);
>+out_removeirq:
>+      tc3589x_irq_remove(tc3589x);
>+out_free:
>+      i2c_set_clientdata(i2c, NULL);
>+      kfree(tc3589x);
>+      return ret;
>+}
>+
>+static int __devexit tc3589x_remove(struct i2c_client *client)
>+{
>+      struct tc3589x *tc3589x = i2c_get_clientdata(client);
>+
>+      mfd_remove_devices(tc3589x->dev);
>+
>+      free_irq(tc3589x->i2c->irq, tc3589x);
>+      tc3589x_irq_remove(tc3589x);
>+
>+      i2c_set_clientdata(client, NULL);
>+      kfree(tc3589x);
>+
>+      return 0;
>+}
>+
>+#ifdef CONFIG_PM
>+static int tc3589x_suspend(struct device *dev)
>+{
>+      struct tc3589x *tc3589x = dev_get_drvdata(dev);
>+      struct i2c_client *client = tc3589x->i2c;
>+      int ret = 0;
>+
>+      /* put the system to sleep mode */
>+      if (!device_may_wakeup(&client->dev))
>+              ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
>+                              TC3589x_CLKMODE_MODCTL_SLEEP);
>+
>+      return ret;
>+}
>+
>+static int tc3589x_resume(struct device *dev)
>+{
>+      struct tc3589x *tc3589x = dev_get_drvdata(dev);
>+      struct i2c_client *client = tc3589x->i2c;
>+      int ret = 0;
>+
>+      /* enable the system into operation */
>+      if (!device_may_wakeup(&client->dev))
>+              ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
>+                              TC3589x_CLKMODE_MODCTL_OPERATION);
>+
>+      return ret;
>+}
>+
>+
>+static const struct dev_pm_ops tc3589x_dev_pm_ops = {
>+      .suspend = tc3589x_suspend,
>+      .resume  = tc3589x_resume,
>+};
>+#endif
>+
>+static const struct i2c_device_id tc3589x_id[] = {
>+      { "tc3589x", 24 },
>+      { }
>+};
>+MODULE_DEVICE_TABLE(i2c, tc3589x_id);
>+
>+static struct i2c_driver tc3589x_driver = {
>+      .driver.name    = "tc3589x",
>+      .driver.owner   = THIS_MODULE,
>+#ifdef CONFIG_PM
>+      .driver.pm      = &tc3589x_dev_pm_ops,
>+#endif
>+      .probe          = tc3589x_probe,
>+      .remove         = __devexit_p(tc3589x_remove),
>+      .id_table       = tc3589x_id,
>+};
>+
>+static int __init tc3589x_init(void)
>+{
>+      return i2c_add_driver(&tc3589x_driver);
>+}
>+subsys_initcall(tc3589x_init);
>+
>+static void __exit tc3589x_exit(void)
>+{
>+      i2c_del_driver(&tc3589x_driver);
>+}
>+module_exit(tc3589x_exit);
>+
>+MODULE_LICENSE("GPL v2");
>+MODULE_DESCRIPTION("TC3589x MFD core driver");
>+MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
>diff --git a/include/linux/mfd/tc35892.h b/include/linux/mfd/tc35892.h
>deleted file mode 100644
>index eff3094..0000000
>--- a/include/linux/mfd/tc35892.h
>+++ /dev/null
>@@ -1,136 +0,0 @@
>-/*
>- * Copyright (C) ST-Ericsson SA 2010
>- *
>- * License Terms: GNU General Public License, version 2
>- */
>-
>-#ifndef __LINUX_MFD_TC35892_H
>-#define __LINUX_MFD_TC35892_H
>-
>-#include <linux/device.h>
>-
>-#define TC35892_RSTCTRL_IRQRST        (1 << 4)
>-#define TC35892_RSTCTRL_TIMRST        (1 << 3)
>-#define TC35892_RSTCTRL_ROTRST        (1 << 2)
>-#define TC35892_RSTCTRL_KBDRST        (1 << 1)
>-#define TC35892_RSTCTRL_GPIRST        (1 << 0)
>-
>-#define TC35892_IRQST         0x91
>-
>-#define TC35892_MANFCODE_MAGIC        0x03
>-#define TC35892_MANFCODE      0x80
>-#define TC35892_VERSION               0x81
>-#define TC35892_IOCFG         0xA7
>-
>-#define TC35892_CLKMODE               0x88
>-#define TC35892_CLKCFG                0x89
>-#define TC35892_CLKEN         0x8A
>-
>-#define TC35892_RSTCTRL               0x82
>-#define TC35892_EXTRSTN               0x83
>-#define TC35892_RSTINTCLR     0x84
>-
>-#define TC35892_GPIOIS0               0xC9
>-#define TC35892_GPIOIS1               0xCA
>-#define TC35892_GPIOIS2               0xCB
>-#define TC35892_GPIOIBE0      0xCC
>-#define TC35892_GPIOIBE1      0xCD
>-#define TC35892_GPIOIBE2      0xCE
>-#define TC35892_GPIOIEV0      0xCF
>-#define TC35892_GPIOIEV1      0xD0
>-#define TC35892_GPIOIEV2      0xD1
>-#define TC35892_GPIOIE0               0xD2
>-#define TC35892_GPIOIE1               0xD3
>-#define TC35892_GPIOIE2               0xD4
>-#define TC35892_GPIORIS0      0xD6
>-#define TC35892_GPIORIS1      0xD7
>-#define TC35892_GPIORIS2      0xD8
>-#define TC35892_GPIOMIS0      0xD9
>-#define TC35892_GPIOMIS1      0xDA
>-#define TC35892_GPIOMIS2      0xDB
>-#define TC35892_GPIOIC0               0xDC
>-#define TC35892_GPIOIC1               0xDD
>-#define TC35892_GPIOIC2               0xDE
>-
>-#define TC35892_GPIODATA0     0xC0
>-#define TC35892_GPIOMASK0     0xc1
>-#define TC35892_GPIODATA1     0xC2
>-#define TC35892_GPIOMASK1     0xc3
>-#define TC35892_GPIODATA2     0xC4
>-#define TC35892_GPIOMASK2     0xC5
>-
>-#define TC35892_GPIODIR0      0xC6
>-#define TC35892_GPIODIR1      0xC7
>-#define TC35892_GPIODIR2      0xC8
>-
>-#define TC35892_GPIOSYNC0     0xE6
>-#define TC35892_GPIOSYNC1     0xE7
>-#define TC35892_GPIOSYNC2     0xE8
>-
>-#define TC35892_GPIOWAKE0     0xE9
>-#define TC35892_GPIOWAKE1     0xEA
>-#define TC35892_GPIOWAKE2     0xEB
>-
>-#define TC35892_GPIOODM0      0xE0
>-#define TC35892_GPIOODE0      0xE1
>-#define TC35892_GPIOODM1      0xE2
>-#define TC35892_GPIOODE1      0xE3
>-#define TC35892_GPIOODM2      0xE4
>-#define TC35892_GPIOODE2      0xE5
>-
>-#define TC35892_INT_GPIIRQ    0
>-#define TC35892_INT_TI0IRQ    1
>-#define TC35892_INT_TI1IRQ    2
>-#define TC35892_INT_TI2IRQ    3
>-#define TC35892_INT_ROTIRQ    5
>-#define TC35892_INT_KBDIRQ    6
>-#define TC35892_INT_PORIRQ    7
>-
>-#define TC35892_NR_INTERNAL_IRQS      8
>-#define TC35892_INT_GPIO(x)   (TC35892_NR_INTERNAL_IRQS + (x))
>-
>-struct tc35892 {
>-      struct mutex lock;
>-      struct device *dev;
>-      struct i2c_client *i2c;
>-
>-      int irq_base;
>-      int num_gpio;
>-      struct tc35892_platform_data *pdata;
>-};
>-
>-extern int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data);
>-extern int tc35892_reg_read(struct tc35892 *tc35892, u8 reg);
>-extern int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length,
>-                            u8 *values);
>-extern int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length,
>-                             const u8 *values);
>-extern int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val);
>-
>-/**
>- * struct tc35892_gpio_platform_data - TC35892 GPIO platform data
>- * @gpio_base: first gpio number assigned to TC35892.  A maximum of
>- *           %TC35892_NR_GPIOS GPIOs will be allocated.
>- * @setup: callback for board-specific initialization
>- * @remove: callback for board-specific teardown
>- */
>-struct tc35892_gpio_platform_data {
>-      int gpio_base;
>-      void (*setup)(struct tc35892 *tc35892, unsigned gpio_base);
>-      void (*remove)(struct tc35892 *tc35892, unsigned gpio_base);
>-};
>-
>-/**
>- * struct tc35892_platform_data - TC35892 platform data
>- * @irq_base: base IRQ number.  %TC35892_NR_IRQS irqs will be used.
>- * @gpio: GPIO-specific platform data
>- */
>-struct tc35892_platform_data {
>-      int irq_base;
>-      struct tc35892_gpio_platform_data *gpio;
>-};
>-
>-#define TC35892_NR_GPIOS      24
>-#define TC35892_NR_IRQS               TC35892_INT_GPIO(TC35892_NR_GPIOS)
>-
>-#endif
>diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h
>new file mode 100644
>index 0000000..ef7d6fe
>--- /dev/null
>+++ b/include/linux/mfd/tc3589x.h
>@@ -0,0 +1,192 @@
>+/*
>+ * Copyright (C) ST-Ericsson SA 2010
>+ *
>+ * License Terms: GNU General Public License, version 2
>+ */
>+
>+#ifndef __LINUX_MFD_TC3589x_H
>+#define __LINUX_MFD_TC3589x_H
>+
>+#include <linux/device.h>
>+
>+#define TC3589x_RSTCTRL_IRQRST        (1 << 4)
>+#define TC3589x_RSTCTRL_TIMRST        (1 << 3)
>+#define TC3589x_RSTCTRL_ROTRST        (1 << 2)
>+#define TC3589x_RSTCTRL_KBDRST        (1 << 1)
>+#define TC3589x_RSTCTRL_GPIRST        (1 << 0)
>+
>+/* Keyboard Configuration Registers Index */
>+#define TC3589x_KBDSETTLE_REG   0x01
>+#define TC3589x_KBDBOUNCE       0x02
>+#define TC3589x_KBDSIZE         0x03
>+#define TC3589x_KBCFG_LSB       0x04
>+#define TC3589x_KBCFG_MSB       0x05
>+#define TC3589x_KBDIC           0x08
>+#define TC3589x_KBDMSK          0x09
>+#define TC3589x_EVTCODE_FIFO    0x10
>+
>+/* Pull up/down  configuration registers */
>+#define TC3589x_IOCFG           0xA7
>+#define TC3589x_IOPULLCFG0_LSB  0xAA
>+#define TC3589x_IOPULLCFG0_MSB  0xAB
>+#define TC3589x_IOPULLCFG1_LSB  0xAC
>+#define TC3589x_IOPULLCFG1_MSB  0xAD
>+#define TC3589x_IOPULLCFG2_LSB  0xAE
>+
>+#define TC3589x_IRQST         0x91
>+
>+#define TC3589x_MANFCODE_MAGIC        0x03
>+#define TC3589x_MANFCODE      0x80
>+#define TC3589x_VERSION               0x81
>+#define TC3589x_IOCFG         0xA7
>+
>+#define TC3589x_CLKMODE               0x88
>+#define TC3589x_CLKCFG                0x89
>+#define TC3589x_CLKEN         0x8A
>+
>+#define TC3589x_RSTCTRL               0x82
>+#define TC3589x_EXTRSTN               0x83
>+#define TC3589x_RSTINTCLR     0x84
>+
>+#define TC3589x_KBDMFS                0x8F
>+
>+#define TC3589x_GPIOIS0               0xC9
>+#define TC3589x_GPIOIS1               0xCA
>+#define TC3589x_GPIOIS2               0xCB
>+#define TC3589x_GPIOIBE0      0xCC
>+#define TC3589x_GPIOIBE1      0xCD
>+#define TC3589x_GPIOIBE2      0xCE
>+#define TC3589x_GPIOIEV0      0xCF
>+#define TC3589x_GPIOIEV1      0xD0
>+#define TC3589x_GPIOIEV2      0xD1
>+#define TC3589x_GPIOIE0               0xD2
>+#define TC3589x_GPIOIE1               0xD3
>+#define TC3589x_GPIOIE2               0xD4
>+#define TC3589x_GPIORIS0      0xD6
>+#define TC3589x_GPIORIS1      0xD7
>+#define TC3589x_GPIORIS2      0xD8
>+#define TC3589x_GPIOMIS0      0xD9
>+#define TC3589x_GPIOMIS1      0xDA
>+#define TC3589x_GPIOMIS2      0xDB
>+#define TC3589x_GPIOIC0               0xDC
>+#define TC3589x_GPIOIC1               0xDD
>+#define TC3589x_GPIOIC2               0xDE
>+
>+#define TC3589x_GPIODATA0     0xC0
>+#define TC3589x_GPIOMASK0     0xc1
>+#define TC3589x_GPIODATA1     0xC2
>+#define TC3589x_GPIOMASK1     0xc3
>+#define TC3589x_GPIODATA2     0xC4
>+#define TC3589x_GPIOMASK2     0xC5
>+
>+#define TC3589x_GPIODIR0      0xC6
>+#define TC3589x_GPIODIR1      0xC7
>+#define TC3589x_GPIODIR2      0xC8
>+
>+#define TC3589x_GPIOSYNC0     0xE6
>+#define TC3589x_GPIOSYNC1     0xE7
>+#define TC3589x_GPIOSYNC2     0xE8
>+
>+#define TC3589x_GPIOWAKE0     0xE9
>+#define TC3589x_GPIOWAKE1     0xEA
>+#define TC3589x_GPIOWAKE2     0xEB
>+
>+#define TC3589x_GPIOODM0      0xE0
>+#define TC3589x_GPIOODE0      0xE1
>+#define TC3589x_GPIOODM1      0xE2
>+#define TC3589x_GPIOODE1      0xE3
>+#define TC3589x_GPIOODM2      0xE4
>+#define TC3589x_GPIOODE2      0xE5
>+
>+#define TC3589x_INT_GPIIRQ    0
>+#define TC3589x_INT_TI0IRQ    1
>+#define TC3589x_INT_TI1IRQ    2
>+#define TC3589x_INT_TI2IRQ    3
>+#define TC3589x_INT_ROTIRQ    5
>+#define TC3589x_INT_KBDIRQ    6
>+#define TC3589x_INT_PORIRQ    7
>+
>+#define TC3589x_NR_INTERNAL_IRQS      8
>+#define TC3589x_INT_GPIO(x)   (TC3589x_NR_INTERNAL_IRQS + (x))
>+
>+struct tc3589x {
>+      struct mutex lock;
>+      struct device *dev;
>+      struct i2c_client *i2c;
>+
>+      int irq_base;
>+      int num_gpio;
>+      struct tc3589x_platform_data *pdata;
>+};
>+
>+extern int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data);
>+extern int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg);
>+extern int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length,
>+                            u8 *values);
>+extern int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
>+                             const u8 *values);
>+extern int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val);
>+
>+/*
>+ * Keypad related platform specific constants
>+ * These values may be modified for fine tuning
>+ */
>+#define TC_KPD_ROWS             0x8
>+#define TC_KPD_COLUMNS          0x8
>+#define TC_KPD_DEBOUNCE_PERIOD  0xA3
>+#define TC_KPD_SETTLE_TIME      0xA3
>+
>+/**
>+ * struct tc35893_platform_data - data structure for platform specific data
>+ * @keymap_data:        matrix scan code table for keycodes
>+ * @krow:               mask for available rows, value is 0xFF
>+ * @kcol:               mask for available columns, value is 0xFF
>+ * @debounce_period:    platform specific debounce time
>+ * @settle_time:        platform specific settle down time
>+ * @irqtype:            type of interrupt, falling or rising edge
>+ * @irq:                irq no,
>+ * @enable_wakeup:      specifies if keypad event can wake up system from sleep
>+ * @no_autorepeat:      flag for auto repetition
>+ */
>+struct tc3589x_keypad_platform_data {
>+        struct matrix_keymap_data *keymap_data;
>+        u8                      krow;
>+        u8                      kcol;
>+        u8                      debounce_period;
>+        u8                      settle_time;
>+        unsigned long           irqtype;
>+        int                     irq;
>+        bool                    enable_wakeup;
>+        bool                    no_autorepeat;
>+};
>+
>+/**
>+ * struct tc3589x_gpio_platform_data - TC3589x GPIO platform data
>+ * @gpio_base: first gpio number assigned to TC3589x.  A maximum of
>+ *           %TC3589x_NR_GPIOS GPIOs will be allocated.
>+ */
>+struct tc3589x_gpio_platform_data {
>+      int gpio_base;
>+};
>+
>+enum tx3589x_block {
>+      TC3589x_BLOCK_GPIO        = 1 << 0,
>+      TC3589x_BLOCK_KEYPAD      = 1 << 1,
>+};
>+
>+/**
>+ * struct tc3589x_platform_data - TC3589x platform data
>+ * @irq_base: base IRQ number.  %TC3589x_NR_IRQS irqs will be used.
>+ * @gpio: GPIO-specific platform data
>+ */
>+struct tc3589x_platform_data {
>+      int block;
>+      int irq_base;
>+      struct tc3589x_gpio_platform_data *gpio;
>+      struct tc3589x_keypad_platform_data *keypad;
>+};
>+
>+#define TC3589x_NR_GPIOS      24
>+#define TC3589x_NR_IRQS               TC3589x_INT_GPIO(TC3589x_NR_GPIOS)
>+
>+#endif
>--
>1.7.2.dirty

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux