gpio: zynq: Add Versal support
[linux-2.6-microblaze.git] / drivers / gpio / gpio-zynq.c
index fb93b35..9ac6914 100644 (file)
@@ -22,6 +22,8 @@
 /* Maximum banks */
 #define ZYNQ_GPIO_MAX_BANK     4
 #define ZYNQMP_GPIO_MAX_BANK   6
+#define VERSAL_GPIO_MAX_BANK   4
+#define VERSAL_UNUSED_BANKS    2
 
 #define ZYNQ_GPIO_BANK0_NGPIO  32
 #define ZYNQ_GPIO_BANK1_NGPIO  22
@@ -96,6 +98,7 @@
 /* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */
 #define ZYNQ_GPIO_QUIRK_IS_ZYNQ        BIT(0)
 #define GPIO_QUIRK_DATA_RO_BUG BIT(1)
+#define GPIO_QUIRK_VERSAL      BIT(2)
 
 struct gpio_regs {
        u32 datamsw[ZYNQMP_GPIO_MAX_BANK];
@@ -199,6 +202,8 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
                                        gpio->p_data->bank_min[bank];
                        return;
                }
+               if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+                       bank = bank + VERSAL_UNUSED_BANKS;
        }
 
        /* default */
@@ -656,6 +661,8 @@ static void zynq_gpio_irqhandler(struct irq_desc *desc)
                int_enb = readl_relaxed(gpio->base_addr +
                                        ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
                zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb);
+               if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+                       bank_num = bank_num + VERSAL_UNUSED_BANKS;
        }
 
        chained_irq_exit(irqchip, desc);
@@ -685,6 +692,8 @@ static void zynq_gpio_save_context(struct zynq_gpio *gpio)
                gpio->context.int_any[bank_num] =
                                readl_relaxed(gpio->base_addr +
                                ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+               if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+                       bank_num = bank_num + VERSAL_UNUSED_BANKS;
        }
 }
 
@@ -716,6 +725,8 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
                writel_relaxed(~(gpio->context.int_en[bank_num]),
                               gpio->base_addr +
                               ZYNQ_GPIO_INTEN_OFFSET(bank_num));
+               if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+                       bank_num = bank_num + VERSAL_UNUSED_BANKS;
        }
 }
 
@@ -787,6 +798,17 @@ static const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
                           zynq_gpio_runtime_resume, NULL)
 };
 
+static const struct zynq_platform_data versal_gpio_def = {
+       .label = "versal_gpio",
+       .quirks = GPIO_QUIRK_VERSAL,
+       .ngpio = 58,
+       .max_bank = VERSAL_GPIO_MAX_BANK,
+       .bank_min[0] = 0,
+       .bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
+       .bank_min[3] = 26,
+       .bank_max[3] = 57, /* Bank 3 is connected to FMIOs (32 pins) */
+};
+
 static const struct zynq_platform_data zynqmp_gpio_def = {
        .label = "zynqmp_gpio",
        .quirks = GPIO_QUIRK_DATA_RO_BUG,
@@ -824,6 +846,7 @@ static const struct zynq_platform_data zynq_gpio_def = {
 static const struct of_device_id zynq_gpio_of_match[] = {
        { .compatible = "xlnx,zynq-gpio-1.0", .data = &zynq_gpio_def },
        { .compatible = "xlnx,zynqmp-gpio-1.0", .data = &zynqmp_gpio_def },
+       { .compatible = "xlnx,versal-gpio-1.0", .data = &versal_gpio_def },
        { /* end of table */ }
 };
 MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
@@ -903,9 +926,12 @@ static int zynq_gpio_probe(struct platform_device *pdev)
                goto err_pm_dis;
 
        /* disable interrupts for all banks */
-       for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++)
+       for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
                writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
                               ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
+               if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+                       bank_num = bank_num + VERSAL_UNUSED_BANKS;
+       }
 
        /* Set up the GPIO irqchip */
        girq = &chip->irq;