[U-Boot] [PATCH 1/7] gpio: zynq: Convert Zynq GPIO to driver model

From: Siva Durga Prasad Paladugu siva.durga.paladugu@xilinx.com
Convert Zynq GPIO driver to driver model
Signed-off-by: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
drivers/gpio/zynq_gpio.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+)
diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c index 83a2c465d011..92c9f0ecd12e 100644 --- a/drivers/gpio/zynq_gpio.c +++ b/drivers/gpio/zynq_gpio.c @@ -14,6 +14,17 @@ #include <asm/io.h> #include <asm/errno.h>
+#ifdef CONFIG_DM_GPIO +#include <dm.h> +#include <fdtdec.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct zynq_gpio_privdata { + phys_addr_t base; +}; +#endif + /** * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank * for a given pin in the GPIO device @@ -68,6 +79,7 @@ static int check_gpio(unsigned gpio) return 0; }
+#ifndef CONFIG_DM_GPIO /** * gpio_get_value - Get the state of the specified pin of GPIO device * @gpio: gpio pin number within the device @@ -218,3 +230,142 @@ int gpio_free(unsigned gpio) { return 0; } +#else +static int zynq_gpio_get_value(struct udevice *dev, unsigned gpio) +{ + u32 data; + unsigned int bank_num, bank_pin_num; + struct zynq_gpio_privdata *priv = dev_get_priv(dev); + + if (check_gpio(gpio) < 0) + return -1; + + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + + data = readl(priv->base + + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); + + return (data >> bank_pin_num) & 1; +} + +static int zynq_gpio_set_value(struct udevice *dev, unsigned gpio, int value) +{ + unsigned int reg_offset, bank_num, bank_pin_num; + struct zynq_gpio_privdata *priv = dev_get_priv(dev); + + if (check_gpio(gpio) < 0) + return -1; + + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + + if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) { + /* only 16 data bits in bit maskable reg */ + bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM; + reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num); + } else { + reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num); + } + + /* + * get the 32 bit value to be written to the mask/data register where + * the upper 16 bits is the mask and lower 16 bits is the data + */ + value = !!value; + value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) & + ((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK); + + writel(value, priv->base + reg_offset); + + return 0; +} + +static int zynq_gpio_direction_input(struct udevice *dev, unsigned gpio) +{ + u32 reg; + unsigned int bank_num, bank_pin_num; + struct zynq_gpio_privdata *priv = dev_get_priv(dev); + + if (check_gpio(gpio) < 0) + return -1; + + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + + /* bank 0 pins 7 and 8 are special and cannot be used as inputs */ + if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8)) + return -1; + + /* clear the bit in direction mode reg to set the pin as input */ + reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + reg &= ~BIT(bank_pin_num); + writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + + return 0; +} + +static int zynq_gpio_direction_output(struct udevice *dev, unsigned gpio, + int value) +{ + u32 reg; + unsigned int bank_num, bank_pin_num; + struct zynq_gpio_privdata *priv = dev_get_priv(dev); + + if (check_gpio(gpio) < 0) + return -1; + + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + + /* set the GPIO pin as output */ + reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + reg |= BIT(bank_pin_num); + writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + + /* configure the output enable reg for the pin */ + reg = readl(priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); + reg |= BIT(bank_pin_num); + writel(reg, priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); + + /* set the state of the pin */ + gpio_set_value(gpio, value); + return 0; +} + +static const struct dm_gpio_ops gpio_zynq_ops = { + .direction_input = zynq_gpio_direction_input, + .direction_output = zynq_gpio_direction_output, + .get_value = zynq_gpio_get_value, + .set_value = zynq_gpio_set_value, +}; + +static int zynq_gpio_probe(struct udevice *dev) +{ + struct zynq_gpio_privdata *priv = dev_get_priv(dev); + + priv->base = dev_get_addr(dev); + + return 0; +} + +static int zynq_gpio_ofdata_to_platdata(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + uc_priv->gpio_count = ZYNQ_GPIO_NR_GPIOS; + + return 0; +} + +static const struct udevice_id zynq_gpio_ids[] = { + { .compatible = "xlnx,zynq-gpio-1.0" }, + { } +}; + +U_BOOT_DRIVER(gpio_zynq) = { + .name = "gpio_zynq", + .id = UCLASS_GPIO, + .ops = &gpio_zynq_ops, + .of_match = zynq_gpio_ids, + .ofdata_to_platdata = zynq_gpio_ofdata_to_platdata, + .probe = zynq_gpio_probe, + .priv_auto_alloc_size = sizeof(struct zynq_gpio_privdata), +}; +#endif

