1ce8dc094SAlexandre Belloni // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2ce8dc094SAlexandre Belloni /* 3ce8dc094SAlexandre Belloni * Microsemi SoCs pinctrl driver 4ce8dc094SAlexandre Belloni * 5ce8dc094SAlexandre Belloni * Author: <alexandre.belloni@free-electrons.com> 6ce8dc094SAlexandre Belloni * License: Dual MIT/GPL 7ce8dc094SAlexandre Belloni * Copyright (c) 2017 Microsemi Corporation 8ce8dc094SAlexandre Belloni */ 9ce8dc094SAlexandre Belloni 10ce8dc094SAlexandre Belloni #include <linux/gpio/driver.h> 11ce8dc094SAlexandre Belloni #include <linux/interrupt.h> 12ce8dc094SAlexandre Belloni #include <linux/io.h> 13ce8dc094SAlexandre Belloni #include <linux/of_device.h> 14be36abb7SQuentin Schulz #include <linux/of_irq.h> 15ce8dc094SAlexandre Belloni #include <linux/of_platform.h> 16ce8dc094SAlexandre Belloni #include <linux/pinctrl/pinctrl.h> 17ce8dc094SAlexandre Belloni #include <linux/pinctrl/pinmux.h> 18ce8dc094SAlexandre Belloni #include <linux/pinctrl/pinconf.h> 19ce8dc094SAlexandre Belloni #include <linux/pinctrl/pinconf-generic.h> 20ce8dc094SAlexandre Belloni #include <linux/platform_device.h> 21ce8dc094SAlexandre Belloni #include <linux/regmap.h> 22ce8dc094SAlexandre Belloni #include <linux/slab.h> 23ce8dc094SAlexandre Belloni 24ce8dc094SAlexandre Belloni #include "core.h" 25ce8dc094SAlexandre Belloni #include "pinconf.h" 26ce8dc094SAlexandre Belloni #include "pinmux.h" 27ce8dc094SAlexandre Belloni 28f8a74760SLars Povlsen #define ocelot_clrsetbits(addr, clear, set) \ 29f8a74760SLars Povlsen writel((readl(addr) & ~(clear)) | (set), (addr)) 30f8a74760SLars Povlsen 31f8a74760SLars Povlsen /* PINCONFIG bits (sparx5 only) */ 32f8a74760SLars Povlsen enum { 33f8a74760SLars Povlsen PINCONF_BIAS, 34f8a74760SLars Povlsen PINCONF_SCHMITT, 35f8a74760SLars Povlsen PINCONF_DRIVE_STRENGTH, 36f8a74760SLars Povlsen }; 37f8a74760SLars Povlsen 38f8a74760SLars Povlsen #define BIAS_PD_BIT BIT(4) 39f8a74760SLars Povlsen #define BIAS_PU_BIT BIT(3) 40f8a74760SLars Povlsen #define BIAS_BITS (BIAS_PD_BIT|BIAS_PU_BIT) 41f8a74760SLars Povlsen #define SCHMITT_BIT BIT(2) 42f8a74760SLars Povlsen #define DRIVE_BITS GENMASK(1, 0) 43f8a74760SLars Povlsen 44f8a74760SLars Povlsen /* GPIO standard registers */ 45ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OUT_SET 0x0 46ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OUT_CLR 0x4 47ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OUT 0x8 48ce8dc094SAlexandre Belloni #define OCELOT_GPIO_IN 0xc 49ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OE 0x10 50ce8dc094SAlexandre Belloni #define OCELOT_GPIO_INTR 0x14 51ce8dc094SAlexandre Belloni #define OCELOT_GPIO_INTR_ENA 0x18 52ce8dc094SAlexandre Belloni #define OCELOT_GPIO_INTR_IDENT 0x1c 53ce8dc094SAlexandre Belloni #define OCELOT_GPIO_ALT0 0x20 54ce8dc094SAlexandre Belloni #define OCELOT_GPIO_ALT1 0x24 55ce8dc094SAlexandre Belloni #define OCELOT_GPIO_SD_MAP 0x28 56ce8dc094SAlexandre Belloni 57ce8dc094SAlexandre Belloni #define OCELOT_FUNC_PER_PIN 4 58ce8dc094SAlexandre Belloni 59ce8dc094SAlexandre Belloni enum { 60ce8dc094SAlexandre Belloni FUNC_NONE, 61ce8dc094SAlexandre Belloni FUNC_GPIO, 62f8a74760SLars Povlsen FUNC_IRQ0, 63ce8dc094SAlexandre Belloni FUNC_IRQ0_IN, 64ce8dc094SAlexandre Belloni FUNC_IRQ0_OUT, 65f8a74760SLars Povlsen FUNC_IRQ1, 66ce8dc094SAlexandre Belloni FUNC_IRQ1_IN, 67ce8dc094SAlexandre Belloni FUNC_IRQ1_OUT, 68f8a74760SLars Povlsen FUNC_EXT_IRQ, 69edc72546SLars Povlsen FUNC_MIIM, 70f8a74760SLars Povlsen FUNC_PHY_LED, 71ce8dc094SAlexandre Belloni FUNC_PCI_WAKE, 72f8a74760SLars Povlsen FUNC_MD, 73ce8dc094SAlexandre Belloni FUNC_PTP0, 74ce8dc094SAlexandre Belloni FUNC_PTP1, 75ce8dc094SAlexandre Belloni FUNC_PTP2, 76ce8dc094SAlexandre Belloni FUNC_PTP3, 77ce8dc094SAlexandre Belloni FUNC_PWM, 78edc72546SLars Povlsen FUNC_RECO_CLK, 79edc72546SLars Povlsen FUNC_SFP, 80ce8dc094SAlexandre Belloni FUNC_SG0, 81da801ab5SAlexandre Belloni FUNC_SG1, 82da801ab5SAlexandre Belloni FUNC_SG2, 83ce8dc094SAlexandre Belloni FUNC_SI, 84f8a74760SLars Povlsen FUNC_SI2, 85ce8dc094SAlexandre Belloni FUNC_TACHO, 86ce8dc094SAlexandre Belloni FUNC_TWI, 87da801ab5SAlexandre Belloni FUNC_TWI2, 88f8a74760SLars Povlsen FUNC_TWI3, 89ce8dc094SAlexandre Belloni FUNC_TWI_SCL_M, 90ce8dc094SAlexandre Belloni FUNC_UART, 91ce8dc094SAlexandre Belloni FUNC_UART2, 92f8a74760SLars Povlsen FUNC_UART3, 93f8a74760SLars Povlsen FUNC_PLL_STAT, 94f8a74760SLars Povlsen FUNC_EMMC, 95f8a74760SLars Povlsen FUNC_REF_CLK, 96f8a74760SLars Povlsen FUNC_RCVRD_CLK, 97ce8dc094SAlexandre Belloni FUNC_MAX 98ce8dc094SAlexandre Belloni }; 99ce8dc094SAlexandre Belloni 100ce8dc094SAlexandre Belloni static const char *const ocelot_function_names[] = { 101ce8dc094SAlexandre Belloni [FUNC_NONE] = "none", 102ce8dc094SAlexandre Belloni [FUNC_GPIO] = "gpio", 103f8a74760SLars Povlsen [FUNC_IRQ0] = "irq0", 104ce8dc094SAlexandre Belloni [FUNC_IRQ0_IN] = "irq0_in", 105ce8dc094SAlexandre Belloni [FUNC_IRQ0_OUT] = "irq0_out", 106f8a74760SLars Povlsen [FUNC_IRQ1] = "irq1", 107ce8dc094SAlexandre Belloni [FUNC_IRQ1_IN] = "irq1_in", 108ce8dc094SAlexandre Belloni [FUNC_IRQ1_OUT] = "irq1_out", 109f8a74760SLars Povlsen [FUNC_EXT_IRQ] = "ext_irq", 110edc72546SLars Povlsen [FUNC_MIIM] = "miim", 111f8a74760SLars Povlsen [FUNC_PHY_LED] = "phy_led", 112ce8dc094SAlexandre Belloni [FUNC_PCI_WAKE] = "pci_wake", 113f8a74760SLars Povlsen [FUNC_MD] = "md", 114ce8dc094SAlexandre Belloni [FUNC_PTP0] = "ptp0", 115ce8dc094SAlexandre Belloni [FUNC_PTP1] = "ptp1", 116ce8dc094SAlexandre Belloni [FUNC_PTP2] = "ptp2", 117ce8dc094SAlexandre Belloni [FUNC_PTP3] = "ptp3", 118ce8dc094SAlexandre Belloni [FUNC_PWM] = "pwm", 119edc72546SLars Povlsen [FUNC_RECO_CLK] = "reco_clk", 120edc72546SLars Povlsen [FUNC_SFP] = "sfp", 121ce8dc094SAlexandre Belloni [FUNC_SG0] = "sg0", 122da801ab5SAlexandre Belloni [FUNC_SG1] = "sg1", 123da801ab5SAlexandre Belloni [FUNC_SG2] = "sg2", 124ce8dc094SAlexandre Belloni [FUNC_SI] = "si", 125f8a74760SLars Povlsen [FUNC_SI2] = "si2", 126ce8dc094SAlexandre Belloni [FUNC_TACHO] = "tacho", 127ce8dc094SAlexandre Belloni [FUNC_TWI] = "twi", 128da801ab5SAlexandre Belloni [FUNC_TWI2] = "twi2", 129f8a74760SLars Povlsen [FUNC_TWI3] = "twi3", 130ce8dc094SAlexandre Belloni [FUNC_TWI_SCL_M] = "twi_scl_m", 131ce8dc094SAlexandre Belloni [FUNC_UART] = "uart", 132ce8dc094SAlexandre Belloni [FUNC_UART2] = "uart2", 133f8a74760SLars Povlsen [FUNC_UART3] = "uart3", 134f8a74760SLars Povlsen [FUNC_PLL_STAT] = "pll_stat", 135f8a74760SLars Povlsen [FUNC_EMMC] = "emmc", 136f8a74760SLars Povlsen [FUNC_REF_CLK] = "ref_clk", 137f8a74760SLars Povlsen [FUNC_RCVRD_CLK] = "rcvrd_clk", 138ce8dc094SAlexandre Belloni }; 139ce8dc094SAlexandre Belloni 140ce8dc094SAlexandre Belloni struct ocelot_pmx_func { 141ce8dc094SAlexandre Belloni const char **groups; 142ce8dc094SAlexandre Belloni unsigned int ngroups; 143ce8dc094SAlexandre Belloni }; 144ce8dc094SAlexandre Belloni 145ce8dc094SAlexandre Belloni struct ocelot_pin_caps { 146ce8dc094SAlexandre Belloni unsigned int pin; 147ce8dc094SAlexandre Belloni unsigned char functions[OCELOT_FUNC_PER_PIN]; 148ce8dc094SAlexandre Belloni }; 149ce8dc094SAlexandre Belloni 150ce8dc094SAlexandre Belloni struct ocelot_pinctrl { 151ce8dc094SAlexandre Belloni struct device *dev; 152ce8dc094SAlexandre Belloni struct pinctrl_dev *pctl; 153ce8dc094SAlexandre Belloni struct gpio_chip gpio_chip; 154ce8dc094SAlexandre Belloni struct regmap *map; 155f8a74760SLars Povlsen void __iomem *pincfg; 156da801ab5SAlexandre Belloni struct pinctrl_desc *desc; 157ce8dc094SAlexandre Belloni struct ocelot_pmx_func func[FUNC_MAX]; 158da801ab5SAlexandre Belloni u8 stride; 159ce8dc094SAlexandre Belloni }; 160ce8dc094SAlexandre Belloni 161ce8dc094SAlexandre Belloni #define OCELOT_P(p, f0, f1, f2) \ 162ce8dc094SAlexandre Belloni static struct ocelot_pin_caps ocelot_pin_##p = { \ 163ce8dc094SAlexandre Belloni .pin = p, \ 164ce8dc094SAlexandre Belloni .functions = { \ 165ce8dc094SAlexandre Belloni FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_##f2, \ 166ce8dc094SAlexandre Belloni }, \ 167ce8dc094SAlexandre Belloni } 168ce8dc094SAlexandre Belloni 169ce8dc094SAlexandre Belloni OCELOT_P(0, SG0, NONE, NONE); 170ce8dc094SAlexandre Belloni OCELOT_P(1, SG0, NONE, NONE); 171ce8dc094SAlexandre Belloni OCELOT_P(2, SG0, NONE, NONE); 172ce8dc094SAlexandre Belloni OCELOT_P(3, SG0, NONE, NONE); 17317f79084SAlexandre Belloni OCELOT_P(4, IRQ0_IN, IRQ0_OUT, TWI_SCL_M); 174ce8dc094SAlexandre Belloni OCELOT_P(5, IRQ1_IN, IRQ1_OUT, PCI_WAKE); 175ce8dc094SAlexandre Belloni OCELOT_P(6, UART, TWI_SCL_M, NONE); 176ce8dc094SAlexandre Belloni OCELOT_P(7, UART, TWI_SCL_M, NONE); 177ce8dc094SAlexandre Belloni OCELOT_P(8, SI, TWI_SCL_M, IRQ0_OUT); 178ce8dc094SAlexandre Belloni OCELOT_P(9, SI, TWI_SCL_M, IRQ1_OUT); 179edc72546SLars Povlsen OCELOT_P(10, PTP2, TWI_SCL_M, SFP); 180edc72546SLars Povlsen OCELOT_P(11, PTP3, TWI_SCL_M, SFP); 181edc72546SLars Povlsen OCELOT_P(12, UART2, TWI_SCL_M, SFP); 182edc72546SLars Povlsen OCELOT_P(13, UART2, TWI_SCL_M, SFP); 183edc72546SLars Povlsen OCELOT_P(14, MIIM, TWI_SCL_M, SFP); 184edc72546SLars Povlsen OCELOT_P(15, MIIM, TWI_SCL_M, SFP); 185ce8dc094SAlexandre Belloni OCELOT_P(16, TWI, NONE, SI); 186ce8dc094SAlexandre Belloni OCELOT_P(17, TWI, TWI_SCL_M, SI); 187ce8dc094SAlexandre Belloni OCELOT_P(18, PTP0, TWI_SCL_M, NONE); 188ce8dc094SAlexandre Belloni OCELOT_P(19, PTP1, TWI_SCL_M, NONE); 189edc72546SLars Povlsen OCELOT_P(20, RECO_CLK, TACHO, TWI_SCL_M); 190edc72546SLars Povlsen OCELOT_P(21, RECO_CLK, PWM, TWI_SCL_M); 191ce8dc094SAlexandre Belloni 192ce8dc094SAlexandre Belloni #define OCELOT_PIN(n) { \ 193ce8dc094SAlexandre Belloni .number = n, \ 194ce8dc094SAlexandre Belloni .name = "GPIO_"#n, \ 195ce8dc094SAlexandre Belloni .drv_data = &ocelot_pin_##n \ 196ce8dc094SAlexandre Belloni } 197ce8dc094SAlexandre Belloni 198ce8dc094SAlexandre Belloni static const struct pinctrl_pin_desc ocelot_pins[] = { 199ce8dc094SAlexandre Belloni OCELOT_PIN(0), 200ce8dc094SAlexandre Belloni OCELOT_PIN(1), 201ce8dc094SAlexandre Belloni OCELOT_PIN(2), 202ce8dc094SAlexandre Belloni OCELOT_PIN(3), 203ce8dc094SAlexandre Belloni OCELOT_PIN(4), 204ce8dc094SAlexandre Belloni OCELOT_PIN(5), 205ce8dc094SAlexandre Belloni OCELOT_PIN(6), 206ce8dc094SAlexandre Belloni OCELOT_PIN(7), 207ce8dc094SAlexandre Belloni OCELOT_PIN(8), 208ce8dc094SAlexandre Belloni OCELOT_PIN(9), 209ce8dc094SAlexandre Belloni OCELOT_PIN(10), 210ce8dc094SAlexandre Belloni OCELOT_PIN(11), 211ce8dc094SAlexandre Belloni OCELOT_PIN(12), 212ce8dc094SAlexandre Belloni OCELOT_PIN(13), 213ce8dc094SAlexandre Belloni OCELOT_PIN(14), 214ce8dc094SAlexandre Belloni OCELOT_PIN(15), 215ce8dc094SAlexandre Belloni OCELOT_PIN(16), 216ce8dc094SAlexandre Belloni OCELOT_PIN(17), 217ce8dc094SAlexandre Belloni OCELOT_PIN(18), 218ce8dc094SAlexandre Belloni OCELOT_PIN(19), 219ce8dc094SAlexandre Belloni OCELOT_PIN(20), 220ce8dc094SAlexandre Belloni OCELOT_PIN(21), 221ce8dc094SAlexandre Belloni }; 222ce8dc094SAlexandre Belloni 223da801ab5SAlexandre Belloni #define JAGUAR2_P(p, f0, f1) \ 224da801ab5SAlexandre Belloni static struct ocelot_pin_caps jaguar2_pin_##p = { \ 225da801ab5SAlexandre Belloni .pin = p, \ 226da801ab5SAlexandre Belloni .functions = { \ 227da801ab5SAlexandre Belloni FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_NONE \ 228da801ab5SAlexandre Belloni }, \ 229da801ab5SAlexandre Belloni } 230da801ab5SAlexandre Belloni 231da801ab5SAlexandre Belloni JAGUAR2_P(0, SG0, NONE); 232da801ab5SAlexandre Belloni JAGUAR2_P(1, SG0, NONE); 233da801ab5SAlexandre Belloni JAGUAR2_P(2, SG0, NONE); 234da801ab5SAlexandre Belloni JAGUAR2_P(3, SG0, NONE); 235da801ab5SAlexandre Belloni JAGUAR2_P(4, SG1, NONE); 236da801ab5SAlexandre Belloni JAGUAR2_P(5, SG1, NONE); 237da801ab5SAlexandre Belloni JAGUAR2_P(6, IRQ0_IN, IRQ0_OUT); 238da801ab5SAlexandre Belloni JAGUAR2_P(7, IRQ1_IN, IRQ1_OUT); 239da801ab5SAlexandre Belloni JAGUAR2_P(8, PTP0, NONE); 240da801ab5SAlexandre Belloni JAGUAR2_P(9, PTP1, NONE); 241da801ab5SAlexandre Belloni JAGUAR2_P(10, UART, NONE); 242da801ab5SAlexandre Belloni JAGUAR2_P(11, UART, NONE); 243da801ab5SAlexandre Belloni JAGUAR2_P(12, SG1, NONE); 244da801ab5SAlexandre Belloni JAGUAR2_P(13, SG1, NONE); 245da801ab5SAlexandre Belloni JAGUAR2_P(14, TWI, TWI_SCL_M); 246da801ab5SAlexandre Belloni JAGUAR2_P(15, TWI, NONE); 247da801ab5SAlexandre Belloni JAGUAR2_P(16, SI, TWI_SCL_M); 248da801ab5SAlexandre Belloni JAGUAR2_P(17, SI, TWI_SCL_M); 249da801ab5SAlexandre Belloni JAGUAR2_P(18, SI, TWI_SCL_M); 250da801ab5SAlexandre Belloni JAGUAR2_P(19, PCI_WAKE, NONE); 251da801ab5SAlexandre Belloni JAGUAR2_P(20, IRQ0_OUT, TWI_SCL_M); 252da801ab5SAlexandre Belloni JAGUAR2_P(21, IRQ1_OUT, TWI_SCL_M); 253da801ab5SAlexandre Belloni JAGUAR2_P(22, TACHO, NONE); 254da801ab5SAlexandre Belloni JAGUAR2_P(23, PWM, NONE); 255da801ab5SAlexandre Belloni JAGUAR2_P(24, UART2, NONE); 256da801ab5SAlexandre Belloni JAGUAR2_P(25, UART2, SI); 257da801ab5SAlexandre Belloni JAGUAR2_P(26, PTP2, SI); 258da801ab5SAlexandre Belloni JAGUAR2_P(27, PTP3, SI); 259da801ab5SAlexandre Belloni JAGUAR2_P(28, TWI2, SI); 260da801ab5SAlexandre Belloni JAGUAR2_P(29, TWI2, SI); 261da801ab5SAlexandre Belloni JAGUAR2_P(30, SG2, SI); 262da801ab5SAlexandre Belloni JAGUAR2_P(31, SG2, SI); 263da801ab5SAlexandre Belloni JAGUAR2_P(32, SG2, SI); 264da801ab5SAlexandre Belloni JAGUAR2_P(33, SG2, SI); 265da801ab5SAlexandre Belloni JAGUAR2_P(34, NONE, TWI_SCL_M); 266da801ab5SAlexandre Belloni JAGUAR2_P(35, NONE, TWI_SCL_M); 267da801ab5SAlexandre Belloni JAGUAR2_P(36, NONE, TWI_SCL_M); 268da801ab5SAlexandre Belloni JAGUAR2_P(37, NONE, TWI_SCL_M); 269da801ab5SAlexandre Belloni JAGUAR2_P(38, NONE, TWI_SCL_M); 270da801ab5SAlexandre Belloni JAGUAR2_P(39, NONE, TWI_SCL_M); 271da801ab5SAlexandre Belloni JAGUAR2_P(40, NONE, TWI_SCL_M); 272da801ab5SAlexandre Belloni JAGUAR2_P(41, NONE, TWI_SCL_M); 273da801ab5SAlexandre Belloni JAGUAR2_P(42, NONE, TWI_SCL_M); 274da801ab5SAlexandre Belloni JAGUAR2_P(43, NONE, TWI_SCL_M); 275edc72546SLars Povlsen JAGUAR2_P(44, NONE, SFP); 276edc72546SLars Povlsen JAGUAR2_P(45, NONE, SFP); 277edc72546SLars Povlsen JAGUAR2_P(46, NONE, SFP); 278edc72546SLars Povlsen JAGUAR2_P(47, NONE, SFP); 279edc72546SLars Povlsen JAGUAR2_P(48, SFP, NONE); 280edc72546SLars Povlsen JAGUAR2_P(49, SFP, SI); 281edc72546SLars Povlsen JAGUAR2_P(50, SFP, SI); 282edc72546SLars Povlsen JAGUAR2_P(51, SFP, SI); 283edc72546SLars Povlsen JAGUAR2_P(52, SFP, NONE); 284edc72546SLars Povlsen JAGUAR2_P(53, SFP, NONE); 285edc72546SLars Povlsen JAGUAR2_P(54, SFP, NONE); 286edc72546SLars Povlsen JAGUAR2_P(55, SFP, NONE); 287edc72546SLars Povlsen JAGUAR2_P(56, MIIM, SFP); 288edc72546SLars Povlsen JAGUAR2_P(57, MIIM, SFP); 289edc72546SLars Povlsen JAGUAR2_P(58, MIIM, SFP); 290edc72546SLars Povlsen JAGUAR2_P(59, MIIM, SFP); 291da801ab5SAlexandre Belloni JAGUAR2_P(60, NONE, NONE); 292da801ab5SAlexandre Belloni JAGUAR2_P(61, NONE, NONE); 293da801ab5SAlexandre Belloni JAGUAR2_P(62, NONE, NONE); 294da801ab5SAlexandre Belloni JAGUAR2_P(63, NONE, NONE); 295da801ab5SAlexandre Belloni 296da801ab5SAlexandre Belloni #define JAGUAR2_PIN(n) { \ 297da801ab5SAlexandre Belloni .number = n, \ 298da801ab5SAlexandre Belloni .name = "GPIO_"#n, \ 299da801ab5SAlexandre Belloni .drv_data = &jaguar2_pin_##n \ 300da801ab5SAlexandre Belloni } 301da801ab5SAlexandre Belloni 302da801ab5SAlexandre Belloni static const struct pinctrl_pin_desc jaguar2_pins[] = { 303da801ab5SAlexandre Belloni JAGUAR2_PIN(0), 304da801ab5SAlexandre Belloni JAGUAR2_PIN(1), 305da801ab5SAlexandre Belloni JAGUAR2_PIN(2), 306da801ab5SAlexandre Belloni JAGUAR2_PIN(3), 307da801ab5SAlexandre Belloni JAGUAR2_PIN(4), 308da801ab5SAlexandre Belloni JAGUAR2_PIN(5), 309da801ab5SAlexandre Belloni JAGUAR2_PIN(6), 310da801ab5SAlexandre Belloni JAGUAR2_PIN(7), 311da801ab5SAlexandre Belloni JAGUAR2_PIN(8), 312da801ab5SAlexandre Belloni JAGUAR2_PIN(9), 313da801ab5SAlexandre Belloni JAGUAR2_PIN(10), 314da801ab5SAlexandre Belloni JAGUAR2_PIN(11), 315da801ab5SAlexandre Belloni JAGUAR2_PIN(12), 316da801ab5SAlexandre Belloni JAGUAR2_PIN(13), 317da801ab5SAlexandre Belloni JAGUAR2_PIN(14), 318da801ab5SAlexandre Belloni JAGUAR2_PIN(15), 319da801ab5SAlexandre Belloni JAGUAR2_PIN(16), 320da801ab5SAlexandre Belloni JAGUAR2_PIN(17), 321da801ab5SAlexandre Belloni JAGUAR2_PIN(18), 322da801ab5SAlexandre Belloni JAGUAR2_PIN(19), 323da801ab5SAlexandre Belloni JAGUAR2_PIN(20), 324da801ab5SAlexandre Belloni JAGUAR2_PIN(21), 325da801ab5SAlexandre Belloni JAGUAR2_PIN(22), 326da801ab5SAlexandre Belloni JAGUAR2_PIN(23), 327da801ab5SAlexandre Belloni JAGUAR2_PIN(24), 328da801ab5SAlexandre Belloni JAGUAR2_PIN(25), 329da801ab5SAlexandre Belloni JAGUAR2_PIN(26), 330da801ab5SAlexandre Belloni JAGUAR2_PIN(27), 331da801ab5SAlexandre Belloni JAGUAR2_PIN(28), 332da801ab5SAlexandre Belloni JAGUAR2_PIN(29), 333da801ab5SAlexandre Belloni JAGUAR2_PIN(30), 334da801ab5SAlexandre Belloni JAGUAR2_PIN(31), 335da801ab5SAlexandre Belloni JAGUAR2_PIN(32), 336da801ab5SAlexandre Belloni JAGUAR2_PIN(33), 337da801ab5SAlexandre Belloni JAGUAR2_PIN(34), 338da801ab5SAlexandre Belloni JAGUAR2_PIN(35), 339da801ab5SAlexandre Belloni JAGUAR2_PIN(36), 340da801ab5SAlexandre Belloni JAGUAR2_PIN(37), 341da801ab5SAlexandre Belloni JAGUAR2_PIN(38), 342da801ab5SAlexandre Belloni JAGUAR2_PIN(39), 343da801ab5SAlexandre Belloni JAGUAR2_PIN(40), 344da801ab5SAlexandre Belloni JAGUAR2_PIN(41), 345da801ab5SAlexandre Belloni JAGUAR2_PIN(42), 346da801ab5SAlexandre Belloni JAGUAR2_PIN(43), 347da801ab5SAlexandre Belloni JAGUAR2_PIN(44), 348da801ab5SAlexandre Belloni JAGUAR2_PIN(45), 349da801ab5SAlexandre Belloni JAGUAR2_PIN(46), 350da801ab5SAlexandre Belloni JAGUAR2_PIN(47), 351da801ab5SAlexandre Belloni JAGUAR2_PIN(48), 352da801ab5SAlexandre Belloni JAGUAR2_PIN(49), 353da801ab5SAlexandre Belloni JAGUAR2_PIN(50), 354da801ab5SAlexandre Belloni JAGUAR2_PIN(51), 355da801ab5SAlexandre Belloni JAGUAR2_PIN(52), 356da801ab5SAlexandre Belloni JAGUAR2_PIN(53), 357da801ab5SAlexandre Belloni JAGUAR2_PIN(54), 358da801ab5SAlexandre Belloni JAGUAR2_PIN(55), 359da801ab5SAlexandre Belloni JAGUAR2_PIN(56), 360da801ab5SAlexandre Belloni JAGUAR2_PIN(57), 361da801ab5SAlexandre Belloni JAGUAR2_PIN(58), 362da801ab5SAlexandre Belloni JAGUAR2_PIN(59), 363da801ab5SAlexandre Belloni JAGUAR2_PIN(60), 364da801ab5SAlexandre Belloni JAGUAR2_PIN(61), 365da801ab5SAlexandre Belloni JAGUAR2_PIN(62), 366da801ab5SAlexandre Belloni JAGUAR2_PIN(63), 367da801ab5SAlexandre Belloni }; 368da801ab5SAlexandre Belloni 369f8a74760SLars Povlsen #define SPARX5_P(p, f0, f1, f2) \ 370f8a74760SLars Povlsen static struct ocelot_pin_caps sparx5_pin_##p = { \ 371f8a74760SLars Povlsen .pin = p, \ 372f8a74760SLars Povlsen .functions = { \ 373f8a74760SLars Povlsen FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_##f2 \ 374f8a74760SLars Povlsen }, \ 375f8a74760SLars Povlsen } 376f8a74760SLars Povlsen 377f8a74760SLars Povlsen SPARX5_P(0, SG0, PLL_STAT, NONE); 378f8a74760SLars Povlsen SPARX5_P(1, SG0, NONE, NONE); 379f8a74760SLars Povlsen SPARX5_P(2, SG0, NONE, NONE); 380f8a74760SLars Povlsen SPARX5_P(3, SG0, NONE, NONE); 381f8a74760SLars Povlsen SPARX5_P(4, SG1, NONE, NONE); 382f8a74760SLars Povlsen SPARX5_P(5, SG1, NONE, NONE); 383f8a74760SLars Povlsen SPARX5_P(6, IRQ0_IN, IRQ0_OUT, SFP); 384f8a74760SLars Povlsen SPARX5_P(7, IRQ1_IN, IRQ1_OUT, SFP); 385f8a74760SLars Povlsen SPARX5_P(8, PTP0, NONE, SFP); 386f8a74760SLars Povlsen SPARX5_P(9, PTP1, SFP, TWI_SCL_M); 387f8a74760SLars Povlsen SPARX5_P(10, UART, NONE, NONE); 388f8a74760SLars Povlsen SPARX5_P(11, UART, NONE, NONE); 389f8a74760SLars Povlsen SPARX5_P(12, SG1, NONE, NONE); 390f8a74760SLars Povlsen SPARX5_P(13, SG1, NONE, NONE); 391f8a74760SLars Povlsen SPARX5_P(14, TWI, TWI_SCL_M, NONE); 392f8a74760SLars Povlsen SPARX5_P(15, TWI, NONE, NONE); 393f8a74760SLars Povlsen SPARX5_P(16, SI, TWI_SCL_M, SFP); 394f8a74760SLars Povlsen SPARX5_P(17, SI, TWI_SCL_M, SFP); 395f8a74760SLars Povlsen SPARX5_P(18, SI, TWI_SCL_M, SFP); 396f8a74760SLars Povlsen SPARX5_P(19, PCI_WAKE, TWI_SCL_M, SFP); 397f8a74760SLars Povlsen SPARX5_P(20, IRQ0_OUT, TWI_SCL_M, SFP); 398f8a74760SLars Povlsen SPARX5_P(21, IRQ1_OUT, TACHO, SFP); 399f8a74760SLars Povlsen SPARX5_P(22, TACHO, IRQ0_OUT, TWI_SCL_M); 400f8a74760SLars Povlsen SPARX5_P(23, PWM, UART3, TWI_SCL_M); 401f8a74760SLars Povlsen SPARX5_P(24, PTP2, UART3, TWI_SCL_M); 402f8a74760SLars Povlsen SPARX5_P(25, PTP3, SI, TWI_SCL_M); 403f8a74760SLars Povlsen SPARX5_P(26, UART2, SI, TWI_SCL_M); 404f8a74760SLars Povlsen SPARX5_P(27, UART2, SI, TWI_SCL_M); 405f8a74760SLars Povlsen SPARX5_P(28, TWI2, SI, SFP); 406f8a74760SLars Povlsen SPARX5_P(29, TWI2, SI, SFP); 407f8a74760SLars Povlsen SPARX5_P(30, SG2, SI, PWM); 408f8a74760SLars Povlsen SPARX5_P(31, SG2, SI, TWI_SCL_M); 409f8a74760SLars Povlsen SPARX5_P(32, SG2, SI, TWI_SCL_M); 410f8a74760SLars Povlsen SPARX5_P(33, SG2, SI, SFP); 411f8a74760SLars Povlsen SPARX5_P(34, NONE, TWI_SCL_M, EMMC); 412f8a74760SLars Povlsen SPARX5_P(35, SFP, TWI_SCL_M, EMMC); 413f8a74760SLars Povlsen SPARX5_P(36, SFP, TWI_SCL_M, EMMC); 414f8a74760SLars Povlsen SPARX5_P(37, SFP, NONE, EMMC); 415f8a74760SLars Povlsen SPARX5_P(38, NONE, TWI_SCL_M, EMMC); 416f8a74760SLars Povlsen SPARX5_P(39, SI2, TWI_SCL_M, EMMC); 417f8a74760SLars Povlsen SPARX5_P(40, SI2, TWI_SCL_M, EMMC); 418f8a74760SLars Povlsen SPARX5_P(41, SI2, TWI_SCL_M, EMMC); 419f8a74760SLars Povlsen SPARX5_P(42, SI2, TWI_SCL_M, EMMC); 420f8a74760SLars Povlsen SPARX5_P(43, SI2, TWI_SCL_M, EMMC); 421f8a74760SLars Povlsen SPARX5_P(44, SI, SFP, EMMC); 422f8a74760SLars Povlsen SPARX5_P(45, SI, SFP, EMMC); 423f8a74760SLars Povlsen SPARX5_P(46, NONE, SFP, EMMC); 424f8a74760SLars Povlsen SPARX5_P(47, NONE, SFP, EMMC); 425f8a74760SLars Povlsen SPARX5_P(48, TWI3, SI, SFP); 426f8a74760SLars Povlsen SPARX5_P(49, TWI3, NONE, SFP); 427f8a74760SLars Povlsen SPARX5_P(50, SFP, NONE, TWI_SCL_M); 428f8a74760SLars Povlsen SPARX5_P(51, SFP, SI, TWI_SCL_M); 429f8a74760SLars Povlsen SPARX5_P(52, SFP, MIIM, TWI_SCL_M); 430f8a74760SLars Povlsen SPARX5_P(53, SFP, MIIM, TWI_SCL_M); 431f8a74760SLars Povlsen SPARX5_P(54, SFP, PTP2, TWI_SCL_M); 432f8a74760SLars Povlsen SPARX5_P(55, SFP, PTP3, PCI_WAKE); 433f8a74760SLars Povlsen SPARX5_P(56, MIIM, SFP, TWI_SCL_M); 434f8a74760SLars Povlsen SPARX5_P(57, MIIM, SFP, TWI_SCL_M); 435f8a74760SLars Povlsen SPARX5_P(58, MIIM, SFP, TWI_SCL_M); 436f8a74760SLars Povlsen SPARX5_P(59, MIIM, SFP, NONE); 437f8a74760SLars Povlsen SPARX5_P(60, RECO_CLK, NONE, NONE); 438f8a74760SLars Povlsen SPARX5_P(61, RECO_CLK, NONE, NONE); 439f8a74760SLars Povlsen SPARX5_P(62, RECO_CLK, PLL_STAT, NONE); 440f8a74760SLars Povlsen SPARX5_P(63, RECO_CLK, NONE, NONE); 441f8a74760SLars Povlsen 442f8a74760SLars Povlsen #define SPARX5_PIN(n) { \ 443f8a74760SLars Povlsen .number = n, \ 444f8a74760SLars Povlsen .name = "GPIO_"#n, \ 445f8a74760SLars Povlsen .drv_data = &sparx5_pin_##n \ 446f8a74760SLars Povlsen } 447f8a74760SLars Povlsen 448f8a74760SLars Povlsen static const struct pinctrl_pin_desc sparx5_pins[] = { 449f8a74760SLars Povlsen SPARX5_PIN(0), 450f8a74760SLars Povlsen SPARX5_PIN(1), 451f8a74760SLars Povlsen SPARX5_PIN(2), 452f8a74760SLars Povlsen SPARX5_PIN(3), 453f8a74760SLars Povlsen SPARX5_PIN(4), 454f8a74760SLars Povlsen SPARX5_PIN(5), 455f8a74760SLars Povlsen SPARX5_PIN(6), 456f8a74760SLars Povlsen SPARX5_PIN(7), 457f8a74760SLars Povlsen SPARX5_PIN(8), 458f8a74760SLars Povlsen SPARX5_PIN(9), 459f8a74760SLars Povlsen SPARX5_PIN(10), 460f8a74760SLars Povlsen SPARX5_PIN(11), 461f8a74760SLars Povlsen SPARX5_PIN(12), 462f8a74760SLars Povlsen SPARX5_PIN(13), 463f8a74760SLars Povlsen SPARX5_PIN(14), 464f8a74760SLars Povlsen SPARX5_PIN(15), 465f8a74760SLars Povlsen SPARX5_PIN(16), 466f8a74760SLars Povlsen SPARX5_PIN(17), 467f8a74760SLars Povlsen SPARX5_PIN(18), 468f8a74760SLars Povlsen SPARX5_PIN(19), 469f8a74760SLars Povlsen SPARX5_PIN(20), 470f8a74760SLars Povlsen SPARX5_PIN(21), 471f8a74760SLars Povlsen SPARX5_PIN(22), 472f8a74760SLars Povlsen SPARX5_PIN(23), 473f8a74760SLars Povlsen SPARX5_PIN(24), 474f8a74760SLars Povlsen SPARX5_PIN(25), 475f8a74760SLars Povlsen SPARX5_PIN(26), 476f8a74760SLars Povlsen SPARX5_PIN(27), 477f8a74760SLars Povlsen SPARX5_PIN(28), 478f8a74760SLars Povlsen SPARX5_PIN(29), 479f8a74760SLars Povlsen SPARX5_PIN(30), 480f8a74760SLars Povlsen SPARX5_PIN(31), 481f8a74760SLars Povlsen SPARX5_PIN(32), 482f8a74760SLars Povlsen SPARX5_PIN(33), 483f8a74760SLars Povlsen SPARX5_PIN(34), 484f8a74760SLars Povlsen SPARX5_PIN(35), 485f8a74760SLars Povlsen SPARX5_PIN(36), 486f8a74760SLars Povlsen SPARX5_PIN(37), 487f8a74760SLars Povlsen SPARX5_PIN(38), 488f8a74760SLars Povlsen SPARX5_PIN(39), 489f8a74760SLars Povlsen SPARX5_PIN(40), 490f8a74760SLars Povlsen SPARX5_PIN(41), 491f8a74760SLars Povlsen SPARX5_PIN(42), 492f8a74760SLars Povlsen SPARX5_PIN(43), 493f8a74760SLars Povlsen SPARX5_PIN(44), 494f8a74760SLars Povlsen SPARX5_PIN(45), 495f8a74760SLars Povlsen SPARX5_PIN(46), 496f8a74760SLars Povlsen SPARX5_PIN(47), 497f8a74760SLars Povlsen SPARX5_PIN(48), 498f8a74760SLars Povlsen SPARX5_PIN(49), 499f8a74760SLars Povlsen SPARX5_PIN(50), 500f8a74760SLars Povlsen SPARX5_PIN(51), 501f8a74760SLars Povlsen SPARX5_PIN(52), 502f8a74760SLars Povlsen SPARX5_PIN(53), 503f8a74760SLars Povlsen SPARX5_PIN(54), 504f8a74760SLars Povlsen SPARX5_PIN(55), 505f8a74760SLars Povlsen SPARX5_PIN(56), 506f8a74760SLars Povlsen SPARX5_PIN(57), 507f8a74760SLars Povlsen SPARX5_PIN(58), 508f8a74760SLars Povlsen SPARX5_PIN(59), 509f8a74760SLars Povlsen SPARX5_PIN(60), 510f8a74760SLars Povlsen SPARX5_PIN(61), 511f8a74760SLars Povlsen SPARX5_PIN(62), 512f8a74760SLars Povlsen SPARX5_PIN(63), 513f8a74760SLars Povlsen }; 514f8a74760SLars Povlsen 515ce8dc094SAlexandre Belloni static int ocelot_get_functions_count(struct pinctrl_dev *pctldev) 516ce8dc094SAlexandre Belloni { 517ce8dc094SAlexandre Belloni return ARRAY_SIZE(ocelot_function_names); 518ce8dc094SAlexandre Belloni } 519ce8dc094SAlexandre Belloni 520ce8dc094SAlexandre Belloni static const char *ocelot_get_function_name(struct pinctrl_dev *pctldev, 521ce8dc094SAlexandre Belloni unsigned int function) 522ce8dc094SAlexandre Belloni { 523ce8dc094SAlexandre Belloni return ocelot_function_names[function]; 524ce8dc094SAlexandre Belloni } 525ce8dc094SAlexandre Belloni 526ce8dc094SAlexandre Belloni static int ocelot_get_function_groups(struct pinctrl_dev *pctldev, 527ce8dc094SAlexandre Belloni unsigned int function, 528ce8dc094SAlexandre Belloni const char *const **groups, 529ce8dc094SAlexandre Belloni unsigned *const num_groups) 530ce8dc094SAlexandre Belloni { 531ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 532ce8dc094SAlexandre Belloni 533ce8dc094SAlexandre Belloni *groups = info->func[function].groups; 534ce8dc094SAlexandre Belloni *num_groups = info->func[function].ngroups; 535ce8dc094SAlexandre Belloni 536ce8dc094SAlexandre Belloni return 0; 537ce8dc094SAlexandre Belloni } 538ce8dc094SAlexandre Belloni 539da801ab5SAlexandre Belloni static int ocelot_pin_function_idx(struct ocelot_pinctrl *info, 540da801ab5SAlexandre Belloni unsigned int pin, unsigned int function) 541ce8dc094SAlexandre Belloni { 542da801ab5SAlexandre Belloni struct ocelot_pin_caps *p = info->desc->pins[pin].drv_data; 543ce8dc094SAlexandre Belloni int i; 544ce8dc094SAlexandre Belloni 545ce8dc094SAlexandre Belloni for (i = 0; i < OCELOT_FUNC_PER_PIN; i++) { 546ce8dc094SAlexandre Belloni if (function == p->functions[i]) 547ce8dc094SAlexandre Belloni return i; 548ce8dc094SAlexandre Belloni } 549ce8dc094SAlexandre Belloni 550ce8dc094SAlexandre Belloni return -1; 551ce8dc094SAlexandre Belloni } 552ce8dc094SAlexandre Belloni 5534b36082eSAlexandre Belloni #define REG_ALT(msb, info, p) (OCELOT_GPIO_ALT0 * (info)->stride + 4 * ((msb) + ((info)->stride * ((p) / 32)))) 554da801ab5SAlexandre Belloni 555ce8dc094SAlexandre Belloni static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev, 556ce8dc094SAlexandre Belloni unsigned int selector, unsigned int group) 557ce8dc094SAlexandre Belloni { 558ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 559da801ab5SAlexandre Belloni struct ocelot_pin_caps *pin = info->desc->pins[group].drv_data; 560da801ab5SAlexandre Belloni unsigned int p = pin->pin % 32; 561ce8dc094SAlexandre Belloni int f; 562ce8dc094SAlexandre Belloni 563da801ab5SAlexandre Belloni f = ocelot_pin_function_idx(info, group, selector); 564ce8dc094SAlexandre Belloni if (f < 0) 565ce8dc094SAlexandre Belloni return -EINVAL; 566ce8dc094SAlexandre Belloni 567ce8dc094SAlexandre Belloni /* 568ce8dc094SAlexandre Belloni * f is encoded on two bits. 5694b36082eSAlexandre Belloni * bit 0 of f goes in BIT(pin) of ALT[0], bit 1 of f goes in BIT(pin) of 5704b36082eSAlexandre Belloni * ALT[1] 571ce8dc094SAlexandre Belloni * This is racy because both registers can't be updated at the same time 572ce8dc094SAlexandre Belloni * but it doesn't matter much for now. 573f8a74760SLars Povlsen * Note: ALT0/ALT1 are organized specially for 64 gpio targets 574ce8dc094SAlexandre Belloni */ 5754b36082eSAlexandre Belloni regmap_update_bits(info->map, REG_ALT(0, info, pin->pin), 576da801ab5SAlexandre Belloni BIT(p), f << p); 5774b36082eSAlexandre Belloni regmap_update_bits(info->map, REG_ALT(1, info, pin->pin), 578da801ab5SAlexandre Belloni BIT(p), f << (p - 1)); 579ce8dc094SAlexandre Belloni 580ce8dc094SAlexandre Belloni return 0; 581ce8dc094SAlexandre Belloni } 582ce8dc094SAlexandre Belloni 5834b36082eSAlexandre Belloni #define REG(r, info, p) ((r) * (info)->stride + (4 * ((p) / 32))) 5844b36082eSAlexandre Belloni 585ce8dc094SAlexandre Belloni static int ocelot_gpio_set_direction(struct pinctrl_dev *pctldev, 586ce8dc094SAlexandre Belloni struct pinctrl_gpio_range *range, 587ce8dc094SAlexandre Belloni unsigned int pin, bool input) 588ce8dc094SAlexandre Belloni { 589ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 590da801ab5SAlexandre Belloni unsigned int p = pin % 32; 591ce8dc094SAlexandre Belloni 592f2818ba3SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_OE, info, pin), BIT(p), 593da801ab5SAlexandre Belloni input ? 0 : BIT(p)); 594ce8dc094SAlexandre Belloni 595ce8dc094SAlexandre Belloni return 0; 596ce8dc094SAlexandre Belloni } 597ce8dc094SAlexandre Belloni 598ce8dc094SAlexandre Belloni static int ocelot_gpio_request_enable(struct pinctrl_dev *pctldev, 599ce8dc094SAlexandre Belloni struct pinctrl_gpio_range *range, 600ce8dc094SAlexandre Belloni unsigned int offset) 601ce8dc094SAlexandre Belloni { 602ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 603da801ab5SAlexandre Belloni unsigned int p = offset % 32; 604ce8dc094SAlexandre Belloni 6054b36082eSAlexandre Belloni regmap_update_bits(info->map, REG_ALT(0, info, offset), 606da801ab5SAlexandre Belloni BIT(p), 0); 6074b36082eSAlexandre Belloni regmap_update_bits(info->map, REG_ALT(1, info, offset), 608da801ab5SAlexandre Belloni BIT(p), 0); 609ce8dc094SAlexandre Belloni 610ce8dc094SAlexandre Belloni return 0; 611ce8dc094SAlexandre Belloni } 612ce8dc094SAlexandre Belloni 613ce8dc094SAlexandre Belloni static const struct pinmux_ops ocelot_pmx_ops = { 614ce8dc094SAlexandre Belloni .get_functions_count = ocelot_get_functions_count, 615ce8dc094SAlexandre Belloni .get_function_name = ocelot_get_function_name, 616ce8dc094SAlexandre Belloni .get_function_groups = ocelot_get_function_groups, 617ce8dc094SAlexandre Belloni .set_mux = ocelot_pinmux_set_mux, 618ce8dc094SAlexandre Belloni .gpio_set_direction = ocelot_gpio_set_direction, 619ce8dc094SAlexandre Belloni .gpio_request_enable = ocelot_gpio_request_enable, 620ce8dc094SAlexandre Belloni }; 621ce8dc094SAlexandre Belloni 622ce8dc094SAlexandre Belloni static int ocelot_pctl_get_groups_count(struct pinctrl_dev *pctldev) 623ce8dc094SAlexandre Belloni { 624da801ab5SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 625da801ab5SAlexandre Belloni 626da801ab5SAlexandre Belloni return info->desc->npins; 627ce8dc094SAlexandre Belloni } 628ce8dc094SAlexandre Belloni 629ce8dc094SAlexandre Belloni static const char *ocelot_pctl_get_group_name(struct pinctrl_dev *pctldev, 630ce8dc094SAlexandre Belloni unsigned int group) 631ce8dc094SAlexandre Belloni { 632da801ab5SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 633da801ab5SAlexandre Belloni 634da801ab5SAlexandre Belloni return info->desc->pins[group].name; 635ce8dc094SAlexandre Belloni } 636ce8dc094SAlexandre Belloni 637ce8dc094SAlexandre Belloni static int ocelot_pctl_get_group_pins(struct pinctrl_dev *pctldev, 638ce8dc094SAlexandre Belloni unsigned int group, 639ce8dc094SAlexandre Belloni const unsigned int **pins, 640ce8dc094SAlexandre Belloni unsigned int *num_pins) 641ce8dc094SAlexandre Belloni { 642da801ab5SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 643da801ab5SAlexandre Belloni 644da801ab5SAlexandre Belloni *pins = &info->desc->pins[group].number; 645ce8dc094SAlexandre Belloni *num_pins = 1; 646ce8dc094SAlexandre Belloni 647ce8dc094SAlexandre Belloni return 0; 648ce8dc094SAlexandre Belloni } 649ce8dc094SAlexandre Belloni 650f8a74760SLars Povlsen static int ocelot_hw_get_value(struct ocelot_pinctrl *info, 651f8a74760SLars Povlsen unsigned int pin, 652f8a74760SLars Povlsen unsigned int reg, 653f8a74760SLars Povlsen int *val) 654f8a74760SLars Povlsen { 655f8a74760SLars Povlsen int ret = -EOPNOTSUPP; 656f8a74760SLars Povlsen 657f8a74760SLars Povlsen if (info->pincfg) { 658f8a74760SLars Povlsen u32 regcfg = readl(info->pincfg + (pin * sizeof(u32))); 659f8a74760SLars Povlsen 660f8a74760SLars Povlsen ret = 0; 661f8a74760SLars Povlsen switch (reg) { 662f8a74760SLars Povlsen case PINCONF_BIAS: 663f8a74760SLars Povlsen *val = regcfg & BIAS_BITS; 664f8a74760SLars Povlsen break; 665f8a74760SLars Povlsen 666f8a74760SLars Povlsen case PINCONF_SCHMITT: 667f8a74760SLars Povlsen *val = regcfg & SCHMITT_BIT; 668f8a74760SLars Povlsen break; 669f8a74760SLars Povlsen 670f8a74760SLars Povlsen case PINCONF_DRIVE_STRENGTH: 671f8a74760SLars Povlsen *val = regcfg & DRIVE_BITS; 672f8a74760SLars Povlsen break; 673f8a74760SLars Povlsen 674f8a74760SLars Povlsen default: 675f8a74760SLars Povlsen ret = -EOPNOTSUPP; 676f8a74760SLars Povlsen break; 677f8a74760SLars Povlsen } 678f8a74760SLars Povlsen } 679f8a74760SLars Povlsen return ret; 680f8a74760SLars Povlsen } 681f8a74760SLars Povlsen 682f8a74760SLars Povlsen static int ocelot_hw_set_value(struct ocelot_pinctrl *info, 683f8a74760SLars Povlsen unsigned int pin, 684f8a74760SLars Povlsen unsigned int reg, 685f8a74760SLars Povlsen int val) 686f8a74760SLars Povlsen { 687f8a74760SLars Povlsen int ret = -EOPNOTSUPP; 688f8a74760SLars Povlsen 689f8a74760SLars Povlsen if (info->pincfg) { 690f8a74760SLars Povlsen void __iomem *regaddr = info->pincfg + (pin * sizeof(u32)); 691f8a74760SLars Povlsen 692f8a74760SLars Povlsen ret = 0; 693f8a74760SLars Povlsen switch (reg) { 694f8a74760SLars Povlsen case PINCONF_BIAS: 695f8a74760SLars Povlsen ocelot_clrsetbits(regaddr, BIAS_BITS, val); 696f8a74760SLars Povlsen break; 697f8a74760SLars Povlsen 698f8a74760SLars Povlsen case PINCONF_SCHMITT: 699f8a74760SLars Povlsen ocelot_clrsetbits(regaddr, SCHMITT_BIT, val); 700f8a74760SLars Povlsen break; 701f8a74760SLars Povlsen 702f8a74760SLars Povlsen case PINCONF_DRIVE_STRENGTH: 703f8a74760SLars Povlsen if (val <= 3) 704f8a74760SLars Povlsen ocelot_clrsetbits(regaddr, DRIVE_BITS, val); 705f8a74760SLars Povlsen else 706f8a74760SLars Povlsen ret = -EINVAL; 707f8a74760SLars Povlsen break; 708f8a74760SLars Povlsen 709f8a74760SLars Povlsen default: 710f8a74760SLars Povlsen ret = -EOPNOTSUPP; 711f8a74760SLars Povlsen break; 712f8a74760SLars Povlsen } 713f8a74760SLars Povlsen } 714f8a74760SLars Povlsen return ret; 715f8a74760SLars Povlsen } 716f8a74760SLars Povlsen 717f8a74760SLars Povlsen static int ocelot_pinconf_get(struct pinctrl_dev *pctldev, 718f8a74760SLars Povlsen unsigned int pin, unsigned long *config) 719f8a74760SLars Povlsen { 720f8a74760SLars Povlsen struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 721f8a74760SLars Povlsen u32 param = pinconf_to_config_param(*config); 722f8a74760SLars Povlsen int val, err; 723f8a74760SLars Povlsen 724f8a74760SLars Povlsen switch (param) { 725f8a74760SLars Povlsen case PIN_CONFIG_BIAS_DISABLE: 726f8a74760SLars Povlsen case PIN_CONFIG_BIAS_PULL_UP: 727f8a74760SLars Povlsen case PIN_CONFIG_BIAS_PULL_DOWN: 728f8a74760SLars Povlsen err = ocelot_hw_get_value(info, pin, PINCONF_BIAS, &val); 729f8a74760SLars Povlsen if (err) 730f8a74760SLars Povlsen return err; 731f8a74760SLars Povlsen if (param == PIN_CONFIG_BIAS_DISABLE) 732f8a74760SLars Povlsen val = (val == 0 ? true : false); 733f8a74760SLars Povlsen else if (param == PIN_CONFIG_BIAS_PULL_DOWN) 734f8a74760SLars Povlsen val = (val & BIAS_PD_BIT ? true : false); 735f8a74760SLars Povlsen else /* PIN_CONFIG_BIAS_PULL_UP */ 736f8a74760SLars Povlsen val = (val & BIAS_PU_BIT ? true : false); 737f8a74760SLars Povlsen break; 738f8a74760SLars Povlsen 739f8a74760SLars Povlsen case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 740f8a74760SLars Povlsen err = ocelot_hw_get_value(info, pin, PINCONF_SCHMITT, &val); 741f8a74760SLars Povlsen if (err) 742f8a74760SLars Povlsen return err; 743f8a74760SLars Povlsen 744f8a74760SLars Povlsen val = (val & SCHMITT_BIT ? true : false); 745f8a74760SLars Povlsen break; 746f8a74760SLars Povlsen 747f8a74760SLars Povlsen case PIN_CONFIG_DRIVE_STRENGTH: 748f8a74760SLars Povlsen err = ocelot_hw_get_value(info, pin, PINCONF_DRIVE_STRENGTH, 749f8a74760SLars Povlsen &val); 750f8a74760SLars Povlsen if (err) 751f8a74760SLars Povlsen return err; 752f8a74760SLars Povlsen break; 753f8a74760SLars Povlsen 754f8a74760SLars Povlsen case PIN_CONFIG_OUTPUT: 755f8a74760SLars Povlsen err = regmap_read(info->map, REG(OCELOT_GPIO_OUT, info, pin), 756f8a74760SLars Povlsen &val); 757f8a74760SLars Povlsen if (err) 758f8a74760SLars Povlsen return err; 759f8a74760SLars Povlsen val = !!(val & BIT(pin % 32)); 760f8a74760SLars Povlsen break; 761f8a74760SLars Povlsen 762f8a74760SLars Povlsen case PIN_CONFIG_INPUT_ENABLE: 763f8a74760SLars Povlsen case PIN_CONFIG_OUTPUT_ENABLE: 764f8a74760SLars Povlsen err = regmap_read(info->map, REG(OCELOT_GPIO_OE, info, pin), 765f8a74760SLars Povlsen &val); 766f8a74760SLars Povlsen if (err) 767f8a74760SLars Povlsen return err; 768f8a74760SLars Povlsen val = val & BIT(pin % 32); 769f8a74760SLars Povlsen if (param == PIN_CONFIG_OUTPUT_ENABLE) 770f8a74760SLars Povlsen val = !!val; 771f8a74760SLars Povlsen else 772f8a74760SLars Povlsen val = !val; 773f8a74760SLars Povlsen break; 774f8a74760SLars Povlsen 775f8a74760SLars Povlsen default: 776f8a74760SLars Povlsen return -EOPNOTSUPP; 777f8a74760SLars Povlsen } 778f8a74760SLars Povlsen 779f8a74760SLars Povlsen *config = pinconf_to_config_packed(param, val); 780f8a74760SLars Povlsen 781f8a74760SLars Povlsen return 0; 782f8a74760SLars Povlsen } 783f8a74760SLars Povlsen 784f8a74760SLars Povlsen static int ocelot_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 785f8a74760SLars Povlsen unsigned long *configs, unsigned int num_configs) 786f8a74760SLars Povlsen { 787f8a74760SLars Povlsen struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 788f8a74760SLars Povlsen u32 param, arg, p; 789f8a74760SLars Povlsen int cfg, err = 0; 790f8a74760SLars Povlsen 791f8a74760SLars Povlsen for (cfg = 0; cfg < num_configs; cfg++) { 792f8a74760SLars Povlsen param = pinconf_to_config_param(configs[cfg]); 793f8a74760SLars Povlsen arg = pinconf_to_config_argument(configs[cfg]); 794f8a74760SLars Povlsen 795f8a74760SLars Povlsen switch (param) { 796f8a74760SLars Povlsen case PIN_CONFIG_BIAS_DISABLE: 797f8a74760SLars Povlsen case PIN_CONFIG_BIAS_PULL_UP: 798f8a74760SLars Povlsen case PIN_CONFIG_BIAS_PULL_DOWN: 799f8a74760SLars Povlsen arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 : 800f8a74760SLars Povlsen (param == PIN_CONFIG_BIAS_PULL_UP) ? BIAS_PU_BIT : 801f8a74760SLars Povlsen BIAS_PD_BIT; 802f8a74760SLars Povlsen 803f8a74760SLars Povlsen err = ocelot_hw_set_value(info, pin, PINCONF_BIAS, arg); 804f8a74760SLars Povlsen if (err) 805f8a74760SLars Povlsen goto err; 806f8a74760SLars Povlsen 807f8a74760SLars Povlsen break; 808f8a74760SLars Povlsen 809f8a74760SLars Povlsen case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 810f8a74760SLars Povlsen arg = arg ? SCHMITT_BIT : 0; 811f8a74760SLars Povlsen err = ocelot_hw_set_value(info, pin, PINCONF_SCHMITT, 812f8a74760SLars Povlsen arg); 813f8a74760SLars Povlsen if (err) 814f8a74760SLars Povlsen goto err; 815f8a74760SLars Povlsen 816f8a74760SLars Povlsen break; 817f8a74760SLars Povlsen 818f8a74760SLars Povlsen case PIN_CONFIG_DRIVE_STRENGTH: 819f8a74760SLars Povlsen err = ocelot_hw_set_value(info, pin, 820f8a74760SLars Povlsen PINCONF_DRIVE_STRENGTH, 821f8a74760SLars Povlsen arg); 822f8a74760SLars Povlsen if (err) 823f8a74760SLars Povlsen goto err; 824f8a74760SLars Povlsen 825f8a74760SLars Povlsen break; 826f8a74760SLars Povlsen 827f8a74760SLars Povlsen case PIN_CONFIG_OUTPUT_ENABLE: 828f8a74760SLars Povlsen case PIN_CONFIG_INPUT_ENABLE: 829f8a74760SLars Povlsen case PIN_CONFIG_OUTPUT: 830f8a74760SLars Povlsen p = pin % 32; 831f8a74760SLars Povlsen if (arg) 832f8a74760SLars Povlsen regmap_write(info->map, 833f8a74760SLars Povlsen REG(OCELOT_GPIO_OUT_SET, info, 834f8a74760SLars Povlsen pin), 835f8a74760SLars Povlsen BIT(p)); 836f8a74760SLars Povlsen else 837f8a74760SLars Povlsen regmap_write(info->map, 838f8a74760SLars Povlsen REG(OCELOT_GPIO_OUT_CLR, info, 839f8a74760SLars Povlsen pin), 840f8a74760SLars Povlsen BIT(p)); 841f8a74760SLars Povlsen regmap_update_bits(info->map, 842f8a74760SLars Povlsen REG(OCELOT_GPIO_OE, info, pin), 843f8a74760SLars Povlsen BIT(p), 844f8a74760SLars Povlsen param == PIN_CONFIG_INPUT_ENABLE ? 845f8a74760SLars Povlsen 0 : BIT(p)); 846f8a74760SLars Povlsen break; 847f8a74760SLars Povlsen 848f8a74760SLars Povlsen default: 849f8a74760SLars Povlsen err = -EOPNOTSUPP; 850f8a74760SLars Povlsen } 851f8a74760SLars Povlsen } 852f8a74760SLars Povlsen err: 853f8a74760SLars Povlsen return err; 854f8a74760SLars Povlsen } 855f8a74760SLars Povlsen 856f8a74760SLars Povlsen static const struct pinconf_ops ocelot_confops = { 857f8a74760SLars Povlsen .is_generic = true, 858f8a74760SLars Povlsen .pin_config_get = ocelot_pinconf_get, 859f8a74760SLars Povlsen .pin_config_set = ocelot_pinconf_set, 860f8a74760SLars Povlsen .pin_config_config_dbg_show = pinconf_generic_dump_config, 861f8a74760SLars Povlsen }; 862f8a74760SLars Povlsen 863ce8dc094SAlexandre Belloni static const struct pinctrl_ops ocelot_pctl_ops = { 864ce8dc094SAlexandre Belloni .get_groups_count = ocelot_pctl_get_groups_count, 865ce8dc094SAlexandre Belloni .get_group_name = ocelot_pctl_get_group_name, 866ce8dc094SAlexandre Belloni .get_group_pins = ocelot_pctl_get_group_pins, 867ce8dc094SAlexandre Belloni .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 868ce8dc094SAlexandre Belloni .dt_free_map = pinconf_generic_dt_free_map, 869ce8dc094SAlexandre Belloni }; 870ce8dc094SAlexandre Belloni 871ce8dc094SAlexandre Belloni static struct pinctrl_desc ocelot_desc = { 872ce8dc094SAlexandre Belloni .name = "ocelot-pinctrl", 873ce8dc094SAlexandre Belloni .pins = ocelot_pins, 874ce8dc094SAlexandre Belloni .npins = ARRAY_SIZE(ocelot_pins), 875ce8dc094SAlexandre Belloni .pctlops = &ocelot_pctl_ops, 876ce8dc094SAlexandre Belloni .pmxops = &ocelot_pmx_ops, 877ce8dc094SAlexandre Belloni .owner = THIS_MODULE, 878ce8dc094SAlexandre Belloni }; 879ce8dc094SAlexandre Belloni 880da801ab5SAlexandre Belloni static struct pinctrl_desc jaguar2_desc = { 881da801ab5SAlexandre Belloni .name = "jaguar2-pinctrl", 882da801ab5SAlexandre Belloni .pins = jaguar2_pins, 883da801ab5SAlexandre Belloni .npins = ARRAY_SIZE(jaguar2_pins), 884da801ab5SAlexandre Belloni .pctlops = &ocelot_pctl_ops, 885da801ab5SAlexandre Belloni .pmxops = &ocelot_pmx_ops, 886da801ab5SAlexandre Belloni .owner = THIS_MODULE, 887da801ab5SAlexandre Belloni }; 888da801ab5SAlexandre Belloni 889f8a74760SLars Povlsen static struct pinctrl_desc sparx5_desc = { 890f8a74760SLars Povlsen .name = "sparx5-pinctrl", 891f8a74760SLars Povlsen .pins = sparx5_pins, 892f8a74760SLars Povlsen .npins = ARRAY_SIZE(sparx5_pins), 893f8a74760SLars Povlsen .pctlops = &ocelot_pctl_ops, 894f8a74760SLars Povlsen .pmxops = &ocelot_pmx_ops, 895f8a74760SLars Povlsen .confops = &ocelot_confops, 896f8a74760SLars Povlsen .owner = THIS_MODULE, 897f8a74760SLars Povlsen }; 898f8a74760SLars Povlsen 899ce8dc094SAlexandre Belloni static int ocelot_create_group_func_map(struct device *dev, 900ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info) 901ce8dc094SAlexandre Belloni { 902ce8dc094SAlexandre Belloni int f, npins, i; 903da801ab5SAlexandre Belloni u8 *pins = kcalloc(info->desc->npins, sizeof(u8), GFP_KERNEL); 904da801ab5SAlexandre Belloni 905da801ab5SAlexandre Belloni if (!pins) 906da801ab5SAlexandre Belloni return -ENOMEM; 907ce8dc094SAlexandre Belloni 908ce8dc094SAlexandre Belloni for (f = 0; f < FUNC_MAX; f++) { 909da801ab5SAlexandre Belloni for (npins = 0, i = 0; i < info->desc->npins; i++) { 910da801ab5SAlexandre Belloni if (ocelot_pin_function_idx(info, i, f) >= 0) 911ce8dc094SAlexandre Belloni pins[npins++] = i; 912ce8dc094SAlexandre Belloni } 913ce8dc094SAlexandre Belloni 914da801ab5SAlexandre Belloni if (!npins) 915da801ab5SAlexandre Belloni continue; 916da801ab5SAlexandre Belloni 917ce8dc094SAlexandre Belloni info->func[f].ngroups = npins; 918da801ab5SAlexandre Belloni info->func[f].groups = devm_kcalloc(dev, npins, sizeof(char *), 919ce8dc094SAlexandre Belloni GFP_KERNEL); 920da801ab5SAlexandre Belloni if (!info->func[f].groups) { 921da801ab5SAlexandre Belloni kfree(pins); 922ce8dc094SAlexandre Belloni return -ENOMEM; 923da801ab5SAlexandre Belloni } 924ce8dc094SAlexandre Belloni 925ce8dc094SAlexandre Belloni for (i = 0; i < npins; i++) 926f8a74760SLars Povlsen info->func[f].groups[i] = 927f8a74760SLars Povlsen info->desc->pins[pins[i]].name; 928ce8dc094SAlexandre Belloni } 929ce8dc094SAlexandre Belloni 930da801ab5SAlexandre Belloni kfree(pins); 931da801ab5SAlexandre Belloni 932ce8dc094SAlexandre Belloni return 0; 933ce8dc094SAlexandre Belloni } 934ce8dc094SAlexandre Belloni 935ce8dc094SAlexandre Belloni static int ocelot_pinctrl_register(struct platform_device *pdev, 936ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info) 937ce8dc094SAlexandre Belloni { 938ce8dc094SAlexandre Belloni int ret; 939ce8dc094SAlexandre Belloni 940ce8dc094SAlexandre Belloni ret = ocelot_create_group_func_map(&pdev->dev, info); 941ce8dc094SAlexandre Belloni if (ret) { 942ce8dc094SAlexandre Belloni dev_err(&pdev->dev, "Unable to create group func map.\n"); 943ce8dc094SAlexandre Belloni return ret; 944ce8dc094SAlexandre Belloni } 945ce8dc094SAlexandre Belloni 946da801ab5SAlexandre Belloni info->pctl = devm_pinctrl_register(&pdev->dev, info->desc, info); 947ce8dc094SAlexandre Belloni if (IS_ERR(info->pctl)) { 948ce8dc094SAlexandre Belloni dev_err(&pdev->dev, "Failed to register pinctrl\n"); 949ce8dc094SAlexandre Belloni return PTR_ERR(info->pctl); 950ce8dc094SAlexandre Belloni } 951ce8dc094SAlexandre Belloni 952ce8dc094SAlexandre Belloni return 0; 953ce8dc094SAlexandre Belloni } 954ce8dc094SAlexandre Belloni 955ce8dc094SAlexandre Belloni static int ocelot_gpio_get(struct gpio_chip *chip, unsigned int offset) 956ce8dc094SAlexandre Belloni { 957ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = gpiochip_get_data(chip); 958ce8dc094SAlexandre Belloni unsigned int val; 959ce8dc094SAlexandre Belloni 960da801ab5SAlexandre Belloni regmap_read(info->map, REG(OCELOT_GPIO_IN, info, offset), &val); 961ce8dc094SAlexandre Belloni 962da801ab5SAlexandre Belloni return !!(val & BIT(offset % 32)); 963ce8dc094SAlexandre Belloni } 964ce8dc094SAlexandre Belloni 965ce8dc094SAlexandre Belloni static void ocelot_gpio_set(struct gpio_chip *chip, unsigned int offset, 966ce8dc094SAlexandre Belloni int value) 967ce8dc094SAlexandre Belloni { 968ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = gpiochip_get_data(chip); 969ce8dc094SAlexandre Belloni 970ce8dc094SAlexandre Belloni if (value) 971da801ab5SAlexandre Belloni regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset), 972da801ab5SAlexandre Belloni BIT(offset % 32)); 973ce8dc094SAlexandre Belloni else 974da801ab5SAlexandre Belloni regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset), 975da801ab5SAlexandre Belloni BIT(offset % 32)); 976ce8dc094SAlexandre Belloni } 977ce8dc094SAlexandre Belloni 978ce8dc094SAlexandre Belloni static int ocelot_gpio_get_direction(struct gpio_chip *chip, 979ce8dc094SAlexandre Belloni unsigned int offset) 980ce8dc094SAlexandre Belloni { 981ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = gpiochip_get_data(chip); 982ce8dc094SAlexandre Belloni unsigned int val; 983ce8dc094SAlexandre Belloni 984da801ab5SAlexandre Belloni regmap_read(info->map, REG(OCELOT_GPIO_OE, info, offset), &val); 985ce8dc094SAlexandre Belloni 9863c827873SMatti Vaittinen if (val & BIT(offset % 32)) 9873c827873SMatti Vaittinen return GPIO_LINE_DIRECTION_OUT; 9883c827873SMatti Vaittinen 9893c827873SMatti Vaittinen return GPIO_LINE_DIRECTION_IN; 990ce8dc094SAlexandre Belloni } 991ce8dc094SAlexandre Belloni 992ce8dc094SAlexandre Belloni static int ocelot_gpio_direction_input(struct gpio_chip *chip, 993ce8dc094SAlexandre Belloni unsigned int offset) 994ce8dc094SAlexandre Belloni { 995ce8dc094SAlexandre Belloni return pinctrl_gpio_direction_input(chip->base + offset); 996ce8dc094SAlexandre Belloni } 997ce8dc094SAlexandre Belloni 998ce8dc094SAlexandre Belloni static int ocelot_gpio_direction_output(struct gpio_chip *chip, 999ce8dc094SAlexandre Belloni unsigned int offset, int value) 1000ce8dc094SAlexandre Belloni { 1001ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = gpiochip_get_data(chip); 1002da801ab5SAlexandre Belloni unsigned int pin = BIT(offset % 32); 1003ce8dc094SAlexandre Belloni 1004ce8dc094SAlexandre Belloni if (value) 1005da801ab5SAlexandre Belloni regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset), 1006da801ab5SAlexandre Belloni pin); 1007ce8dc094SAlexandre Belloni else 1008da801ab5SAlexandre Belloni regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset), 1009da801ab5SAlexandre Belloni pin); 1010ce8dc094SAlexandre Belloni 1011ce8dc094SAlexandre Belloni return pinctrl_gpio_direction_output(chip->base + offset); 1012ce8dc094SAlexandre Belloni } 1013ce8dc094SAlexandre Belloni 1014ce8dc094SAlexandre Belloni static const struct gpio_chip ocelot_gpiolib_chip = { 1015ce8dc094SAlexandre Belloni .request = gpiochip_generic_request, 1016ce8dc094SAlexandre Belloni .free = gpiochip_generic_free, 1017ce8dc094SAlexandre Belloni .set = ocelot_gpio_set, 1018ce8dc094SAlexandre Belloni .get = ocelot_gpio_get, 1019ce8dc094SAlexandre Belloni .get_direction = ocelot_gpio_get_direction, 1020ce8dc094SAlexandre Belloni .direction_input = ocelot_gpio_direction_input, 1021ce8dc094SAlexandre Belloni .direction_output = ocelot_gpio_direction_output, 1022ce8dc094SAlexandre Belloni .owner = THIS_MODULE, 1023ce8dc094SAlexandre Belloni }; 1024ce8dc094SAlexandre Belloni 1025be36abb7SQuentin Schulz static void ocelot_irq_mask(struct irq_data *data) 1026be36abb7SQuentin Schulz { 1027be36abb7SQuentin Schulz struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 1028be36abb7SQuentin Schulz struct ocelot_pinctrl *info = gpiochip_get_data(chip); 1029be36abb7SQuentin Schulz unsigned int gpio = irqd_to_hwirq(data); 1030be36abb7SQuentin Schulz 1031da801ab5SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio), 1032da801ab5SAlexandre Belloni BIT(gpio % 32), 0); 1033be36abb7SQuentin Schulz } 1034be36abb7SQuentin Schulz 1035be36abb7SQuentin Schulz static void ocelot_irq_unmask(struct irq_data *data) 1036be36abb7SQuentin Schulz { 1037be36abb7SQuentin Schulz struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 1038be36abb7SQuentin Schulz struct ocelot_pinctrl *info = gpiochip_get_data(chip); 1039be36abb7SQuentin Schulz unsigned int gpio = irqd_to_hwirq(data); 1040be36abb7SQuentin Schulz 1041da801ab5SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio), 1042da801ab5SAlexandre Belloni BIT(gpio % 32), BIT(gpio % 32)); 1043be36abb7SQuentin Schulz } 1044be36abb7SQuentin Schulz 1045be36abb7SQuentin Schulz static void ocelot_irq_ack(struct irq_data *data) 1046be36abb7SQuentin Schulz { 1047be36abb7SQuentin Schulz struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 1048be36abb7SQuentin Schulz struct ocelot_pinctrl *info = gpiochip_get_data(chip); 1049be36abb7SQuentin Schulz unsigned int gpio = irqd_to_hwirq(data); 1050be36abb7SQuentin Schulz 1051da801ab5SAlexandre Belloni regmap_write_bits(info->map, REG(OCELOT_GPIO_INTR, info, gpio), 1052da801ab5SAlexandre Belloni BIT(gpio % 32), BIT(gpio % 32)); 1053be36abb7SQuentin Schulz } 1054be36abb7SQuentin Schulz 1055be36abb7SQuentin Schulz static int ocelot_irq_set_type(struct irq_data *data, unsigned int type); 1056be36abb7SQuentin Schulz 1057be36abb7SQuentin Schulz static struct irq_chip ocelot_eoi_irqchip = { 1058be36abb7SQuentin Schulz .name = "gpio", 1059be36abb7SQuentin Schulz .irq_mask = ocelot_irq_mask, 1060be36abb7SQuentin Schulz .irq_eoi = ocelot_irq_ack, 1061be36abb7SQuentin Schulz .irq_unmask = ocelot_irq_unmask, 1062be36abb7SQuentin Schulz .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED, 1063be36abb7SQuentin Schulz .irq_set_type = ocelot_irq_set_type, 1064be36abb7SQuentin Schulz }; 1065be36abb7SQuentin Schulz 1066be36abb7SQuentin Schulz static struct irq_chip ocelot_irqchip = { 1067be36abb7SQuentin Schulz .name = "gpio", 1068be36abb7SQuentin Schulz .irq_mask = ocelot_irq_mask, 1069be36abb7SQuentin Schulz .irq_ack = ocelot_irq_ack, 1070be36abb7SQuentin Schulz .irq_unmask = ocelot_irq_unmask, 1071be36abb7SQuentin Schulz .irq_set_type = ocelot_irq_set_type, 1072be36abb7SQuentin Schulz }; 1073be36abb7SQuentin Schulz 1074be36abb7SQuentin Schulz static int ocelot_irq_set_type(struct irq_data *data, unsigned int type) 1075be36abb7SQuentin Schulz { 1076be36abb7SQuentin Schulz type &= IRQ_TYPE_SENSE_MASK; 1077be36abb7SQuentin Schulz 1078be36abb7SQuentin Schulz if (!(type & (IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_HIGH))) 1079be36abb7SQuentin Schulz return -EINVAL; 1080be36abb7SQuentin Schulz 1081be36abb7SQuentin Schulz if (type & IRQ_TYPE_LEVEL_HIGH) 1082be36abb7SQuentin Schulz irq_set_chip_handler_name_locked(data, &ocelot_eoi_irqchip, 1083be36abb7SQuentin Schulz handle_fasteoi_irq, NULL); 1084be36abb7SQuentin Schulz if (type & IRQ_TYPE_EDGE_BOTH) 1085be36abb7SQuentin Schulz irq_set_chip_handler_name_locked(data, &ocelot_irqchip, 1086be36abb7SQuentin Schulz handle_edge_irq, NULL); 1087be36abb7SQuentin Schulz 1088be36abb7SQuentin Schulz return 0; 1089be36abb7SQuentin Schulz } 1090be36abb7SQuentin Schulz 1091be36abb7SQuentin Schulz static void ocelot_irq_handler(struct irq_desc *desc) 1092be36abb7SQuentin Schulz { 1093be36abb7SQuentin Schulz struct irq_chip *parent_chip = irq_desc_get_chip(desc); 1094be36abb7SQuentin Schulz struct gpio_chip *chip = irq_desc_get_handler_data(desc); 1095be36abb7SQuentin Schulz struct ocelot_pinctrl *info = gpiochip_get_data(chip); 10960b47afc6SLars Povlsen unsigned int id_reg = OCELOT_GPIO_INTR_IDENT * info->stride; 1097da801ab5SAlexandre Belloni unsigned int reg = 0, irq, i; 1098be36abb7SQuentin Schulz unsigned long irqs; 1099be36abb7SQuentin Schulz 1100da801ab5SAlexandre Belloni for (i = 0; i < info->stride; i++) { 11010b47afc6SLars Povlsen regmap_read(info->map, id_reg + 4 * i, ®); 1102be36abb7SQuentin Schulz if (!reg) 1103da801ab5SAlexandre Belloni continue; 1104be36abb7SQuentin Schulz 1105be36abb7SQuentin Schulz chained_irq_enter(parent_chip, desc); 1106be36abb7SQuentin Schulz 1107be36abb7SQuentin Schulz irqs = reg; 1108be36abb7SQuentin Schulz 1109da801ab5SAlexandre Belloni for_each_set_bit(irq, &irqs, 1110da801ab5SAlexandre Belloni min(32U, info->desc->npins - 32 * i)) 1111da801ab5SAlexandre Belloni generic_handle_irq(irq_linear_revmap(chip->irq.domain, 1112da801ab5SAlexandre Belloni irq + 32 * i)); 1113be36abb7SQuentin Schulz 1114be36abb7SQuentin Schulz chained_irq_exit(parent_chip, desc); 1115be36abb7SQuentin Schulz } 1116da801ab5SAlexandre Belloni } 1117be36abb7SQuentin Schulz 1118ce8dc094SAlexandre Belloni static int ocelot_gpiochip_register(struct platform_device *pdev, 1119ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info) 1120ce8dc094SAlexandre Belloni { 1121ce8dc094SAlexandre Belloni struct gpio_chip *gc; 1122d874becaSLinus Walleij struct gpio_irq_chip *girq; 1123be36abb7SQuentin Schulz int ret, irq; 1124ce8dc094SAlexandre Belloni 1125ce8dc094SAlexandre Belloni info->gpio_chip = ocelot_gpiolib_chip; 1126ce8dc094SAlexandre Belloni 1127ce8dc094SAlexandre Belloni gc = &info->gpio_chip; 1128da801ab5SAlexandre Belloni gc->ngpio = info->desc->npins; 1129ce8dc094SAlexandre Belloni gc->parent = &pdev->dev; 1130ce8dc094SAlexandre Belloni gc->base = 0; 1131ce8dc094SAlexandre Belloni gc->of_node = info->dev->of_node; 1132ce8dc094SAlexandre Belloni gc->label = "ocelot-gpio"; 1133ce8dc094SAlexandre Belloni 1134550713e3SLars Povlsen irq = irq_of_parse_and_map(gc->of_node, 0); 1135550713e3SLars Povlsen if (irq) { 1136d874becaSLinus Walleij girq = &gc->irq; 1137d874becaSLinus Walleij girq->chip = &ocelot_irqchip; 1138d874becaSLinus Walleij girq->parent_handler = ocelot_irq_handler; 1139d874becaSLinus Walleij girq->num_parents = 1; 1140550713e3SLars Povlsen girq->parents = devm_kcalloc(&pdev->dev, 1, 1141550713e3SLars Povlsen sizeof(*girq->parents), 1142d874becaSLinus Walleij GFP_KERNEL); 1143d874becaSLinus Walleij if (!girq->parents) 1144d874becaSLinus Walleij return -ENOMEM; 1145d874becaSLinus Walleij girq->parents[0] = irq; 1146d874becaSLinus Walleij girq->default_type = IRQ_TYPE_NONE; 1147d874becaSLinus Walleij girq->handler = handle_edge_irq; 1148550713e3SLars Povlsen } 1149d874becaSLinus Walleij 1150d874becaSLinus Walleij ret = devm_gpiochip_add_data(&pdev->dev, gc, info); 1151be36abb7SQuentin Schulz if (ret) 1152be36abb7SQuentin Schulz return ret; 1153be36abb7SQuentin Schulz 1154ce8dc094SAlexandre Belloni return 0; 1155ce8dc094SAlexandre Belloni } 1156ce8dc094SAlexandre Belloni 1157ce8dc094SAlexandre Belloni static const struct of_device_id ocelot_pinctrl_of_match[] = { 1158da801ab5SAlexandre Belloni { .compatible = "mscc,ocelot-pinctrl", .data = &ocelot_desc }, 1159da801ab5SAlexandre Belloni { .compatible = "mscc,jaguar2-pinctrl", .data = &jaguar2_desc }, 1160f8a74760SLars Povlsen { .compatible = "microchip,sparx5-pinctrl", .data = &sparx5_desc }, 1161ce8dc094SAlexandre Belloni {}, 1162ce8dc094SAlexandre Belloni }; 1163ce8dc094SAlexandre Belloni 1164ce3e7f0eSColin Ian King static int ocelot_pinctrl_probe(struct platform_device *pdev) 1165ce8dc094SAlexandre Belloni { 1166ce8dc094SAlexandre Belloni struct device *dev = &pdev->dev; 1167ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info; 1168ce8dc094SAlexandre Belloni void __iomem *base; 1169f8a74760SLars Povlsen struct resource *res; 1170ce8dc094SAlexandre Belloni int ret; 1171da801ab5SAlexandre Belloni struct regmap_config regmap_config = { 1172da801ab5SAlexandre Belloni .reg_bits = 32, 1173da801ab5SAlexandre Belloni .val_bits = 32, 1174da801ab5SAlexandre Belloni .reg_stride = 4, 1175da801ab5SAlexandre Belloni }; 1176ce8dc094SAlexandre Belloni 1177ce8dc094SAlexandre Belloni info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); 1178ce8dc094SAlexandre Belloni if (!info) 1179ce8dc094SAlexandre Belloni return -ENOMEM; 1180ce8dc094SAlexandre Belloni 1181da801ab5SAlexandre Belloni info->desc = (struct pinctrl_desc *)device_get_match_data(dev); 1182da801ab5SAlexandre Belloni 1183ce8dc094SAlexandre Belloni base = devm_ioremap_resource(dev, 1184ce8dc094SAlexandre Belloni platform_get_resource(pdev, IORESOURCE_MEM, 0)); 1185ce8dc094SAlexandre Belloni if (IS_ERR(base)) { 1186ce8dc094SAlexandre Belloni dev_err(dev, "Failed to ioremap registers\n"); 1187ce8dc094SAlexandre Belloni return PTR_ERR(base); 1188ce8dc094SAlexandre Belloni } 1189ce8dc094SAlexandre Belloni 1190da801ab5SAlexandre Belloni info->stride = 1 + (info->desc->npins - 1) / 32; 1191f8a74760SLars Povlsen 1192da801ab5SAlexandre Belloni regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4; 1193da801ab5SAlexandre Belloni 1194da801ab5SAlexandre Belloni info->map = devm_regmap_init_mmio(dev, base, ®map_config); 1195ce8dc094SAlexandre Belloni if (IS_ERR(info->map)) { 1196ce8dc094SAlexandre Belloni dev_err(dev, "Failed to create regmap\n"); 1197ce8dc094SAlexandre Belloni return PTR_ERR(info->map); 1198ce8dc094SAlexandre Belloni } 1199ce8dc094SAlexandre Belloni dev_set_drvdata(dev, info->map); 1200ce8dc094SAlexandre Belloni info->dev = dev; 1201ce8dc094SAlexandre Belloni 1202f8a74760SLars Povlsen /* Pinconf registers */ 1203f8a74760SLars Povlsen if (info->desc->confops) { 1204f8a74760SLars Povlsen res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1205f8a74760SLars Povlsen base = devm_ioremap_resource(dev, res); 1206f8a74760SLars Povlsen if (IS_ERR(base)) 1207f8a74760SLars Povlsen dev_dbg(dev, "Failed to ioremap config registers (no extended pinconf)\n"); 1208f8a74760SLars Povlsen else 1209f8a74760SLars Povlsen info->pincfg = base; 1210f8a74760SLars Povlsen } 1211f8a74760SLars Povlsen 1212ce8dc094SAlexandre Belloni ret = ocelot_pinctrl_register(pdev, info); 1213ce8dc094SAlexandre Belloni if (ret) 1214ce8dc094SAlexandre Belloni return ret; 1215ce8dc094SAlexandre Belloni 1216ce8dc094SAlexandre Belloni ret = ocelot_gpiochip_register(pdev, info); 1217ce8dc094SAlexandre Belloni if (ret) 1218ce8dc094SAlexandre Belloni return ret; 1219ce8dc094SAlexandre Belloni 1220f8a74760SLars Povlsen dev_info(dev, "driver registered\n"); 1221f8a74760SLars Povlsen 1222ce8dc094SAlexandre Belloni return 0; 1223ce8dc094SAlexandre Belloni } 1224ce8dc094SAlexandre Belloni 1225ce8dc094SAlexandre Belloni static struct platform_driver ocelot_pinctrl_driver = { 1226ce8dc094SAlexandre Belloni .driver = { 1227ce8dc094SAlexandre Belloni .name = "pinctrl-ocelot", 1228ce8dc094SAlexandre Belloni .of_match_table = of_match_ptr(ocelot_pinctrl_of_match), 1229ce8dc094SAlexandre Belloni .suppress_bind_attrs = true, 1230ce8dc094SAlexandre Belloni }, 1231ce8dc094SAlexandre Belloni .probe = ocelot_pinctrl_probe, 1232ce8dc094SAlexandre Belloni }; 1233ce8dc094SAlexandre Belloni builtin_platform_driver(ocelot_pinctrl_driver); 1234