pinctrl: ocelot: add MSCC Jaguar2 support
authorAlexandre Belloni <alexandre.belloni@bootlin.com>
Thu, 20 Dec 2018 14:44:31 +0000 (15:44 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Fri, 21 Dec 2018 10:50:48 +0000 (11:50 +0100)
Jaguar2 has the same register layout as Ocelot but it has 64 pins, meaning
that there are 2 registers instead of one.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.txt
drivers/pinctrl/Kconfig
drivers/pinctrl/pinctrl-ocelot.c

index 24a210e0c59add5676516d62c72d13769eafc032..32a8a8fa7805dbc06e26684864493e75502dec9b 100644 (file)
@@ -2,7 +2,8 @@ Microsemi Ocelot pin controller Device Tree Bindings
 ----------------------------------------------------
 
 Required properties:
- - compatible          : Should be "mscc,ocelot-pinctrl"
+ - compatible          : Should be "mscc,ocelot-pinctrl" or
+                               "mscc,jaguar2-pinctrl"
  - reg                 : Address and length of the register set for the device
  - gpio-controller     : Indicates this device is a GPIO controller
  - #gpio-cells         : Must be 2.
index 4c6e83ef716de8afc540ad76c1810e73831fee0e..a80fca28dc48cec093af93e2b3a3165c880c11b5 100644 (file)
@@ -350,15 +350,14 @@ config PINCTRL_RK805
          This selects the pinctrl driver for RK805.
 
 config PINCTRL_OCELOT
-       bool "Pinctrl driver for the Microsemi Ocelot SoCs"
-       default y
+       bool "Pinctrl driver for the Microsemi Ocelot and Jaguar2 SoCs"
        depends on OF
-       depends on MSCC_OCELOT || COMPILE_TEST
        select GPIOLIB
        select GPIOLIB_IRQCHIP
        select GENERIC_PINCONF
        select GENERIC_PINCTRL_GROUPS
        select GENERIC_PINMUX_FUNCTIONS
+       select OF_GPIO
        select REGMAP_MMIO
 
 source "drivers/pinctrl/actions/Kconfig"
index f9fc2b3a8731ff9b7ee9267b5f482ecd83080e41..3b4ca52d2456f72b85638ea88394e5c92b02f7bd 100644 (file)
@@ -37,7 +37,6 @@
 #define OCELOT_GPIO_ALT1       0x24
 #define OCELOT_GPIO_SD_MAP     0x28
 
-#define OCELOT_PINS            22
 #define OCELOT_FUNC_PER_PIN    4
 
 enum {
@@ -48,6 +47,7 @@ enum {
        FUNC_IRQ1_IN,
        FUNC_IRQ1_OUT,
        FUNC_MIIM1,
+       FUNC_MIIM2,
        FUNC_PCI_WAKE,
        FUNC_PTP0,
        FUNC_PTP1,
@@ -62,10 +62,23 @@ enum {
        FUNC_SFP3,
        FUNC_SFP4,
        FUNC_SFP5,
+       FUNC_SFP6,
+       FUNC_SFP7,
+       FUNC_SFP8,
+       FUNC_SFP9,
+       FUNC_SFP10,
+       FUNC_SFP11,
+       FUNC_SFP12,
+       FUNC_SFP13,
+       FUNC_SFP14,
+       FUNC_SFP15,
        FUNC_SG0,
+       FUNC_SG1,
+       FUNC_SG2,
        FUNC_SI,
        FUNC_TACHO,
        FUNC_TWI,
+       FUNC_TWI2,
        FUNC_TWI_SCL_M,
        FUNC_UART,
        FUNC_UART2,
@@ -80,6 +93,7 @@ static const char *const ocelot_function_names[] = {
        [FUNC_IRQ1_IN]          = "irq1_in",
        [FUNC_IRQ1_OUT]         = "irq1_out",
        [FUNC_MIIM1]            = "miim1",
+       [FUNC_MIIM2]            = "miim2",
        [FUNC_PCI_WAKE]         = "pci_wake",
        [FUNC_PTP0]             = "ptp0",
        [FUNC_PTP1]             = "ptp1",
@@ -94,10 +108,23 @@ static const char *const ocelot_function_names[] = {
        [FUNC_SFP3]             = "sfp3",
        [FUNC_SFP4]             = "sfp4",
        [FUNC_SFP5]             = "sfp5",
+       [FUNC_SFP6]             = "sfp6",
+       [FUNC_SFP7]             = "sfp7",
+       [FUNC_SFP8]             = "sfp8",
+       [FUNC_SFP9]             = "sfp9",
+       [FUNC_SFP10]            = "sfp10",
+       [FUNC_SFP11]            = "sfp11",
+       [FUNC_SFP12]            = "sfp12",
+       [FUNC_SFP13]            = "sfp13",
+       [FUNC_SFP14]            = "sfp14",
+       [FUNC_SFP15]            = "sfp15",
        [FUNC_SG0]              = "sg0",
+       [FUNC_SG1]              = "sg1",
+       [FUNC_SG2]              = "sg2",
        [FUNC_SI]               = "si",
        [FUNC_TACHO]            = "tacho",
        [FUNC_TWI]              = "twi",
+       [FUNC_TWI2]             = "twi2",
        [FUNC_TWI_SCL_M]        = "twi_scl_m",
        [FUNC_UART]             = "uart",
        [FUNC_UART2]            = "uart2",
@@ -118,7 +145,9 @@ struct ocelot_pinctrl {
        struct pinctrl_dev *pctl;
        struct gpio_chip gpio_chip;
        struct regmap *map;
+       struct pinctrl_desc *desc;
        struct ocelot_pmx_func func[FUNC_MAX];
+       u8 stride;
 };
 
 #define OCELOT_P(p, f0, f1, f2)                                                \
@@ -183,6 +212,152 @@ static const struct pinctrl_pin_desc ocelot_pins[] = {
        OCELOT_PIN(21),
 };
 
+#define JAGUAR2_P(p, f0, f1)                                           \
+static struct ocelot_pin_caps jaguar2_pin_##p = {                      \
+       .pin = p,                                                       \
+       .functions = {                                                  \
+                       FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_NONE      \
+       },                                                              \
+}
+
+JAGUAR2_P(0,  SG0,       NONE);
+JAGUAR2_P(1,  SG0,       NONE);
+JAGUAR2_P(2,  SG0,       NONE);
+JAGUAR2_P(3,  SG0,       NONE);
+JAGUAR2_P(4,  SG1,       NONE);
+JAGUAR2_P(5,  SG1,       NONE);
+JAGUAR2_P(6,  IRQ0_IN,   IRQ0_OUT);
+JAGUAR2_P(7,  IRQ1_IN,   IRQ1_OUT);
+JAGUAR2_P(8,  PTP0,      NONE);
+JAGUAR2_P(9,  PTP1,      NONE);
+JAGUAR2_P(10, UART,      NONE);
+JAGUAR2_P(11, UART,      NONE);
+JAGUAR2_P(12, SG1,       NONE);
+JAGUAR2_P(13, SG1,       NONE);
+JAGUAR2_P(14, TWI,       TWI_SCL_M);
+JAGUAR2_P(15, TWI,       NONE);
+JAGUAR2_P(16, SI,        TWI_SCL_M);
+JAGUAR2_P(17, SI,        TWI_SCL_M);
+JAGUAR2_P(18, SI,        TWI_SCL_M);
+JAGUAR2_P(19, PCI_WAKE,  NONE);
+JAGUAR2_P(20, IRQ0_OUT,  TWI_SCL_M);
+JAGUAR2_P(21, IRQ1_OUT,  TWI_SCL_M);
+JAGUAR2_P(22, TACHO,     NONE);
+JAGUAR2_P(23, PWM,       NONE);
+JAGUAR2_P(24, UART2,     NONE);
+JAGUAR2_P(25, UART2,     SI);
+JAGUAR2_P(26, PTP2,      SI);
+JAGUAR2_P(27, PTP3,      SI);
+JAGUAR2_P(28, TWI2,      SI);
+JAGUAR2_P(29, TWI2,      SI);
+JAGUAR2_P(30, SG2,       SI);
+JAGUAR2_P(31, SG2,       SI);
+JAGUAR2_P(32, SG2,       SI);
+JAGUAR2_P(33, SG2,       SI);
+JAGUAR2_P(34, NONE,      TWI_SCL_M);
+JAGUAR2_P(35, NONE,      TWI_SCL_M);
+JAGUAR2_P(36, NONE,      TWI_SCL_M);
+JAGUAR2_P(37, NONE,      TWI_SCL_M);
+JAGUAR2_P(38, NONE,      TWI_SCL_M);
+JAGUAR2_P(39, NONE,      TWI_SCL_M);
+JAGUAR2_P(40, NONE,      TWI_SCL_M);
+JAGUAR2_P(41, NONE,      TWI_SCL_M);
+JAGUAR2_P(42, NONE,      TWI_SCL_M);
+JAGUAR2_P(43, NONE,      TWI_SCL_M);
+JAGUAR2_P(44, NONE,      SFP8);
+JAGUAR2_P(45, NONE,      SFP9);
+JAGUAR2_P(46, NONE,      SFP10);
+JAGUAR2_P(47, NONE,      SFP11);
+JAGUAR2_P(48, SFP0,      NONE);
+JAGUAR2_P(49, SFP1,      SI);
+JAGUAR2_P(50, SFP2,      SI);
+JAGUAR2_P(51, SFP3,      SI);
+JAGUAR2_P(52, SFP4,      NONE);
+JAGUAR2_P(53, SFP5,      NONE);
+JAGUAR2_P(54, SFP6,      NONE);
+JAGUAR2_P(55, SFP7,      NONE);
+JAGUAR2_P(56, MIIM1,     SFP12);
+JAGUAR2_P(57, MIIM1,     SFP13);
+JAGUAR2_P(58, MIIM2,     SFP14);
+JAGUAR2_P(59, MIIM2,     SFP15);
+JAGUAR2_P(60, NONE,      NONE);
+JAGUAR2_P(61, NONE,      NONE);
+JAGUAR2_P(62, NONE,      NONE);
+JAGUAR2_P(63, NONE,      NONE);
+
+#define JAGUAR2_PIN(n) {                                       \
+       .number = n,                                            \
+       .name = "GPIO_"#n,                                      \
+       .drv_data = &jaguar2_pin_##n                            \
+}
+
+static const struct pinctrl_pin_desc jaguar2_pins[] = {
+       JAGUAR2_PIN(0),
+       JAGUAR2_PIN(1),
+       JAGUAR2_PIN(2),
+       JAGUAR2_PIN(3),
+       JAGUAR2_PIN(4),
+       JAGUAR2_PIN(5),
+       JAGUAR2_PIN(6),
+       JAGUAR2_PIN(7),
+       JAGUAR2_PIN(8),
+       JAGUAR2_PIN(9),
+       JAGUAR2_PIN(10),
+       JAGUAR2_PIN(11),
+       JAGUAR2_PIN(12),
+       JAGUAR2_PIN(13),
+       JAGUAR2_PIN(14),
+       JAGUAR2_PIN(15),
+       JAGUAR2_PIN(16),
+       JAGUAR2_PIN(17),
+       JAGUAR2_PIN(18),
+       JAGUAR2_PIN(19),
+       JAGUAR2_PIN(20),
+       JAGUAR2_PIN(21),
+       JAGUAR2_PIN(22),
+       JAGUAR2_PIN(23),
+       JAGUAR2_PIN(24),
+       JAGUAR2_PIN(25),
+       JAGUAR2_PIN(26),
+       JAGUAR2_PIN(27),
+       JAGUAR2_PIN(28),
+       JAGUAR2_PIN(29),
+       JAGUAR2_PIN(30),
+       JAGUAR2_PIN(31),
+       JAGUAR2_PIN(32),
+       JAGUAR2_PIN(33),
+       JAGUAR2_PIN(34),
+       JAGUAR2_PIN(35),
+       JAGUAR2_PIN(36),
+       JAGUAR2_PIN(37),
+       JAGUAR2_PIN(38),
+       JAGUAR2_PIN(39),
+       JAGUAR2_PIN(40),
+       JAGUAR2_PIN(41),
+       JAGUAR2_PIN(42),
+       JAGUAR2_PIN(43),
+       JAGUAR2_PIN(44),
+       JAGUAR2_PIN(45),
+       JAGUAR2_PIN(46),
+       JAGUAR2_PIN(47),
+       JAGUAR2_PIN(48),
+       JAGUAR2_PIN(49),
+       JAGUAR2_PIN(50),
+       JAGUAR2_PIN(51),
+       JAGUAR2_PIN(52),
+       JAGUAR2_PIN(53),
+       JAGUAR2_PIN(54),
+       JAGUAR2_PIN(55),
+       JAGUAR2_PIN(56),
+       JAGUAR2_PIN(57),
+       JAGUAR2_PIN(58),
+       JAGUAR2_PIN(59),
+       JAGUAR2_PIN(60),
+       JAGUAR2_PIN(61),
+       JAGUAR2_PIN(62),
+       JAGUAR2_PIN(63),
+};
+
 static int ocelot_get_functions_count(struct pinctrl_dev *pctldev)
 {
        return ARRAY_SIZE(ocelot_function_names);
@@ -207,9 +382,10 @@ static int ocelot_get_function_groups(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-static int ocelot_pin_function_idx(unsigned int pin, unsigned int function)
+static int ocelot_pin_function_idx(struct ocelot_pinctrl *info,
+                                  unsigned int pin, unsigned int function)
 {
-       struct ocelot_pin_caps *p = ocelot_pins[pin].drv_data;
+       struct ocelot_pin_caps *p = info->desc->pins[pin].drv_data;
        int i;
 
        for (i = 0; i < OCELOT_FUNC_PER_PIN; i++) {
@@ -220,14 +396,17 @@ static int ocelot_pin_function_idx(unsigned int pin, unsigned int function)
        return -1;
 }
 
+#define REG(r, info, p) ((r) * (info)->stride + (4 * ((p) / 32)))
+
 static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
                                 unsigned int selector, unsigned int group)
 {
        struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-       struct ocelot_pin_caps *pin = ocelot_pins[group].drv_data;
+       struct ocelot_pin_caps *pin = info->desc->pins[group].drv_data;
+       unsigned int p = pin->pin % 32;
        int f;
 
-       f = ocelot_pin_function_idx(group, selector);
+       f = ocelot_pin_function_idx(info, group, selector);
        if (f < 0)
                return -EINVAL;
 
@@ -238,10 +417,10 @@ static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
         * This is racy because both registers can't be updated at the same time
         * but it doesn't matter much for now.
         */
-       regmap_update_bits(info->map, OCELOT_GPIO_ALT0, BIT(pin->pin),
-                          f << pin->pin);
-       regmap_update_bits(info->map, OCELOT_GPIO_ALT1, BIT(pin->pin),
-                          f << (pin->pin - 1));
+       regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT0, info, pin->pin),
+                          BIT(p), f << p);
+       regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT1, info, pin->pin),
+                          BIT(p), f << (p - 1));
 
        return 0;
 }
@@ -251,9 +430,10 @@ static int ocelot_gpio_set_direction(struct pinctrl_dev *pctldev,
                                     unsigned int pin, bool input)
 {
        struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+       unsigned int p = pin % 32;
 
-       regmap_update_bits(info->map, OCELOT_GPIO_OE, BIT(pin),
-                          input ? 0 : BIT(pin));
+       regmap_update_bits(info->map, REG(OCELOT_GPIO_OE, info, p), BIT(p),
+                          input ? 0 : BIT(p));
 
        return 0;
 }
@@ -263,9 +443,12 @@ static int ocelot_gpio_request_enable(struct pinctrl_dev *pctldev,
                                      unsigned int offset)
 {
        struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+       unsigned int p = offset % 32;
 
-       regmap_update_bits(info->map, OCELOT_GPIO_ALT0, BIT(offset), 0);
-       regmap_update_bits(info->map, OCELOT_GPIO_ALT1, BIT(offset), 0);
+       regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT0, info, offset),
+                          BIT(p), 0);
+       regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT1, info, offset),
+                          BIT(p), 0);
 
        return 0;
 }