From: Siva Durga Prasad Paladugu siva.durga.paladugu@xilinx.com
Enable DM GPIO and ZYNQ GPIO using kconfig instead of the board config file.
Signed-off-by: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
There could be conflict with pca953x in Kconfig
--- arch/arm/Kconfig | 1 + drivers/gpio/Kconfig | 7 +++++++ include/configs/zynq-common.h | 2 -- 3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c8e033789393..802d3b430cd6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -579,6 +579,7 @@ config ARCH_ZYNQ select SPL_OF_CONTROL if SPL select DM select DM_ETH + select DM_GPIO select SPL_DM if SPL select DM_MMC select DM_SPI diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f56a60621ff0..4d2cc500bfaf 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -136,4 +136,11 @@ config MVEBU_GPIO help Say yes here to support Marvell MVEBU (Armada XP/38x) GPIOs.
+config ZYNQ_GPIO + bool "Zynq GPIO driver" + depends on DM_GPIO && ARCH_ZYNQ + default y + help + Supports GPIO access on Zynq SoC. + endmenu diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h index c96b9c52500f..49d9fd059f3c 100644 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@ -39,8 +39,6 @@ #define CONFIG_ARM_DCC #define CONFIG_ZYNQ_SERIAL
-#define CONFIG_ZYNQ_GPIO - /* Ethernet driver */ #if defined(CONFIG_ZYNQ_GEM) # define CONFIG_MII

From: Siva Durga Prasad Paladugu siva.durga.paladugu@xilinx.com
Remove non driver model support as it moved to driver model. Dont need non driver model anymore.
Signed-off-by: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
arch/arm/mach-zynq/include/mach/gpio.h | 2 - drivers/gpio/zynq_gpio.c | 158 +-------------------------------- 2 files changed, 1 insertion(+), 159 deletions(-)
diff --git a/arch/arm/mach-zynq/include/mach/gpio.h b/arch/arm/mach-zynq/include/mach/gpio.h index 0789c497368d..956492b7600a 100644 --- a/arch/arm/mach-zynq/include/mach/gpio.h +++ b/arch/arm/mach-zynq/include/mach/gpio.h @@ -8,8 +8,6 @@ #ifndef _ZYNQ_GPIO_H #define _ZYNQ_GPIO_H
-#define ZYNQ_GPIO_BASE_ADDRESS 0xE000A000 - /* Maximum banks */ #define ZYNQ_GPIO_MAX_BANK 4
diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c index 92c9f0ecd12e..07c2eb54ff30 100644 --- a/drivers/gpio/zynq_gpio.c +++ b/drivers/gpio/zynq_gpio.c @@ -13,8 +13,6 @@ #include <asm/gpio.h> #include <asm/io.h> #include <asm/errno.h> - -#ifdef CONFIG_DM_GPIO #include <dm.h> #include <fdtdec.h>
@@ -23,7 +21,6 @@ DECLARE_GLOBAL_DATA_PTR; struct zynq_gpio_privdata { phys_addr_t base; }; -#endif
/** * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank @@ -65,7 +62,7 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num, } }
-int gpio_is_valid(unsigned gpio) +static int gpio_is_valid(unsigned gpio) { return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS); } @@ -79,158 +76,6 @@ static int check_gpio(unsigned gpio) return 0; }
-#ifndef CONFIG_DM_GPIO -/** - * gpio_get_value - Get the state of the specified pin of GPIO device - * @gpio: gpio pin number within the device - * - * This function reads the state of the specified pin of the GPIO device. - * - * Return: 0 if the pin is low, 1 if pin is high. - */ -int gpio_get_value(unsigned gpio) -{ - u32 data; - unsigned int bank_num, bank_pin_num; - - if (check_gpio(gpio) < 0) - return -1; - - zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); - - data = readl(ZYNQ_GPIO_BASE_ADDRESS + - ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); - - return (data >> bank_pin_num) & 1; -} - -/** - * gpio_set_value - Modify the value of the pin with specified value - * @gpio: gpio pin number within the device - * @value: value used to modify the value of the specified pin - * - * This function calculates the register offset (i.e to lower 16 bits or - * upper 16 bits) based on the given pin number and sets the value of a - * gpio pin to the specified value. The value is either 0 or non-zero. - */ -int gpio_set_value(unsigned gpio, int value) -{ - unsigned int reg_offset, bank_num, bank_pin_num; - - if (check_gpio(gpio) < 0) - return -1; - - zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); - - if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) { - /* only 16 data bits in bit maskable reg */ - bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM; - reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num); - } else { - reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num); - } - - /* - * get the 32 bit value to be written to the mask/data register where - * the upper 16 bits is the mask and lower 16 bits is the data - */ - value = !!value; - value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) & - ((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK); - - writel(value, ZYNQ_GPIO_BASE_ADDRESS + reg_offset); - - return 0; -} - -/** - * gpio_direction_input - Set the direction of the specified GPIO pin as input - * @gpio: gpio pin number within the device - * - * This function uses the read-modify-write sequence to set the direction of - * the gpio pin as input. - * - * Return: -1 if invalid gpio specified, 0 if successul - */ -int gpio_direction_input(unsigned gpio) -{ - u32 reg; - unsigned int bank_num, bank_pin_num; - - if (check_gpio(gpio) < 0) - return -1; - - zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); - - /* bank 0 pins 7 and 8 are special and cannot be used as inputs */ - if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8)) - return -1; - - /* clear the bit in direction mode reg to set the pin as input */ - reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); - reg &= ~BIT(bank_pin_num); - writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); - - return 0; -} - -/** - * gpio_direction_output - Set the direction of the specified GPIO pin as output - * @gpio: gpio pin number within the device - * @value: value to be written to specified pin - * - * This function sets the direction of specified GPIO pin as output, configures - * the Output Enable register for the pin and uses zynq_gpio_set to set - * the value of the pin to the value specified. - * - * Return: 0 always - */ -int gpio_direction_output(unsigned gpio, int value) -{ - u32 reg; - unsigned int bank_num, bank_pin_num; - - if (check_gpio(gpio) < 0) - return -1; - - zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); - - /* set the GPIO pin as output */ - reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); - reg |= BIT(bank_pin_num); - writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); - - /* configure the output enable reg for the pin */ - reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); - reg |= BIT(bank_pin_num); - writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); - - /* set the state of the pin */ - gpio_set_value(gpio, value); - return 0; -} - -/** - * Request a gpio before using it. - * - * NOTE: Argument 'label' is unused. - */ -int gpio_request(unsigned gpio, const char *label) -{ - if (check_gpio(gpio) < 0) - return -1; - - return 0; -} - -/** - * Reset and free the gpio after using it. - */ -int gpio_free(unsigned gpio) -{ - return 0; -} -#else static int zynq_gpio_get_value(struct udevice *dev, unsigned gpio) { u32 data; @@ -368,4 +213,3 @@ U_BOOT_DRIVER(gpio_zynq) = { .probe = zynq_gpio_probe, .priv_auto_alloc_size = sizeof(struct zynq_gpio_privdata), }; -#endif

