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/omap_gpio.c') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index 13dcf798730..d2d2640db89 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.2.3 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/omap_gpio.c') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index d2d2640db89..a4651bc700b 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.2.3 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/omap_gpio.c') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index a4651bc700b..f3a7ccb51e9 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.2.3