diff options
author | Tom Rini <trini@ti.com> | 2014-10-26 21:03:08 +0300 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2014-10-26 21:03:08 +0300 |
commit | 84a6df09c78bc9e9cbc6265d99c9097f5f1079f2 (patch) | |
tree | 3b2bf1b3689e9aad0d20f5a69ada168cae3cc769 /drivers/gpio | |
parent | c69ecd9722af22d50295eff81d0b9cd5b8adc2e0 (diff) | |
parent | c2ded962d4703a3f9522553004db4a6fe540f7e6 (diff) | |
download | u-boot-84a6df09c78bc9e9cbc6265d99c9097f5f1079f2.tar.xz |
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/Kconfig | 6 | ||||
-rw-r--r-- | drivers/gpio/bcm2835_gpio.c | 89 | ||||
-rw-r--r-- | drivers/gpio/gpio-uclass.c | 236 | ||||
-rw-r--r-- | drivers/gpio/intel_ich6_gpio.c | 250 | ||||
-rw-r--r-- | drivers/gpio/mxc_gpio.c | 116 | ||||
-rw-r--r-- | drivers/gpio/omap_gpio.c | 183 | ||||
-rw-r--r-- | drivers/gpio/s5p_gpio.c | 101 | ||||
-rw-r--r-- | drivers/gpio/sandbox.c | 93 | ||||
-rw-r--r-- | drivers/gpio/tegra_gpio.c | 113 |
9 files changed, 497 insertions, 690 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e69de29bb2..d21302f8da 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 332cfc2b23..0244c01882 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 f1bbc58796..45e9a5ad22 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 7d9fac7233..d3381b0369 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 3f7b7d2441..8bb9e39b72 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(®s->gpio_psr) >> offset) & 0x01; } -static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset) -{ - return (readl(®s->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 13dcf79873..f3a7ccb51e 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 13d74eb951..6c41a42c17 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 75ada5d387..53c80d5be6 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 70663fc4de..88f7ef5bf0 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, }; /** |