From: "Ying-Chun Liu (PaulLiu)" <paul....@linaro.org>

Add DA9052 gpio driver from Dialog.
Modify Kconfig/Makefile for DA9052 gpio driver.

Signed-off-by: Zhou Jingyu <jingyu.z...@freescale.com>
Acked-by: Lily Zhang <r58...@freescale.com>
Signed-off-by: Ying-Chun Liu (PaulLiu) <paul....@linaro.org>
---
 drivers/gpio/Kconfig       |    7 +
 drivers/gpio/Makefile      |    1 +
 drivers/gpio/da9052-gpio.c |  731 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 739 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpio/da9052-gpio.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 2967002..ab93c7ab 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -453,4 +453,11 @@ config GPIO_TPS65910
        help
          Select this option to enable GPIO driver for the TPS65910
          chip family.
+
+config DA9052_GPIO_ENABLE
+       bool "Dialog DA9052 GPIO"
+       depends on PMIC_DIALOG
+       help
+         Say Y  to enable the GPIO driver for the DA9052 chip
+
 endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index b605f8e..cebe1c3 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -48,3 +48,4 @@ obj-$(CONFIG_GPIO_VX855)      += vx855_gpio.o
 obj-$(CONFIG_GPIO_ML_IOH)      += ml_ioh_gpio.o
 obj-$(CONFIG_AB8500_GPIO)       += ab8500-gpio.o
 obj-$(CONFIG_GPIO_TPS65910)    += tps65910-gpio.o