@@ -281,13 +464,17 @@ static const struct pinmux_ops ocelot_pmx_ops = {
 
 static int ocelot_pctl_get_groups_count(struct pinctrl_dev *pctldev)
 {
-       return ARRAY_SIZE(ocelot_pins);
+       struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+       return info->desc->npins;
 }
 
 static const char *ocelot_pctl_get_group_name(struct pinctrl_dev *pctldev,
                                              unsigned int group)
 {
-       return ocelot_pins[group].name;
+       struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+       return info->desc->pins[group].name;
 }
 
 static int ocelot_pctl_get_group_pins(struct pinctrl_dev *pctldev,
@@ -295,7 +482,9 @@ static int ocelot_pctl_get_group_pins(struct pinctrl_dev *pctldev,
                                      const unsigned int **pins,
                                      unsigned int *num_pins)
 {
-       *pins = &ocelot_pins[group].number;
+       struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = &info->desc->pins[group].number;
        *num_pins = 1;
 
        return 0;
@@ -318,30 +507,47 @@ static struct pinctrl_desc ocelot_desc = {
        .owner = THIS_MODULE,
 };
 
+static struct pinctrl_desc jaguar2_desc = {
+       .name = "jaguar2-pinctrl",
+       .pins = jaguar2_pins,
+       .npins = ARRAY_SIZE(jaguar2_pins),
+       .pctlops = &ocelot_pctl_ops,
+       .pmxops = &ocelot_pmx_ops,
+       .owner = THIS_MODULE,
+};
+
 static int ocelot_create_group_func_map(struct device *dev,
                                        struct ocelot_pinctrl *info)
 {
-       u16 pins[ARRAY_SIZE(ocelot_pins)];
        int f, npins, i;
+       u8 *pins = kcalloc(info->desc->npins, sizeof(u8), GFP_KERNEL);
+
+       if (!pins)
+               return -ENOMEM;
 
        for (f = 0; f < FUNC_MAX; f++) {
-               for (npins = 0, i = 0; i < ARRAY_SIZE(ocelot_pins); i++) {
-                       if (ocelot_pin_function_idx(i, f) >= 0)
+               for (npins = 0, i = 0; i < info->desc->npins; i++) {
+                       if (ocelot_pin_function_idx(info, i, f) >= 0)
                                pins[npins++] = i;
                }
 
+               if (!npins)
+                       continue;
+
                info->func[f].ngroups = npins;
-               info->func[f].groups = devm_kcalloc(dev,
-                                                        npins,
-                                                        sizeof(char *),
-                                                        GFP_KERNEL);
-               if (!info->func[f].groups)
+               info->func[f].groups = devm_kcalloc(dev, npins, sizeof(char *),
+                                                   GFP_KERNEL);
+               if (!info->func[f].groups) {
+                       kfree(pins);
                        return -ENOMEM;
+               }
 
                for (i = 0; i < npins; i++)
-                       info->func[f].groups[i] = ocelot_pins[pins[i]].name;
+                       info->func[f].groups[i] = info->desc->pins[pins[i]].name;
        }
 
+       kfree(pins);
+
        return 0;
 }
 
@@ -356,7 +562,7 @@ static int ocelot_pinctrl_register(struct platform_device *pdev,
                return ret;
        }
 
-       info->pctl = devm_pinctrl_register(&pdev->dev, &ocelot_desc, info);
+       info->pctl = devm_pinctrl_register(&pdev->dev, info->desc, info);
        if (IS_ERR(info->pctl)) {
                dev_err(&pdev->dev, "Failed to register pinctrl\n");
                return PTR_ERR(info->pctl);
@@ -370,9 +576,9 @@ static int ocelot_gpio_get(struct gpio_chip *chip, unsigned int offset)
        struct ocelot_pinctrl *info = gpiochip_get_data(chip);
        unsigned int val;
 
-       regmap_read(info->map, OCELOT_GPIO_IN, &val);
+       regmap_read(info->map, REG(OCELOT_GPIO_IN, info, offset), &val);
 
-       return !!(val & BIT(offset));
+       return !!(val & BIT(offset % 32));
 }
 
 static void ocelot_gpio_set(struct gpio_chip *chip, unsigned int offset,
@@ -381,9 +587,11 @@ static void ocelot_gpio_set(struct gpio_chip *chip, unsigned int offset,
        struct ocelot_pinctrl *info = gpiochip_get_data(chip);
 
        if (value)
-               regmap_write(info->map, OCELOT_GPIO_OUT_SET, BIT(offset));
+               regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset),
+                            BIT(offset % 32));
        else
-               regmap_write(info->map, OCELOT_GPIO_OUT_CLR, BIT(offset));
+               regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset),
+                            BIT(offset % 32));
 }
 
 static int ocelot_gpio_get_direction(struct gpio_chip *chip,
@@ -392,9 +600,9 @@ static int ocelot_gpio_get_direction(struct gpio_chip *chip,
        struct ocelot_pinctrl *info = gpiochip_get_data(chip);
        unsigned int val;
 
-       regmap_read(info->map, OCELOT_GPIO_OE, &val);
+       regmap_read(info->map, REG(OCELOT_GPIO_OE, info, offset), &val);
 
-       return !(val & BIT(offset));
+       return !(val & BIT(offset % 32));
 }
 
 static int ocelot_gpio_direction_input(struct gpio_chip *chip,
@@ -407,12 +615,14 @@ static int ocelot_gpio_direction_output(struct gpio_chip *chip,
                                        unsigned int offset, int value)
 {
        struct ocelot_pinctrl *info = gpiochip_get_data(chip);
-       unsigned int pin = BIT(offset);
+       unsigned int pin = BIT(offset % 32);
 
        if (value)
-               regmap_write(info->map, OCELOT_GPIO_OUT_SET, pin);
+               regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset),
+                            pin);
        else
-               regmap_write(info->map, OCELOT_GPIO_OUT_CLR, pin);
+               regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset),
+                            pin);
 
        return pinctrl_gpio_direction_output(chip->base + offset);
 }
