From 24e5219754111b52b2f59cd48d96f934f9bbf02b Mon Sep 17 00:00:00 2001 From: Darwin Rambo Date: Tue, 11 Feb 2014 11:06:35 -0800 Subject: [PATCH] gpio: kona: Add Kona gpio driver Add support for the Kona GPIO controller found on Broadcom mobile SoCs. Signed-off-by: Darwin Rambo Reviewed-by: Steve Rae Reviewed-by: Markus Mayer Reviewed-by: Tim Kryger --- drivers/gpio/Makefile | 1 + drivers/gpio/kona_gpio.c | 141 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 drivers/gpio/kona_gpio.c diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index b903c45c52..ed2c0c735b 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 0000000000..65117438c5 --- /dev/null +++ b/drivers/gpio/kona_gpio.c @@ -0,0 +1,141 @@ +/* + * Copyright 2013 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#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); +} -- 2.39.5