From: Siva Durga Prasad Paladugu siva.durga.paladugu@xilinx.com
Move all the gpio definitions to driver file as there is no use of them in other files.
Signed-off-by: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
arch/arm/mach-zynq/include/mach/gpio.h | 61 ---------------------------------- drivers/gpio/zynq_gpio.c | 61 ++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 61 deletions(-)
diff --git a/arch/arm/mach-zynq/include/mach/gpio.h b/arch/arm/mach-zynq/include/mach/gpio.h index 956492b7600a..f3dfd65b98a4 100644 --- a/arch/arm/mach-zynq/include/mach/gpio.h +++ b/arch/arm/mach-zynq/include/mach/gpio.h @@ -8,65 +8,4 @@ #ifndef _ZYNQ_GPIO_H #define _ZYNQ_GPIO_H
-/* Maximum banks */ -#define ZYNQ_GPIO_MAX_BANK 4 - -#define ZYNQ_GPIO_BANK0_NGPIO 32 -#define ZYNQ_GPIO_BANK1_NGPIO 22 -#define ZYNQ_GPIO_BANK2_NGPIO 32 -#define ZYNQ_GPIO_BANK3_NGPIO 32 - -#define ZYNQ_GPIO_NR_GPIOS (ZYNQ_GPIO_BANK0_NGPIO + \ - ZYNQ_GPIO_BANK1_NGPIO + \ - ZYNQ_GPIO_BANK2_NGPIO + \ - ZYNQ_GPIO_BANK3_NGPIO) - -#define ZYNQ_GPIO_BANK0_PIN_MIN 0 -#define ZYNQ_GPIO_BANK0_PIN_MAX (ZYNQ_GPIO_BANK0_PIN_MIN + \ - ZYNQ_GPIO_BANK0_NGPIO - 1) -#define ZYNQ_GPIO_BANK1_PIN_MIN (ZYNQ_GPIO_BANK0_PIN_MAX + 1) -#define ZYNQ_GPIO_BANK1_PIN_MAX (ZYNQ_GPIO_BANK1_PIN_MIN + \ - ZYNQ_GPIO_BANK1_NGPIO - 1) -#define ZYNQ_GPIO_BANK2_PIN_MIN (ZYNQ_GPIO_BANK1_PIN_MAX + 1) -#define ZYNQ_GPIO_BANK2_PIN_MAX (ZYNQ_GPIO_BANK2_PIN_MIN + \ - ZYNQ_GPIO_BANK2_NGPIO - 1) -#define ZYNQ_GPIO_BANK3_PIN_MIN (ZYNQ_GPIO_BANK2_PIN_MAX + 1) -#define ZYNQ_GPIO_BANK3_PIN_MAX (ZYNQ_GPIO_BANK3_PIN_MIN + \ - ZYNQ_GPIO_BANK3_NGPIO - 1) - -/* Register offsets for the GPIO device */ -/* LSW Mask & Data -WO */ -#define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK) (0x000 + (8 * BANK)) -/* MSW Mask & Data -WO */ -#define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK) (0x004 + (8 * BANK)) -/* Data Register-RW */ -#define ZYNQ_GPIO_DATA_RO_OFFSET(BANK) (0x060 + (4 * BANK)) -/* Direction mode reg-RW */ -#define ZYNQ_GPIO_DIRM_OFFSET(BANK) (0x204 + (0x40 * BANK)) -/* Output enable reg-RW */ -#define ZYNQ_GPIO_OUTEN_OFFSET(BANK) (0x208 + (0x40 * BANK)) -/* Interrupt mask reg-RO */ -#define ZYNQ_GPIO_INTMASK_OFFSET(BANK) (0x20C + (0x40 * BANK)) -/* Interrupt enable reg-WO */ -#define ZYNQ_GPIO_INTEN_OFFSET(BANK) (0x210 + (0x40 * BANK)) -/* Interrupt disable reg-WO */ -#define ZYNQ_GPIO_INTDIS_OFFSET(BANK) (0x214 + (0x40 * BANK)) -/* Interrupt status reg-RO */ -#define ZYNQ_GPIO_INTSTS_OFFSET(BANK) (0x218 + (0x40 * BANK)) -/* Interrupt type reg-RW */ -#define ZYNQ_GPIO_INTTYPE_OFFSET(BANK) (0x21C + (0x40 * BANK)) -/* Interrupt polarity reg-RW */ -#define ZYNQ_GPIO_INTPOL_OFFSET(BANK) (0x220 + (0x40 * BANK)) -/* Interrupt on any, reg-RW */ -#define ZYNQ_GPIO_INTANY_OFFSET(BANK) (0x224 + (0x40 * BANK)) - -/* Disable all interrupts mask */ -#define ZYNQ_GPIO_IXR_DISABLE_ALL 0xFFFFFFFF - -/* Mid pin number of a bank */ -#define ZYNQ_GPIO_MID_PIN_NUM 16 - -/* GPIO upper 16 bit mask */ -#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000 - #endif /* _ZYNQ_GPIO_H */ diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c index 07c2eb54ff30..05de9c56519b 100644 --- a/drivers/gpio/zynq_gpio.c +++ b/drivers/gpio/zynq_gpio.c @@ -18,6 +18,67 @@
DECLARE_GLOBAL_DATA_PTR;
+/* Maximum banks */ +#define ZYNQ_GPIO_MAX_BANK 4 + +#define ZYNQ_GPIO_BANK0_NGPIO 32 +#define ZYNQ_GPIO_BANK1_NGPIO 22 +#define ZYNQ_GPIO_BANK2_NGPIO 32 +#define ZYNQ_GPIO_BANK3_NGPIO 32 + +#define ZYNQ_GPIO_NR_GPIOS (ZYNQ_GPIO_BANK0_NGPIO + \ + ZYNQ_GPIO_BANK1_NGPIO + \ + ZYNQ_GPIO_BANK2_NGPIO + \ + ZYNQ_GPIO_BANK3_NGPIO) + +#define ZYNQ_GPIO_BANK0_PIN_MIN 0 +#define ZYNQ_GPIO_BANK0_PIN_MAX (ZYNQ_GPIO_BANK0_PIN_MIN + \ + ZYNQ_GPIO_BANK0_NGPIO - 1) +#define ZYNQ_GPIO_BANK1_PIN_MIN (ZYNQ_GPIO_BANK0_PIN_MAX + 1) +#define ZYNQ_GPIO_BANK1_PIN_MAX (ZYNQ_GPIO_BANK1_PIN_MIN + \ + ZYNQ_GPIO_BANK1_NGPIO - 1) +#define ZYNQ_GPIO_BANK2_PIN_MIN (ZYNQ_GPIO_BANK1_PIN_MAX + 1) +#define ZYNQ_GPIO_BANK2_PIN_MAX (ZYNQ_GPIO_BANK2_PIN_MIN + \ + ZYNQ_GPIO_BANK2_NGPIO - 1) +#define ZYNQ_GPIO_BANK3_PIN_MIN (ZYNQ_GPIO_BANK2_PIN_MAX + 1) +#define ZYNQ_GPIO_BANK3_PIN_MAX (ZYNQ_GPIO_BANK3_PIN_MIN + \ + ZYNQ_GPIO_BANK3_NGPIO - 1) + +/* Register offsets for the GPIO device */ +/* LSW Mask & Data -WO */ +#define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK) (0x000 + (8 * BANK)) +/* MSW Mask & Data -WO */ +#define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK) (0x004 + (8 * BANK)) +/* Data Register-RW */ +#define ZYNQ_GPIO_DATA_RO_OFFSET(BANK) (0x060 + (4 * BANK)) +/* Direction mode reg-RW */ +#define ZYNQ_GPIO_DIRM_OFFSET(BANK) (0x204 + (0x40 * BANK)) +/* Output enable reg-RW */ +#define ZYNQ_GPIO_OUTEN_OFFSET(BANK) (0x208 + (0x40 * BANK)) +/* Interrupt mask reg-RO */ +#define ZYNQ_GPIO_INTMASK_OFFSET(BANK) (0x20C + (0x40 * BANK)) +/* Interrupt enable reg-WO */ +#define ZYNQ_GPIO_INTEN_OFFSET(BANK) (0x210 + (0x40 * BANK)) +/* Interrupt disable reg-WO */ +#define ZYNQ_GPIO_INTDIS_OFFSET(BANK) (0x214 + (0x40 * BANK)) +/* Interrupt status reg-RO */ +#define ZYNQ_GPIO_INTSTS_OFFSET(BANK) (0x218 + (0x40 * BANK)) +/* Interrupt type reg-RW */ +#define ZYNQ_GPIO_INTTYPE_OFFSET(BANK) (0x21C + (0x40 * BANK)) +/* Interrupt polarity reg-RW */ +#define ZYNQ_GPIO_INTPOL_OFFSET(BANK) (0x220 + (0x40 * BANK)) +/* Interrupt on any, reg-RW */ +#define ZYNQ_GPIO_INTANY_OFFSET(BANK) (0x224 + (0x40 * BANK)) + +/* Disable all interrupts mask */ +#define ZYNQ_GPIO_IXR_DISABLE_ALL 0xFFFFFFFF + +/* Mid pin number of a bank */ +#define ZYNQ_GPIO_MID_PIN_NUM 16 + +/* GPIO upper 16 bit mask */ +#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000 + struct zynq_gpio_privdata { phys_addr_t base; };