@@ -434,7 +644,8 @@ static void ocelot_irq_mask(struct irq_data *data)
        struct ocelot_pinctrl *info = gpiochip_get_data(chip);
        unsigned int gpio = irqd_to_hwirq(data);
 
-       regmap_update_bits(info->map, OCELOT_GPIO_INTR_ENA, BIT(gpio), 0);
+       regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio),
+                          BIT(gpio % 32), 0);
 }
 
 static void ocelot_irq_unmask(struct irq_data *data)
@@ -443,8 +654,8 @@ static void ocelot_irq_unmask(struct irq_data *data)
        struct ocelot_pinctrl *info = gpiochip_get_data(chip);
        unsigned int gpio = irqd_to_hwirq(data);
 
-       regmap_update_bits(info->map, OCELOT_GPIO_INTR_ENA, BIT(gpio),
-                          BIT(gpio));
+       regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio),
+                          BIT(gpio % 32), BIT(gpio % 32));
 }
 
 static void ocelot_irq_ack(struct irq_data *data)
@@ -453,7 +664,8 @@ static void ocelot_irq_ack(struct irq_data *data)
        struct ocelot_pinctrl *info = gpiochip_get_data(chip);
        unsigned int gpio = irqd_to_hwirq(data);
 
-       regmap_write_bits(info->map, OCELOT_GPIO_INTR, BIT(gpio), BIT(gpio));
+       regmap_write_bits(info->map, REG(OCELOT_GPIO_INTR, info, gpio),
+                         BIT(gpio % 32), BIT(gpio % 32));
 }
 
 static int ocelot_irq_set_type(struct irq_data *data, unsigned int type);
