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') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index f1bbc58796..a5ffd85c42 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.2.1 From c487fd476c8779dbd6ee1427489f1312b34bfc5e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 22 Oct 2014 21:37:02 -0600 Subject: dm: serial: Reset the watchdog while waiting in getc() We have moved the busy-wait loop out of drivers and into the uclass. This means that we must reset the watchdog when busy-waiting. Note: some drivers may still have a busy-wait even with driver model, as a transition mechanism. Driver model will tolerate this, and is can be cleaned up when all users of the driver use driver model. An example is ns16550. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/serial/serial-uclass.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 1a75950d19..1983a3d55b 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -11,9 +11,12 @@ #include #include #include +#include #include #include +#include + DECLARE_GLOBAL_DATA_PTR; /* The currently-selected console serial device */ @@ -119,6 +122,8 @@ static int serial_getc_dev(struct udevice *dev) do { err = ops->getc(dev); + if (err == -EAGAIN) + WATCHDOG_RESET(); } while (err == -EAGAIN); return err >= 0 ? err : 0; -- cgit v1.2.1 From aea2be2012f474ddc9f372547e487ee74d4eb67a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 22 Oct 2014 21:37:03 -0600 Subject: dm: serial: ns16550: Correct logic for checking for character There is a bug in the logic which checks for an available character. This can cause invalid characters to be received - this was noticed on beaglebone. Fix it. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/serial/ns16550.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 63a9ef6844..fe6cc26afe 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -253,7 +253,7 @@ static int ns16550_serial_getc(struct udevice *dev) { struct NS16550 *const com_port = dev_get_priv(dev); - if (!serial_in(&com_port->lsr) & UART_LSR_DR) + if (!(serial_in(&com_port->lsr) & UART_LSR_DR)) return -EAGAIN; return serial_in(&com_port->rbr); -- cgit v1.2.1 From 167efe01bc5a9de2aa4f7ce2663dbe398f9d43f6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 22 Oct 2014 21:37:04 -0600 Subject: dm: ns16550: Use an address instead of a pointer for the uart base It is inconvenient to have to use casts when specifying platform data. Also it is not strictly correct, since we should use map_sysmem() to convert an address to a pointer. Adjust the platform data to use an address. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/serial/ns16550.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index fe6cc26afe..2301f0af48 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -61,7 +61,7 @@ static void ns16550_writeb(NS16550_t port, int offset, int value) unsigned char *addr; offset *= 1 << plat->reg_shift; - addr = plat->base + offset; + addr = map_sysmem(plat->base, 0) + offset; /* * As far as we know it doesn't make sense to support selection of * these options at run-time, so use the existing CONFIG options. @@ -85,7 +85,7 @@ static int ns16550_readb(NS16550_t port, int offset) unsigned char *addr; offset *= 1 << plat->reg_shift; - addr = plat->base + offset; + addr = map_sysmem(plat->base, 0) + offset; #ifdef CONFIG_SYS_NS16550_PORT_MAPPED return inb(addr); #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) @@ -291,7 +291,7 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) if (addr == FDT_ADDR_T_NONE) return -EINVAL; - plat->base = (unsigned char *)addr; + plat->base = addr; plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg-shift", 1); com_port->plat = plat; -- cgit v1.2.1 From 11c1a87893a1005180e9609925b35cee241ec88c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 22 Oct 2014 21:37:05 -0600 Subject: dm: ns16550: Correct the probe logic for platform data The probe logic sets up the pointer to the platform data in the device tree decode method. It should be done in the probe() method, and anyway the device tree decode method can't be used when CONFIG_OF_CONTROL is not enabled. Fix these two problems. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/serial/ns16550.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 2301f0af48..0799aa4cd3 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -276,14 +276,15 @@ int ns16550_serial_probe(struct udevice *dev) { struct NS16550 *const com_port = dev_get_priv(dev); + com_port->plat = dev_get_platdata(dev); NS16550_init(com_port, -1); return 0; } +#ifdef CONFIG_OF_CONTROL int ns16550_serial_ofdata_to_platdata(struct udevice *dev) { - struct NS16550 *const com_port = dev_get_priv(dev); struct ns16550_platdata *plat = dev->platdata; fdt_addr_t addr; @@ -294,10 +295,10 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) plat->base = addr; plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg-shift", 1); - com_port->plat = plat; return 0; } +#endif const struct dm_serial_ops ns16550_serial_ops = { .putc = ns16550_serial_putc, -- cgit v1.2.1 From 91155c65604904b2048f7ad79d8303eb9a27e351 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 22 Oct 2014 21:37:06 -0600 Subject: dm: serial: Support CONFIG_CONS_INDEX if available Try to use this option to select the correct uart for the console. This mimics the behaviour of drivers/serial.c. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/serial/serial-uclass.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 1983a3d55b..c9383dcd00 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -50,13 +50,22 @@ static void serial_find_console_or_panic(void) } #endif /* + * Try to use CONFIG_CONS_INDEX if available (it is numbered from 1!). + * * Failing that, get the device with sequence number 0, or in extremis * just the first serial device we can find. But we insist on having * a console (even if it is silent). */ - if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) && +#ifdef CONFIG_CONS_INDEX +#define INDEX (CONFIG_CONS_INDEX - 1) +#else +#define INDEX 0 +#endif + if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &cur_dev) && + uclass_get_device(UCLASS_SERIAL, INDEX, &cur_dev) && (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev)) panic("No serial driver found"); +#undef INDEX } /* Called prior to relocation */ -- cgit v1.2.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') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index 13dcf79873..d2d2640db8 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.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 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/mmc/omap_hsmmc.c | 15 ++-- 2 files changed, 231 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index d2d2640db8..a4651bc700 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 */ diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 5b0c302069..ef2cbf9e2f 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -67,14 +67,19 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, #ifdef OMAP_HSMMC_USE_GPIO static int omap_mmc_setup_gpio_in(int gpio, const char *label) { - if (!gpio_is_valid(gpio)) - return -1; + int ret; - if (gpio_request(gpio, label) < 0) +#ifndef CONFIG_DM_GPIO + if (!gpio_is_valid(gpio)) return -1; +#endif + ret = gpio_request(gpio, label); + if (ret) + return ret; - if (gpio_direction_input(gpio) < 0) - return -1; + ret = gpio_direction_input(gpio); + if (ret) + return ret; return gpio; } -- cgit v1.2.1 From 0bf249511fe76c4de40f29a0bf6f2854935c36c6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 22 Oct 2014 21:37:12 -0600 Subject: dm: omap: serial: Add driver model support Add driver model support to this driver, while retaining support for the legacy system. Driver model serial support is enabled with CONFIG_DM_SERIAL as usual. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/serial/Makefile | 1 + drivers/serial/serial_omap.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 drivers/serial/serial_omap.c (limited to 'drivers') diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 17c56ea66e..cd87d18cf7 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o obj-$(CONFIG_ARC_SERIAL) += serial_arc.o obj-$(CONFIG_TEGRA_SERIAL) += serial_tegra.o obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o +obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_USB_TTY) += usbtty.o diff --git a/drivers/serial/serial_omap.c b/drivers/serial/serial_omap.c new file mode 100644 index 0000000000..265fe007a0 --- /dev/null +++ b/drivers/serial/serial_omap.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_OF_CONTROL +static const struct udevice_id omap_serial_ids[] = { + { .compatible = "ti,omap3-uart" }, + { } +}; + +static int omap_serial_ofdata_to_platdata(struct udevice *dev) +{ + struct ns16550_platdata *plat = dev_get_platdata(dev); + int ret; + + ret = ns16550_serial_ofdata_to_platdata(dev); + if (ret) + return ret; + plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "clock-frequency", -1); + plat->reg_shift = 2; + + return 0; +} +#endif + +U_BOOT_DRIVER(serial_omap_ns16550) = { + .name = "serial_omap", + .id = UCLASS_SERIAL, + .of_match = of_match_ptr(omap_serial_ids), + .ofdata_to_platdata = of_match_ptr(omap_serial_ofdata_to_platdata), + .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), + .priv_auto_alloc_size = sizeof(struct NS16550), + .probe = ns16550_serial_probe, + .ops = &ns16550_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; -- cgit v1.2.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') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index a5ffd85c42..e11c5a69c5 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.2.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') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index e11c5a69c5..04b7b16fd6 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.2.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') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 04b7b16fd6..6367093210 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.2.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') diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index 75ada5d387..7aa8b1f0f8 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.2.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') diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index 7aa8b1f0f8..13b32538cd 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.2.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') diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index 13b32538cd..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,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.2.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') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 6367093210..45e9a5ad22 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -130,6 +130,27 @@ int gpio_request(unsigned gpio, const char *label) 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]; + + 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.2.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') 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, }; /** -- cgit v1.2.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') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index a4651bc700..f3a7ccb51e 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.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') 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 #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.2.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') 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) -- cgit v1.2.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') 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[] = { -- cgit v1.2.1 From 1f77690e164e95fba0423a18b4597fd3ecd2817b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Oct 2014 07:49:13 -0600 Subject: dm: serial: ns16550: Add a cast to the I/O operations This generates a warning when driver model is enabled, so fix it by adding a cast. Signed-off-by: Simon Glass --- drivers/serial/ns16550.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 0799aa4cd3..8f051914f5 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -67,7 +67,7 @@ static void ns16550_writeb(NS16550_t port, int offset, int value) * these options at run-time, so use the existing CONFIG options. */ #ifdef CONFIG_SYS_NS16550_PORT_MAPPED - outb(value, addr); + outb(value, (ulong)addr); #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) out_le32(addr, value); #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) @@ -87,7 +87,7 @@ static int ns16550_readb(NS16550_t port, int offset) offset *= 1 << plat->reg_shift; addr = map_sysmem(plat->base, 0) + offset; #ifdef CONFIG_SYS_NS16550_PORT_MAPPED - return inb(addr); + return inb((ulong)addr); #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) return in_le32(addr); #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) -- cgit v1.2.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') 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 +#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.2.1 From e98a03ca68ca0edd08c260126aacc8c0f550804a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Oct 2014 07:49:20 -0600 Subject: dm: x86: Convert coreboot serial to use driver model This makes use of the existing device tree node to use driver model for the serial console. Signed-off-by: Simon Glass --- drivers/serial/Makefile | 1 + drivers/serial/serial_coreboot.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 drivers/serial/serial_coreboot.c (limited to 'drivers') diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index cd87d18cf7..2c19ebc288 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_ARC_SERIAL) += serial_arc.o obj-$(CONFIG_TEGRA_SERIAL) += serial_tegra.o obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o +obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_USB_TTY) += usbtty.o diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c new file mode 100644 index 0000000000..5c6a76c59c --- /dev/null +++ b/drivers/serial/serial_coreboot.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static const struct udevice_id coreboot_serial_ids[] = { + { .compatible = "coreboot-uart" }, + { } +}; + +static int coreboot_serial_ofdata_to_platdata(struct udevice *dev) +{ + struct ns16550_platdata *plat = dev_get_platdata(dev); + int ret; + + ret = ns16550_serial_ofdata_to_platdata(dev); + if (ret) + return ret; + plat->clock = 1843200; + + return 0; +} +U_BOOT_DRIVER(serial_ns16550) = { + .name = "serial_coreboot", + .id = UCLASS_SERIAL, + .of_match = coreboot_serial_ids, + .ofdata_to_platdata = coreboot_serial_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), + .priv_auto_alloc_size = sizeof(struct NS16550), + .probe = ns16550_serial_probe, + .ops = &ns16550_serial_ops, +}; -- cgit v1.2.1 From 86256b796ee757b7d1407233d0ca71576a7b8182 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 24 Oct 2014 12:41:19 +0900 Subject: dm: move platform data headers to include/dm/platform_data The platform_data definitions are generally referenced from both drivers and board files. That is why header files defining platform_data sturectures are placed in "include" directory, but our top level "include" directory is already too cluttered. Let's collect platform_data definitions under the directory "include/dm/platform_data" like Linux gathers ones around under "include/linux/platform_data". This commit moves two header files: include/serial_mxc.h -> include/dm/platform_data/serial_mxc.h include/serial_pl01x.h -> include/dm/platform_data/serial_pl01x.h Signed-off-by: Masahiro Yamada --- drivers/serial/serial_mxc.c | 2 +- drivers/serial/serial_pl01x.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index 9ce24f9f93..d6cf1d874a 100644 --- a/drivers/serial/serial_mxc.c +++ b/drivers/serial/serial_mxc.c @@ -7,10 +7,10 @@ #include #include #include -#include #include #include #include +#include #include #include diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index e6313ad3d3..38dda91021 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include "serial_pl01x_internal.h" -- cgit v1.2.1 From 3fdd0bb2b0dc20f192e9ea8682d5c18f37daadc1 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 23 Oct 2014 22:26:05 +0900 Subject: serial: add static directive to local functions The functions _serial_putc, _serial_putc_raw, _serial_puts, _serial_getc, _serial_tstc, _serial_setbrg are defined and used locally in each of serial_ns16550.c and serial_s3c24x0.c. Add static directive to them and remove declarations from include/common.h. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- drivers/serial/serial_ns16550.c | 21 +++++++-------------- drivers/serial/serial_s3c24x0.c | 10 +++++----- 2 files changed, 12 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c index 632da4cf70..799ef6a667 100644 --- a/drivers/serial/serial_ns16550.c +++ b/drivers/serial/serial_ns16550.c @@ -119,8 +119,7 @@ static NS16550_t serial_ports[6] = { .puts = eserial##port##_puts, \ } -void -_serial_putc(const char c,const int port) +static void _serial_putc(const char c, const int port) { if (c == '\n') NS16550_putc(PORT, '\r'); @@ -128,35 +127,29 @@ _serial_putc(const char c,const int port) NS16550_putc(PORT, c); } -void -_serial_putc_raw(const char c,const int port) +static void _serial_putc_raw(const char c, const int port) { NS16550_putc(PORT, c); } -void -_serial_puts (const char *s,const int port) +static void _serial_puts(const char *s, const int port) { while (*s) { - _serial_putc (*s++,port); + _serial_putc(*s++, port); } } - -int -_serial_getc(const int port) +static int _serial_getc(const int port) { return NS16550_getc(PORT); } -int -_serial_tstc(const int port) +static int _serial_tstc(const int port) { return NS16550_tstc(PORT); } -void -_serial_setbrg (const int port) +static void _serial_setbrg(const int port) { int clock_divisor; diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c index c07f4c9b47..7afc5044a8 100644 --- a/drivers/serial/serial_s3c24x0.c +++ b/drivers/serial/serial_s3c24x0.c @@ -69,7 +69,7 @@ DECLARE_GLOBAL_DATA_PTR; static int hwflow; #endif -void _serial_setbrg(const int dev_index) +static void _serial_setbrg(const int dev_index) { struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); unsigned int reg = 0; @@ -131,7 +131,7 @@ static int serial_init_dev(const int dev_index) * otherwise. When the function is succesfull, the character read is * written into its argument c. */ -int _serial_getc(const int dev_index) +static int _serial_getc(const int dev_index) { struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); @@ -181,7 +181,7 @@ void enable_putc(void) /* * Output a single byte to the serial port. */ -void _serial_putc(const char c, const int dev_index) +static void _serial_putc(const char c, const int dev_index) { struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); #ifdef CONFIG_MODEM_SUPPORT @@ -212,7 +212,7 @@ static inline void serial_putc_dev(unsigned int dev_index, const char c) /* * Test whether a character is in the RX buffer */ -int _serial_tstc(const int dev_index) +static int _serial_tstc(const int dev_index) { struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); @@ -224,7 +224,7 @@ static inline int serial_tstc_dev(unsigned int dev_index) return _serial_tstc(dev_index); } -void _serial_puts(const char *s, const int dev_index) +static void _serial_puts(const char *s, const int dev_index) { while (*s) { _serial_putc(*s++, dev_index); -- cgit v1.2.1 From bac644675ac900e27dc079cf062b55fa71a4c211 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 23 Oct 2014 22:26:06 +0900 Subject: dm: serial: fix console putc Commit b8893327e9d2 (dm: serial: Put common code into separate functions) consolidated getc() correctly, but introduced another bug to putc(); serial_stub_putc() passes sdev->priv to serial_putc_dev(), but serial_putc_dev() uses cur_dev instead of the given argument. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- drivers/serial/serial-uclass.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index c9383dcd00..6b41e0b7b0 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -85,14 +85,14 @@ void serial_initialize(void) static void serial_putc_dev(struct udevice *dev, char ch) { - struct dm_serial_ops *ops = serial_get_ops(cur_dev); + struct dm_serial_ops *ops = serial_get_ops(dev); int err; do { - err = ops->putc(cur_dev, ch); + err = ops->putc(dev, ch); } while (err == -EAGAIN); if (ch == '\n') - serial_putc('\r'); + serial_putc_dev(dev, '\r'); } void serial_putc(char ch) -- cgit v1.2.1 From 52a0a6f0dcd662c5069737687d53d8bfb1e17bfb Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 23 Oct 2014 22:26:07 +0900 Subject: dm: serial: remove unnecessary casting The type (void *) can be directly passed to a function that takes a specific pointer type. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- drivers/serial/serial-uclass.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 6b41e0b7b0..8bea715b49 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -149,9 +149,7 @@ void serial_stdio_init(void) static void serial_stub_putc(struct stdio_dev *sdev, const char ch) { - struct udevice *dev = sdev->priv; - - serial_putc_dev(dev, ch); + serial_putc_dev(sdev->priv, ch); } void serial_stub_puts(struct stdio_dev *sdev, const char *str) @@ -162,9 +160,7 @@ void serial_stub_puts(struct stdio_dev *sdev, const char *str) int serial_stub_getc(struct stdio_dev *sdev) { - struct udevice *dev = sdev->priv; - - return serial_getc_dev(dev); + return serial_getc_dev(sdev->priv); } int serial_stub_tstc(struct stdio_dev *sdev) -- cgit v1.2.1 From eea5a4cc1baa1b7f2697c4385aeae881430bff24 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 23 Oct 2014 22:26:08 +0900 Subject: dm: serial: consolidate common code more Commit b8893327e9d2 (dm: serial: Put common code into separate functions) consolidated getc() and putc(). This commit does more puts() and tsts(). Also rename locally used functions to _serial_*() for clarification because we have similar functions names here are there in this file. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- drivers/serial/serial-uclass.c | 79 ++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 8bea715b49..71f1a5cb91 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -83,7 +83,7 @@ void serial_initialize(void) serial_find_console_or_panic(); } -static void serial_putc_dev(struct udevice *dev, char ch) +static void _serial_putc(struct udevice *dev, char ch) { struct dm_serial_ops *ops = serial_get_ops(dev); int err; @@ -92,55 +92,65 @@ static void serial_putc_dev(struct udevice *dev, char ch) err = ops->putc(dev, ch); } while (err == -EAGAIN); if (ch == '\n') - serial_putc_dev(dev, '\r'); + _serial_putc(dev, '\r'); } -void serial_putc(char ch) +static void _serial_puts(struct udevice *dev, const char *str) { - serial_putc_dev(cur_dev, ch); + while (*str) + _serial_putc(dev, *str++); } -void serial_setbrg(void) +static int _serial_getc(struct udevice *dev) { - struct dm_serial_ops *ops = serial_get_ops(cur_dev); + struct dm_serial_ops *ops = serial_get_ops(dev); + int err; - if (ops->setbrg) - ops->setbrg(cur_dev, gd->baudrate); -} + do { + err = ops->getc(dev); + if (err == -EAGAIN) + WATCHDOG_RESET(); + } while (err == -EAGAIN); -void serial_puts(const char *str) -{ - while (*str) - serial_putc(*str++); + return err >= 0 ? err : 0; } -int serial_tstc(void) +static int _serial_tstc(struct udevice *dev) { - struct dm_serial_ops *ops = serial_get_ops(cur_dev); + struct dm_serial_ops *ops = serial_get_ops(dev); if (ops->pending) - return ops->pending(cur_dev, true); + return ops->pending(dev, true); return 1; } -static int serial_getc_dev(struct udevice *dev) +void serial_putc(char ch) { - struct dm_serial_ops *ops = serial_get_ops(dev); - int err; - - do { - err = ops->getc(dev); - if (err == -EAGAIN) - WATCHDOG_RESET(); - } while (err == -EAGAIN); + _serial_putc(cur_dev, ch); +} - return err >= 0 ? err : 0; +void serial_puts(const char *str) +{ + _serial_puts(cur_dev, str); } int serial_getc(void) { - return serial_getc_dev(cur_dev); + return _serial_getc(cur_dev); +} + +int serial_tstc(void) +{ + return _serial_tstc(cur_dev); +} + +void serial_setbrg(void) +{ + struct dm_serial_ops *ops = serial_get_ops(cur_dev); + + if (ops->setbrg) + ops->setbrg(cur_dev, gd->baudrate); } void serial_stdio_init(void) @@ -149,29 +159,22 @@ void serial_stdio_init(void) static void serial_stub_putc(struct stdio_dev *sdev, const char ch) { - serial_putc_dev(sdev->priv, ch); + _serial_putc(sdev->priv, ch); } void serial_stub_puts(struct stdio_dev *sdev, const char *str) { - while (*str) - serial_stub_putc(sdev, *str++); + _serial_puts(sdev->priv, str); } int serial_stub_getc(struct stdio_dev *sdev) { - return serial_getc_dev(sdev->priv); + return _serial_getc(sdev->priv); } int serial_stub_tstc(struct stdio_dev *sdev) { - struct udevice *dev = sdev->priv; - struct dm_serial_ops *ops = serial_get_ops(dev); - - if (ops->pending) - return ops->pending(dev, true); - - return 1; + return _serial_tstc(sdev->priv); } static int serial_post_probe(struct udevice *dev) -- cgit v1.2.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/core/Kconfig | 6 ++++++ drivers/gpio/Kconfig | 6 ++++++ drivers/serial/Kconfig | 6 ++++++ drivers/spi/Kconfig | 6 ++++++ 4 files changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index e69de29bb2..d2799dc861 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -0,0 +1,6 @@ +config DM + bool "Enable Driver Model" + depends on !SPL_BUILD + help + This config option enables Driver Model. + To use legacy drivers, say N. 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/serial/Kconfig b/drivers/serial/Kconfig index e69de29bb2..6a392ba24f 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -0,0 +1,6 @@ +config DM_SERIAL + bool "Enable Driver Model for serial drivers" + depends on DM + help + If you want to use driver model for serial drivers, say Y. + To use legacy serial drivers, say N. diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index e69de29bb2..e1678e63e6 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -0,0 +1,6 @@ +config DM_SPI + bool "Enable Driver Model for SPI drivers" + depends on DM + help + If you want to use driver model for SPI drivers, say Y. + To use legacy SPI drivers, say N. -- cgit v1.2.1 From d064cbffff37367b64b53f6e6942cbea67109237 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 23 Oct 2014 22:26:10 +0900 Subject: dm: serial: use Driver Model for UniPhier serial driver This commit converts UniPhier on-chip serial driver to driver model. Since UniPhier SoCs do not have Device Tree support, some board files should be added under arch/arm/cpu/armv7/uniphier/ph1-*/ directories. (Device Tree support for UniPhier platform is still under way.) Now the base address and master clock frequency are passed from platform data, so CONFIG_SYS_UNIPHIER_SERIAL_BASE* and CONFIG_SYS_UNIPHIER_UART_CLK should be removed. Tested on UniPhier PH1-LD4 ref board. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- drivers/serial/serial_uniphier.c | 199 ++++++++++++++------------------------- 1 file changed, 73 insertions(+), 126 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c index f8c9d921e2..9114b3ed60 100644 --- a/drivers/serial/serial_uniphier.c +++ b/drivers/serial/serial_uniphier.c @@ -2,14 +2,14 @@ * Copyright (C) 2012-2014 Panasonic Corporation * Author: Masahiro Yamada * - * Based on serial_ns16550.c - * (C) Copyright 2000 - * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. - * * SPDX-License-Identifier: GPL-2.0+ */ #include +#include +#include +#include +#include #include #define UART_REG(x) \ @@ -48,157 +48,104 @@ struct uniphier_serial { #define UART_LSR_DR 0x01 /* Data ready */ #define UART_LSR_THRE 0x20 /* Xmit holding register empty */ -DECLARE_GLOBAL_DATA_PTR; +struct uniphier_serial_private_data { + struct uniphier_serial __iomem *membase; +}; + +#define uniphier_serial_port(dev) \ + ((struct uniphier_serial_private_data *)dev_get_priv(dev))->membase -static void uniphier_serial_init(struct uniphier_serial *port) +int uniphier_serial_setbrg(struct udevice *dev, int baudrate) { + struct uniphier_serial_platform_data *plat = dev_get_platdata(dev); + struct uniphier_serial __iomem *port = uniphier_serial_port(dev); const unsigned int mode_x_div = 16; unsigned int divisor; writeb(UART_LCR_WLS_8, &port->lcr); - divisor = DIV_ROUND_CLOSEST(CONFIG_SYS_UNIPHIER_UART_CLK, - mode_x_div * gd->baudrate); + divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate); writew(divisor, &port->dlr); -} -static void uniphier_serial_setbrg(struct uniphier_serial *port) -{ - uniphier_serial_init(port); + return 0; } -static int uniphier_serial_tstc(struct uniphier_serial *port) +static int uniphier_serial_getc(struct udevice *dev) { - return (readb(&port->lsr) & UART_LSR_DR) != 0; -} + struct uniphier_serial __iomem *port = uniphier_serial_port(dev); -static int uniphier_serial_getc(struct uniphier_serial *port) -{ - while (!uniphier_serial_tstc(port)) - ; + if (!(readb(&port->lsr) & UART_LSR_DR)) + return -EAGAIN; return readb(&port->rbr); } -static void uniphier_serial_putc(struct uniphier_serial *port, const char c) +static int uniphier_serial_putc(struct udevice *dev, const char c) { - if (c == '\n') - uniphier_serial_putc(port, '\r'); + struct uniphier_serial __iomem *port = uniphier_serial_port(dev); - while (!(readb(&port->lsr) & UART_LSR_THRE)) - ; + if (!(readb(&port->lsr) & UART_LSR_THRE)) + return -EAGAIN; writeb(c, &port->thr); + + return 0; } -static struct uniphier_serial *serial_ports[4] = { -#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE0 - (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE0, -#else - NULL, -#endif -#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE1 - (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE1, -#else - NULL, -#endif -#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE2 - (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE2, -#else - NULL, -#endif -#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE3 - (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE3, -#else - NULL, -#endif -}; +int uniphier_serial_probe(struct udevice *dev) +{ + struct uniphier_serial_private_data *priv = dev_get_priv(dev); + struct uniphier_serial_platform_data *plat = dev_get_platdata(dev); -/* Multi serial device functions */ -#define DECLARE_ESERIAL_FUNCTIONS(port) \ - static int eserial##port##_init(void) \ - { \ - uniphier_serial_init(serial_ports[port]); \ - return 0 ; \ - } \ - static void eserial##port##_setbrg(void) \ - { \ - uniphier_serial_setbrg(serial_ports[port]); \ - } \ - static int eserial##port##_getc(void) \ - { \ - return uniphier_serial_getc(serial_ports[port]); \ - } \ - static int eserial##port##_tstc(void) \ - { \ - return uniphier_serial_tstc(serial_ports[port]); \ - } \ - static void eserial##port##_putc(const char c) \ - { \ - uniphier_serial_putc(serial_ports[port], c); \ - } - -/* Serial device descriptor */ -#define INIT_ESERIAL_STRUCTURE(port, __name) { \ - .name = __name, \ - .start = eserial##port##_init, \ - .stop = NULL, \ - .setbrg = eserial##port##_setbrg, \ - .getc = eserial##port##_getc, \ - .tstc = eserial##port##_tstc, \ - .putc = eserial##port##_putc, \ - .puts = default_serial_puts, \ -} + priv->membase = map_sysmem(plat->base, sizeof(struct uniphier_serial)); -#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0) -DECLARE_ESERIAL_FUNCTIONS(0); -struct serial_device uniphier_serial0_device = - INIT_ESERIAL_STRUCTURE(0, "ttyS0"); -#endif -#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1) -DECLARE_ESERIAL_FUNCTIONS(1); -struct serial_device uniphier_serial1_device = - INIT_ESERIAL_STRUCTURE(1, "ttyS1"); -#endif -#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2) -DECLARE_ESERIAL_FUNCTIONS(2); -struct serial_device uniphier_serial2_device = - INIT_ESERIAL_STRUCTURE(2, "ttyS2"); -#endif -#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3) -DECLARE_ESERIAL_FUNCTIONS(3); -struct serial_device uniphier_serial3_device = - INIT_ESERIAL_STRUCTURE(3, "ttyS3"); -#endif + if (!priv->membase) + return -ENOMEM; -__weak struct serial_device *default_serial_console(void) + return 0; +} + +int uniphier_serial_remove(struct udevice *dev) { -#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0) - return &uniphier_serial0_device; -#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1) - return &uniphier_serial1_device; -#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2) - return &uniphier_serial2_device; -#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3) - return &uniphier_serial3_device; -#else -#error "No uniphier serial ports configured." -#endif + unmap_sysmem(uniphier_serial_port(dev)); + + return 0; } -void uniphier_serial_initialize(void) +#ifdef CONFIG_OF_CONTROL +static const struct udevice_id uniphier_uart_of_match = { + { .compatible = "panasonic,uniphier-uart"}, + {}, +}; + +static int uniphier_serial_ofdata_to_platdata(struct udevice *dev) { -#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0) - serial_register(&uniphier_serial0_device); -#endif -#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1) - serial_register(&uniphier_serial1_device); -#endif -#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2) - serial_register(&uniphier_serial2_device); -#endif -#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3) - serial_register(&uniphier_serial3_device); -#endif + /* + * TODO: Masahiro Yamada (yamada.m@jp.panasonic.com) + * + * Implement conversion code from DTB to platform data + * when supporting CONFIG_OF_CONTROL on UniPhir platform. + */ } +#endif + +static const struct dm_serial_ops uniphier_serial_ops = { + .setbrg = uniphier_serial_setbrg, + .getc = uniphier_serial_getc, + .putc = uniphier_serial_putc, +}; + +U_BOOT_DRIVER(uniphier_serial) = { + .name = DRIVER_NAME, + .id = UCLASS_SERIAL, + .of_match = of_match_ptr(uniphier_uart_of_match), + .ofdata_to_platdata = of_match_ptr(uniphier_serial_ofdata_to_platdata), + .probe = uniphier_serial_probe, + .remove = uniphier_serial_remove, + .priv_auto_alloc_size = sizeof(struct uniphier_serial_private_data), + .platdata_auto_alloc_size = + sizeof(struct uniphier_serial_platform_data), + .ops = &uniphier_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; -- cgit v1.2.1 From ff247b7a0d2f4051786f5be1e73cf90a86b4b641 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 23 Oct 2014 22:26:11 +0900 Subject: serial: uniphier: move CONFIG_UNIPHIER_SERIAL to Kconfig Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- drivers/serial/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 6a392ba24f..a0b6e02b54 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -4,3 +4,9 @@ config DM_SERIAL help If you want to use driver model for serial drivers, say Y. To use legacy serial drivers, say N. + +config UNIPHIER_SERIAL + bool "UniPhier on-chip UART support" + depends on ARCH_UNIPHIER && DM_SERIAL + help + Support for the on-chip UARTs on the Panasonic UniPhier platform. -- cgit v1.2.1 From c2ded962d4703a3f9522553004db4a6fe540f7e6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 23 Oct 2014 22:26:12 +0900 Subject: serial: remove uniphier_serial_initialize() call The UniPhier serial driver has been converted to driver model. Let's remove uniphier_serial_initialize() call from the old serial driver framework. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- drivers/serial/serial.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index 82fbbd92e2..bbe60af627 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -157,7 +157,6 @@ serial_initfunc(sh_serial_initialize); serial_initfunc(arm_dcc_initialize); serial_initfunc(mxs_auart_initialize); serial_initfunc(arc_serial_initialize); -serial_initfunc(uniphier_serial_initialize); /** * serial_register() - Register serial driver with serial driver core @@ -251,7 +250,6 @@ void serial_initialize(void) arm_dcc_initialize(); mxs_auart_initialize(); arc_serial_initialize(); - uniphier_serial_initialize(); serial_assign(default_serial_console()->name); } -- cgit v1.2.1