+obj-$(CONFIG_DA9052_GPIO_ENABLE)+= da9052-gpio.o
diff --git a/drivers/gpio/da9052-gpio.c b/drivers/gpio/da9052-gpio.c
new file mode 100644
index 0000000..a9c53f2
--- /dev/null
+++ b/drivers/gpio/da9052-gpio.c
@@ -0,0 +1,731 @@
+/*
+ * da9052-gpio.c  --  GPIO Driver for Dialog DA9052
+ *
+ * Copyright(c) 2009 Dialog Semiconductor Ltd.
+ *
+ * Author: Dialog Semiconductor Ltd <dc...@diasemi.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/syscalls.h>
+#include <linux/seq_file.h>
+#include <linux/gpio.h>
+
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/reg.h>
+#include <linux/mfd/da9052/gpio.h>
+
+#define DRIVER_NAME "da9052-gpio"
+static inline struct da9052_gpio_chip *to_da9052_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct da9052_gpio_chip, gp);
+}
+
+void da9052_gpio_notifier(struct da9052_eh_nb *eh_data, unsigned int event)
+{
+       struct da9052_gpio_chip *gpio =
+                       container_of(eh_data, struct da9052_gpio_chip, eh_data);
+       kobject_uevent(&gpio->gp.dev->kobj, KOBJ_CHANGE);
+       printk(KERN_INFO "Event received from GPIO8\n");
+}
+
+static u8 create_gpio_config_value(u8 gpio_function, u8 gpio_type, u8 
gpio_mode)
+{
+       /* The format is -
+               function - 2 bits
+               type - 1 bit
+               mode - 1 bit */
+       return gpio_function | (gpio_type << 2) | (gpio_mode << 3);
+}
+
+static s32 write_default_gpio_values(struct da9052 *da9052)
+{
+       struct da9052_ssc_msg msg;
+       u8 created_val = 0;
+
+#if (DA9052_GPIO_PIN_0 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0001_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO0_FUNCTION,
+                       DEFAULT_GPIO0_TYPE, DEFAULT_GPIO0_MODE);
+       msg.data &= DA9052_GPIO_MASK_UPPER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+#if (DA9052_GPIO_PIN_1 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0001_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO1_FUNCTION,
+                       DEFAULT_GPIO1_TYPE, DEFAULT_GPIO1_MODE);
+       created_val = created_val << DA9052_GPIO_NIBBLE_SHIFT;
+       msg.data &= DA9052_GPIO_MASK_LOWER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+/* GPIO 2-3*/
+#if (DA9052_GPIO_PIN_2 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0203_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO2_FUNCTION,
+                       DEFAULT_GPIO2_TYPE, DEFAULT_GPIO2_MODE);
+       msg.data &= DA9052_GPIO_MASK_UPPER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+#if (DA9052_GPIO_PIN_3 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0203_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO3_FUNCTION,
+                       DEFAULT_GPIO3_TYPE, DEFAULT_GPIO3_MODE);
+       created_val = created_val << DA9052_GPIO_NIBBLE_SHIFT;
+       msg.data &= DA9052_GPIO_MASK_LOWER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+/* GPIO 4-5*/
+#if (DA9052_GPIO_PIN_4 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0405_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO4_FUNCTION,
+                       DEFAULT_GPIO4_TYPE, DEFAULT_GPIO4_MODE);
+       msg.data &= DA9052_GPIO_MASK_UPPER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+#if (DA9052_GPIO_PIN_5 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0405_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO5_FUNCTION,
+                       DEFAULT_GPIO5_TYPE, DEFAULT_GPIO5_MODE);
+       created_val = created_val << DA9052_GPIO_NIBBLE_SHIFT;
+       msg.data &= DA9052_GPIO_MASK_LOWER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+/* GPIO 6-7*/
+#if (DA9052_GPIO_PIN_6 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0607_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO6_FUNCTION,
+                       DEFAULT_GPIO6_TYPE, DEFAULT_GPIO6_MODE);
+       msg.data &= DA9052_GPIO_MASK_UPPER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+#if (DA9052_GPIO_PIN_7 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0607_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO7_FUNCTION,
+                       DEFAULT_GPIO7_TYPE, DEFAULT_GPIO7_MODE);
+       created_val = created_val << DA9052_GPIO_NIBBLE_SHIFT;
+       msg.data &= DA9052_GPIO_MASK_LOWER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+/* GPIO 8-9*/
+#if (DA9052_GPIO_PIN_8 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0809_REG;
+       msg.data = 0;
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO8_FUNCTION,
+                       DEFAULT_GPIO8_TYPE, DEFAULT_GPIO8_MODE);
+       msg.data &= DA9052_GPIO_MASK_UPPER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+#if (DA9052_GPIO_PIN_9 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO0809_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO9_FUNCTION,
+                       DEFAULT_GPIO9_TYPE, DEFAULT_GPIO9_MODE);
+       created_val = created_val << DA9052_GPIO_NIBBLE_SHIFT;
+       msg.data &= DA9052_GPIO_MASK_LOWER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+/* GPIO 10-11*/
+#if (DA9052_GPIO_PIN_10 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO1011_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO10_FUNCTION,
+                       DEFAULT_GPIO10_TYPE, DEFAULT_GPIO10_MODE);
+       msg.data &= DA9052_GPIO_MASK_UPPER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+#if (DA9052_GPIO_PIN_11 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO1011_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO11_FUNCTION,
+                       DEFAULT_GPIO11_TYPE, DEFAULT_GPIO11_MODE);
+       created_val = created_val << DA9052_GPIO_NIBBLE_SHIFT;
+       msg.data &= DA9052_GPIO_MASK_LOWER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+/* GPIO 12-13*/
+#if (DA9052_GPIO_PIN_12 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO1213_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO12_FUNCTION,
+                       DEFAULT_GPIO12_TYPE, DEFAULT_GPIO12_MODE);
+       msg.data &= DA9052_GPIO_MASK_UPPER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+#if (DA9052_GPIO_PIN_13 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO1213_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO13_FUNCTION,
+                       DEFAULT_GPIO13_TYPE, DEFAULT_GPIO13_MODE);
+       created_val = created_val << DA9052_GPIO_NIBBLE_SHIFT;
+       msg.data &= DA9052_GPIO_MASK_LOWER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+/* GPIO 14-15*/
+#if (DA9052_GPIO_PIN_14 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO1415_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO14_FUNCTION,
+                       DEFAULT_GPIO14_TYPE, DEFAULT_GPIO14_MODE);
+       msg.data &= DA9052_GPIO_MASK_UPPER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+#if (DA9052_GPIO_PIN_15 == DA9052_GPIO_CONFIG)
+       da9052_lock(da9052);
+       msg.addr = DA9052_GPIO1415_REG;
+       msg.data = 0;
+
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+
+       created_val = create_gpio_config_value(DEFAULT_GPIO15_FUNCTION,
+                       DEFAULT_GPIO15_TYPE, DEFAULT_GPIO15_MODE);
+       created_val = created_val << DA9052_GPIO_NIBBLE_SHIFT;
+       msg.data &= DA9052_GPIO_MASK_LOWER_NIBBLE;
+       msg.data |= created_val;
+
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+#endif
+       return 0;
+}
+
+s32 da9052_gpio_read_port(struct da9052_gpio_read_write *read_port,
+                               struct da9052 *da9052)
+{
+       struct da9052_ssc_msg msg;
+       u8 shift_value = 0;
+       u8 port_functionality = 0;
+       msg.addr = (read_port->port_number / 2) + DA9052_GPIO0001_REG;
+       msg.data = 0;
+       da9052_lock(da9052);
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+       port_functionality =
+                       (read_port->port_number % 2) ?
+                       ((msg.data & DA9052_GPIO_ODD_PORT_FUNCTIONALITY) >>
+                                       DA9052_GPIO_NIBBLE_SHIFT) :
+                       (msg.data & DA9052_GPIO_EVEN_PORT_FUNCTIONALITY);
+
+       if (port_functionality != INPUT)
+               return DA9052_GPIO_INVALID_PORTNUMBER;
+
+       if (read_port->port_number >= (DA9052_GPIO_MAX_PORTNUMBER))
+               return DA9052_GPIO_INVALID_PORTNUMBER;
+
+       if (read_port->port_number < DA9052_GPIO_MAX_PORTS_PER_REGISTER)
+               msg.addr = DA9052_STATUSC_REG;
+       else
+               msg.addr = DA9052_STATUSD_REG;
+       msg.data = 0;
+
+       da9052_lock(da9052);
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+
+       shift_value = msg.data &
+               (1 << DA9052_GPIO_SHIFT_COUNT(read_port->port_number));
+       read_port->read_write_value = (shift_value >>
+                       DA9052_GPIO_SHIFT_COUNT(read_port->port_number));
+
+       return 0;
+}
+
+s32 da9052_gpio_multiple_read(struct da9052_gpio_multiple_read *multiple_port,
+                               struct da9052 *da9052)
+{
+       struct da9052_ssc_msg msg[2];
+       u8 port_number = 0;
+       u8 loop_index = 0;
+       msg[loop_index++].addr = DA9052_STATUSC_REG;
+       msg[loop_index++].addr = DA9052_STATUSD_REG;
+
+       da9052_lock(da9052);
+       if (da9052->read_many(da9052, msg, loop_index)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+       loop_index = 0;
+       for (port_number = 0; port_number < DA9052_GPIO_MAX_PORTS_PER_REGISTER;
+                                                       port_number++) {
+               multiple_port->signal_value[port_number] =
+                       msg[loop_index].data & 1;
+               msg[loop_index].data = msg[loop_index].data >> 1;
+       }
+       loop_index++;
+       for (port_number = DA9052_GPIO_MAX_PORTS_PER_REGISTER;
+               port_number < DA9052_GPIO_MAX_PORTNUMBER; port_number++) {
+               multiple_port->signal_value[port_number] =
+                       msg[loop_index].data & 1;
+               msg[loop_index].data = msg[loop_index].data >> 1;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(da9052_gpio_multiple_read);
+
+s32 da9052_gpio_write_port(struct da9052_gpio_read_write *write_port,
+                               struct da9052 *da9052)
+{
+       struct da9052_ssc_msg msg;
+       u8 port_functionality  = 0;
+       u8 bit_pos = 0;
+       msg.addr = DA9052_GPIO0001_REG + (write_port->port_number / 2);
+       msg.data = 0;
+
+       da9052_lock(da9052);
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+
+       port_functionality =
+                       (write_port->port_number % 2) ?
+                       ((msg.data & DA9052_GPIO_ODD_PORT_FUNCTIONALITY) >>
+                                               DA9052_GPIO_NIBBLE_SHIFT) :
+                       (msg.data & DA9052_GPIO_EVEN_PORT_FUNCTIONALITY);
+
+       if (port_functionality < 2)
+               return DA9052_GPIO_INVALID_PORTNUMBER;
+
+       bit_pos = (write_port->port_number % 2) ?
+                       DA9052_GPIO_ODD_PORT_WRITE_MODE :
+                               DA9052_GPIO_EVEN_PORT_WRITE_MODE;
+
+       if (write_port->read_write_value)
+               msg.data = msg.data | bit_pos;
+       else
+               msg.data = (msg.data & ~(bit_pos));
+
+       da9052_lock(da9052);
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+       return 0;
+}
+
+s32 da9052_gpio_configure_port(struct da9052_gpio *gpio_data,
+                               struct da9052 *da9052)
+{
+       struct da9052_ssc_msg msg;
+       u8 register_value = 0;
+       u8 function = 0;
+       u8 port_functionality = 0;
+       msg.addr = (gpio_data->port_number / 2) + DA9052_GPIO0001_REG;
+       msg.data = 0;
+
+       da9052_lock(da9052);
+       if (da9052->read(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+
+       port_functionality =
+                       (gpio_data->port_number % 2) ?
+                       ((msg.data & DA9052_GPIO_ODD_PORT_FUNCTIONALITY) >>
+                                       DA9052_GPIO_NIBBLE_SHIFT) :
+                       (msg.data & DA9052_GPIO_EVEN_PORT_FUNCTIONALITY);
+       if (port_functionality < INPUT)
+               return DA9052_GPIO_INVALID_PORTNUMBER;
+       if (gpio_data->gpio_config.input.type > ACTIVE_HIGH)
+               return DA9052_GPIO_INVALID_TYPE;
+       if (gpio_data->gpio_config.input.mode > DEBOUNCING_ON)
+               return DA9052_GPIO_INVALID_MODE;
+       function = gpio_data->gpio_function;
+       switch (function) {
+       case INPUT:
+               register_value = create_gpio_config_value(function,
+                                       gpio_data->gpio_config.input.type,
+                                       gpio_data->gpio_config.input.mode);
+       break;
+       case OUTPUT_OPENDRAIN:
+       case OUTPUT_PUSHPULL:
+               register_value = create_gpio_config_value(function,
+                                       gpio_data->gpio_config.input.type,
+                                       gpio_data->gpio_config.input.mode);
+       break;
+       default:
+               return DA9052_GPIO_INVALID_FUNCTION;
+       break;
+       }
+
+       if (gpio_data->port_number % 2) {
+               msg.data = (msg.data & ~(DA9052_GPIO_MASK_UPPER_NIBBLE)) |
+                               (register_value << DA9052_GPIO_NIBBLE_SHIFT);
+       } else {
+               msg.data = (msg.data & ~(DA9052_GPIO_MASK_LOWER_NIBBLE)) |
+                               register_value;
+       }
+       da9052_lock(da9052);
+       if (da9052->write(da9052, &msg)) {
+               da9052_unlock(da9052);
+               return -EIO;
+       }
+       da9052_unlock(da9052);
+       return 0;
+}
+
+static s32 da9052_gpio_read(struct gpio_chip *gc, u32 offset)
+{
+       struct da9052_gpio_chip *gpio;
+       gpio = to_da9052_gpio(gc);
+       gpio->read_write.port_number            = offset;
+       da9052_gpio_read_port(&gpio->read_write, gpio->da9052);
+       return gpio->read_write.read_write_value;
+}
+
+static void da9052_gpio_write(struct gpio_chip *gc, u32 offset, s32 value)
+{
+       struct da9052_gpio_chip *gpio;
+       gpio = to_da9052_gpio(gc);
+       gpio->read_write.port_number            = offset;
+       gpio->read_write.read_write_value       = (u8)value;
+       da9052_gpio_write_port(&gpio->read_write, gpio->da9052);
+}
+
+static s32 da9052_gpio_ip(struct gpio_chip *gc, u32 offset)
+{
+       struct da9052_gpio_chip *gpio;
+       gpio = to_da9052_gpio(gc);
+       gpio->gpio.gpio_function                        = INPUT;
+       gpio->gpio.gpio_config.input.type       = ACTIVE_LOW;
+       gpio->gpio.gpio_config.input.mode       = DEBOUNCING_ON;
+       gpio->gpio.port_number                          = offset;
+       return da9052_gpio_configure_port(&gpio->gpio, gpio->da9052);
+}
+
+static s32 da9052_gpio_op(struct gpio_chip *gc, u32 offset, s32 value)
+{
+       struct da9052_gpio_chip *gpio;
+       gpio = to_da9052_gpio(gc);
+       gpio->gpio.gpio_function                = OUTPUT_PUSHPULL;
+       gpio->gpio.gpio_config.output.type      = SUPPLY_VDD_IO1;
+       gpio->gpio.gpio_config.output.mode      = value;
+       gpio->gpio.port_number                  = offset;
+       return da9052_gpio_configure_port(&gpio->gpio, gpio->da9052);
+}
+
+static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
+{
+       struct da9052_gpio_chip *gpio;
+       gpio = to_da9052_gpio(gc);
+       kobject_uevent(&gpio->gp.dev->kobj, KOBJ_CHANGE);
+       printk(KERN_INFO"gpio->gp.base +offset = %d\n", gpio->gp.base + offset);
+       printk(KERN_INFO"Test1\n\n");
+       return gpio->gp.base + offset;
+}
+
+static int __devinit da9052_gpio_probe(struct platform_device *pdev)
+{
+       struct da9052_gpio_chip *gpio;
+       struct da9052_platform_data *pdata = (pdev->dev.platform_data);
+       s32 ret;
+       gpio = kzalloc(sizeof(*gpio), GFP_KERNEL);
+       if (gpio == NULL)
+               return -ENOMEM;
+       gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
+       gpio->gp.get                    = da9052_gpio_read;
+       gpio->gp.direction_input        = da9052_gpio_ip;
+       gpio->gp.direction_output       = da9052_gpio_op;
+       gpio->gp.set                    = da9052_gpio_write;
+
+       gpio->gp.base                           = pdata->gpio_base;
+       gpio->gp.ngpio                          = DA9052_GPIO_MAX_PORTNUMBER;
+       gpio->gp.can_sleep                      = 1;
+       gpio->gp.dev                            = &pdev->dev;
+       gpio->gp.owner                          = THIS_MODULE;
+       gpio->gp.label                          = "da9052-gpio";
+       gpio->gp.to_irq                         = da9052_gpio_to_irq;
+
+       gpio->eh_data.eve_type = GPI8_EVE;
+       gpio->eh_data.call_back = &da9052_gpio_notifier;
+       ret = gpio->da9052->register_event_notifier(gpio->da9052,
+                       &gpio->eh_data);
+
+       ret = write_default_gpio_values(gpio->da9052);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "GPIO initial config failed, %d\n",
+                       ret);
+               goto ret;
+       }
+
+       ret = gpiochip_add(&gpio->gp);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+                       ret);
+               goto ret;
+       }
+       platform_set_drvdata(pdev, gpio);
+
+       return ret;
+
+ret:
+       kfree(gpio);
+       return ret;
+
+}
+
+static int __devexit da9052_gpio_remove(struct platform_device *pdev)
+{
+       struct da9052_gpio_chip *gpio = platform_get_drvdata(pdev);
+       int ret;
+
+       gpio->da9052->unregister_event_notifier
+                       (gpio->da9052, &gpio->eh_data);
+       ret = gpiochip_remove(&gpio->gp);
+       if (ret == 0)
+               kfree(gpio);
+       return 0;
+}
+
+static struct platform_driver da9052_gpio_driver = {
+       .probe          = da9052_gpio_probe,
+       .remove         = __devexit_p(da9052_gpio_remove),
+       .driver         = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init da9052_gpio_init(void)
+{
+       return platform_driver_register(&da9052_gpio_driver);
+}
+
+static void __exit da9052_gpio_exit(void)
+{
+       return platform_driver_unregister(&da9052_gpio_driver);
+}
+
+module_init(da9052_gpio_init);
+module_exit(da9052_gpio_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dc...@diasemi.com>");
+MODULE_DESCRIPTION("DA9052 GPIO Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
-- 
1.7.5.3


_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to