diff mbox

[v2,14/16] Davinci: tnetv107x gpio implementation

Message ID 1269553439-14886-15-git-send-email-cyril@ti.com (mailing list archive)
State Changes Requested
Headers show

Commit Message

Cyril Chemparathy March 25, 2010, 9:43 p.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index 6aac880..0284a4c 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -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
diff --git a/arch/arm/mach-davinci/gpio-tnetv107x.c b/arch/arm/mach-davinci/gpio-tnetv107x.c
new file mode 100644
index 0000000..d868b46
--- /dev/null
+++ b/arch/arm/mach-davinci/gpio-tnetv107x.c
@@ -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);
+}
diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h
index 0099e6e..7d242a4 100644
--- a/arch/arm/mach-davinci/include/mach/gpio.h
+++ b/arch/arm/mach-davinci/include/mach/gpio.h
@@ -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);
diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h
index 5b6c597..0c0772b 100644
--- a/arch/arm/mach-davinci/include/mach/tnetv107x.h
+++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h
@@ -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 */