aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPer Forlin <per.forlin@linaro.org>2012-01-16 22:31:46 -0700
committerJohn Rigby <john.rigby@linaro.org>2012-04-25 07:54:07 -0600
commit6c2c97ff988701fa5d2d7dee89cb3d246f5c7432 (patch)
tree45f87b87dbcd04ae905a605753b47b5ac2dd6785
parentf77f298b98b8c3bc551433ed7d89c164104bd705 (diff)
downloadu-boot-linaro-stable-6c2c97ff988701fa5d2d7dee89cb3d246f5c7432.tar.gz
snowball: igloo copy port of gpio driver support
Signed-off-by: Per Forlin <per.forlin@linaro.org>
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/db8500_gpio.c226
-rw-r--r--include/db8500_gpio.h43
-rw-r--r--include/db8500_pincfg.h173
4 files changed, 444 insertions, 0 deletions
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fb3b09ae7..d7f726307 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libgpio.o
COBJS-$(CONFIG_AT91_GPIO) += at91_gpio.o
+COBJS-$(CONFIG_DB8500_GPIO) += db8500_gpio.o
COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
COBJS-$(CONFIG_MARVELL_GPIO) += mvgpio.o
COBJS-$(CONFIG_MARVELL_MFP) += mvmfp.o
@@ -39,6 +40,7 @@ COBJS-$(CONFIG_TEGRA2_GPIO) += tegra2_gpio.o
COBJS-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o
COBJS-$(CONFIG_ALTERA_PIO) += altera_pio.o
COBJS-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o
+COBJS-$(CONFIG_TC35892_GPIO) += tc35892.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
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/include/db8500_gpio.h b/include/db8500_gpio.h
new file mode 100644
index 000000000..67d7e4d56
--- /dev/null
+++ b/include/db8500_gpio.h
@@ -0,0 +1,43 @@
+/*
+ * Structures and registers for GPIO access in the Nomadik SoC
+ *
+ * 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.
+ *
+ * Ported to U-boot by:
+ * Copyright (C) 2010 Joakim Axelsson <joakim.axelsson AT stericsson.com>
+ * Copyright (C) 2008 STMicroelectronics
+ * Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
+ *
+ * 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.
+ */
+
+#ifndef __DB8500_GPIO_H__
+#define __DB8500_GPIO_H__
+
+/* Alternate functions: function C is set in hw by setting both A and B */
+enum db8500_gpio_alt {
+ DB8500_GPIO_ALT_GPIO = 0,
+ DB8500_GPIO_ALT_A = 1,
+ DB8500_GPIO_ALT_B = 2,
+ DB8500_GPIO_ALT_C = (DB8500_GPIO_ALT_A | DB8500_GPIO_ALT_B)
+};
+
+enum db8500_gpio_pull {
+ DB8500_GPIO_PULL_NONE,
+ DB8500_GPIO_PULL_UP,
+ DB8500_GPIO_PULL_DOWN
+};
+
+void db8500_gpio_set_pull(unsigned gpio, enum db8500_gpio_pull pull);
+void db8500_gpio_make_input(unsigned gpio);
+int db8500_gpio_get_input(unsigned gpio);
+void db8500_gpio_make_output(unsigned gpio, int val);
+void db8500_gpio_set_output(unsigned gpio, int val);
+
+#endif /* __DB8500_GPIO_H__ */
+
diff --git a/include/db8500_pincfg.h b/include/db8500_pincfg.h
new file mode 100644
index 000000000..d1bcb65a9
--- /dev/null
+++ b/include/db8500_pincfg.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * 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. Ported 2010 to U-boot by:
+ * Author: Joakim Axelsson <joakim.axelsson AT stericsson.com>
+ *
+ * License terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ *
+ *
+ * Based on arch/arm/mach-pxa/include/mach/mfp.h:
+ * Copyright (C) 2007 Marvell International Ltd.
+ * eric miao <eric.miao@marvell.com>
+ */
+
+#ifndef __DB8500_PINCFG_H
+#define __DB8500_PINCFG_H
+
+#include "db8500_gpio.h"
+
+/*
+ * U-boot info:
+ * SLPM (sleep mode) config will be ignored by U-boot but it is still
+ * possible to configure it in order to keep cut-n-paste compability
+ * with Linux kernel config.
+ *
+ * pin configurations are represented by 32-bit integers:
+ *
+ * bit 0.. 8 - Pin Number (512 Pins Maximum)
+ * bit 9..10 - Alternate Function Selection
+ * bit 11..12 - Pull up/down state
+ * bit 13 - Sleep mode behaviour (not used in U-boot)
+ * bit 14 - Direction
+ * bit 15 - Value (if output)
+ * bit 16..18 - SLPM pull up/down state (not used in U-boot)
+ * bit 19..20 - SLPM direction (not used in U-boot)
+ * bit 21..22 - SLPM Value (if output) (not used in U-boot)
+ *
+ * to facilitate the definition, the following macros are provided
+ *
+ * PIN_CFG_DEFAULT - default config (0):
+ * pull up/down = disabled
+ * sleep mode = input/wakeup
+ * direction = input
+ * value = low
+ * SLPM direction = same as normal
+ * SLPM pull = same as normal
+ * SLPM value = same as normal
+ *
+ * PIN_CFG - default config with alternate function
+ * PIN_CFG_PULL - default config with alternate function and pull up/down
+ */
+
+typedef unsigned long pin_cfg_t;
+
+/* Sleep mode */
+enum db8500_gpio_slpm {
+ DB8500_GPIO_SLPM_INPUT,
+ DB8500_GPIO_SLPM_WAKEUP_ENABLE = DB8500_GPIO_SLPM_INPUT,
+ DB8500_GPIO_SLPM_NOCHANGE,
+ DB8500_GPIO_SLPM_WAKEUP_DISABLE = DB8500_GPIO_SLPM_NOCHANGE,
+};
+
+#define PIN_NUM_MASK 0x1ff
+#define PIN_NUM(x) ((x) & PIN_NUM_MASK)
+
+#define PIN_ALT_SHIFT 9
+#define PIN_ALT_MASK (0x3 << PIN_ALT_SHIFT)
+#define PIN_ALT(x) (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
+#define PIN_GPIO (DB8500_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
+#define PIN_ALT_A (DB8500_GPIO_ALT_A << PIN_ALT_SHIFT)
+#define PIN_ALT_B (DB8500_GPIO_ALT_B << PIN_ALT_SHIFT)
+#define PIN_ALT_C (DB8500_GPIO_ALT_C << PIN_ALT_SHIFT)
+
+#define PIN_PULL_SHIFT 11
+#define PIN_PULL_MASK (0x3 << PIN_PULL_SHIFT)
+#define PIN_PULL(x) (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
+#define PIN_PULL_NONE (DB8500_GPIO_PULL_NONE << PIN_PULL_SHIFT)
+#define PIN_PULL_UP (DB8500_GPIO_PULL_UP << PIN_PULL_SHIFT)
+#define PIN_PULL_DOWN (DB8500_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
+
+#define PIN_SLPM_SHIFT 13
+#define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT)
+#define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
+#define PIN_SLPM_MAKE_INPUT (DB8500_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
+#define PIN_SLPM_NOCHANGE (DB8500_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
+/* These two replace the above in DB8500v2+ */
+#define PIN_SLPM_WAKEUP_ENABLE \
+ (DB8500_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_WAKEUP_DISABLE \
+ (DB8500_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
+
+#define PIN_DIR_SHIFT 14
+#define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT)
+#define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
+#define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT)
+#define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT)
+
+#define PIN_VAL_SHIFT 15
+#define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT)
+#define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
+#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT)
+#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT)
+
+#define PIN_SLPM_PULL_SHIFT 16
+#define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL(x) \
+ (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_NONE \
+ ((1 + DB8500_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_UP \
+ ((1 + DB8500_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_DOWN \
+ ((1 + DB8500_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
+
+#define PIN_SLPM_DIR_SHIFT 19
+#define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR(x) \
+ (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT)
+
+#define PIN_SLPM_VAL_SHIFT 21
+#define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL(x) \
+ (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT)
+
+/* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */
+#define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN)
+#define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP)
+#define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE)
+#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW)
+#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH)
+
+#define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
+#define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
+#define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
+#define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
+#define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
+
+#define PIN_CFG_DEFAULT (0)
+
+#define PIN_CFG(num, alt) \
+ (PIN_CFG_DEFAULT |\
+ (PIN_NUM(num) | PIN_##alt))
+
+#define PIN_CFG_INPUT(num, alt, pull) \
+ (PIN_CFG_DEFAULT |\
+ (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
+
+#define PIN_CFG_OUTPUT(num, alt, val) \
+ (PIN_CFG_DEFAULT |\
+ (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
+
+#define PIN_CFG_PULL(num, alt, pull) \
+ ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\
+ (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull))
+
+/**
+ * db8500_gpio_config_pins - configure several pins at once
+ * @cfgs: array of pin configurations
+ * @num: number of elments in the array
+ *
+ * Configures several GPIO pins.
+ */
+void db8500_gpio_config_pins(pin_cfg_t *cfgs, size_t num);
+
+#endif
+