[U-Boot] [PATCH v3 0/3] UniPhier: add GPIO support

Changes in v3: - one gpio bank per register
Changes in v2: - Do not use "ngpio" property to specify the number of GPIO pins. Instead, use .data field of OF match table.
Masahiro Yamada (3): gpio: uniphier: add driver for UniPhier GPIO controller gpio: do not include <asm/arch/gpio.h> for UniPhier ARM: uniphier: enable GPIO command and driver for UniPhier SoCs
arch/arm/Kconfig | 1 + arch/arm/include/asm/gpio.h | 2 + configs/uniphier_ld4_sld8_defconfig | 2 + configs/uniphier_pro4_defconfig | 2 + configs/uniphier_pro5_defconfig | 2 + configs/uniphier_pxs2_ld6b_defconfig | 2 + configs/uniphier_sld3_defconfig | 2 + drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-uniphier.c | 134 +++++++++++++++++++++++++++++++++++ 10 files changed, 154 insertions(+) create mode 100644 drivers/gpio/gpio-uniphier.c

This GPIO controller device is used on UniPhier SoCs.
Signed-off-by: Masahiro Yamada yamada.masahiro@socionext.com Acked-by: Simon Glass sjg@chromium.org ---
Changes in v3: - one gpio bank per register
Changes in v2: - Do not use "ngpio" property to specify the number of GPIO pins. Instead, use .data field of OF match table.
drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-uniphier.c | 134 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 drivers/gpio/gpio-uniphier.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 845dc72..94fabb9 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -76,6 +76,12 @@ config SANDBOX_GPIO_COUNT of 'anonymous' GPIOs that do not belong to any device or bank. Select a suitable value depending on your needs.
+config GPIO_UNIPHIER + bool "UniPhier GPIO" + depends on ARCH_UNIPHIER + help + Say yes here to support UniPhier GPIOs. + config VYBRID_GPIO bool "Vybrid GPIO driver" depends on DM diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 845a6d4..ca8c487 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -43,6 +43,7 @@ oby-$(CONFIG_SX151X) += sx151x.o obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o obj-$(CONFIG_STM32_GPIO) += stm32_gpio.o +obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c new file mode 100644 index 0000000..3dd4fa8 --- /dev/null +++ b/drivers/gpio/gpio-uniphier.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2016 Masahiro Yamada yamada.masahiro@socionext.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm/device.h> +#include <mapmem.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <asm/errno.h> +#include <asm/gpio.h> + +#define UNIPHIER_GPIO_PORTS_PER_BANK 8 + +#define UNIPHIER_GPIO_REG_DATA 0 /* data */ +#define UNIPHIER_GPIO_REG_DIR 4 /* direction (1:in, 0:out) */ + +struct uniphier_gpio_priv { + void __iomem *base; +}; + +static void uniphier_gpio_offset_write(struct udevice *dev, unsigned offset, + unsigned reg, int value) +{ + struct uniphier_gpio_priv *priv = dev_get_priv(dev); + u32 tmp; + + tmp = readl(priv->base + reg); + if (value) + tmp |= BIT(offset); + else + tmp &= ~BIT(offset); + writel(tmp, priv->base + reg); +} + +static int uniphier_gpio_offset_read(struct udevice *dev, unsigned offset, + unsigned reg) +{ + struct uniphier_gpio_priv *priv = dev_get_priv(dev); + + return !!(readl(priv->base + reg) & BIT(offset)); +} + +static int uniphier_gpio_direction_input(struct udevice *dev, unsigned offset) +{ + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DIR, 1); + + return 0; +} + +static int uniphier_gpio_direction_output(struct udevice *dev, unsigned offset, + int value) +{ + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DATA, value); + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DIR, 0); + + return 0; +} + +static int uniphier_gpio_get_value(struct udevice *dev, unsigned offset) +{ + return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_REG_DATA); +} + +static int uniphier_gpio_set_value(struct udevice *dev, unsigned offset, + int value) +{ + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DATA, value); + + return 0; +} + +static int uniphier_gpio_get_function(struct udevice *dev, unsigned offset) +{ + return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_REG_DIR) ? + GPIOF_INPUT : GPIOF_OUTPUT; +} + +static const struct dm_gpio_ops uniphier_gpio_ops = { + .direction_input = uniphier_gpio_direction_input, + .direction_output = uniphier_gpio_direction_output, + .get_value = uniphier_gpio_get_value, + .set_value = uniphier_gpio_set_value, + .get_function = uniphier_gpio_get_function, +}; + +static int uniphier_gpio_probe(struct udevice *dev) +{ + struct uniphier_gpio_priv *priv = dev_get_priv(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + DECLARE_GLOBAL_DATA_PTR; + fdt_addr_t addr; + fdt_size_t size; + + addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", + &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = map_sysmem(addr, size); + if (!priv->base) + return -ENOMEM; + + uc_priv->gpio_count = UNIPHIER_GPIO_PORTS_PER_BANK; + + return 0; +} + +static int uniphier_gpio_remove(struct udevice *dev) +{ + struct uniphier_gpio_priv *priv = dev_get_priv(dev); + + unmap_sysmem(priv->base); + + return 0; +} + +/* .data = the number of GPIO banks */ +static const struct udevice_id uniphier_gpio_match[] = { + { .compatible = "socionext,uniphier-gpio" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(uniphier_gpio) = { + .name = "uniphier_gpio", + .id = UCLASS_GPIO, + .of_match = uniphier_gpio_match, + .probe = uniphier_gpio_probe, + .remove = uniphier_gpio_remove, + .priv_auto_alloc_size = sizeof(struct uniphier_gpio_priv), + .ops = &uniphier_gpio_ops, +};

