diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/db8500_gpio.c | 226 | ||||
-rw-r--r-- | drivers/spi/u8500_spi.c | 76 | ||||
-rwxr-xr-x | drivers/usb/gadget/u8500_udc.c | 3 |
4 files changed, 229 insertions, 77 deletions
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index fc3ee5ea9..64f0bd718 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -25,6 +25,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libgpio.a +COBJS-$(CONFIG_DB8500_GPIO) += db8500_gpio.o COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o COBJS-$(CONFIG_MX31_GPIO) += mx31_gpio.o COBJS-$(CONFIG_PCA953X) += pca953x.o diff --git a/drivers/gpio/db8500_gpio.c b/drivers/gpio/db8500_gpio.c new file mode 100644 index 000000000..1ed4ba15d --- /dev/null +++ b/drivers/gpio/db8500_gpio.c @@ -0,0 +1,226 @@ +/* + * 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 <db8500_gpio.h> +#include <db8500_pincfg.h> + +/* + * Macros to work with IO space + * Not actually used? + */ +#define __iomem +#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(pin_cfg_t 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(pin_cfg_t *cfgs, size_t num) +{ + size_t i; + + for (i = 0; i < num; i++) + config_pin(cfgs[i]); +} + diff --git a/drivers/spi/u8500_spi.c b/drivers/spi/u8500_spi.c index 3b1ae6a5e..a5f4422ce 100644 --- a/drivers/spi/u8500_spi.c +++ b/drivers/spi/u8500_spi.c @@ -13,7 +13,6 @@ #include <asm/io.h> #include <asm/arch/clock.h> #include <asm/arch/hardware.h> -#include <asm/arch/gpio.h> #include <spi.h> @@ -357,9 +356,6 @@ int spi_claim_bus(struct spi_slave *slave) { struct stm_spi_slave *sss = to_stm_spi_slave(slave); int ret = 0; - gpio_config pin_config; - gpio_pin clk_pin, frm_pin, txd_pin, rxd_pin; - gpio_alt_function altfunc; pr_dbg("slave 0x%p", slave); @@ -372,31 +368,16 @@ int spi_claim_bus(struct spi_slave *slave) switch (sss->slave.bus) { #if defined(SPI_0_BASE) && defined(CONFIG_U8500) case 0: - altfunc = GPIO_ALT_SPI_0; - clk_pin = GPIO_PIN_220; - frm_pin = GPIO_PIN_223; - txd_pin = GPIO_PIN_224; - rxd_pin = GPIO_PIN_225; u8500_clock_enable(2, 8, -1); break; #endif #if defined(SPI_1_BASE) && defined(CONFIG_U8500) case 1: - altfunc = GPIO_ALT_SPI_1; - clk_pin = GPIO_PIN_209; - frm_pin = GPIO_PIN_212; - txd_pin = GPIO_PIN_213; - rxd_pin = GPIO_PIN_214; u8500_clock_enable(2, 2, -1); break; #endif #if defined(SPI_2_BASE) && defined(CONFIG_U8500) case 2: - altfunc = GPIO_ALT_SPI_2; - clk_pin = GPIO_PIN_217; - frm_pin = GPIO_PIN_216; - txd_pin = GPIO_PIN_215; - rxd_pin = GPIO_PIN_218; u8500_clock_enable(2, 1, -1); /* @@ -412,11 +393,6 @@ int spi_claim_bus(struct spi_slave *slave) #endif #if defined(SPI_3_BASE) && defined(CONFIG_U8500) case 3: - altfunc = GPIO_ALT_SPI_3; - clk_pin = GPIO_PIN_29; - frm_pin = GPIO_PIN_31; - txd_pin = GPIO_PIN_32; - rxd_pin = GPIO_PIN_30; u8500_clock_enable(1, 7, -1); break; #endif @@ -447,57 +423,9 @@ int spi_claim_bus(struct spi_slave *slave) /* - * 3. Program the GPIO on which SPI port signals are attached to - * deliver the SPI signals by setting bits alternate function - * enable GPIO_AFSLAx = 1b in GPIO register. - * - * First the GPIO's are configured in software mode so - * the pull-up/pull-down configuration is correctly applied. - * After that pins are set to the correct alternate mode. + * 3. Program the GPIO on which SPI port signals are attached to. + * This should already be done by the Board GPIO setup */ - pin_config.dev_name = "SPI_CLK"; - pin_config.direction = GPIO_DIR_OUTPUT; - pin_config.mode = GPIO_MODE_SOFTWARE; - pin_config.trig = GPIO_TRIG_DISABLE; - ret = gpio_setpinconfig(clk_pin, &pin_config); - if (ret != 0) { - pr_err("Error %i when configuring '%s' (pin %i) for '%s'", - ret, pin_config.dev_name, clk_pin, sss->dev_name); - return ret; - } - - pin_config.dev_name = "SPI_FRM"; - ret = gpio_setpinconfig(frm_pin, &pin_config); - if (ret != 0) { - pr_err("Error %i when configuring '%s' (pin %i) for '%s'", - ret, pin_config.dev_name, frm_pin, sss->dev_name); - return ret; - } - - pin_config.dev_name = "SPI_TXD"; - ret = gpio_setpinconfig(txd_pin, &pin_config); - if (ret != 0) { - pr_err("Error %i when configuring '%s' (pin %i) for '%s'", - ret, pin_config.dev_name, txd_pin, sss->dev_name); - return ret; - } - - pin_config.dev_name = "SPI_RXD"; - pin_config.direction = GPIO_DIR_INPUT; - ret = gpio_setpinconfig(rxd_pin, &pin_config); - if (ret != 0) { - pr_err("Error %i when configuring '%s' (pin %i) for '%s'", - ret, pin_config.dev_name, rxd_pin, sss->dev_name); - return ret; - } - - ret = gpio_altfuncenable(altfunc, sss->dev_name); - if (ret != 0) { - pr_err("Error %i when configuring '%s' to %i", - ret, sss->dev_name, altfunc); - return ret; - } - /* * 4. Program the SPI clock prescale register, SPI_CPSR, diff --git a/drivers/usb/gadget/u8500_udc.c b/drivers/usb/gadget/u8500_udc.c index 109e11dda..92f1b57c8 100755 --- a/drivers/usb/gadget/u8500_udc.c +++ b/drivers/usb/gadget/u8500_udc.c @@ -21,7 +21,6 @@ #include <common.h> #include "u8500_udc.h" -#include <asm/arch/gpio.h> static volatile struct mg_dev_register *pRegs = 0; @@ -32,8 +31,6 @@ int udc_musb_platform_init(void) u8 soft_reset; u16 temp; pRegs = (volatile struct mg_dev_register *) CONFIG_USB_BASE; - - gpio_altfuncenable(GPIO_ALT_USB_OTG, "USB-OTG"); top = pRegs->OTG_TOPCTRL; pRegs->OTG_TOPCTRL = (top | MODE_ULPI); |