From: Siva Durga Prasad Paladugu siva.durga.paladugu@xilinx.com
Add GPIO driver support for ZynqMP platform
Signed-off-by: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
drivers/gpio/zynq_gpio.c | 200 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 147 insertions(+), 53 deletions(-)
diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c index 05de9c56519b..3a995f610cb3 100644 --- a/drivers/gpio/zynq_gpio.c +++ b/drivers/gpio/zynq_gpio.c @@ -31,18 +31,35 @@ DECLARE_GLOBAL_DATA_PTR; ZYNQ_GPIO_BANK2_NGPIO + \ ZYNQ_GPIO_BANK3_NGPIO)
-#define ZYNQ_GPIO_BANK0_PIN_MIN 0 -#define ZYNQ_GPIO_BANK0_PIN_MAX (ZYNQ_GPIO_BANK0_PIN_MIN + \ - ZYNQ_GPIO_BANK0_NGPIO - 1) -#define ZYNQ_GPIO_BANK1_PIN_MIN (ZYNQ_GPIO_BANK0_PIN_MAX + 1) -#define ZYNQ_GPIO_BANK1_PIN_MAX (ZYNQ_GPIO_BANK1_PIN_MIN + \ - ZYNQ_GPIO_BANK1_NGPIO - 1) -#define ZYNQ_GPIO_BANK2_PIN_MIN (ZYNQ_GPIO_BANK1_PIN_MAX + 1) -#define ZYNQ_GPIO_BANK2_PIN_MAX (ZYNQ_GPIO_BANK2_PIN_MIN + \ - ZYNQ_GPIO_BANK2_NGPIO - 1) -#define ZYNQ_GPIO_BANK3_PIN_MIN (ZYNQ_GPIO_BANK2_PIN_MAX + 1) -#define ZYNQ_GPIO_BANK3_PIN_MAX (ZYNQ_GPIO_BANK3_PIN_MIN + \ - ZYNQ_GPIO_BANK3_NGPIO - 1) +#define ZYNQMP_GPIO_MAX_BANK 6 + +#define ZYNQMP_GPIO_BANK0_NGPIO 26 +#define ZYNQMP_GPIO_BANK1_NGPIO 26 +#define ZYNQMP_GPIO_BANK2_NGPIO 26 +#define ZYNQMP_GPIO_BANK3_NGPIO 32 +#define ZYNQMP_GPIO_BANK4_NGPIO 32 +#define ZYNQMP_GPIO_BANK5_NGPIO 32 + +#define ZYNQMP_GPIO_NR_GPIOS 174 + +#define ZYNQ_GPIO_BANK0_PIN_MIN(str) 0 +#define ZYNQ_GPIO_BANK0_PIN_MAX(str) (ZYNQ_GPIO_BANK0_PIN_MIN(str) + \ + ZYNQ##str##_GPIO_BANK0_NGPIO - 1) +#define ZYNQ_GPIO_BANK1_PIN_MIN(str) (ZYNQ_GPIO_BANK0_PIN_MAX(str) + 1) +#define ZYNQ_GPIO_BANK1_PIN_MAX(str) (ZYNQ_GPIO_BANK1_PIN_MIN(str) + \ + ZYNQ##str##_GPIO_BANK1_NGPIO - 1) +#define ZYNQ_GPIO_BANK2_PIN_MIN(str) (ZYNQ_GPIO_BANK1_PIN_MAX(str) + 1) +#define ZYNQ_GPIO_BANK2_PIN_MAX(str) (ZYNQ_GPIO_BANK2_PIN_MIN(str) + \ + ZYNQ##str##_GPIO_BANK2_NGPIO - 1) +#define ZYNQ_GPIO_BANK3_PIN_MIN(str) (ZYNQ_GPIO_BANK2_PIN_MAX(str) + 1) +#define ZYNQ_GPIO_BANK3_PIN_MAX(str) (ZYNQ_GPIO_BANK3_PIN_MIN(str) + \ + ZYNQ##str##_GPIO_BANK3_NGPIO - 1) +#define ZYNQ_GPIO_BANK4_PIN_MIN(str) (ZYNQ_GPIO_BANK3_PIN_MAX(str) + 1) +#define ZYNQ_GPIO_BANK4_PIN_MAX(str) (ZYNQ_GPIO_BANK4_PIN_MIN(str) + \ + ZYNQ##str##_GPIO_BANK4_NGPIO - 1) +#define ZYNQ_GPIO_BANK5_PIN_MIN(str) (ZYNQ_GPIO_BANK4_PIN_MAX(str) + 1) +#define ZYNQ_GPIO_BANK5_PIN_MAX(str) (ZYNQ_GPIO_BANK5_PIN_MIN(str) + \ + ZYNQ##str##_GPIO_BANK5_NGPIO - 1)
/* Register offsets for the GPIO device */ /* LSW Mask & Data -WO */ @@ -81,6 +98,55 @@ DECLARE_GLOBAL_DATA_PTR;
struct zynq_gpio_privdata { phys_addr_t base; + const struct zynq_platform_data *p_data; +}; + +/** + * struct zynq_platform_data - zynq gpio platform data structure + * @label: string to store in gpio->label + * @ngpio: max number of gpio pins + * @max_bank: maximum number of gpio banks + * @bank_min: this array represents bank's min pin + * @bank_max: this array represents bank's max pin + */ +struct zynq_platform_data { + const char *label; + u16 ngpio; + int max_bank; + int bank_min[ZYNQMP_GPIO_MAX_BANK]; + int bank_max[ZYNQMP_GPIO_MAX_BANK]; +}; + +static const struct zynq_platform_data zynqmp_gpio_def = { + .label = "zynqmp_gpio", + .ngpio = ZYNQMP_GPIO_NR_GPIOS, + .max_bank = ZYNQMP_GPIO_MAX_BANK, + .bank_min[0] = ZYNQ_GPIO_BANK0_PIN_MIN(MP), + .bank_max[0] = ZYNQ_GPIO_BANK0_PIN_MAX(MP), + .bank_min[1] = ZYNQ_GPIO_BANK1_PIN_MIN(MP), + .bank_max[1] = ZYNQ_GPIO_BANK1_PIN_MAX(MP), + .bank_min[2] = ZYNQ_GPIO_BANK2_PIN_MIN(MP), + .bank_max[2] = ZYNQ_GPIO_BANK2_PIN_MAX(MP), + .bank_min[3] = ZYNQ_GPIO_BANK3_PIN_MIN(MP), + .bank_max[3] = ZYNQ_GPIO_BANK3_PIN_MAX(MP), + .bank_min[4] = ZYNQ_GPIO_BANK4_PIN_MIN(MP), + .bank_max[4] = ZYNQ_GPIO_BANK4_PIN_MAX(MP), + .bank_min[5] = ZYNQ_GPIO_BANK5_PIN_MIN(MP), + .bank_max[5] = ZYNQ_GPIO_BANK5_PIN_MAX(MP), +}; + +static const struct zynq_platform_data zynq_gpio_def = { + .label = "zynq_gpio", + .ngpio = ZYNQ_GPIO_NR_GPIOS, + .max_bank = ZYNQ_GPIO_MAX_BANK, + .bank_min[0] = ZYNQ_GPIO_BANK0_PIN_MIN(), + .bank_max[0] = ZYNQ_GPIO_BANK0_PIN_MAX(), + .bank_min[1] = ZYNQ_GPIO_BANK1_PIN_MIN(), + .bank_max[1] = ZYNQ_GPIO_BANK1_PIN_MAX(), + .bank_min[2] = ZYNQ_GPIO_BANK2_PIN_MIN(), + .bank_max[2] = ZYNQ_GPIO_BANK2_PIN_MAX(), + .bank_min[3] = ZYNQ_GPIO_BANK3_PIN_MIN(), + .bank_max[3] = ZYNQ_GPIO_BANK3_PIN_MAX(), };
/** @@ -96,41 +162,39 @@ struct zynq_gpio_privdata { */ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num, unsigned int *bank_num, - unsigned int *bank_pin_num) + unsigned int *bank_pin_num, + struct udevice *dev) { - switch (pin_num) { - case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX: - *bank_num = 0; - *bank_pin_num = pin_num; - break; - case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX: - *bank_num = 1; - *bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN; - break; - case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX: - *bank_num = 2; - *bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN; - break; - case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX: - *bank_num = 3; - *bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN; - break; - default: - printf("invalid GPIO pin number: %u\n", pin_num); + struct zynq_gpio_privdata *priv = dev_get_priv(dev); + int bank; + + for (bank = 0; bank < priv->p_data->max_bank; bank++) { + if ((pin_num >= priv->p_data->bank_min[bank]) && + (pin_num <= priv->p_data->bank_max[bank])) { + *bank_num = bank; + *bank_pin_num = pin_num - + priv->p_data->bank_min[bank]; + return; + } + } + + if (bank >= priv->p_data->max_bank) { + printf("Inavlid bank and pin num\n"); *bank_num = 0; *bank_pin_num = 0; - break; } }
-static int gpio_is_valid(unsigned gpio) +static int gpio_is_valid(unsigned gpio, struct udevice *dev) { - return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS); + struct zynq_gpio_privdata *priv = dev_get_priv(dev); + + return (gpio >= 0) && (gpio < priv->p_data->ngpio); }
-static int check_gpio(unsigned gpio) +static int check_gpio(unsigned gpio, struct udevice *dev) { - if (!gpio_is_valid(gpio)) { + if (!gpio_is_valid(gpio, dev)) { printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); return -1; } @@ -143,10 +207,10 @@ static int zynq_gpio_get_value(struct udevice *dev, unsigned gpio) unsigned int bank_num, bank_pin_num; struct zynq_gpio_privdata *priv = dev_get_priv(dev);
- if (check_gpio(gpio) < 0) + if (check_gpio(gpio, dev) < 0) return -1;
- zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num, dev);
data = readl(priv->base + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); @@ -159,10 +223,10 @@ static int zynq_gpio_set_value(struct udevice *dev, unsigned gpio, int value) unsigned int reg_offset, bank_num, bank_pin_num; struct zynq_gpio_privdata *priv = dev_get_priv(dev);
- if (check_gpio(gpio) < 0) + if (check_gpio(gpio, dev) < 0) return -1;
- zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num, dev);
if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) { /* only 16 data bits in bit maskable reg */ @@ -191,10 +255,10 @@ static int zynq_gpio_direction_input(struct udevice *dev, unsigned gpio) unsigned int bank_num, bank_pin_num; struct zynq_gpio_privdata *priv = dev_get_priv(dev);
- if (check_gpio(gpio) < 0) + if (check_gpio(gpio, dev) < 0) return -1;
- zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num, dev);
/* bank 0 pins 7 and 8 are special and cannot be used as inputs */ if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8)) @@ -215,10 +279,10 @@ static int zynq_gpio_direction_output(struct udevice *dev, unsigned gpio, unsigned int bank_num, bank_pin_num; struct zynq_gpio_privdata *priv = dev_get_priv(dev);
- if (check_gpio(gpio) < 0) + if (check_gpio(gpio, dev) < 0) return -1;
- zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num, dev);
/* set the GPIO pin as output */ reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); @@ -242,29 +306,59 @@ static const struct dm_gpio_ops gpio_zynq_ops = { .set_value = zynq_gpio_set_value, };
+static const struct udevice_id zynq_gpio_ids[] = { + { .compatible = "xlnx,zynq-gpio-1.0", + .data = (ulong)&zynq_gpio_def}, + { .compatible = "xlnx,zynqmp-gpio-1.0", + .data = (ulong)&zynqmp_gpio_def}, + { } +}; + +static void zynq_gpio_getplat_data(struct udevice *dev) +{ + const struct udevice_id *of_match = zynq_gpio_ids; + int ret; + struct zynq_gpio_privdata *priv = dev_get_priv(dev); + + while (of_match->compatible) { + ret = fdt_node_offset_by_compatible(gd->fdt_blob, -1, + of_match->compatible); + if (ret >= 0) { + priv->p_data = + (struct zynq_platform_data *)of_match->data; + break; + } else { + of_match++; + continue; + } + } + + if (!priv->p_data) + printf("No Platform data found\n"); +} + static int zynq_gpio_probe(struct udevice *dev) { struct zynq_gpio_privdata *priv = dev_get_priv(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
- priv->base = dev_get_addr(dev); + zynq_gpio_getplat_data(dev); + + if (priv->p_data) + uc_priv->gpio_count = priv->p_data->ngpio;
return 0; }
static int zynq_gpio_ofdata_to_platdata(struct udevice *dev) { - struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct zynq_gpio_privdata *priv = dev_get_priv(dev);
- uc_priv->gpio_count = ZYNQ_GPIO_NR_GPIOS; + priv->base = dev_get_addr(dev);
return 0; }
-static const struct udevice_id zynq_gpio_ids[] = { - { .compatible = "xlnx,zynq-gpio-1.0" }, - { } -}; - U_BOOT_DRIVER(gpio_zynq) = { .name = "gpio_zynq", .id = UCLASS_GPIO,

From: Siva Durga Prasad Paladugu siva.durga.paladugu@xilinx.com
Enable ZYNQ_GPIO for ZynqMP using Kconfig. It enables the GPIO driver support for ZynqMP.
Signed-off-by: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Michal Simek michal.simek@xilinx.com ---
drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4d2cc500bfaf..2b4624d7f807 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -138,7 +138,7 @@ config MVEBU_GPIO
config ZYNQ_GPIO bool "Zynq GPIO driver" - depends on DM_GPIO && ARCH_ZYNQ + depends on DM_GPIO && (ARCH_ZYNQ || ARCH_ZYNQMP) default y help Supports GPIO access on Zynq SoC.

Enable missing GPIO options.
Signed-off-by: Michal Simek michal.simek@xilinx.com ---
configs/xilinx_zynqmp_ep_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig index 9f72abaabb05..b45c7f281c2f 100644 --- a/configs/xilinx_zynqmp_ep_defconfig +++ b/configs/xilinx_zynqmp_ep_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_ep" CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_MALLOC_F_LEN=0x4000 +CONFIG_DM_GPIO=y CONFIG_ZYNQMP_USB=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-ep108" @@ -17,6 +18,7 @@ CONFIG_SYS_PROMPT="ZynqMP> " # CONFIG_CMD_LOADB is not set # CONFIG_CMD_LOADS is not set # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y # CONFIG_CMD_ITEST is not set # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TFTPPUT=y
participants (1)
-
Michal Simek