@@ -497,22 +709,25 @@ static void ocelot_irq_handler(struct irq_desc *desc)
        struct irq_chip *parent_chip = irq_desc_get_chip(desc);
        struct gpio_chip *chip = irq_desc_get_handler_data(desc);
        struct ocelot_pinctrl *info = gpiochip_get_data(chip);
-       unsigned int reg = 0, irq;
+       unsigned int reg = 0, irq, i;
        unsigned long irqs;
 
-       regmap_read(info->map, OCELOT_GPIO_INTR_IDENT, &reg);
-       if (!reg)
-               return;
+       for (i = 0; i < info->stride; i++) {
+               regmap_read(info->map, OCELOT_GPIO_INTR_IDENT + 4 * i, &reg);
+               if (!reg)
+                       continue;
 
-       chained_irq_enter(parent_chip, desc);
+               chained_irq_enter(parent_chip, desc);
 
-       irqs = reg;
+               irqs = reg;
 
-       for_each_set_bit(irq, &irqs, OCELOT_PINS) {
-               generic_handle_irq(irq_linear_revmap(chip->irq.domain, irq));
-       }
+               for_each_set_bit(irq, &irqs,
+                                min(32U, info->desc->npins - 32 * i))
+                       generic_handle_irq(irq_linear_revmap(chip->irq.domain,
+                                                            irq + 32 * i));
 
-       chained_irq_exit(parent_chip, desc);
+               chained_irq_exit(parent_chip, desc);
+       }
 }
 
 static int ocelot_gpiochip_register(struct platform_device *pdev,
@@ -524,7 +739,7 @@ static int ocelot_gpiochip_register(struct platform_device *pdev,
        info->gpio_chip = ocelot_gpiolib_chip;
 
        gc = &info->gpio_chip;
-       gc->ngpio = OCELOT_PINS;
+       gc->ngpio = info->desc->npins;
        gc->parent = &pdev->dev;
        gc->base = 0;
        gc->of_node = info->dev->of_node;
@@ -549,15 +764,9 @@ static int ocelot_gpiochip_register(struct platform_device *pdev,
        return 0;
 }
 
-static const struct regmap_config ocelot_pinctrl_regmap_config = {
-       .reg_bits = 32,
-       .val_bits = 32,
-       .reg_stride = 4,
-       .max_register = 0x64,
-};
-
 static const struct of_device_id ocelot_pinctrl_of_match[] = {
-       { .compatible = "mscc,ocelot-pinctrl" },
+       { .compatible = "mscc,ocelot-pinctrl", .data = &ocelot_desc },
+       { .compatible = "mscc,jaguar2-pinctrl", .data = &jaguar2_desc },
        {},
 };
 
@@ -567,11 +776,18 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
        struct ocelot_pinctrl *info;
        void __iomem *base;
        int ret;
+       struct regmap_config regmap_config = {
+               .reg_bits = 32,
+               .val_bits = 32,
+               .reg_stride = 4,
+       };
 
        info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
+       info->desc = (struct pinctrl_desc *)device_get_match_data(dev);
+
        base = devm_ioremap_resource(dev,
                        platform_get_resource(pdev, IORESOURCE_MEM, 0));
        if (IS_ERR(base)) {
@@ -579,8 +795,10 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
                return PTR_ERR(base);
        }
 
-       info->map = devm_regmap_init_mmio(dev, base,
-                                         &ocelot_pinctrl_regmap_config);
+       info->stride = 1 + (info->desc->npins - 1) / 32;
+       regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4;
+
+       info->map = devm_regmap_init_mmio(dev, base, &regmap_config);
        if (IS_ERR(info->map)) {
                dev_err(dev, "Failed to create regmap\n");
                return PTR_ERR(info->map);