gpio: kona: Add Kona gpio driver
authorDarwin Rambo <drambo@broadcom.com>
Tue, 11 Feb 2014 19:06:35 +0000 (11:06 -0800)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Sat, 22 Feb 2014 18:30:27 +0000 (19:30 +0100)
Add support for the Kona GPIO controller found on Broadcom mobile SoCs.

Signed-off-by: Darwin Rambo <drambo@broadcom.com>
Reviewed-by: Steve Rae <srae@broadcom.com>
Reviewed-by: Markus Mayer <markus.mayer@linaro.org>
Reviewed-by: Tim Kryger <tkryger@linaro.org>
drivers/gpio/Makefile
drivers/gpio/kona_gpio.c [new file with mode: 0644]

index b903c45c5249fe0e67f289fba4f788bc63f471c8..ed2c0c735b0258cff58a00cadd9db52e2be3081b 100644 (file)
@@ -8,6 +8,7 @@
 obj-$(CONFIG_AT91_GPIO)        += at91_gpio.o
 obj-$(CONFIG_INTEL_ICH6_GPIO)  += intel_ich6_gpio.o
 obj-$(CONFIG_KIRKWOOD_GPIO)    += kw_gpio.o
+obj-$(CONFIG_KONA_GPIO)        += kona_gpio.o
 obj-$(CONFIG_MARVELL_GPIO)     += mvgpio.o
 obj-$(CONFIG_MARVELL_MFP)      += mvmfp.o
 obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o
diff --git a/drivers/gpio/kona_gpio.c b/drivers/gpio/kona_gpio.c
new file mode 100644 (file)
index 0000000..6511743
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sysmap.h>
+
+#define GPIO_BASE                              (void *)GPIO2_BASE_ADDR
+
+#define GPIO_PASSWD                            0x00a5a501
+#define GPIO_PER_BANK                          32
+#define GPIO_MAX_BANK_NUM                      8
+
+#define GPIO_BANK(gpio)                                ((gpio) >> 5)
+#define GPIO_BITMASK(gpio)     \
+       (1UL << ((gpio) & (GPIO_PER_BANK - 1)))
+
+#define GPIO_OUT_STATUS(bank)                  (0x00000000 + ((bank) << 2))
+#define GPIO_IN_STATUS(bank)                   (0x00000020 + ((bank) << 2))
+#define GPIO_OUT_SET(bank)                     (0x00000040 + ((bank) << 2))
+#define GPIO_OUT_CLEAR(bank)                   (0x00000060 + ((bank) << 2))
+#define GPIO_INT_STATUS(bank)                  (0x00000080 + ((bank) << 2))
+#define GPIO_INT_MASK(bank)                    (0x000000a0 + ((bank) << 2))
+#define GPIO_INT_MSKCLR(bank)                  (0x000000c0 + ((bank) << 2))
+#define GPIO_CONTROL(bank)                     (0x00000100 + ((bank) << 2))
+#define GPIO_PWD_STATUS(bank)                  (0x00000500 + ((bank) << 2))
+
+#define GPIO_GPPWR_OFFSET                      0x00000520
+
+#define GPIO_GPCTR0_DBR_SHIFT                  5
+#define GPIO_GPCTR0_DBR_MASK                   0x000001e0
+
+#define GPIO_GPCTR0_ITR_SHIFT                  3
+#define GPIO_GPCTR0_ITR_MASK                   0x00000018
+#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE                0x00000001
+#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE       0x00000002
+#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE          0x00000003
+
+#define GPIO_GPCTR0_IOTR_MASK                  0x00000001
+#define GPIO_GPCTR0_IOTR_CMD_0UTPUT            0x00000000
+#define GPIO_GPCTR0_IOTR_CMD_INPUT             0x00000001
+
+int gpio_request(unsigned gpio, const char *label)
+{
+       unsigned int value, off;
+
+       writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
+       off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
+       value = readl(GPIO_BASE + off) & ~GPIO_BITMASK(gpio);
+       writel(value, GPIO_BASE + off);
+
+       return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+       unsigned int value, off;
+
+       writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
+       off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
+       value = readl(GPIO_BASE + off) | GPIO_BITMASK(gpio);
+       writel(value, GPIO_BASE + off);
+
+       return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+       u32 val;
+
+       val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+       val &= ~GPIO_GPCTR0_IOTR_MASK;
+       val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
+       writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
+
+       return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+       int bank_id = GPIO_BANK(gpio);
+       int bitmask = GPIO_BITMASK(gpio);
+       u32 val, off;
+
+       val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+       val &= ~GPIO_GPCTR0_IOTR_MASK;
+       val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT;
+       writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
+       off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+       val = readl(GPIO_BASE + off);
+       val |= bitmask;
+       writel(val, GPIO_BASE + off);
+
+       return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+       int bank_id = GPIO_BANK(gpio);
+       int bitmask = GPIO_BITMASK(gpio);
+       u32 val, off;
+
+       /* determine the GPIO pin direction */
+       val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+       val &= GPIO_GPCTR0_IOTR_MASK;
+
+       /* read the GPIO bank status */
+       off = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ?
+           GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
+       val = readl(GPIO_BASE + off);
+
+       /* return the specified bit status */
+       return !!(val & bitmask);
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+       int bank_id = GPIO_BANK(gpio);
+       int bitmask = GPIO_BITMASK(gpio);
+       u32 val, off;
+
+       /* determine the GPIO pin direction */
+       val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+       val &= GPIO_GPCTR0_IOTR_MASK;
+
+       /* this function only applies to output pin */
+       if (GPIO_GPCTR0_IOTR_CMD_INPUT == val) {
+               printf("%s: Cannot set an input pin %d\n", __func__, gpio);
+               return;
+       }
+
+       off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+       val = readl(GPIO_BASE + off);
+       val |= bitmask;
+       writel(val, GPIO_BASE + off);
+}