I implemented a GPIO driver based on Driver Model for the UniPhier SoC family, but I could not find any good reason why such SoC specific GPIO headers are needed.
Signed-off-by: Masahiro Yamada yamada.masahiro@socionext.com Acked-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
arch/arm/include/asm/gpio.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index d49ad08..fe4419c 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,2 +1,4 @@ +#ifndef CONFIG_ARCH_UNIPHIER #include <asm/arch/gpio.h> +#endif #include <asm-generic/gpio.h>

Signed-off-by: Masahiro Yamada yamada.masahiro@socionext.com Acked-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
arch/arm/Kconfig | 1 + configs/uniphier_ld4_sld8_defconfig | 2 ++ configs/uniphier_pro4_defconfig | 2 ++ configs/uniphier_pro5_defconfig | 2 ++ configs/uniphier_pxs2_ld6b_defconfig | 2 ++ configs/uniphier_sld3_defconfig | 2 ++ 6 files changed, 11 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d8b63e9..94bd7ec 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -697,6 +697,7 @@ config ARCH_UNIPHIER select SPL_OF_CONTROL select DM select SPL_DM + select DM_GPIO select DM_SERIAL select DM_I2C help diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig index 535f96f..dbee08e 100644 --- a/configs/uniphier_ld4_sld8_defconfig +++ b/configs/uniphier_ld4_sld8_defconfig @@ -13,12 +13,14 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y +CONFIG_GPIO_UNIPHIER=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_pro4_defconfig b/configs/uniphier_pro4_defconfig index 2361db6..3c2f7b0 100644 --- a/configs/uniphier_pro4_defconfig +++ b/configs/uniphier_pro4_defconfig @@ -12,12 +12,14 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y +CONFIG_GPIO_UNIPHIER=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_pro5_defconfig b/configs/uniphier_pro5_defconfig index be0d7b5..cf5f1ce 100644 --- a/configs/uniphier_pro5_defconfig +++ b/configs/uniphier_pro5_defconfig @@ -12,12 +12,14 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y +CONFIG_GPIO_UNIPHIER=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_pxs2_ld6b_defconfig index f8cb794..00a2900 100644 --- a/configs/uniphier_pxs2_ld6b_defconfig +++ b/configs/uniphier_pxs2_ld6b_defconfig @@ -13,12 +13,14 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y +CONFIG_GPIO_UNIPHIER=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_sld3_defconfig b/configs/uniphier_sld3_defconfig index e369c45..013fc8a 100644 --- a/configs/uniphier_sld3_defconfig +++ b/configs/uniphier_sld3_defconfig @@ -11,11 +11,13 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_GPIO_UNIPHIER=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
participants (1)
-
Masahiro Yamada