From patchwork Thu Dec 20 14:44:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Belloni X-Patchwork-Id: 1016799 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43LF0J4C1Bz9rxp for ; Fri, 21 Dec 2018 01:44:48 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387679AbeLTOor (ORCPT ); Thu, 20 Dec 2018 09:44:47 -0500 Received: from mail.bootlin.com ([62.4.15.54]:35649 "EHLO mail.bootlin.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387703AbeLTOor (ORCPT ); Thu, 20 Dec 2018 09:44:47 -0500 Received: by mail.bootlin.com (Postfix, from userid 110) id E59F42072F; Thu, 20 Dec 2018 15:44:42 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.2 Received: from localhost (242.171.71.37.rev.sfr.net [37.71.171.242]) by mail.bootlin.com (Postfix) with ESMTPSA id A14FB206A1; Thu, 20 Dec 2018 15:44:32 +0100 (CET) From: Alexandre Belloni To: Linus Walleij Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Belloni Subject: [PATCH v2] pinctrl: ocelot: add MSCC Jaguar2 support Date: Thu, 20 Dec 2018 15:44:31 +0100 Message-Id: <20181220144431.11143-1-alexandre.belloni@bootlin.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org 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 --- Changes in v2: - select OF_GPIO to avoid build issues .../bindings/pinctrl/mscc,ocelot-pinctrl.txt | 3 +- drivers/pinctrl/Kconfig | 5 +- drivers/pinctrl/pinctrl-ocelot.c | 338 ++++++++++++++---- 3 files changed, 282 insertions(+), 64 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.txt index 24a210e0c59a..32a8a8fa7805 100644 --- a/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.txt @@ -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. diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 4d8c00eac742..bba52f659153 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -339,15 +339,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" diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c index f9fc2b3a8731..3b4ca52d2456 100644 --- a/drivers/pinctrl/pinctrl-ocelot.c +++ b/drivers/pinctrl/pinctrl-ocelot.c @@ -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, ®); - if (!reg) - return; + for (i = 0; i < info->stride; i++) { + regmap_read(info->map, OCELOT_GPIO_INTR_IDENT + 4 * i, ®); + 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, ®map_config); if (IS_ERR(info->map)) { dev_err(dev, "Failed to create regmap\n"); return PTR_ERR(info->map);