summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/db8500_gpio.c226
-rw-r--r--drivers/spi/u8500_spi.c76
-rwxr-xr-xdrivers/usb/gadget/u8500_udc.c3
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);