From 8e51c0f254063f4da2e91c2cf47fad37285be73d Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Sun, 10 Jun 2018 22:25:57 -0500 Subject: [PATCH] dm: gpio: Add DM compatibility to GPIO driver for Davinci This adds DM_GPIO support for the davinici GPIO driver with DT support. Signed-off-by: Adam Ford --- arch/arm/mach-davinci/include/mach/gpio.h | 14 ++- board/davinci/da8xxevm/da850evm.c | 2 + configs/da850evm_defconfig | 2 +- drivers/gpio/da8xx_gpio.c | 193 ++++++++++++++++++++++++++---- include/configs/da850evm.h | 2 +- 5 files changed, 186 insertions(+), 27 deletions(-) diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h index f1d4d9e..d4b25c3 100644 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ b/arch/arm/mach-davinci/include/mach/gpio.h @@ -39,7 +39,7 @@ struct davinci_gpio_bank { unsigned int irq_num; unsigned int irq_mask; unsigned long *in_use; - unsigned long base; + struct davinci_gpio *base; }; #define davinci_gpio_bank01 ((struct davinci_gpio *)DAVINCI_GPIO_BANK01) @@ -48,7 +48,9 @@ struct davinci_gpio_bank { #define davinci_gpio_bank67 ((struct davinci_gpio *)DAVINCI_GPIO_BANK67) #define davinci_gpio_bank8 ((struct davinci_gpio *)DAVINCI_GPIO_BANK8) +#ifndef CONFIG_DM_GPIO #define gpio_status() gpio_info() +#endif #define GPIO_NAME_SIZE 20 #if defined(CONFIG_SOC_DM644X) /* GPIO0 to GPIO53, omit the V3.3 volts one */ @@ -63,4 +65,14 @@ struct davinci_gpio_bank { void gpio_info(void); +#ifdef CONFIG_DM_GPIO + +/* Information about a GPIO bank */ +struct davinci_gpio_platdata { + int bank_index; + ulong base; /* address of registers in physical memory */ + const char *port_name; +}; +#endif + #endif diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c index c565ba7..5583b45 100644 --- a/board/davinci/da8xxevm/da850evm.c +++ b/board/davinci/da8xxevm/da850evm.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #ifdef CONFIG_MMC_DAVINCI #include diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig index bb1368b..6a2b7ae 100644 --- a/configs/da850evm_defconfig +++ b/configs/da850evm_defconfig @@ -23,7 +23,6 @@ CONFIG_SYS_PROMPT="U-Boot > " CONFIG_CRC32_VERIFY=y # CONFIG_CMD_EEPROM is not set # CONFIG_CMD_FLASH is not set -# CONFIG_CMD_GPIO is not set # CONFIG_CMD_GPT is not set # CONFIG_CMD_PART is not set # CONFIG_CMD_SETEXPR is not set @@ -37,6 +36,7 @@ CONFIG_CMD_DIAG=y CONFIG_OF_CONTROL=y CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_DM=y +CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y CONFIG_DM_SPI_FLASH=y diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c index e410f5f..1a1d37a 100644 --- a/drivers/gpio/da8xx_gpio.c +++ b/drivers/gpio/da8xx_gpio.c @@ -7,11 +7,14 @@ */ #include +#include +#include #include #include #include #include +#ifndef CONFIG_DM_GPIO static struct gpio_registry { int is_registered; char name[GPIO_NAME_SIZE]; @@ -303,7 +306,7 @@ static const struct pinmux_config gpio_pinmux[] = { #define davinci_configure_pin_mux(a, b) #endif /* CONFIG_SOC_DA8XX */ -int gpio_request(unsigned gpio, const char *label) +int gpio_request(unsigned int gpio, const char *label) { if (gpio >= MAX_NUM_GPIOS) return -1; @@ -320,7 +323,7 @@ int gpio_request(unsigned gpio, const char *label) return 0; } -int gpio_free(unsigned gpio) +int gpio_free(unsigned int gpio) { if (gpio >= MAX_NUM_GPIOS) return -1; @@ -333,42 +336,30 @@ int gpio_free(unsigned gpio) /* Do not configure as input or change pin mux here */ return 0; } +#endif -int gpio_direction_input(unsigned gpio) +static int _gpio_direction_output(struct davinci_gpio *bank, unsigned int gpio, int value) { - struct davinci_gpio *bank; - - bank = GPIO_BANK(gpio); - setbits_le32(&bank->dir, 1U << GPIO_BIT(gpio)); + clrbits_le32(&bank->dir, 1U << GPIO_BIT(gpio)); + gpio_set_value(gpio, value); return 0; } -int gpio_direction_output(unsigned gpio, int value) +static int _gpio_direction_input(struct davinci_gpio *bank, unsigned int gpio) { - struct davinci_gpio *bank; - - bank = GPIO_BANK(gpio); - clrbits_le32(&bank->dir, 1U << GPIO_BIT(gpio)); - gpio_set_value(gpio, value); + setbits_le32(&bank->dir, 1U << GPIO_BIT(gpio)); return 0; } -int gpio_get_value(unsigned gpio) +static int _gpio_get_value(struct davinci_gpio *bank, unsigned int gpio) { - struct davinci_gpio *bank; unsigned int ip; - - bank = GPIO_BANK(gpio); ip = in_le32(&bank->in_data) & (1U << GPIO_BIT(gpio)); return ip ? 1 : 0; } -int gpio_set_value(unsigned gpio, int value) +static int _gpio_set_value(struct davinci_gpio *bank, unsigned int gpio, int value) { - struct davinci_gpio *bank; - - bank = GPIO_BANK(gpio); - if (value) bank->set_data = 1U << GPIO_BIT(gpio); else @@ -377,14 +368,21 @@ int gpio_set_value(unsigned gpio, int value) return 0; } +static int _gpio_get_dir(struct davinci_gpio *bank, unsigned int gpio) +{ + return in_le32(&bank->dir) & (1U << GPIO_BIT(gpio)); +} + +#ifndef CONFIG_DM_GPIO + void gpio_info(void) { - unsigned gpio, dir, val; + unsigned int gpio, dir, val; struct davinci_gpio *bank; for (gpio = 0; gpio < MAX_NUM_GPIOS; ++gpio) { bank = GPIO_BANK(gpio); - dir = in_le32(&bank->dir) & (1U << GPIO_BIT(gpio)); + dir = _gpio_get_dir(bank, gpio); val = gpio_get_value(gpio); printf("% 4d: %s: %d [%c] %s\n", @@ -393,3 +391,150 @@ void gpio_info(void) gpio_registry[gpio].name); } } + +int gpio_direction_input(unsigned int gpio) +{ + struct davinci_gpio *bank; + + bank = GPIO_BANK(gpio); + return _gpio_direction_input(bank, gpio); +} + +int gpio_direction_output(unsigned int gpio, int value) +{ + struct davinci_gpio *bank; + + bank = GPIO_BANK(gpio); + return _gpio_direction_output(bank, gpio, value); +} + +int gpio_get_value(unsigned int gpio) +{ + struct davinci_gpio *bank; + + bank = GPIO_BANK(gpio); + return _gpio_get_value(bank, gpio); +} + +int gpio_set_value(unsigned int gpio, int value) +{ + struct davinci_gpio *bank; + + bank = GPIO_BANK(gpio); + return _gpio_set_value(bank, gpio, value); +} + +#else /* CONFIG_DM_GPIO */ + +static struct davinci_gpio *davinci_get_gpio_bank(struct udevice *dev, unsigned int offset) +{ + struct davinci_gpio_bank *bank = dev_get_priv(dev); + + /* The device tree is not broken into banks but the infrastructure is + * expecting it this way, so we'll first include the 0x10 offset, then + * calculate the bank manually based on the offset. + */ + + return ((struct davinci_gpio *)bank->base) + 0x10 + (offset >> 5); +} + +static int davinci_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + _gpio_direction_input(base, offset); + return 0; +} + +static int davinci_gpio_direction_output(struct udevice *dev, unsigned int offset, + int value) +{ + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + _gpio_direction_output(base, offset, value); + return 0; +} + +static int davinci_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + return _gpio_get_value(base, offset); +} + +static int davinci_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) +{ + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + _gpio_set_value(base, offset, value); + + return 0; +} + +static int davinci_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + unsigned int dir; + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + dir = _gpio_get_dir(base, offset); + + if (dir) + return GPIOF_INPUT; + + return GPIOF_OUTPUT; +} + +static const struct dm_gpio_ops gpio_davinci_ops = { + .direction_input = davinci_gpio_direction_input, + .direction_output = davinci_gpio_direction_output, + .get_value = davinci_gpio_get_value, + .set_value = davinci_gpio_set_value, + .get_function = davinci_gpio_get_function, +}; + +static int davinci_gpio_probe(struct udevice *dev) +{ + struct davinci_gpio_bank *bank = dev_get_priv(dev); + struct davinci_gpio_platdata *plat = dev_get_platdata(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + const void *fdt = gd->fdt_blob; + int node = dev_of_offset(dev); + + uc_priv->bank_name = plat->port_name; + uc_priv->gpio_count = fdtdec_get_int(fdt, node, "ti,ngpio", -1); + bank->base = (struct davinci_gpio *)plat->base; + return 0; +} + +static const struct udevice_id davinci_gpio_ids[] = { + { .compatible = "ti,dm6441-gpio" }, + { } +}; + +static int davinci_gpio_ofdata_to_platdata(struct udevice *dev) +{ + struct davinci_gpio_platdata *plat = dev_get_platdata(dev); + fdt_addr_t addr; + + addr = devfdt_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->base = addr; + return 0; +} + +U_BOOT_DRIVER(gpio_davinci) = { + .name = "gpio_davinci", + .id = UCLASS_GPIO, + .ops = &gpio_davinci_ops, + .ofdata_to_platdata = of_match_ptr(davinci_gpio_ofdata_to_platdata), + .of_match = davinci_gpio_ids, + .bind = dm_scan_fdt_dev, + .platdata_auto_alloc_size = sizeof(struct davinci_gpio_platdata), + .probe = davinci_gpio_probe, + .priv_auto_alloc_size = sizeof(struct davinci_gpio_bank), +}; + +#endif diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h index d2cd440..ebfdd1c 100644 --- a/include/configs/da850evm.h +++ b/include/configs/da850evm.h @@ -40,7 +40,6 @@ #ifdef CONFIG_DIRECT_NOR_BOOT #define CONFIG_ARCH_CPU_INIT -#define CONFIG_DA8XX_GPIO #define CONFIG_SYS_DV_NOR_BOOT_CFG (0x11) #endif @@ -227,6 +226,7 @@ #define CONFIG_MTD_PARTITIONS /* required for UBI partition support */ #endif +#define CONFIG_DA8XX_GPIO /* * U-Boot general configuration */ -- 2.7.4