summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorTom Rini <trini@ti.com>2014-10-26 14:03:08 -0400
committerTom Rini <trini@ti.com>2014-10-26 14:03:08 -0400
commit84a6df09c78bc9e9cbc6265d99c9097f5f1079f2 (patch)
tree3b2bf1b3689e9aad0d20f5a69ada168cae3cc769 /drivers/gpio
parentc69ecd9722af22d50295eff81d0b9cd5b8adc2e0 (diff)
parentc2ded962d4703a3f9522553004db4a6fe540f7e6 (diff)
downloadu-boot-imx-84a6df09c78bc9e9cbc6265d99c9097f5f1079f2.zip
u-boot-imx-84a6df09c78bc9e9cbc6265d99c9097f5f1079f2.tar.gz
u-boot-imx-84a6df09c78bc9e9cbc6265d99c9097f5f1079f2.tar.bz2
Merge git://git.denx.de/u-boot-dm
Fix a trivial conflict over adding <dm.h> Conflicts: arch/arm/cpu/armv7/omap3/board.c Signed-off-by: Tom Rini <trini@ti.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/bcm2835_gpio.c89
-rw-r--r--drivers/gpio/gpio-uclass.c236
-rw-r--r--drivers/gpio/intel_ich6_gpio.c250
-rw-r--r--drivers/gpio/mxc_gpio.c116
-rw-r--r--drivers/gpio/omap_gpio.c183
-rw-r--r--drivers/gpio/s5p_gpio.c101
-rw-r--r--drivers/gpio/sandbox.c93
-rw-r--r--drivers/gpio/tegra_gpio.c113
9 files changed, 497 insertions, 690 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e69de29..d21302f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -0,0 +1,6 @@
+config DM_GPIO
+ bool "Enable Driver Model for GPIO drivers"
+ depends on DM
+ help
+ If you want to use driver model for GPIO drivers, say Y.
+ To use legacy GPIO drivers, say N.
diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c
index 332cfc2..0244c01 100644
--- a/drivers/gpio/bcm2835_gpio.c
+++ b/drivers/gpio/bcm2835_gpio.c
@@ -11,67 +11,10 @@
#include <asm/gpio.h>
#include <asm/io.h>
-#define GPIO_NAME_SIZE 20
-
struct bcm2835_gpios {
- char label[BCM2835_GPIO_COUNT][GPIO_NAME_SIZE];
struct bcm2835_gpio_regs *reg;
};
-/**
- * gpio_is_requested() - check if a GPIO has been requested
- *
- * @bank: Bank to check
- * @offset: GPIO offset within bank to check
- * @return true if marked as requested, false if not
- */
-static inline bool gpio_is_requested(struct bcm2835_gpios *gpios, int offset)
-{
- return *gpios->label[offset] != '\0';
-}
-
-static int check_requested(struct udevice *dev, unsigned offset,
- const char *func)
-{
- struct bcm2835_gpios *gpios = dev_get_priv(dev);
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-
- if (!gpio_is_requested(gpios, offset)) {
- printf("omap_gpio: %s: error: gpio %s%d not requested\n",
- func, uc_priv->bank_name, offset);
- return -EPERM;
- }
-
- return 0;
-}
-
-static int bcm2835_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
-{
- struct bcm2835_gpios *gpios = dev_get_priv(dev);
-
- if (gpio_is_requested(gpios, offset))
- return -EBUSY;
-
- strncpy(gpios->label[offset], label, GPIO_NAME_SIZE);
- gpios->label[offset][GPIO_NAME_SIZE - 1] = '\0';
-
- return 0;
-}
-
-static int bcm2835_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct bcm2835_gpios *gpios = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
- gpios->label[offset][0] = '\0';
-
- return 0;
-}
-
static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
@@ -142,9 +85,6 @@ static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
- if (!gpio_is_requested(gpios, offset))
- return GPIOF_UNUSED;
-
/* GPIOF_FUNC is not implemented yet */
if (bcm2835_gpio_is_output(gpios, offset))
return GPIOF_OUTPUT;
@@ -152,42 +92,13 @@ static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
-static int bcm2835_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct bcm2835_gpios *gpios = dev_get_priv(dev);
- const char *label;
- bool requested;
- bool is_output;
- int size;
-
- label = gpios->label[offset];
- is_output = bcm2835_gpio_is_output(gpios, offset);
- size = snprintf(buf, bufsize, "%s%d: ",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset);
- buf += size;
- bufsize -= size;
- requested = gpio_is_requested(gpios, offset);
- snprintf(buf, bufsize, "%s: %d [%c]%s%s",
- is_output ? "out" : " in",
- bcm2835_get_value(gpios, offset),
- requested ? 'x' : ' ',
- requested ? " " : "",
- label);
-
- return 0;
-}
static const struct dm_gpio_ops gpio_bcm2835_ops = {
- .request = bcm2835_gpio_request,
- .free = bcm2835_gpio_free,
.direction_input = bcm2835_gpio_direction_input,
.direction_output = bcm2835_gpio_direction_output,
.get_value = bcm2835_gpio_get_value,
.set_value = bcm2835_gpio_set_value,
.get_function = bcm2835_gpio_get_function,
- .get_state = bcm2835_gpio_get_state,
};
static int bcm2835_gpio_probe(struct udevice *dev)
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index f1bbc58..45e9a5a 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -7,7 +7,9 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
+#include <malloc.h>
#include <asm/gpio.h>
+#include <linux/ctype.h>
/**
* gpio_to_device() - Convert global GPIO number to device, number
@@ -43,35 +45,47 @@ static int gpio_to_device(unsigned int gpio, struct udevice **devp,
int gpio_lookup_name(const char *name, struct udevice **devp,
unsigned int *offsetp, unsigned int *gpiop)
{
- struct gpio_dev_priv *uc_priv;
+ struct gpio_dev_priv *uc_priv = NULL;
struct udevice *dev;
+ ulong offset;
+ int numeric;
int ret;
if (devp)
*devp = NULL;
+ numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
for (ret = uclass_first_device(UCLASS_GPIO, &dev);
dev;
ret = uclass_next_device(&dev)) {
- ulong offset;
int len;
uc_priv = dev->uclass_priv;
+ if (numeric != -1) {
+ offset = numeric - uc_priv->gpio_base;
+ /* Allow GPIOs to be numbered from 0 */
+ if (offset >= 0 && offset < uc_priv->gpio_count)
+ break;
+ }
+
len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
if (!strncasecmp(name, uc_priv->bank_name, len)) {
- if (strict_strtoul(name + len, 10, &offset))
- continue;
- if (devp)
- *devp = dev;
- if (offsetp)
- *offsetp = offset;
- if (gpiop)
- *gpiop = uc_priv->gpio_base + offset;
- return 0;
+ if (!strict_strtoul(name + len, 10, &offset))
+ break;
}
}
- return ret ? ret : -EINVAL;
+ if (!dev)
+ return ret ? ret : -EINVAL;
+
+ if (devp)
+ *devp = dev;
+ if (offsetp)
+ *offsetp = offset;
+ if (gpiop)
+ *gpiop = uc_priv->gpio_base + offset;
+
+ return 0;
}
/**
@@ -79,24 +93,62 @@ int gpio_lookup_name(const char *name, struct udevice **devp,
* gpio: GPIO number
* label: Name for the requested GPIO
*
+ * The label is copied and allocated so the caller does not need to keep
+ * the pointer around.
+ *
* This function implements the API that's compatible with current
* GPIO API used in U-Boot. The request is forwarded to particular
* GPIO driver. Returns 0 on success, negative value on error.
*/
int gpio_request(unsigned gpio, const char *label)
{
+ struct gpio_dev_priv *uc_priv;
unsigned int offset;
struct udevice *dev;
+ char *str;
int ret;
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
- if (!gpio_get_ops(dev)->request)
- return 0;
+ uc_priv = dev->uclass_priv;
+ if (uc_priv->name[offset])
+ return -EBUSY;
+ str = strdup(label);
+ if (!str)
+ return -ENOMEM;
+ if (gpio_get_ops(dev)->request) {
+ ret = gpio_get_ops(dev)->request(dev, offset, label);
+ if (ret) {
+ free(str);
+ return ret;
+ }
+ }
+ uc_priv->name[offset] = str;
+
+ return 0;
+}
+
+/**
+ * gpio_requestf() - [COMPAT] Request GPIO
+ * @gpio: GPIO number
+ * @fmt: Format string for the requested GPIO
+ * @...: Arguments for the printf() format string
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_requestf(unsigned gpio, const char *fmt, ...)
+{
+ va_list args;
+ char buf[40];
- return gpio_get_ops(dev)->request(dev, offset, label);
+ va_start(args, fmt);
+ vscnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ return gpio_request(gpio, buf);
}
/**
@@ -109,6 +161,7 @@ int gpio_request(unsigned gpio, const char *label)
*/
int gpio_free(unsigned gpio)
{
+ struct gpio_dev_priv *uc_priv;
unsigned int offset;
struct udevice *dev;
int ret;
@@ -117,9 +170,34 @@ int gpio_free(unsigned gpio)
if (ret)
return ret;
- if (!gpio_get_ops(dev)->free)
- return 0;
- return gpio_get_ops(dev)->free(dev, offset);
+ uc_priv = dev->uclass_priv;
+ if (!uc_priv->name[offset])
+ return -ENXIO;
+ if (gpio_get_ops(dev)->free) {
+ ret = gpio_get_ops(dev)->free(dev, offset);
+ if (ret)
+ return ret;
+ }
+
+ free(uc_priv->name[offset]);
+ uc_priv->name[offset] = NULL;
+
+ return 0;
+}
+
+static int check_reserved(struct udevice *dev, unsigned offset,
+ const char *func)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ if (!uc_priv->name[offset]) {
+ printf("%s: %s: error: gpio %s%d not reserved\n",
+ dev->name, func,
+ uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+ return -EBUSY;
+ }
+
+ return 0;
}
/**
@@ -139,8 +217,9 @@ int gpio_direction_input(unsigned gpio)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
+ ret = check_reserved(dev, offset, "dir_input");
- return gpio_get_ops(dev)->direction_input(dev, offset);
+ return ret ? ret : gpio_get_ops(dev)->direction_input(dev, offset);
}
/**
@@ -161,8 +240,10 @@ int gpio_direction_output(unsigned gpio, int value)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
+ ret = check_reserved(dev, offset, "dir_output");
- return gpio_get_ops(dev)->direction_output(dev, offset, value);
+ return ret ? ret :
+ gpio_get_ops(dev)->direction_output(dev, offset, value);
}
/**
@@ -183,8 +264,9 @@ int gpio_get_value(unsigned gpio)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
+ ret = check_reserved(dev, offset, "get_value");
- return gpio_get_ops(dev)->get_value(dev, offset);
+ return ret ? ret : gpio_get_ops(dev)->get_value(dev, offset);
}
/**
@@ -205,8 +287,9 @@ int gpio_set_value(unsigned gpio, int value)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
+ ret = check_reserved(dev, offset, "set_value");
- return gpio_get_ops(dev)->set_value(dev, offset, value);
+ return ret ? ret : gpio_get_ops(dev)->set_value(dev, offset, value);
}
const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
@@ -221,8 +304,94 @@ const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
return priv->bank_name;
}
+static const char * const gpio_function[GPIOF_COUNT] = {
+ "input",
+ "output",
+ "unused",
+ "unknown",
+ "func",
+};
+
+int get_function(struct udevice *dev, int offset, bool skip_unused,
+ const char **namep)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct dm_gpio_ops *ops = gpio_get_ops(dev);
+
+ BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
+ if (!device_active(dev))
+ return -ENODEV;
+ if (offset < 0 || offset >= uc_priv->gpio_count)
+ return -EINVAL;
+ if (namep)
+ *namep = uc_priv->name[offset];
+ if (skip_unused && !uc_priv->name[offset])
+ return GPIOF_UNUSED;
+ if (ops->get_function) {
+ int ret;
+
+ ret = ops->get_function(dev, offset);
+ if (ret < 0)
+ return ret;
+ if (ret >= ARRAY_SIZE(gpio_function))
+ return -ENODATA;
+ return ret;
+ }
+
+ return GPIOF_UNKNOWN;
+}
+
+int gpio_get_function(struct udevice *dev, int offset, const char **namep)
+{
+ return get_function(dev, offset, true, namep);
+}
+
+int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
+{
+ return get_function(dev, offset, false, namep);
+}
+
+int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
+{
+ struct dm_gpio_ops *ops = gpio_get_ops(dev);
+ struct gpio_dev_priv *priv;
+ char *str = buf;
+ int func;
+ int ret;
+ int len;
+
+ BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
+
+ *buf = 0;
+ priv = dev->uclass_priv;
+ ret = gpio_get_raw_function(dev, offset, NULL);
+ if (ret < 0)
+ return ret;
+ func = ret;
+ len = snprintf(str, buffsize, "%s%d: %s",
+ priv->bank_name ? priv->bank_name : "",
+ offset, gpio_function[func]);
+ if (func == GPIOF_INPUT || func == GPIOF_OUTPUT ||
+ func == GPIOF_UNUSED) {
+ const char *label;
+ bool used;
+
+ ret = ops->get_value(dev, offset);
+ if (ret < 0)
+ return ret;
+ used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
+ snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
+ ret,
+ used ? 'x' : ' ',
+ used ? " " : "",
+ label ? label : "");
+ }
+
+ return 0;
+}
+
/* We need to renumber the GPIOs when any driver is probed/removed */
-static int gpio_renumber(void)
+static int gpio_renumber(struct udevice *removed_dev)
{
struct gpio_dev_priv *uc_priv;
struct udevice *dev;
@@ -237,7 +406,7 @@ static int gpio_renumber(void)
/* Ensure that we have a base for each bank */
base = 0;
uclass_foreach_dev(dev, uc) {
- if (device_active(dev)) {
+ if (device_active(dev) && dev != removed_dev) {
uc_priv = dev->uclass_priv;
uc_priv->gpio_base = base;
base += uc_priv->gpio_count;
@@ -249,12 +418,27 @@ static int gpio_renumber(void)
static int gpio_post_probe(struct udevice *dev)
{
- return gpio_renumber();
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
+ if (!uc_priv->name)
+ return -ENOMEM;
+
+ return gpio_renumber(NULL);
}
static int gpio_pre_remove(struct udevice *dev)
{
- return gpio_renumber();
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ int i;
+
+ for (i = 0; i < uc_priv->gpio_count; i++) {
+ if (uc_priv->name[i])
+ free(uc_priv->name[i]);
+ }
+ free(uc_priv->name);
+
+ return gpio_renumber(dev);
}
UCLASS_DRIVER(gpio) = {
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 7d9fac7..d3381b0 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -27,88 +27,46 @@
*/
#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
#include <pci.h>
#include <asm/gpio.h>
#include <asm/io.h>
+#define GPIO_PER_BANK 32
+
/* Where in config space is the register that points to the GPIO registers? */
#define PCI_CFG_GPIOBASE 0x48
-#define NUM_BANKS 3
-
-/* Within the I/O space, where are the registers to control the GPIOs? */
-static struct {
- u8 use_sel;
- u8 io_sel;
- u8 lvl;
-} gpio_bank[NUM_BANKS] = {
- { 0x00, 0x04, 0x0c }, /* Bank 0 */
- { 0x30, 0x34, 0x38 }, /* Bank 1 */
- { 0x40, 0x44, 0x48 } /* Bank 2 */
+struct ich6_bank_priv {
+ /* These are I/O addresses */
+ uint32_t use_sel;
+ uint32_t io_sel;
+ uint32_t lvl;
};
-static pci_dev_t dev; /* handle for 0:1f:0 */
-static u32 gpiobase; /* offset into I/O space */
-static int found_it_once; /* valid GPIO device? */
-static u32 lock[NUM_BANKS]; /* "lock" for access to pins */
-
-static int bad_arg(int num, int *bank, int *bitnum)
-{
- int i = num / 32;
- int j = num % 32;
-
- if (num < 0 || i > NUM_BANKS) {
- debug("%s: bogus gpio num: %d\n", __func__, num);
- return -1;
- }
- *bank = i;
- *bitnum = j;
- return 0;
-}
-
-static int mark_gpio(int bank, int bitnum)
-{
- if (lock[bank] & (1UL << bitnum)) {
- debug("%s: %d.%d already marked\n", __func__, bank, bitnum);
- return -1;
- }
- lock[bank] |= (1 << bitnum);
- return 0;
-}
-
-static void clear_gpio(int bank, int bitnum)
-{
- lock[bank] &= ~(1 << bitnum);
-}
-
-static int notmine(int num, int *bank, int *bitnum)
-{
- if (bad_arg(num, bank, bitnum))
- return -1;
- return !(lock[*bank] & (1UL << *bitnum));
-}
-
-static int gpio_init(void)
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
{
+ struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+ pci_dev_t pci_dev; /* handle for 0:1f:0 */
u8 tmpbyte;
u16 tmpword;
u32 tmplong;
-
- /* Have we already done this? */
- if (found_it_once)
- return 0;
+ u32 gpiobase;
+ int offset;
/* Where should it be? */
- dev = PCI_BDF(0, 0x1f, 0);
+ pci_dev = PCI_BDF(0, 0x1f, 0);
/* Is the device present? */
- pci_read_config_word(dev, PCI_VENDOR_ID, &tmpword);
+ pci_read_config_word(pci_dev, PCI_VENDOR_ID, &tmpword);
if (tmpword != PCI_VENDOR_ID_INTEL) {
debug("%s: wrong VendorID\n", __func__);
- return -1;
+ return -ENODEV;
}
- pci_read_config_word(dev, PCI_DEVICE_ID, &tmpword);
+ pci_read_config_word(pci_dev, PCI_DEVICE_ID, &tmpword);
debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
/*
* We'd like to validate the Device ID too, but pretty much any
@@ -118,37 +76,37 @@ static int gpio_init(void)
*/
/* I/O should already be enabled (it's a RO bit). */
- pci_read_config_word(dev, PCI_COMMAND, &tmpword);
+ pci_read_config_word(pci_dev, PCI_COMMAND, &tmpword);
if (!(tmpword & PCI_COMMAND_IO)) {
debug("%s: device IO not enabled\n", __func__);
- return -1;
+ return -ENODEV;
}
/* Header Type must be normal (bits 6-0 only; see spec.) */
- pci_read_config_byte(dev, PCI_HEADER_TYPE, &tmpbyte);
+ pci_read_config_byte(pci_dev, PCI_HEADER_TYPE, &tmpbyte);
if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
debug("%s: invalid Header type\n", __func__);
- return -1;
+ return -ENODEV;
}
/* Base Class must be a bridge device */
- pci_read_config_byte(dev, PCI_CLASS_CODE, &tmpbyte);
+ pci_read_config_byte(pci_dev, PCI_CLASS_CODE, &tmpbyte);
if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
debug("%s: invalid class\n", __func__);
- return -1;
+ return -ENODEV;
}
/* Sub Class must be ISA */
- pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &tmpbyte);
+ pci_read_config_byte(pci_dev, PCI_CLASS_SUB_CODE, &tmpbyte);
if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
debug("%s: invalid subclass\n", __func__);
- return -1;
+ return -ENODEV;
}
/* Programming Interface must be 0x00 (no others exist) */
- pci_read_config_byte(dev, PCI_CLASS_PROG, &tmpbyte);
+ pci_read_config_byte(pci_dev, PCI_CLASS_PROG, &tmpbyte);
if (tmpbyte != 0x00) {
debug("%s: invalid interface type\n", __func__);
- return -1;
+ return -ENODEV;
}
/*
@@ -156,11 +114,11 @@ static int gpio_init(void)
* that it was unused (or undocumented). Check that it looks
* okay: not all ones or zeros, and mapped to I/O space (bit 0).
*/
- pci_read_config_dword(dev, PCI_CFG_GPIOBASE, &tmplong);
+ pci_read_config_dword(pci_dev, PCI_CFG_GPIOBASE, &tmplong);
if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
!(tmplong & 0x00000001)) {
debug("%s: unexpected GPIOBASE value\n", __func__);
- return -1;
+ return -ENODEV;
}
/*
@@ -170,105 +128,137 @@ static int gpio_init(void)
* an I/O address, not a memory address, so mask that off.
*/
gpiobase = tmplong & 0xfffffffe;
+ offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
+ if (offset == -1) {
+ debug("%s: Invalid register offset %d\n", __func__, offset);
+ return -EINVAL;
+ }
+ plat->base_addr = gpiobase + offset;
+ plat->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
+ "bank-name", NULL);
- /* Finally. These are the droids we're looking for. */
- found_it_once = 1;
return 0;
}
-int gpio_request(unsigned num, const char *label /* UNUSED */)
+int ich6_gpio_probe(struct udevice *dev)
{
- u32 tmplong;
- int i = 0, j = 0;
+ struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
+
+ uc_priv->gpio_count = GPIO_PER_BANK;
+ uc_priv->bank_name = plat->bank_name;
+ bank->use_sel = plat->base_addr;
+ bank->io_sel = plat->base_addr + 4;
+ bank->lvl = plat->base_addr + 8;
- /* Is the hardware ready? */
- if (gpio_init())
- return -1;
+ return 0;
+}
- if (bad_arg(num, &i, &j))
- return -1;
+int ich6_gpio_request(struct udevice *dev, unsigned offset, const char *label)
+{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
+ u32 tmplong;
/*
* Make sure that the GPIO pin we want isn't already in use for some
* built-in hardware function. We have to check this for every
* requested pin.
*/
- tmplong = inl(gpiobase + gpio_bank[i].use_sel);
- if (!(tmplong & (1UL << j))) {
+ tmplong = inl(bank->use_sel);
+ if (!(tmplong & (1UL << offset))) {
debug("%s: gpio %d is reserved for internal use\n", __func__,
- num);
- return -1;
+ offset);
+ return -EPERM;
}
- return mark_gpio(i, j);
-}
-
-int gpio_free(unsigned num)
-{
- int i = 0, j = 0;
-
- if (notmine(num, &i, &j))
- return -1;
-
- clear_gpio(i, j);
return 0;
}
-int gpio_direction_input(unsigned num)
+static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
- int i = 0, j = 0;
-
- if (notmine(num, &i, &j))
- return -1;
- tmplong = inl(gpiobase + gpio_bank[i].io_sel);
- tmplong |= (1UL << j);
- outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+ tmplong = inl(bank->io_sel);
+ tmplong |= (1UL << offset);
+ outl(bank->io_sel, tmplong);
return 0;
}
-int gpio_direction_output(unsigned num, int value)
+static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
- int i = 0, j = 0;
- if (notmine(num, &i, &j))
- return -1;
-
- tmplong = inl(gpiobase + gpio_bank[i].io_sel);
- tmplong &= ~(1UL << j);
- outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+ tmplong = inl(bank->io_sel);
+ tmplong &= ~(1UL << offset);
+ outl(bank->io_sel, tmplong);
return 0;
}
-int gpio_get_value(unsigned num)
+static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
+
{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
- int i = 0, j = 0;
int r;
- if (notmine(num, &i, &j))
- return -1;
-
- tmplong = inl(gpiobase + gpio_bank[i].lvl);
- r = (tmplong & (1UL << j)) ? 1 : 0;
+ tmplong = inl(bank->lvl);
+ r = (tmplong & (1UL << offset)) ? 1 : 0;
return r;
}
-int gpio_set_value(unsigned num, int value)
+static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
+ int value)
{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
- int i = 0, j = 0;
- if (notmine(num, &i, &j))
- return -1;
-
- tmplong = inl(gpiobase + gpio_bank[i].lvl);
+ tmplong = inl(bank->lvl);
if (value)
- tmplong |= (1UL << j);
+ tmplong |= (1UL << offset);
else
- tmplong &= ~(1UL << j);
- outl(gpiobase + gpio_bank[i].lvl, tmplong);
+ tmplong &= ~(1UL << offset);
+ outl(bank->lvl, tmplong);
return 0;
}
+
+static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
+ u32 mask = 1UL << offset;
+
+ if (!(inl(bank->use_sel) & mask))
+ return GPIOF_FUNC;
+ if (inl(bank->io_sel) & mask)
+ return GPIOF_INPUT;
+ else
+ return GPIOF_OUTPUT;
+}
+
+static const struct dm_gpio_ops gpio_ich6_ops = {
+ .request = ich6_gpio_request,
+ .direction_input = ich6_gpio_direction_input,
+ .direction_output = ich6_gpio_direction_output,
+ .get_value = ich6_gpio_get_value,
+ .set_value = ich6_gpio_set_value,
+ .get_function = ich6_gpio_get_function,
+};
+
+static const struct udevice_id intel_ich6_gpio_ids[] = {
+ { .compatible = "intel,ich6-gpio" },
+ { }
+};
+
+U_BOOT_DRIVER(gpio_ich6) = {
+ .name = "gpio_ich6",
+ .id = UCLASS_GPIO,
+ .of_match = intel_ich6_gpio_ids,
+ .ops = &gpio_ich6_ops,
+ .ofdata_to_platdata = gpio_ich6_ofdata_to_platdata,
+ .probe = ich6_gpio_probe,
+ .priv_auto_alloc_size = sizeof(struct ich6_bank_priv),
+ .platdata_auto_alloc_size = sizeof(struct ich6_bank_platdata),
+};
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index 3f7b7d2..8bb9e39 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -20,7 +20,6 @@ enum mxc_gpio_direction {
MXC_GPIO_DIRECTION_OUT,
};
-#define GPIO_NAME_SIZE 20
#define GPIO_PER_BANK 32
struct mxc_gpio_plat {
@@ -28,7 +27,6 @@ struct mxc_gpio_plat {
};
struct mxc_bank_info {
- char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
struct gpio_regs *regs;
};
@@ -152,18 +150,6 @@ int gpio_direction_output(unsigned gpio, int value)
#endif
#ifdef CONFIG_DM_GPIO
-/**
- * gpio_is_requested() - check if a GPIO has been requested
- *
- * @bank: Bank to check
- * @offset: GPIO offset within bank to check
- * @return true if marked as requested, false if not
- */
-static inline bool gpio_is_requested(struct mxc_bank_info *bank, int offset)
-{
- return *bank->label[offset] != '\0';
-}
-
static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
{
u32 val;
@@ -208,35 +194,10 @@ static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
return (readl(&regs->gpio_psr) >> offset) & 0x01;
}
-static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset)
-{
- return (readl(&regs->gpio_dr) >> offset) & 0x01;
-}
-
-static int check_requested(struct udevice *dev, unsigned offset,
- const char *func)
-{
- struct mxc_bank_info *bank = dev_get_priv(dev);
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-
- if (!gpio_is_requested(bank, offset)) {
- printf("mxc_gpio: %s: error: gpio %s%d not requested\n",
- func, uc_priv->bank_name, offset);
- return -EPERM;
- }
-
- return 0;
-}
-
/* set GPIO pin 'gpio' as an input */
static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO direction as input. */
mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
@@ -249,11 +210,6 @@ static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO output value. */
mxc_gpio_bank_set_value(bank->regs, offset, value);
@@ -268,11 +224,6 @@ static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
return mxc_gpio_bank_get_value(bank->regs, offset);
}
@@ -282,80 +233,16 @@ static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
mxc_gpio_bank_set_value(bank->regs, offset, value);
return 0;
}
-static int mxc_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct mxc_bank_info *bank = dev_get_priv(dev);
- const char *label;
- bool requested;
- bool is_output;
- int size;
-
- label = bank->label[offset];
- is_output = mxc_gpio_is_output(bank->regs, offset);
- size = snprintf(buf, bufsize, "%s%d: ",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset);
- buf += size;
- bufsize -= size;
- requested = gpio_is_requested(bank, offset);
- snprintf(buf, bufsize, "%s: %d [%c]%s%s",
- is_output ? "out" : " in",
- is_output ?
- mxc_gpio_bank_get_output_value(bank->regs, offset) :
- mxc_gpio_bank_get_value(bank->regs, offset),
- requested ? 'x' : ' ',
- requested ? " " : "",
- label);
-
- return 0;
-}
-
-static int mxc_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
-{
- struct mxc_bank_info *bank = dev_get_priv(dev);
-
- if (gpio_is_requested(bank, offset))
- return -EBUSY;
-
- strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
- bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
-
- return 0;
-}
-
-static int mxc_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
- bank->label[offset][0] = '\0';
-
- return 0;
-}
-
static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- if (!gpio_is_requested(bank, offset))
- return GPIOF_UNUSED;
-
/* GPIOF_FUNC is not implemented yet */
if (mxc_gpio_is_output(bank->regs, offset))
return GPIOF_OUTPUT;
@@ -364,14 +251,11 @@ static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
}
static const struct dm_gpio_ops gpio_mxc_ops = {
- .request = mxc_gpio_request,
- .free = mxc_gpio_free,
.direction_input = mxc_gpio_direction_input,
.direction_output = mxc_gpio_direction_output,
.get_value = mxc_gpio_get_value,
.set_value = mxc_gpio_set_value,
.get_function = mxc_gpio_get_function,
- .get_state = mxc_gpio_get_state,
};
static const struct mxc_gpio_plat mxc_plat[] = {
diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c
index 13dcf79..f3a7ccb 100644
--- a/drivers/gpio/omap_gpio.c
+++ b/drivers/gpio/omap_gpio.c
@@ -19,6 +19,7 @@
* Written by Juha Yrjölä <juha.yrjola@nokia.com>
*/
#include <common.h>
+#include <dm.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/errno.h>
@@ -26,10 +27,17 @@
#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];
-}
+#ifdef CONFIG_DM_GPIO
+
+#define GPIO_PER_BANK 32
+
+struct gpio_bank {
+ /* TODO(sjg@chromium.org): Can we use a struct here? */
+ void *base; /* address of registers in physical memory */
+ enum gpio_method method;
+};
+
+#endif
static inline int get_gpio_index(int gpio)
{
@@ -41,15 +49,6 @@ int gpio_is_valid(int gpio)
return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
}
-static int check_gpio(int gpio)
-{
- if (!gpio_is_valid(gpio)) {
- 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)
{
@@ -118,6 +117,48 @@ static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
__raw_writel(l, reg);
}
+static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
+{
+ void *reg = bank->base;
+ int input;
+
+ switch (bank->method) {
+ case METHOD_GPIO_24XX:
+ input = _get_gpio_direction(bank, 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 << gpio)) != 0;
+}
+
+#ifndef CONFIG_DM_GPIO
+
+static inline const struct gpio_bank *get_gpio_bank(int gpio)
+{
+ return &omap_gpio_bank[gpio >> 5];
+}
+
+static int check_gpio(int gpio)
+{
+ if (!gpio_is_valid(gpio)) {
+ printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
+ return -1;
+ }
+ return 0;
+}
+
/**
* Set value of the specified gpio
*/
@@ -139,32 +180,12 @@ int gpio_set_value(unsigned gpio, int value)
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;
+
+ return _get_gpio_value(bank, get_gpio_index(gpio));
}
/**
@@ -220,3 +241,95 @@ int gpio_free(unsigned gpio)
{
return 0;
}
+
+#else /* new driver model interface CONFIG_DM_GPIO */
+
+/* set GPIO pin 'gpio' as an input */
+static int omap_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ /* Configure GPIO direction as input. */
+ _set_gpio_direction(bank, offset, 1);
+
+ return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+static int omap_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ _set_gpio_dataout(bank, offset, value);
+ _set_gpio_direction(bank, offset, 0);
+
+ return 0;
+}
+
+/* read GPIO IN value of pin 'gpio' */
+static int omap_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ return _get_gpio_value(bank, offset);
+}
+
+/* write GPIO OUT value to pin 'gpio' */
+static int omap_gpio_set_value(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ _set_gpio_dataout(bank, offset, value);
+
+ return 0;
+}
+
+static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ /* GPIOF_FUNC is not implemented yet */
+ if (_get_gpio_direction(bank->base, offset) == OMAP_GPIO_DIR_OUT)
+ return GPIOF_OUTPUT;
+ else
+ return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops gpio_omap_ops = {
+ .direction_input = omap_gpio_direction_input,
+ .direction_output = omap_gpio_direction_output,
+ .get_value = omap_gpio_get_value,
+ .set_value = omap_gpio_set_value,
+ .get_function = omap_gpio_get_function,
+};
+
+static int omap_gpio_probe(struct udevice *dev)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+ struct omap_gpio_platdata *plat = dev_get_platdata(dev);
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ char name[18], *str;
+
+ sprintf(name, "GPIO%d_", plat->bank_index);
+ str = strdup(name);
+ if (!str)
+ return -ENOMEM;
+ uc_priv->bank_name = str;
+ uc_priv->gpio_count = GPIO_PER_BANK;
+ bank->base = (void *)plat->base;
+ bank->method = plat->method;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(gpio_omap) = {
+ .name = "gpio_omap",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_omap_ops,
+ .probe = omap_gpio_probe,
+ .priv_auto_alloc_size = sizeof(struct gpio_bank),
+};
+
+#endif /* CONFIG_DM_GPIO */
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 13d74eb..6c41a42 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -33,8 +33,6 @@ DECLARE_GLOBAL_DATA_PTR;
#define RATE_MASK(gpio) (0x1 << (gpio + 16))
#define RATE_SET(gpio) (0x1 << (gpio + 16))
-#define GPIO_NAME_SIZE 20
-
/* Platform data for each bank */
struct exynos_gpio_platdata {
struct s5p_gpio_bank *bank;
@@ -43,7 +41,6 @@ struct exynos_gpio_platdata {
/* Information about each bank at run-time */
struct exynos_bank_info {
- char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
struct s5p_gpio_bank *bank;
};
@@ -189,61 +186,10 @@ int s5p_gpio_get_pin(unsigned gpio)
/* Driver model interface */
#ifndef CONFIG_SPL_BUILD
-static int exynos_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct exynos_bank_info *state = dev_get_priv(dev);
- const char *label;
- bool is_output;
- int size;
- int cfg;
-
- label = state->label[offset];
- cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
- is_output = cfg == S5P_GPIO_OUTPUT;
- size = snprintf(buf, bufsize, "%s%d: ",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset);
- buf += size;
- bufsize -= size;
- if (is_output || cfg == S5P_GPIO_INPUT) {
- snprintf(buf, bufsize, "%s: %d [%c]%s%s",
- is_output ? "out" : " in",
- s5p_gpio_get_value(state->bank, offset),
- *label ? 'x' : ' ',
- *label ? " " : "",
- label);
- } else {
- snprintf(buf, bufsize, "sfpio");
- }
-
- return 0;
-}
-
-static int check_reserved(struct udevice *dev, unsigned offset,
- const char *func)
-{
- struct exynos_bank_info *state = dev_get_priv(dev);
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-
- if (!*state->label[offset]) {
- printf("exynos_gpio: %s: error: gpio %s%d not reserved\n",
- func, uc_priv->bank_name, offset);
- return -EPERM;
- }
-
- return 0;
-}
-
/* set GPIO pin 'gpio' as an input */
static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO direction as input. */
s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT);
@@ -256,11 +202,6 @@ static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
{
struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO output value. */
s5p_gpio_set_value(state->bank, offset, value);
@@ -275,11 +216,6 @@ static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
static int exynos_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
return s5p_gpio_get_value(state->bank, offset);
}
@@ -289,43 +225,11 @@ static int exynos_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
s5p_gpio_set_value(state->bank, offset, value);
return 0;
}
-
-static int exynos_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
-{
- struct exynos_bank_info *state = dev_get_priv(dev);
-
- if (*state->label[offset])
- return -EBUSY;
-
- strncpy(state->label[offset], label, GPIO_NAME_SIZE);
- state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
-
- return 0;
-}
-
-static int exynos_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
- state->label[offset][0] = '\0';
-
- return 0;
-}
#endif /* nCONFIG_SPL_BUILD */
/*
@@ -362,8 +266,6 @@ static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
struct exynos_bank_info *state = dev_get_priv(dev);
int cfg;
- if (!*state->label[offset])
- return GPIOF_UNUSED;
cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
if (cfg == S5P_GPIO_OUTPUT)
return GPIOF_OUTPUT;
@@ -374,14 +276,11 @@ static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
}
static const struct dm_gpio_ops gpio_exynos_ops = {
- .request = exynos_gpio_request,
- .free = exynos_gpio_free,
.direction_input = exynos_gpio_direction_input,
.direction_output = exynos_gpio_direction_output,
.get_value = exynos_gpio_get_value,
.set_value = exynos_gpio_set_value,
.get_function = exynos_gpio_get_function,
- .get_state = exynos_gpio_get_state,
};
static int gpio_exynos_probe(struct udevice *dev)
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 75ada5d..53c80d5 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -14,7 +14,6 @@ DECLARE_GLOBAL_DATA_PTR;
/* Flags for each GPIO */
#define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */
#define GPIOF_HIGH (1 << 1) /* Currently set high */
-#define GPIOF_RESERVED (1 << 2) /* Is in use / requested */
struct gpio_state {
const char *label; /* label given by requester */
@@ -54,18 +53,6 @@ static int set_gpio_flag(struct udevice *dev, unsigned offset, int flag,
return 0;
}
-static int check_reserved(struct udevice *dev, unsigned offset,
- const char *func)
-{
- if (!get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
- printf("sandbox_gpio: %s: error: offset %u not reserved\n",
- func, offset);
- return -1;
- }
-
- return 0;
-}
-
/*
* Back-channel sandbox-internal-only access to GPIO state
*/
@@ -101,9 +88,6 @@ static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
{
debug("%s: offset:%u\n", __func__, offset);
- if (check_reserved(dev, offset, __func__))
- return -1;
-
return sandbox_gpio_set_direction(dev, offset, 0);
}
@@ -113,9 +97,6 @@ static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
{
debug("%s: offset:%u, value = %d\n", __func__, offset, value);
- if (check_reserved(dev, offset, __func__))
- return -1;
-
return sandbox_gpio_set_direction(dev, offset, 1) |
sandbox_gpio_set_value(dev, offset, value);
}
@@ -125,9 +106,6 @@ static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
{
debug("%s: offset:%u\n", __func__, offset);
- if (check_reserved(dev, offset, __func__))
- return -1;
-
return sandbox_gpio_get_value(dev, offset);
}
@@ -136,9 +114,6 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
{
debug("%s: offset:%u, value = %d\n", __func__, offset, value);
- if (check_reserved(dev, offset, __func__))
- return -1;
-
if (!sandbox_gpio_get_direction(dev, offset)) {
printf("sandbox_gpio: error: set_value on input gpio %u\n",
offset);
@@ -148,69 +123,19 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
return sandbox_gpio_set_value(dev, offset, value);
}
-static int sb_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
+static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct gpio_state *state = dev_get_priv(dev);
-
- debug("%s: offset:%u, label:%s\n", __func__, offset, label);
-
- if (offset >= uc_priv->gpio_count) {
- printf("sandbox_gpio: error: invalid gpio %u\n", offset);
- return -1;
- }
-
- if (get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
- printf("sandbox_gpio: error: gpio %u already reserved\n",
- offset);
- return -1;
- }
-
- state[offset].label = label;
- return set_gpio_flag(dev, offset, GPIOF_RESERVED, 1);
-}
-
-static int sb_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct gpio_state *state = dev_get_priv(dev);
-
- debug("%s: offset:%u\n", __func__, offset);
-
- if (check_reserved(dev, offset, __func__))
- return -1;
-
- state[offset].label = NULL;
- return set_gpio_flag(dev, offset, GPIOF_RESERVED, 0);
-}
-
-static int sb_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct gpio_state *state = dev_get_priv(dev);
- const char *label;
-
- label = state[offset].label;
- snprintf(buf, bufsize, "%s%d: %s: %d [%c]%s%s",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset,
- sandbox_gpio_get_direction(dev, offset) ? "out" : " in",
- sandbox_gpio_get_value(dev, offset),
- get_gpio_flag(dev, offset, GPIOF_RESERVED) ? 'x' : ' ',
- label ? " " : "",
- label ? label : "");
-
- return 0;
+ if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
+ return GPIOF_OUTPUT;
+ return GPIOF_INPUT;
}
static const struct dm_gpio_ops gpio_sandbox_ops = {
- .request = sb_gpio_request,
- .free = sb_gpio_free,
.direction_input = sb_gpio_direction_input,
.direction_output = sb_gpio_direction_output,
.get_value = sb_gpio_get_value,
.set_value = sb_gpio_set_value,
- .get_state = sb_gpio_get_state,
+ .get_function = sb_gpio_get_function,
};
static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
@@ -239,6 +164,13 @@ static int gpio_sandbox_probe(struct udevice *dev)
return 0;
}
+static int gpio_sandbox_remove(struct udevice *dev)
+{
+ free(dev->priv);
+
+ return 0;
+}
+
static const struct udevice_id sandbox_gpio_ids[] = {
{ .compatible = "sandbox,gpio" },
{ }
@@ -250,5 +182,6 @@ U_BOOT_DRIVER(gpio_sandbox) = {
.of_match = sandbox_gpio_ids,
.ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
.probe = gpio_sandbox_probe,
+ .remove = gpio_sandbox_remove,
.ops = &gpio_sandbox_ops,
};
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 70663fc..88f7ef5 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -39,7 +39,6 @@ struct tegra_gpio_platdata {
/* Information about each port at run-time */
struct tegra_port_info {
- char label[TEGRA_GPIOS_PER_PORT][GPIO_NAME_SIZE];
struct gpio_ctlr_bank *bank;
int base_gpio; /* Port number for this port (0, 1,.., n-1) */
};
@@ -132,21 +131,6 @@ static void set_level(unsigned gpio, int high)
writel(u, &bank->gpio_out[GPIO_PORT(gpio)]);
}
-static int check_reserved(struct udevice *dev, unsigned offset,
- const char *func)
-{
- struct tegra_port_info *state = dev_get_priv(dev);
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-
- if (!*state->label[offset]) {
- printf("tegra_gpio: %s: error: gpio %s%d not reserved\n",
- func, uc_priv->bank_name, offset);
- return -EBUSY;
- }
-
- return 0;
-}
-
/* set GPIO pin 'gpio' as an output, with polarity 'value' */
int tegra_spl_gpio_direction_output(int gpio, int value)
{
@@ -171,59 +155,16 @@ static int tegra_gpio_request(struct udevice *dev, unsigned offset,
{
struct tegra_port_info *state = dev_get_priv(dev);
- if (!label)
- return -EINVAL;
-
- if (*state->label[offset])
- return -EBUSY;
-
- strncpy(state->label[offset], label, GPIO_NAME_SIZE);
- state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
-
/* Configure as a GPIO */
set_config(state->base_gpio + offset, 1);
return 0;
}
-static int tegra_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct tegra_port_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
- state->label[offset][0] = '\0';
-
- return 0;
-}
-
-/* read GPIO OUT value of pin 'gpio' */
-static int tegra_gpio_get_output_value(unsigned gpio)
-{
- struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
- struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
- int val;
-
- debug("gpio_get_output_value: pin = %d (port %d:bit %d)\n",
- gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
-
- val = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
-
- return (val >> GPIO_BIT(gpio)) & 1;
-}
-
-
/* set GPIO pin 'gpio' as an input */
static int tegra_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct tegra_port_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO direction as input. */
set_direction(state->base_gpio + offset, 0);
@@ -237,11 +178,6 @@ static int tegra_gpio_direction_output(struct udevice *dev, unsigned offset,
{
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO output value. */
set_level(gpio, value);
@@ -257,13 +193,8 @@ static int tegra_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
- int ret;
int val;
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
-
debug("%s: pin = %d (port %d:bit %d)\n", __func__,
gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
@@ -277,11 +208,6 @@ static int tegra_gpio_set_value(struct udevice *dev, unsigned offset, int value)
{
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n",
gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
@@ -317,8 +243,6 @@ static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
- if (!*state->label[offset])
- return GPIOF_UNUSED;
if (!get_config(gpio))
return GPIOF_FUNC;
else if (get_direction(gpio))
@@ -327,50 +251,13 @@ static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
-static int tegra_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct tegra_port_info *state = dev_get_priv(dev);
- int gpio = state->base_gpio + offset;
- const char *label;
- int is_output;
- int is_gpio;
- int size;
-
- label = state->label[offset];
- is_gpio = get_config(gpio); /* GPIO, not SFPIO */
- size = snprintf(buf, bufsize, "%s%d: ",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset);
- buf += size;
- bufsize -= size;
- if (is_gpio) {
- is_output = get_direction(gpio);
-
- snprintf(buf, bufsize, "%s: %d [%c]%s%s",
- is_output ? "out" : " in",
- is_output ?
- tegra_gpio_get_output_value(gpio) :
- tegra_gpio_get_value(dev, offset),
- *label ? 'x' : ' ',
- *label ? " " : "",
- label);
- } else {
- snprintf(buf, bufsize, "sfpio");
- }
-
- return 0;
-}
-
static const struct dm_gpio_ops gpio_tegra_ops = {
.request = tegra_gpio_request,
- .free = tegra_gpio_free,
.direction_input = tegra_gpio_direction_input,
.direction_output = tegra_gpio_direction_output,
.get_value = tegra_gpio_get_value,
.set_value = tegra_gpio_set_value,
.get_function = tegra_gpio_get_function,
- .get_state = tegra_gpio_get_state,
};
/**