diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpio/bcm2835_gpio.c | 89 | ||||
-rw-r--r-- | drivers/gpio/db8500_gpio.c | 221 | ||||
-rw-r--r-- | drivers/gpio/mxc_gpio.c | 10 | ||||
-rw-r--r-- | drivers/gpio/mxs_gpio.c | 16 | ||||
-rw-r--r-- | drivers/gpio/omap_gpio.c | 243 | ||||
-rw-r--r-- | drivers/gpio/tegra_gpio.c | 12 |
7 files changed, 576 insertions, 18 deletions
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 106549dc2c..17f4b739a9 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -41,6 +41,9 @@ COBJS-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o COBJS-$(CONFIG_ALTERA_PIO) += altera_pio.o COBJS-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o COBJS-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o +COBJS-$(CONFIG_OMAP_GPIO) += omap_gpio.o +COBJS-$(CONFIG_DB8500_GPIO) += db8500_gpio.o +COBJS-$(CONFIG_BCM2835_GPIO) += bcm2835_gpio.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c new file mode 100644 index 0000000000..1d50dbd5e0 --- /dev/null +++ b/drivers/gpio/bcm2835_gpio.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2012 Vikram Narayananan + * <vikram186@gmail.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <asm/gpio.h> +#include <asm/io.h> + +inline int gpio_is_valid(unsigned gpio) +{ + return (gpio < BCM2835_GPIO_COUNT); +} + +int gpio_request(unsigned gpio, const char *label) +{ + return !gpio_is_valid(gpio); +} + +int gpio_free(unsigned gpio) +{ + return 0; +} + +int gpio_direction_input(unsigned gpio) +{ + struct bcm2835_gpio_regs *reg = + (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE; + unsigned val; + + val = readl(®->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); + val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio)); + val |= (BCM2835_GPIO_INPUT << BCM2835_GPIO_FSEL_SHIFT(gpio)); + writel(val, ®->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); + + return 0; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + struct bcm2835_gpio_regs *reg = + (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE; + unsigned val; + + gpio_set_value(gpio, value); + + val = readl(®->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); + val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio)); + val |= (BCM2835_GPIO_OUTPUT << BCM2835_GPIO_FSEL_SHIFT(gpio)); + writel(val, ®->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); + + return 0; +} + +int gpio_get_value(unsigned gpio) +{ + struct bcm2835_gpio_regs *reg = + (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE; + unsigned val; + + val = readl(®->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]); + + return (val >> BCM2835_GPIO_COMMON_SHIFT(gpio)) & 0x1; +} + +int gpio_set_value(unsigned gpio, int value) +{ + struct bcm2835_gpio_regs *reg = + (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE; + u32 *output_reg = value ? reg->gpset : reg->gpclr; + + writel(1 << BCM2835_GPIO_COMMON_SHIFT(gpio), + &output_reg[BCM2835_GPIO_COMMON_BANK(gpio)]); + + return 0; +} diff --git a/drivers/gpio/db8500_gpio.c b/drivers/gpio/db8500_gpio.c new file mode 100644 index 0000000000..d5cb383e85 --- /dev/null +++ b/drivers/gpio/db8500_gpio.c @@ -0,0 +1,221 @@ +/* + * Code ported from Nomadik GPIO driver in ST-Ericsson Linux kernel code. + * The purpose is that GPIO config found in kernel should work by simply + * copy-paste it to U-boot. + * + * Original Linux authors: + * Copyright (C) 2008,2009 STMicroelectronics + * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> + * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com> + * + * Ported to U-boot by: + * Copyright (C) 2010 Joakim Axelsson <joakim.axelsson AT stericsson.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <common.h> +#include <asm/io.h> + +#include <asm/arch/db8500_gpio.h> +#include <asm/arch/db8500_pincfg.h> +#include <linux/compiler.h> + +#define IO_ADDR(x) (void *) (x) + +/* + * The GPIO module in the db8500 Systems-on-Chip is an + * AMBA device, managing 32 pins and alternate functions. The logic block + * is currently only used in the db8500. + */ + +#define GPIO_TOTAL_PINS 268 +#define GPIO_PINS_PER_BLOCK 32 +#define GPIO_BLOCKS_COUNT (GPIO_TOTAL_PINS/GPIO_PINS_PER_BLOCK + 1) +#define GPIO_BLOCK(pin) (((pin + GPIO_PINS_PER_BLOCK) >> 5) - 1) +#define GPIO_PIN_WITHIN_BLOCK(pin) ((pin)%(GPIO_PINS_PER_BLOCK)) + +/* Register in the logic block */ +#define DB8500_GPIO_DAT 0x00 +#define DB8500_GPIO_DATS 0x04 +#define DB8500_GPIO_DATC 0x08 +#define DB8500_GPIO_PDIS 0x0c +#define DB8500_GPIO_DIR 0x10 +#define DB8500_GPIO_DIRS 0x14 +#define DB8500_GPIO_DIRC 0x18 +#define DB8500_GPIO_SLPC 0x1c +#define DB8500_GPIO_AFSLA 0x20 +#define DB8500_GPIO_AFSLB 0x24 + +#define DB8500_GPIO_RIMSC 0x40 +#define DB8500_GPIO_FIMSC 0x44 +#define DB8500_GPIO_IS 0x48 +#define DB8500_GPIO_IC 0x4c +#define DB8500_GPIO_RWIMSC 0x50 +#define DB8500_GPIO_FWIMSC 0x54 +#define DB8500_GPIO_WKS 0x58 + +static void __iomem *get_gpio_addr(unsigned gpio) +{ + /* Our list of GPIO chips */ + static void __iomem *gpio_addrs[GPIO_BLOCKS_COUNT] = { + IO_ADDR(CFG_GPIO_0_BASE), + IO_ADDR(CFG_GPIO_1_BASE), + IO_ADDR(CFG_GPIO_2_BASE), + IO_ADDR(CFG_GPIO_3_BASE), + IO_ADDR(CFG_GPIO_4_BASE), + IO_ADDR(CFG_GPIO_5_BASE), + IO_ADDR(CFG_GPIO_6_BASE), + IO_ADDR(CFG_GPIO_7_BASE), + IO_ADDR(CFG_GPIO_8_BASE) + }; + + return gpio_addrs[GPIO_BLOCK(gpio)]; +} + +static unsigned get_gpio_offset(unsigned gpio) +{ + return GPIO_PIN_WITHIN_BLOCK(gpio); +} + +/* Can only be called from config_pin. Don't configure alt-mode directly */ +static void gpio_set_mode(unsigned gpio, enum db8500_gpio_alt mode) +{ + void __iomem *addr = get_gpio_addr(gpio); + unsigned offset = get_gpio_offset(gpio); + u32 bit = 1 << offset; + u32 afunc, bfunc; + + afunc = readl(addr + DB8500_GPIO_AFSLA) & ~bit; + bfunc = readl(addr + DB8500_GPIO_AFSLB) & ~bit; + if (mode & DB8500_GPIO_ALT_A) + afunc |= bit; + if (mode & DB8500_GPIO_ALT_B) + bfunc |= bit; + writel(afunc, addr + DB8500_GPIO_AFSLA); + writel(bfunc, addr + DB8500_GPIO_AFSLB); +} + +/** + * db8500_gpio_set_pull() - enable/disable pull up/down on a gpio + * @gpio: pin number + * @pull: one of DB8500_GPIO_PULL_DOWN, DB8500_GPIO_PULL_UP, + * and DB8500_GPIO_PULL_NONE + * + * Enables/disables pull up/down on a specified pin. This only takes effect if + * the pin is configured as an input (either explicitly or by the alternate + * function). + * + * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is + * configured as an input. Otherwise, due to the way the controller registers + * work, this function will change the value output on the pin. + */ +void db8500_gpio_set_pull(unsigned gpio, enum db8500_gpio_pull pull) +{ + void __iomem *addr = get_gpio_addr(gpio); + unsigned offset = get_gpio_offset(gpio); + u32 bit = 1 << offset; + u32 pdis; + + pdis = readl(addr + DB8500_GPIO_PDIS); + if (pull == DB8500_GPIO_PULL_NONE) + pdis |= bit; + else + pdis &= ~bit; + writel(pdis, addr + DB8500_GPIO_PDIS); + + if (pull == DB8500_GPIO_PULL_UP) + writel(bit, addr + DB8500_GPIO_DATS); + else if (pull == DB8500_GPIO_PULL_DOWN) + writel(bit, addr + DB8500_GPIO_DATC); +} + +void db8500_gpio_make_input(unsigned gpio) +{ + void __iomem *addr = get_gpio_addr(gpio); + unsigned offset = get_gpio_offset(gpio); + + writel(1 << offset, addr + DB8500_GPIO_DIRC); +} + +int db8500_gpio_get_input(unsigned gpio) +{ + void __iomem *addr = get_gpio_addr(gpio); + unsigned offset = get_gpio_offset(gpio); + u32 bit = 1 << offset; + + printf("db8500_gpio_get_input gpio=%u addr=%p offset=%u bit=%#x\n", + gpio, addr, offset, bit); + + return (readl(addr + DB8500_GPIO_DAT) & bit) != 0; +} + +void db8500_gpio_make_output(unsigned gpio, int val) +{ + void __iomem *addr = get_gpio_addr(gpio); + unsigned offset = get_gpio_offset(gpio); + + writel(1 << offset, addr + DB8500_GPIO_DIRS); + db8500_gpio_set_output(gpio, val); +} + +void db8500_gpio_set_output(unsigned gpio, int val) +{ + void __iomem *addr = get_gpio_addr(gpio); + unsigned offset = get_gpio_offset(gpio); + + if (val) + writel(1 << offset, addr + DB8500_GPIO_DATS); + else + writel(1 << offset, addr + DB8500_GPIO_DATC); +} + +/** + * config_pin - configure a pin's mux attributes + * @cfg: pin confguration + * + * Configures a pin's mode (alternate function or GPIO), its pull up status, + * and its sleep mode based on the specified configuration. The @cfg is + * usually one of the SoC specific macros defined in mach/<soc>-pins.h. These + * are constructed using, and can be further enhanced with, the macros in + * plat/pincfg.h. + * + * If a pin's mode is set to GPIO, it is configured as an input to avoid + * side-effects. The gpio can be manipulated later using standard GPIO API + * calls. + */ +static void config_pin(unsigned long cfg) +{ + int pin = PIN_NUM(cfg); + int pull = PIN_PULL(cfg); + int af = PIN_ALT(cfg); + int output = PIN_DIR(cfg); + int val = PIN_VAL(cfg); + + if (output) + db8500_gpio_make_output(pin, val); + else { + db8500_gpio_make_input(pin); + db8500_gpio_set_pull(pin, pull); + } + + gpio_set_mode(pin, af); +} + +/** + * db8500_config_pins - configure several pins at once + * @cfgs: array of pin configurations + * @num: number of elments in the array + * + * Configures several pins using config_pin(). Refer to that function for + * further information. + */ +void db8500_gpio_config_pins(unsigned long *cfgs, size_t num) +{ + size_t i; + + for (i = 0; i < num; i++) + config_pin(cfgs[i]); +} diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c index 661553552e..2c79bff62b 100644 --- a/drivers/gpio/mxc_gpio.c +++ b/drivers/gpio/mxc_gpio.c @@ -41,13 +41,15 @@ static unsigned long gpio_ports[] = { [0] = GPIO1_BASE_ADDR, [1] = GPIO2_BASE_ADDR, [2] = GPIO3_BASE_ADDR, -#if defined(CONFIG_MX25) || defined(CONFIG_MX51) || defined(CONFIG_MX53) || \ - defined(CONFIG_MX6Q) +#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ + defined(CONFIG_MX53) || defined(CONFIG_MX6Q) [3] = GPIO4_BASE_ADDR, #endif -#if defined(CONFIG_MX53) || defined(CONFIG_MX6Q) +#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6Q) [4] = GPIO5_BASE_ADDR, [5] = GPIO6_BASE_ADDR, +#endif +#if defined(CONFIG_MX53) || defined(CONFIG_MX6Q) [6] = GPIO7_BASE_ADDR, #endif }; @@ -116,7 +118,7 @@ int gpio_get_value(unsigned gpio) regs = (struct gpio_regs *)gpio_ports[port]; - val = (readl(®s->gpio_dr) >> gpio) & 0x01; + val = (readl(®s->gpio_psr) >> gpio) & 0x01; return val; } diff --git a/drivers/gpio/mxs_gpio.c b/drivers/gpio/mxs_gpio.c index 38dbc81b45..29f19badda 100644 --- a/drivers/gpio/mxs_gpio.c +++ b/drivers/gpio/mxs_gpio.c @@ -73,8 +73,8 @@ int gpio_get_value(unsigned gpio) { uint32_t bank = PAD_BANK(gpio); uint32_t offset = PINCTRL_DIN(bank); - struct mx28_register_32 *reg = - (struct mx28_register_32 *)(MXS_PINCTRL_BASE + offset); + struct mxs_register_32 *reg = + (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset); return (readl(®->reg) >> PAD_PIN(gpio)) & 1; } @@ -83,8 +83,8 @@ void gpio_set_value(unsigned gpio, int value) { uint32_t bank = PAD_BANK(gpio); uint32_t offset = PINCTRL_DOUT(bank); - struct mx28_register_32 *reg = - (struct mx28_register_32 *)(MXS_PINCTRL_BASE + offset); + struct mxs_register_32 *reg = + (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset); if (value) writel(1 << PAD_PIN(gpio), ®->reg_set); @@ -96,8 +96,8 @@ int gpio_direction_input(unsigned gpio) { uint32_t bank = PAD_BANK(gpio); uint32_t offset = PINCTRL_DOE(bank); - struct mx28_register_32 *reg = - (struct mx28_register_32 *)(MXS_PINCTRL_BASE + offset); + struct mxs_register_32 *reg = + (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset); writel(1 << PAD_PIN(gpio), ®->reg_clr); @@ -108,8 +108,8 @@ int gpio_direction_output(unsigned gpio, int value) { uint32_t bank = PAD_BANK(gpio); uint32_t offset = PINCTRL_DOE(bank); - struct mx28_register_32 *reg = - (struct mx28_register_32 *)(MXS_PINCTRL_BASE + offset); + struct mxs_register_32 *reg = + (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset); writel(1 << PAD_PIN(gpio), ®->reg_set); diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c new file mode 100644 index 0000000000..fc89f2a42b --- /dev/null +++ b/drivers/gpio/omap_gpio.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2009 Wind River Systems, Inc. + * Tom Rix <Tom.Rix@windriver.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * This work is derived from the linux 2.6.27 kernel source + * To fetch, use the kernel repository + * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + * Use the v2.6.27 tag. + * + * Below is the original's header including its copyright + * + * linux/arch/arm/plat-omap/gpio.c + * + * Support functions for OMAP GPIO + * + * Copyright (C) 2003-2005 Nokia Corporation + * Written by Juha Yrjölä <juha.yrjola@nokia.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <common.h> +#include <asm/gpio.h> +#include <asm/io.h> +#include <asm/errno.h> + +#define OMAP_GPIO_DIR_OUT 0 +#define OMAP_GPIO_DIR_IN 1 + +static inline const struct gpio_bank *get_gpio_bank(int gpio) +{ + return &omap_gpio_bank[gpio >> 5]; +} + +static inline int get_gpio_index(int gpio) +{ + return gpio & 0x1f; +} + +static inline int gpio_valid(int gpio) +{ + if (gpio < 0) + return -1; + if (gpio < 192) + return 0; + return -1; +} + +static int check_gpio(int gpio) +{ + if (gpio_valid(gpio) < 0) { + printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); + return -1; + } + return 0; +} + +static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, + int is_input) +{ + void *reg = bank->base; + u32 l; + + switch (bank->method) { + case METHOD_GPIO_24XX: + reg += OMAP_GPIO_OE; + break; + default: + return; + } + l = __raw_readl(reg); + if (is_input) + l |= 1 << gpio; + else + l &= ~(1 << gpio); + __raw_writel(l, reg); +} + +/** + * Get the direction of the GPIO by reading the GPIO_OE register + * corresponding to the specified bank. + */ +static int _get_gpio_direction(const struct gpio_bank *bank, int gpio) +{ + void *reg = bank->base; + u32 v; + + switch (bank->method) { + case METHOD_GPIO_24XX: + reg += OMAP_GPIO_OE; + break; + default: + return -1; + } + + v = __raw_readl(reg); + + if (v & (1 << gpio)) + return OMAP_GPIO_DIR_IN; + else + return OMAP_GPIO_DIR_OUT; +} + +static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio, + int enable) +{ + void *reg = bank->base; + u32 l = 0; + + switch (bank->method) { + case METHOD_GPIO_24XX: + if (enable) + reg += OMAP_GPIO_SETDATAOUT; + else + reg += OMAP_GPIO_CLEARDATAOUT; + l = 1 << gpio; + break; + default: + printf("omap3-gpio unknown bank method %s %d\n", + __FILE__, __LINE__); + return; + } + __raw_writel(l, reg); +} + +/** + * Set value of the specified gpio + */ +int gpio_set_value(unsigned gpio, int value) +{ + const struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return -1; + bank = get_gpio_bank(gpio); + _set_gpio_dataout(bank, get_gpio_index(gpio), value); + + return 0; +} + +/** + * Get value of the specified gpio + */ +int gpio_get_value(unsigned gpio) +{ + const struct gpio_bank *bank; + void *reg; + int input; + + if (check_gpio(gpio) < 0) + return -1; + bank = get_gpio_bank(gpio); + reg = bank->base; + switch (bank->method) { + case METHOD_GPIO_24XX: + input = _get_gpio_direction(bank, get_gpio_index(gpio)); + switch (input) { + case OMAP_GPIO_DIR_IN: + reg += OMAP_GPIO_DATAIN; + break; + case OMAP_GPIO_DIR_OUT: + reg += OMAP_GPIO_DATAOUT; + break; + default: + return -1; + } + break; + default: + return -1; + } + return (__raw_readl(reg) + & (1 << get_gpio_index(gpio))) != 0; +} + +/** + * Set gpio direction as input + */ +int gpio_direction_input(unsigned gpio) +{ + const struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return -1; + + bank = get_gpio_bank(gpio); + _set_gpio_direction(bank, get_gpio_index(gpio), 1); + + return 0; +} + +/** + * Set gpio direction as output + */ +int gpio_direction_output(unsigned gpio, int value) +{ + const struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return -1; + + bank = get_gpio_bank(gpio); + _set_gpio_dataout(bank, get_gpio_index(gpio), value); + _set_gpio_direction(bank, get_gpio_index(gpio), 0); + + return 0; +} + +/** + * Request a gpio before using it. + * + * NOTE: Argument 'label' is unused. + */ +int gpio_request(unsigned gpio, const char *label) +{ + if (check_gpio(gpio) < 0) + return -1; + + return 0; +} + +/** + * Reset and free the gpio after using it. + */ +int gpio_free(unsigned gpio) +{ + return 0; +} diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c index 60ec6e3d78..747f4cf921 100644 --- a/drivers/gpio/tegra_gpio.c +++ b/drivers/gpio/tegra_gpio.c @@ -1,5 +1,5 @@ /* - * NVIDIA Tegra2 GPIO handling. + * NVIDIA Tegra20 GPIO handling. * (C) Copyright 2010-2012 * NVIDIA Corporation <www.nvidia.com> * @@ -30,14 +30,14 @@ #include <common.h> #include <asm/io.h> #include <asm/bitops.h> -#include <asm/arch/tegra2.h> +#include <asm/arch/tegra20.h> #include <asm/gpio.h> enum { - TEGRA2_CMD_INFO, - TEGRA2_CMD_PORT, - TEGRA2_CMD_OUTPUT, - TEGRA2_CMD_INPUT, + TEGRA_CMD_INFO, + TEGRA_CMD_PORT, + TEGRA_CMD_OUTPUT, + TEGRA_CMD_INPUT, }; static struct gpio_names { |