@@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_DAVINCI_DM646x) += dm646x.o devices.o
obj-$(CONFIG_ARCH_DAVINCI_DM365) += dm365.o devices.o
obj-$(CONFIG_ARCH_DAVINCI_DA830) += da830.o devices-da8xx.o
obj-$(CONFIG_ARCH_DAVINCI_DA850) += da850.o devices-da8xx.o
+obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
obj-$(CONFIG_AINTC) += irq.o
obj-$(CONFIG_CP_INTC) += cp_intc.o
new file mode 100644
@@ -0,0 +1,155 @@
+/*
+ * TI TNETV107X GPIO Support
+ *
+ * Author: Cyril Chemparathy <cyril@ti.com>
+ *
+ * 2009 (c) Texas Instruments, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <mach/common.h>
+#include <mach/tnetv107x.h>
+
+struct tnetv107x_gpio_regs {
+ u32 idver;
+ u32 data_in[3];
+ u32 data_out[3];
+ u32 direction[3];
+ u32 enable[3];
+};
+
+struct tnetv107x_gpio_controller {
+ struct tnetv107x_gpio_regs __iomem *regs;
+ struct gpio_chip chip;
+};
+
+static struct tnetv107x_gpio_controller tnetv107x_gpio_controller;
+
+#define gpio_reg_index(gpio) ((gpio) >> 5)
+#define gpio_reg_bit(gpio) BIT((gpio) & 0x1f)
+
+#define gpio_reg_rmw(reg, mask, val) \
+ __raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg))
+
+#define gpio_reg_set_bit(reg, gpio) \
+ gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio))
+
+#define gpio_reg_clear_bit(reg, gpio) \
+ gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0)
+
+#define gpio_reg_get_bit(reg, gpio) \
+ (__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio))
+
+#define chip_to_gpio(chip) \
+ container_of(chip, struct tnetv107x_gpio_controller, chip)
+
+static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned gpio)
+{
+ struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ gpio_reg_set_bit(&ctlr->regs->enable, gpio);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned gpio)
+{
+ struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ gpio_reg_clear_bit(&ctlr->regs->enable, gpio);
+
+ local_irq_restore(flags);
+}
+
+static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
+{
+ struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ gpio_reg_set_bit(&ctlr->regs->direction, gpio);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static int tnetv107x_gpio_dir_out(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (value)
+ gpio_reg_set_bit(&ctlr->regs->data_out, gpio);
+ else
+ gpio_reg_clear_bit(&ctlr->regs->data_out, gpio);
+
+ gpio_reg_clear_bit(&ctlr->regs->direction, gpio);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+ struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+ int ret;
+
+ ret = gpio_reg_get_bit(&ctlr->regs->data_in, gpio);
+
+ return ret ? 1 : 0;
+}
+
+static void tnetv107x_gpio_set(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (value)
+ gpio_reg_set_bit(&ctlr->regs->data_out, gpio);
+ else
+ gpio_reg_clear_bit(&ctlr->regs->data_out, gpio);
+
+ local_irq_restore(flags);
+}
+
+void __init tnetv107x_gpio_init(void)
+{
+ struct tnetv107x_gpio_controller *ctlr = &tnetv107x_gpio_controller;
+
+ ctlr->regs = ioremap(TNETV107X_GPIO_BASE, PAGE_SIZE);
+
+ ctlr->chip.label = "TNETV107X";
+ ctlr->chip.request = tnetv107x_gpio_request;
+ ctlr->chip.free = tnetv107x_gpio_free;
+ ctlr->chip.direction_input = tnetv107x_gpio_dir_in;
+ ctlr->chip.get = tnetv107x_gpio_get;
+ ctlr->chip.direction_output = tnetv107x_gpio_dir_out;
+ ctlr->chip.set = tnetv107x_gpio_set;
+ ctlr->chip.base = 0;
+ ctlr->chip.ngpio = TNETV107X_N_GPIOS;
+ ctlr->chip.can_sleep = 0;
+
+ gpiochip_add(&ctlr->chip);
+}
@@ -101,7 +101,7 @@ static inline u32 __gpio_mask(unsigned gpio)
*/
static inline void gpio_set_value(unsigned gpio, int value)
{
- if (__builtin_constant_p(value) && gpio < DAVINCI_N_GPIO) {
+ if (__builtin_constant_p(value) && gpio < davinci_soc_info.gpio_num) {
struct gpio_controller __iomem *g;
u32 mask;
@@ -130,7 +130,7 @@ static inline int gpio_get_value(unsigned gpio)
{
struct gpio_controller __iomem *g;
- if (!__builtin_constant_p(gpio) || gpio >= DAVINCI_N_GPIO)
+ if (!__builtin_constant_p(gpio) || gpio >= davinci_soc_info.gpio_num)
return __gpio_get_value(gpio);
g = __gpio_to_controller(gpio);
@@ -139,7 +139,7 @@ static inline int gpio_get_value(unsigned gpio)
static inline int gpio_cansleep(unsigned gpio)
{
- if (__builtin_constant_p(gpio) && gpio < DAVINCI_N_GPIO)
+ if (__builtin_constant_p(gpio) && gpio < davinci_soc_info.gpio_num)
return 0;
else
return __gpio_cansleep(gpio);
@@ -69,6 +69,10 @@
#define TNETV107X_N_GPIOS 65
+#ifndef __ASSEMBLY__
+extern void __init tnetv107x_gpio_init(void);
+#endif
+
#endif /* __ASM_ARCH_DAVINCI_TNETV107X_H */