From fe1ef503381c4c03c059de3324271ce21cae3078 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 22 Oct 2014 21:37:01 -0600 Subject: dm: gpio: Support numbered GPIOs At present banks must be named and it is not possible to refer to GPIOs by number in driver model. Some boards use numbering - e.g. OMAP. It is fairly easy to support by detecting the absense of a bank name (which starts with a letter). Add support for numbered GPIOs in addition to the existing bank support. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/gpio/gpio-uclass.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index f1bbc58..a5ffd85 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -8,6 +8,7 @@ #include #include #include +#include /** * gpio_to_device() - Convert global GPIO number to device, number @@ -43,35 +44,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; } /** -- cgit v1.1 From d57b61143d8c74dee392fc5be52cb6ec5a15b8fc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 22 Oct 2014 21:37:08 -0600 Subject: dm: omap: gpio: Put _get_gpio_value() logic into its own function Add a separate internal helper function to get a GPIO value, so that we will be able to call it with the driver model version and avoid code duplication. Also move gpio_get_bank() and check_gpio() down below the helper functions as these won't be needed with driver model. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/gpio/omap_gpio.c | 78 ++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 36 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index 13dcf79..d2d2640 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -26,11 +26,6 @@ #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]; -} - static inline int get_gpio_index(int gpio) { return gpio & 0x1f; @@ -41,15 +36,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 +104,46 @@ 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; +} + +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 +165,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)); } /** -- cgit v1.1 From 5915a2ad0da6086892c587442d4eabd681f987b5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 22 Oct 2014 21:37:09 -0600 Subject: dm: omap: gpio: Support driver model Add driver model support to this driver, while retaining support for the legacy system. Driver model GPIO support is enabled with CONFIG_DM_GPIO as usual. Since gpio_is_valid() no longer exists, we can use the -EINVAL error returned from gpio_request(). Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/gpio/omap_gpio.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index d2d2640..a4651bc 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -19,6 +19,7 @@ * Written by Juha Yrjölä */ #include +#include #include #include #include @@ -26,6 +27,20 @@ #define OMAP_GPIO_DIR_OUT 0 #define OMAP_GPIO_DIR_IN 1 +#ifdef CONFIG_DM_GPIO + +#define GPIO_NAME_SIZE 20 +#define GPIO_PER_BANK 32 + +struct gpio_bank { + char label[GPIO_PER_BANK][GPIO_NAME_SIZE]; + /* 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) { return gpio & 0x1f; @@ -130,6 +145,8 @@ static int _get_gpio_value(const struct gpio_bank *bank, int gpio) 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]; @@ -226,3 +243,207 @@ int gpio_free(unsigned gpio) { return 0; } + +#else /* new driver model interface 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 gpio_bank *bank, int offset) +{ + return *bank->label[offset] != '\0'; +} + +static int omap_gpio_is_output(struct gpio_bank *bank, int offset) +{ + return _get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT; +} + +static int check_requested(struct udevice *dev, unsigned offset, + const char *func) +{ + struct gpio_bank *bank = dev_get_priv(dev); + struct gpio_dev_priv *uc_priv = dev->uclass_priv; + + if (!gpio_is_requested(bank, offset)) { + printf("omap_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 omap_gpio_direction_input(struct udevice *dev, unsigned offset) +{ + struct gpio_bank *bank = dev_get_priv(dev); + int ret; + + ret = check_requested(dev, offset, __func__); + if (ret) + return ret; + + /* 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); + int ret; + + ret = check_requested(dev, offset, __func__); + if (ret) + return ret; + + _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); + int ret; + + ret = check_requested(dev, offset, __func__); + if (ret) + return ret; + + 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); + int ret; + + ret = check_requested(dev, offset, __func__); + if (ret) + return ret; + + _set_gpio_dataout(bank, offset, value); + + return 0; +} + +static int omap_gpio_get_state(struct udevice *dev, unsigned int offset, + char *buf, int bufsize) +{ + struct gpio_dev_priv *uc_priv = dev->uclass_priv; + struct gpio_bank *bank = dev_get_priv(dev); + const char *label; + bool requested; + bool is_output; + int size; + + label = bank->label[offset]; + is_output = omap_gpio_is_output(bank->base, 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", + _get_gpio_value(bank, offset), + requested ? 'x' : ' ', + requested ? " " : "", + label); + + return 0; +} + +static int omap_gpio_request(struct udevice *dev, unsigned offset, + const char *label) +{ + struct gpio_bank *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 omap_gpio_free(struct udevice *dev, unsigned offset) +{ + struct gpio_bank *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 omap_gpio_get_function(struct udevice *dev, unsigned offset) +{ + struct gpio_bank *bank = dev_get_priv(dev); + + if (!gpio_is_requested(bank, offset)) + return GPIOF_UNUSED; + + /* GPIOF_FUNC is not implemented yet */ + if (_get_gpio_direction(bank->base, offset)) + return GPIOF_OUTPUT; + else + return GPIOF_INPUT; +} + +static const struct dm_gpio_ops gpio_omap_ops = { + .request = omap_gpio_request, + .free = omap_gpio_free, + .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, + .get_state = omap_gpio_get_state, +}; + +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 */ -- cgit v1.1 From b892d127ffd448e8adf21e9703c0c5107e2a7814 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:42 -0600 Subject: dm: gpio: Implement GPIO reservation in the uclass We have several GPIO drivers now and all are doing similar things to record which GPIOs are reserved. Move this logic into the uclass to make the drivers similar. We retain the request()/free() methods since currently one driver does use these for setting up the pin. Signed-off-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 92 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 14 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index a5ffd85..e11c5a6 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -92,24 +93,41 @@ 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 gpio_get_ops(dev)->request(dev, offset, label); + return 0; } /** @@ -122,6 +140,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; @@ -130,9 +149,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; } /** @@ -152,8 +196,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); } /** @@ -174,8 +219,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); } /** @@ -196,8 +243,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); } /** @@ -218,8 +266,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) @@ -235,7 +284,7 @@ const char *gpio_get_bank_info(struct udevice *dev, int *bit_count) } /* 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; @@ -250,7 +299,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; @@ -262,12 +311,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) = { -- cgit v1.1 From 6449a506d67b0374bf23a3833f15afa0c92a7a0e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:43 -0600 Subject: dm: gpio: Add gpio_get_function() and friends Add helpers to the uclass to allow finding out the pin function. Signed-off-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index e11c5a6..04b7b16 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -283,6 +283,53 @@ 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); +} + /* We need to renumber the GPIOs when any driver is probed/removed */ static int gpio_renumber(struct udevice *removed_dev) { -- cgit v1.1 From 0757535a7eee3ae5603520fe4a0588a01a590ea7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:44 -0600 Subject: dm: Move the function for getting GPIO status into the uclass This function can be more easily tested if it is in the uclass. Signed-off-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 04b7b16..6367093 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -330,6 +330,45 @@ 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(struct udevice *removed_dev) { -- cgit v1.1 From 699ea9606ca8e4227c8be607197733d348cd12c4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:45 -0600 Subject: dm: gpio: sandbox: Implement the get_function() method Implement this method so that the 'gpio' command can do its job correctly. For sandbox we only support input and output states for a gpio. Signed-off-by: Simon Glass --- drivers/gpio/sandbox.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index 75ada5d..7aa8b1f 100644 --- a/drivers/gpio/sandbox.c +++ b/drivers/gpio/sandbox.c @@ -203,6 +203,13 @@ static int sb_gpio_get_state(struct udevice *dev, unsigned int offset, return 0; } +static int sb_gpio_get_function(struct udevice *dev, unsigned offset) +{ + 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, @@ -210,7 +217,7 @@ static const struct dm_gpio_ops gpio_sandbox_ops = { .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) -- cgit v1.1 From 62cb89d5ebbe1abd22df8d5d5f442989fc7558af Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:46 -0600 Subject: dm: gpio: sandbox: Implement the remove() method This method frees memory so we must make sure to implement it. Signed-off-by: Simon Glass --- drivers/gpio/sandbox.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index 7aa8b1f..13b3253 100644 --- a/drivers/gpio/sandbox.c +++ b/drivers/gpio/sandbox.c @@ -246,6 +246,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" }, { } @@ -257,5 +264,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, }; -- cgit v1.1 From 5e0bbd61df15040c23d7b3246fd522f555074dc6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:47 -0600 Subject: dm: gpio: sandbox: Drop request()/free() in the driver Now that the uclass supports gpio_request/free() there is no need for the driver to implement it too. Drop this unnecessary code. Signed-off-by: Simon Glass --- drivers/gpio/sandbox.c | 82 -------------------------------------------------- 1 file changed, 82 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index 13b3253..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,61 +123,6 @@ 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) -{ - 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; -} - static int sb_gpio_get_function(struct udevice *dev, unsigned offset) { if (get_gpio_flag(dev, offset, GPIOF_OUTPUT)) @@ -211,8 +131,6 @@ static int sb_gpio_get_function(struct udevice *dev, unsigned offset) } 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, -- cgit v1.1 From d44f597b12b8f8099c3c52c3eb09540966cafe79 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:49 -0600 Subject: dm: gpio: Add gpio_requestf() helper for printf() strings Add a helper which permits a printf()-style format string for the requester string. Signed-off-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 6367093..45e9a5a 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -131,6 +131,27 @@ int gpio_request(unsigned gpio, const char *label) } /** + * 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]; + + va_start(args, fmt); + vscnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + return gpio_request(gpio, buf); +} + +/** * gpio_free() - [COMPAT] Relinquish GPIO * gpio: GPIO number * -- cgit v1.1 From 57d99d368e0eff624c5403b1f04d2548c5813598 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:52 -0600 Subject: dm: gpio: tegra: Drop request()/free() in the driver Now that the uclass supports gpio_request/free() there is no need for the driver to implement it too. Drop this unnecessary code. Signed-off-by: Simon Glass --- drivers/gpio/tegra_gpio.c | 113 ---------------------------------------------- 1 file changed, 113 deletions(-) (limited to 'drivers/gpio') 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, }; /** -- cgit v1.1 From 5aff3acdb75bf075a746783eace341300191a061 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:53 -0600 Subject: dm: gpio: omap3: Drop request()/free() in the driver Now that the uclass supports gpio_request/free() there is no need for the driver to implement it too. Drop this unnecessary code. Signed-off-by: Simon Glass --- drivers/gpio/omap_gpio.c | 116 +---------------------------------------------- 1 file changed, 1 insertion(+), 115 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index a4651bc..f3a7ccb 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -29,11 +29,9 @@ #ifdef CONFIG_DM_GPIO -#define GPIO_NAME_SIZE 20 #define GPIO_PER_BANK 32 struct gpio_bank { - char label[GPIO_PER_BANK][GPIO_NAME_SIZE]; /* TODO(sjg@chromium.org): Can we use a struct here? */ void *base; /* address of registers in physical memory */ enum gpio_method method; @@ -246,47 +244,10 @@ int gpio_free(unsigned gpio) #else /* new driver model interface 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 gpio_bank *bank, int offset) -{ - return *bank->label[offset] != '\0'; -} - -static int omap_gpio_is_output(struct gpio_bank *bank, int offset) -{ - return _get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT; -} - -static int check_requested(struct udevice *dev, unsigned offset, - const char *func) -{ - struct gpio_bank *bank = dev_get_priv(dev); - struct gpio_dev_priv *uc_priv = dev->uclass_priv; - - if (!gpio_is_requested(bank, offset)) { - printf("omap_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 omap_gpio_direction_input(struct udevice *dev, unsigned offset) { struct gpio_bank *bank = dev_get_priv(dev); - int ret; - - ret = check_requested(dev, offset, __func__); - if (ret) - return ret; /* Configure GPIO direction as input. */ _set_gpio_direction(bank, offset, 1); @@ -299,11 +260,6 @@ static int omap_gpio_direction_output(struct udevice *dev, unsigned offset, int value) { struct gpio_bank *bank = dev_get_priv(dev); - int ret; - - ret = check_requested(dev, offset, __func__); - if (ret) - return ret; _set_gpio_dataout(bank, offset, value); _set_gpio_direction(bank, offset, 0); @@ -315,11 +271,6 @@ static int omap_gpio_direction_output(struct udevice *dev, unsigned offset, static int omap_gpio_get_value(struct udevice *dev, unsigned offset) { struct gpio_bank *bank = dev_get_priv(dev); - int ret; - - ret = check_requested(dev, offset, __func__); - if (ret) - return ret; return _get_gpio_value(bank, offset); } @@ -329,94 +280,29 @@ static int omap_gpio_set_value(struct udevice *dev, unsigned offset, int value) { struct gpio_bank *bank = dev_get_priv(dev); - int ret; - - ret = check_requested(dev, offset, __func__); - if (ret) - return ret; _set_gpio_dataout(bank, offset, value); return 0; } -static int omap_gpio_get_state(struct udevice *dev, unsigned int offset, - char *buf, int bufsize) -{ - struct gpio_dev_priv *uc_priv = dev->uclass_priv; - struct gpio_bank *bank = dev_get_priv(dev); - const char *label; - bool requested; - bool is_output; - int size; - - label = bank->label[offset]; - is_output = omap_gpio_is_output(bank->base, 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", - _get_gpio_value(bank, offset), - requested ? 'x' : ' ', - requested ? " " : "", - label); - - return 0; -} - -static int omap_gpio_request(struct udevice *dev, unsigned offset, - const char *label) -{ - struct gpio_bank *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 omap_gpio_free(struct udevice *dev, unsigned offset) -{ - struct gpio_bank *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 omap_gpio_get_function(struct udevice *dev, unsigned offset) { struct gpio_bank *bank = dev_get_priv(dev); - if (!gpio_is_requested(bank, offset)) - return GPIOF_UNUSED; - /* GPIOF_FUNC is not implemented yet */ - if (_get_gpio_direction(bank->base, offset)) + 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 = { - .request = omap_gpio_request, - .free = omap_gpio_free, .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, - .get_state = omap_gpio_get_state, }; static int omap_gpio_probe(struct udevice *dev) -- cgit v1.1 From 3dd2d480558f45152a5d2ab5590c657055f1a756 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:54 -0600 Subject: dm: gpio: rpi_b: Drop request()/free() in the driver Now that the uclass supports gpio_request/free() there is no need for the driver to implement it too. Drop this unnecessary code. Signed-off-by: Simon Glass --- drivers/gpio/bcm2835_gpio.c | 89 --------------------------------------------- 1 file changed, 89 deletions(-) (limited to 'drivers/gpio') 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 #include -#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) -- cgit v1.1 From 6227fb87c4afbbabb9fda9894143ae98aa2cadd4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:55 -0600 Subject: dm: gpio: exynos: Drop request()/free() in the driver Now that the uclass supports gpio_request/free() there is no need for the driver to implement it too. Drop this unnecessary code. Signed-off-by: Simon Glass --- drivers/gpio/s5p_gpio.c | 101 ------------------------------------------------ 1 file changed, 101 deletions(-) (limited to 'drivers/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) -- cgit v1.1 From c65dd445c97a28963894451878cdc6b580f3382e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Oct 2014 11:29:56 -0600 Subject: dm: gpio: imx: Drop request()/free() in the driver Now that the uclass supports gpio_request/free() there is no need for the driver to implement it too. Drop this unnecessary code. Signed-off-by: Simon Glass --- drivers/gpio/mxc_gpio.c | 116 ------------------------------------------------ 1 file changed, 116 deletions(-) (limited to 'drivers/gpio') 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(®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[] = { -- cgit v1.1 From 7414112d70727e90be680e77dcb8a31394255ca8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Oct 2014 07:49:18 -0600 Subject: dm: x86: Convert Intel ICH6 GPIO driver to use driver model Convert over this driver, using device tree to pass in the required information. The peripheral is still probed, just the number of GPIO banks and their offsets is in the device tree (previously this was a table in the driver). Signed-off-by: Simon Glass --- drivers/gpio/intel_ich6_gpio.c | 250 ++++++++++++++++++++--------------------- 1 file changed, 120 insertions(+), 130 deletions(-) (limited to 'drivers/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 +#include +#include +#include #include #include #include +#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), +}; -- cgit v1.1 From da333ae73cddf12e8f71a847e42a6571f9435d7c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 23 Oct 2014 22:26:09 +0900 Subject: dm: add entries to Kconfig Create entries of CONFIG_DM, CONFIG_DM_SERIAL, CONFIG_DM_GPIO and CONFIG_DM_SPI. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- drivers/gpio/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpio') 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. -- cgit v1.1