[3/6] gpio: kona: Add Kona gpio driver

Message ID 1390848810-7227-4-git-send-email-drambo@broadcom.com
State New
Headers show

Commit Message

Darwin Rambo Jan. 27, 2014, 6:53 p.m.
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    |    1 +
 drivers/gpio/kona_gpio.c |  143 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 144 insertions(+)
 create mode 100644 drivers/gpio/kona_gpio.c

Patch

diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index b903c45..ed2c0c7 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -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
index 0000000..a5782cc
--- /dev/null
+++ b/drivers/gpio/kona_gpio.c
@@ -0,0 +1,143 @@ 
+/*****************************************************************************
+*
+* Copyright 2013 Broadcom Corporation.  All rights reserved.
+*
+* 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);
+}