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 28ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OUT_SET 0x0 29ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OUT_CLR 0x4 30ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OUT 0x8 31ce8dc094SAlexandre Belloni #define OCELOT_GPIO_IN 0xc 32ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OE 0x10 33ce8dc094SAlexandre Belloni #define OCELOT_GPIO_INTR 0x14 34ce8dc094SAlexandre Belloni #define OCELOT_GPIO_INTR_ENA 0x18 35ce8dc094SAlexandre Belloni #define OCELOT_GPIO_INTR_IDENT 0x1c 36ce8dc094SAlexandre Belloni #define OCELOT_GPIO_ALT0 0x20 37ce8dc094SAlexandre Belloni #define OCELOT_GPIO_ALT1 0x24 38ce8dc094SAlexandre Belloni #define OCELOT_GPIO_SD_MAP 0x28 39ce8dc094SAlexandre Belloni 40ce8dc094SAlexandre Belloni #define OCELOT_FUNC_PER_PIN 4 41ce8dc094SAlexandre Belloni 42ce8dc094SAlexandre Belloni enum { 43ce8dc094SAlexandre Belloni FUNC_NONE, 44ce8dc094SAlexandre Belloni FUNC_GPIO, 45ce8dc094SAlexandre Belloni FUNC_IRQ0_IN, 46ce8dc094SAlexandre Belloni FUNC_IRQ0_OUT, 47ce8dc094SAlexandre Belloni FUNC_IRQ1_IN, 48ce8dc094SAlexandre Belloni FUNC_IRQ1_OUT, 49ce8dc094SAlexandre Belloni FUNC_MIIM1, 50da801ab5SAlexandre Belloni FUNC_MIIM2, 51ce8dc094SAlexandre Belloni FUNC_PCI_WAKE, 52ce8dc094SAlexandre Belloni FUNC_PTP0, 53ce8dc094SAlexandre Belloni FUNC_PTP1, 54ce8dc094SAlexandre Belloni FUNC_PTP2, 55ce8dc094SAlexandre Belloni FUNC_PTP3, 56ce8dc094SAlexandre Belloni FUNC_PWM, 57ce8dc094SAlexandre Belloni FUNC_RECO_CLK0, 58ce8dc094SAlexandre Belloni FUNC_RECO_CLK1, 59ce8dc094SAlexandre Belloni FUNC_SFP0, 60ce8dc094SAlexandre Belloni FUNC_SFP1, 61ce8dc094SAlexandre Belloni FUNC_SFP2, 62ce8dc094SAlexandre Belloni FUNC_SFP3, 63ce8dc094SAlexandre Belloni FUNC_SFP4, 64ce8dc094SAlexandre Belloni FUNC_SFP5, 65da801ab5SAlexandre Belloni FUNC_SFP6, 66da801ab5SAlexandre Belloni FUNC_SFP7, 67da801ab5SAlexandre Belloni FUNC_SFP8, 68da801ab5SAlexandre Belloni FUNC_SFP9, 69da801ab5SAlexandre Belloni FUNC_SFP10, 70da801ab5SAlexandre Belloni FUNC_SFP11, 71da801ab5SAlexandre Belloni FUNC_SFP12, 72da801ab5SAlexandre Belloni FUNC_SFP13, 73da801ab5SAlexandre Belloni FUNC_SFP14, 74da801ab5SAlexandre Belloni FUNC_SFP15, 75ce8dc094SAlexandre Belloni FUNC_SG0, 76da801ab5SAlexandre Belloni FUNC_SG1, 77da801ab5SAlexandre Belloni FUNC_SG2, 78ce8dc094SAlexandre Belloni FUNC_SI, 79ce8dc094SAlexandre Belloni FUNC_TACHO, 80ce8dc094SAlexandre Belloni FUNC_TWI, 81da801ab5SAlexandre Belloni FUNC_TWI2, 82ce8dc094SAlexandre Belloni FUNC_TWI_SCL_M, 83ce8dc094SAlexandre Belloni FUNC_UART, 84ce8dc094SAlexandre Belloni FUNC_UART2, 85ce8dc094SAlexandre Belloni FUNC_MAX 86ce8dc094SAlexandre Belloni }; 87ce8dc094SAlexandre Belloni 88ce8dc094SAlexandre Belloni static const char *const ocelot_function_names[] = { 89ce8dc094SAlexandre Belloni [FUNC_NONE] = "none", 90ce8dc094SAlexandre Belloni [FUNC_GPIO] = "gpio", 91ce8dc094SAlexandre Belloni [FUNC_IRQ0_IN] = "irq0_in", 92ce8dc094SAlexandre Belloni [FUNC_IRQ0_OUT] = "irq0_out", 93ce8dc094SAlexandre Belloni [FUNC_IRQ1_IN] = "irq1_in", 94ce8dc094SAlexandre Belloni [FUNC_IRQ1_OUT] = "irq1_out", 95ce8dc094SAlexandre Belloni [FUNC_MIIM1] = "miim1", 96da801ab5SAlexandre Belloni [FUNC_MIIM2] = "miim2", 97ce8dc094SAlexandre Belloni [FUNC_PCI_WAKE] = "pci_wake", 98ce8dc094SAlexandre Belloni [FUNC_PTP0] = "ptp0", 99ce8dc094SAlexandre Belloni [FUNC_PTP1] = "ptp1", 100ce8dc094SAlexandre Belloni [FUNC_PTP2] = "ptp2", 101ce8dc094SAlexandre Belloni [FUNC_PTP3] = "ptp3", 102ce8dc094SAlexandre Belloni [FUNC_PWM] = "pwm", 103ce8dc094SAlexandre Belloni [FUNC_RECO_CLK0] = "reco_clk0", 104ce8dc094SAlexandre Belloni [FUNC_RECO_CLK1] = "reco_clk1", 105ce8dc094SAlexandre Belloni [FUNC_SFP0] = "sfp0", 106ce8dc094SAlexandre Belloni [FUNC_SFP1] = "sfp1", 107ce8dc094SAlexandre Belloni [FUNC_SFP2] = "sfp2", 108ce8dc094SAlexandre Belloni [FUNC_SFP3] = "sfp3", 109ce8dc094SAlexandre Belloni [FUNC_SFP4] = "sfp4", 110ce8dc094SAlexandre Belloni [FUNC_SFP5] = "sfp5", 111da801ab5SAlexandre Belloni [FUNC_SFP6] = "sfp6", 112da801ab5SAlexandre Belloni [FUNC_SFP7] = "sfp7", 113da801ab5SAlexandre Belloni [FUNC_SFP8] = "sfp8", 114da801ab5SAlexandre Belloni [FUNC_SFP9] = "sfp9", 115da801ab5SAlexandre Belloni [FUNC_SFP10] = "sfp10", 116da801ab5SAlexandre Belloni [FUNC_SFP11] = "sfp11", 117da801ab5SAlexandre Belloni [FUNC_SFP12] = "sfp12", 118da801ab5SAlexandre Belloni [FUNC_SFP13] = "sfp13", 119da801ab5SAlexandre Belloni [FUNC_SFP14] = "sfp14", 120da801ab5SAlexandre Belloni [FUNC_SFP15] = "sfp15", 121ce8dc094SAlexandre Belloni [FUNC_SG0] = "sg0", 122da801ab5SAlexandre Belloni [FUNC_SG1] = "sg1", 123da801ab5SAlexandre Belloni [FUNC_SG2] = "sg2", 124ce8dc094SAlexandre Belloni [FUNC_SI] = "si", 125ce8dc094SAlexandre Belloni [FUNC_TACHO] = "tacho", 126ce8dc094SAlexandre Belloni [FUNC_TWI] = "twi", 127da801ab5SAlexandre Belloni [FUNC_TWI2] = "twi2", 128ce8dc094SAlexandre Belloni [FUNC_TWI_SCL_M] = "twi_scl_m", 129ce8dc094SAlexandre Belloni [FUNC_UART] = "uart", 130ce8dc094SAlexandre Belloni [FUNC_UART2] = "uart2", 131ce8dc094SAlexandre Belloni }; 132ce8dc094SAlexandre Belloni 133ce8dc094SAlexandre Belloni struct ocelot_pmx_func { 134ce8dc094SAlexandre Belloni const char **groups; 135ce8dc094SAlexandre Belloni unsigned int ngroups; 136ce8dc094SAlexandre Belloni }; 137ce8dc094SAlexandre Belloni 138ce8dc094SAlexandre Belloni struct ocelot_pin_caps { 139ce8dc094SAlexandre Belloni unsigned int pin; 140ce8dc094SAlexandre Belloni unsigned char functions[OCELOT_FUNC_PER_PIN]; 141ce8dc094SAlexandre Belloni }; 142ce8dc094SAlexandre Belloni 143ce8dc094SAlexandre Belloni struct ocelot_pinctrl { 144ce8dc094SAlexandre Belloni struct device *dev; 145ce8dc094SAlexandre Belloni struct pinctrl_dev *pctl; 146ce8dc094SAlexandre Belloni struct gpio_chip gpio_chip; 147ce8dc094SAlexandre Belloni struct regmap *map; 148da801ab5SAlexandre Belloni struct pinctrl_desc *desc; 149ce8dc094SAlexandre Belloni struct ocelot_pmx_func func[FUNC_MAX]; 150da801ab5SAlexandre Belloni u8 stride; 151ce8dc094SAlexandre Belloni }; 152ce8dc094SAlexandre Belloni 153ce8dc094SAlexandre Belloni #define OCELOT_P(p, f0, f1, f2) \ 154ce8dc094SAlexandre Belloni static struct ocelot_pin_caps ocelot_pin_##p = { \ 155ce8dc094SAlexandre Belloni .pin = p, \ 156ce8dc094SAlexandre Belloni .functions = { \ 157ce8dc094SAlexandre Belloni FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_##f2, \ 158ce8dc094SAlexandre Belloni }, \ 159ce8dc094SAlexandre Belloni } 160ce8dc094SAlexandre Belloni 161ce8dc094SAlexandre Belloni OCELOT_P(0, SG0, NONE, NONE); 162ce8dc094SAlexandre Belloni OCELOT_P(1, SG0, NONE, NONE); 163ce8dc094SAlexandre Belloni OCELOT_P(2, SG0, NONE, NONE); 164ce8dc094SAlexandre Belloni OCELOT_P(3, SG0, NONE, NONE); 16517f79084SAlexandre Belloni OCELOT_P(4, IRQ0_IN, IRQ0_OUT, TWI_SCL_M); 166ce8dc094SAlexandre Belloni OCELOT_P(5, IRQ1_IN, IRQ1_OUT, PCI_WAKE); 167ce8dc094SAlexandre Belloni OCELOT_P(6, UART, TWI_SCL_M, NONE); 168ce8dc094SAlexandre Belloni OCELOT_P(7, UART, TWI_SCL_M, NONE); 169ce8dc094SAlexandre Belloni OCELOT_P(8, SI, TWI_SCL_M, IRQ0_OUT); 170ce8dc094SAlexandre Belloni OCELOT_P(9, SI, TWI_SCL_M, IRQ1_OUT); 171ce8dc094SAlexandre Belloni OCELOT_P(10, PTP2, TWI_SCL_M, SFP0); 172ce8dc094SAlexandre Belloni OCELOT_P(11, PTP3, TWI_SCL_M, SFP1); 173ce8dc094SAlexandre Belloni OCELOT_P(12, UART2, TWI_SCL_M, SFP2); 174ce8dc094SAlexandre Belloni OCELOT_P(13, UART2, TWI_SCL_M, SFP3); 175ce8dc094SAlexandre Belloni OCELOT_P(14, MIIM1, TWI_SCL_M, SFP4); 176ce8dc094SAlexandre Belloni OCELOT_P(15, MIIM1, TWI_SCL_M, SFP5); 177ce8dc094SAlexandre Belloni OCELOT_P(16, TWI, NONE, SI); 178ce8dc094SAlexandre Belloni OCELOT_P(17, TWI, TWI_SCL_M, SI); 179ce8dc094SAlexandre Belloni OCELOT_P(18, PTP0, TWI_SCL_M, NONE); 180ce8dc094SAlexandre Belloni OCELOT_P(19, PTP1, TWI_SCL_M, NONE); 181ce8dc094SAlexandre Belloni OCELOT_P(20, RECO_CLK0, TACHO, NONE); 182ce8dc094SAlexandre Belloni OCELOT_P(21, RECO_CLK1, PWM, NONE); 183ce8dc094SAlexandre Belloni 184ce8dc094SAlexandre Belloni #define OCELOT_PIN(n) { \ 185ce8dc094SAlexandre Belloni .number = n, \ 186ce8dc094SAlexandre Belloni .name = "GPIO_"#n, \ 187ce8dc094SAlexandre Belloni .drv_data = &ocelot_pin_##n \ 188ce8dc094SAlexandre Belloni } 189ce8dc094SAlexandre Belloni 190ce8dc094SAlexandre Belloni static const struct pinctrl_pin_desc ocelot_pins[] = { 191ce8dc094SAlexandre Belloni OCELOT_PIN(0), 192ce8dc094SAlexandre Belloni OCELOT_PIN(1), 193ce8dc094SAlexandre Belloni OCELOT_PIN(2), 194ce8dc094SAlexandre Belloni OCELOT_PIN(3), 195ce8dc094SAlexandre Belloni OCELOT_PIN(4), 196ce8dc094SAlexandre Belloni OCELOT_PIN(5), 197ce8dc094SAlexandre Belloni OCELOT_PIN(6), 198ce8dc094SAlexandre Belloni OCELOT_PIN(7), 199ce8dc094SAlexandre Belloni OCELOT_PIN(8), 200ce8dc094SAlexandre Belloni OCELOT_PIN(9), 201ce8dc094SAlexandre Belloni OCELOT_PIN(10), 202ce8dc094SAlexandre Belloni OCELOT_PIN(11), 203ce8dc094SAlexandre Belloni OCELOT_PIN(12), 204ce8dc094SAlexandre Belloni OCELOT_PIN(13), 205ce8dc094SAlexandre Belloni OCELOT_PIN(14), 206ce8dc094SAlexandre Belloni OCELOT_PIN(15), 207ce8dc094SAlexandre Belloni OCELOT_PIN(16), 208ce8dc094SAlexandre Belloni OCELOT_PIN(17), 209ce8dc094SAlexandre Belloni OCELOT_PIN(18), 210ce8dc094SAlexandre Belloni OCELOT_PIN(19), 211ce8dc094SAlexandre Belloni OCELOT_PIN(20), 212ce8dc094SAlexandre Belloni OCELOT_PIN(21), 213ce8dc094SAlexandre Belloni }; 214ce8dc094SAlexandre Belloni 215da801ab5SAlexandre Belloni #define JAGUAR2_P(p, f0, f1) \ 216da801ab5SAlexandre Belloni static struct ocelot_pin_caps jaguar2_pin_##p = { \ 217da801ab5SAlexandre Belloni .pin = p, \ 218da801ab5SAlexandre Belloni .functions = { \ 219da801ab5SAlexandre Belloni FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_NONE \ 220da801ab5SAlexandre Belloni }, \ 221da801ab5SAlexandre Belloni } 222da801ab5SAlexandre Belloni 223da801ab5SAlexandre Belloni JAGUAR2_P(0, SG0, NONE); 224da801ab5SAlexandre Belloni JAGUAR2_P(1, SG0, NONE); 225da801ab5SAlexandre Belloni JAGUAR2_P(2, SG0, NONE); 226da801ab5SAlexandre Belloni JAGUAR2_P(3, SG0, NONE); 227da801ab5SAlexandre Belloni JAGUAR2_P(4, SG1, NONE); 228da801ab5SAlexandre Belloni JAGUAR2_P(5, SG1, NONE); 229da801ab5SAlexandre Belloni JAGUAR2_P(6, IRQ0_IN, IRQ0_OUT); 230da801ab5SAlexandre Belloni JAGUAR2_P(7, IRQ1_IN, IRQ1_OUT); 231da801ab5SAlexandre Belloni JAGUAR2_P(8, PTP0, NONE); 232da801ab5SAlexandre Belloni JAGUAR2_P(9, PTP1, NONE); 233da801ab5SAlexandre Belloni JAGUAR2_P(10, UART, NONE); 234da801ab5SAlexandre Belloni JAGUAR2_P(11, UART, NONE); 235da801ab5SAlexandre Belloni JAGUAR2_P(12, SG1, NONE); 236da801ab5SAlexandre Belloni JAGUAR2_P(13, SG1, NONE); 237da801ab5SAlexandre Belloni JAGUAR2_P(14, TWI, TWI_SCL_M); 238da801ab5SAlexandre Belloni JAGUAR2_P(15, TWI, NONE); 239da801ab5SAlexandre Belloni JAGUAR2_P(16, SI, TWI_SCL_M); 240da801ab5SAlexandre Belloni JAGUAR2_P(17, SI, TWI_SCL_M); 241da801ab5SAlexandre Belloni JAGUAR2_P(18, SI, TWI_SCL_M); 242da801ab5SAlexandre Belloni JAGUAR2_P(19, PCI_WAKE, NONE); 243da801ab5SAlexandre Belloni JAGUAR2_P(20, IRQ0_OUT, TWI_SCL_M); 244da801ab5SAlexandre Belloni JAGUAR2_P(21, IRQ1_OUT, TWI_SCL_M); 245da801ab5SAlexandre Belloni JAGUAR2_P(22, TACHO, NONE); 246da801ab5SAlexandre Belloni JAGUAR2_P(23, PWM, NONE); 247da801ab5SAlexandre Belloni JAGUAR2_P(24, UART2, NONE); 248da801ab5SAlexandre Belloni JAGUAR2_P(25, UART2, SI); 249da801ab5SAlexandre Belloni JAGUAR2_P(26, PTP2, SI); 250da801ab5SAlexandre Belloni JAGUAR2_P(27, PTP3, SI); 251da801ab5SAlexandre Belloni JAGUAR2_P(28, TWI2, SI); 252da801ab5SAlexandre Belloni JAGUAR2_P(29, TWI2, SI); 253da801ab5SAlexandre Belloni JAGUAR2_P(30, SG2, SI); 254da801ab5SAlexandre Belloni JAGUAR2_P(31, SG2, SI); 255da801ab5SAlexandre Belloni JAGUAR2_P(32, SG2, SI); 256da801ab5SAlexandre Belloni JAGUAR2_P(33, SG2, SI); 257da801ab5SAlexandre Belloni JAGUAR2_P(34, NONE, TWI_SCL_M); 258da801ab5SAlexandre Belloni JAGUAR2_P(35, NONE, TWI_SCL_M); 259da801ab5SAlexandre Belloni JAGUAR2_P(36, NONE, TWI_SCL_M); 260da801ab5SAlexandre Belloni JAGUAR2_P(37, NONE, TWI_SCL_M); 261da801ab5SAlexandre Belloni JAGUAR2_P(38, NONE, TWI_SCL_M); 262da801ab5SAlexandre Belloni JAGUAR2_P(39, NONE, TWI_SCL_M); 263da801ab5SAlexandre Belloni JAGUAR2_P(40, NONE, TWI_SCL_M); 264da801ab5SAlexandre Belloni JAGUAR2_P(41, NONE, TWI_SCL_M); 265da801ab5SAlexandre Belloni JAGUAR2_P(42, NONE, TWI_SCL_M); 266da801ab5SAlexandre Belloni JAGUAR2_P(43, NONE, TWI_SCL_M); 267da801ab5SAlexandre Belloni JAGUAR2_P(44, NONE, SFP8); 268da801ab5SAlexandre Belloni JAGUAR2_P(45, NONE, SFP9); 269da801ab5SAlexandre Belloni JAGUAR2_P(46, NONE, SFP10); 270da801ab5SAlexandre Belloni JAGUAR2_P(47, NONE, SFP11); 271da801ab5SAlexandre Belloni JAGUAR2_P(48, SFP0, NONE); 272da801ab5SAlexandre Belloni JAGUAR2_P(49, SFP1, SI); 273da801ab5SAlexandre Belloni JAGUAR2_P(50, SFP2, SI); 274da801ab5SAlexandre Belloni JAGUAR2_P(51, SFP3, SI); 275da801ab5SAlexandre Belloni JAGUAR2_P(52, SFP4, NONE); 276da801ab5SAlexandre Belloni JAGUAR2_P(53, SFP5, NONE); 277da801ab5SAlexandre Belloni JAGUAR2_P(54, SFP6, NONE); 278da801ab5SAlexandre Belloni JAGUAR2_P(55, SFP7, NONE); 279da801ab5SAlexandre Belloni JAGUAR2_P(56, MIIM1, SFP12); 280da801ab5SAlexandre Belloni JAGUAR2_P(57, MIIM1, SFP13); 281da801ab5SAlexandre Belloni JAGUAR2_P(58, MIIM2, SFP14); 282da801ab5SAlexandre Belloni JAGUAR2_P(59, MIIM2, SFP15); 283da801ab5SAlexandre Belloni JAGUAR2_P(60, NONE, NONE); 284da801ab5SAlexandre Belloni JAGUAR2_P(61, NONE, NONE); 285da801ab5SAlexandre Belloni JAGUAR2_P(62, NONE, NONE); 286da801ab5SAlexandre Belloni JAGUAR2_P(63, NONE, NONE); 287da801ab5SAlexandre Belloni 288da801ab5SAlexandre Belloni #define JAGUAR2_PIN(n) { \ 289da801ab5SAlexandre Belloni .number = n, \ 290da801ab5SAlexandre Belloni .name = "GPIO_"#n, \ 291da801ab5SAlexandre Belloni .drv_data = &jaguar2_pin_##n \ 292da801ab5SAlexandre Belloni } 293da801ab5SAlexandre Belloni 294da801ab5SAlexandre Belloni static const struct pinctrl_pin_desc jaguar2_pins[] = { 295da801ab5SAlexandre Belloni JAGUAR2_PIN(0), 296da801ab5SAlexandre Belloni JAGUAR2_PIN(1), 297da801ab5SAlexandre Belloni JAGUAR2_PIN(2), 298da801ab5SAlexandre Belloni JAGUAR2_PIN(3), 299da801ab5SAlexandre Belloni JAGUAR2_PIN(4), 300da801ab5SAlexandre Belloni JAGUAR2_PIN(5), 301da801ab5SAlexandre Belloni JAGUAR2_PIN(6), 302da801ab5SAlexandre Belloni JAGUAR2_PIN(7), 303da801ab5SAlexandre Belloni JAGUAR2_PIN(8), 304da801ab5SAlexandre Belloni JAGUAR2_PIN(9), 305da801ab5SAlexandre Belloni JAGUAR2_PIN(10), 306da801ab5SAlexandre Belloni JAGUAR2_PIN(11), 307da801ab5SAlexandre Belloni JAGUAR2_PIN(12), 308da801ab5SAlexandre Belloni JAGUAR2_PIN(13), 309da801ab5SAlexandre Belloni JAGUAR2_PIN(14), 310da801ab5SAlexandre Belloni JAGUAR2_PIN(15), 311da801ab5SAlexandre Belloni JAGUAR2_PIN(16), 312da801ab5SAlexandre Belloni JAGUAR2_PIN(17), 313da801ab5SAlexandre Belloni JAGUAR2_PIN(18), 314da801ab5SAlexandre Belloni JAGUAR2_PIN(19), 315da801ab5SAlexandre Belloni JAGUAR2_PIN(20), 316da801ab5SAlexandre Belloni JAGUAR2_PIN(21), 317da801ab5SAlexandre Belloni JAGUAR2_PIN(22), 318da801ab5SAlexandre Belloni JAGUAR2_PIN(23), 319da801ab5SAlexandre Belloni JAGUAR2_PIN(24), 320da801ab5SAlexandre Belloni JAGUAR2_PIN(25), 321da801ab5SAlexandre Belloni JAGUAR2_PIN(26), 322da801ab5SAlexandre Belloni JAGUAR2_PIN(27), 323da801ab5SAlexandre Belloni JAGUAR2_PIN(28), 324da801ab5SAlexandre Belloni JAGUAR2_PIN(29), 325da801ab5SAlexandre Belloni JAGUAR2_PIN(30), 326da801ab5SAlexandre Belloni JAGUAR2_PIN(31), 327da801ab5SAlexandre Belloni JAGUAR2_PIN(32), 328da801ab5SAlexandre Belloni JAGUAR2_PIN(33), 329da801ab5SAlexandre Belloni JAGUAR2_PIN(34), 330da801ab5SAlexandre Belloni JAGUAR2_PIN(35), 331da801ab5SAlexandre Belloni JAGUAR2_PIN(36), 332da801ab5SAlexandre Belloni JAGUAR2_PIN(37), 333da801ab5SAlexandre Belloni JAGUAR2_PIN(38), 334da801ab5SAlexandre Belloni JAGUAR2_PIN(39), 335da801ab5SAlexandre Belloni JAGUAR2_PIN(40), 336da801ab5SAlexandre Belloni JAGUAR2_PIN(41), 337da801ab5SAlexandre Belloni JAGUAR2_PIN(42), 338da801ab5SAlexandre Belloni JAGUAR2_PIN(43), 339da801ab5SAlexandre Belloni JAGUAR2_PIN(44), 340da801ab5SAlexandre Belloni JAGUAR2_PIN(45), 341da801ab5SAlexandre Belloni JAGUAR2_PIN(46), 342da801ab5SAlexandre Belloni JAGUAR2_PIN(47), 343da801ab5SAlexandre Belloni JAGUAR2_PIN(48), 344da801ab5SAlexandre Belloni JAGUAR2_PIN(49), 345da801ab5SAlexandre Belloni JAGUAR2_PIN(50), 346da801ab5SAlexandre Belloni JAGUAR2_PIN(51), 347da801ab5SAlexandre Belloni JAGUAR2_PIN(52), 348da801ab5SAlexandre Belloni JAGUAR2_PIN(53), 349da801ab5SAlexandre Belloni JAGUAR2_PIN(54), 350da801ab5SAlexandre Belloni JAGUAR2_PIN(55), 351da801ab5SAlexandre Belloni JAGUAR2_PIN(56), 352da801ab5SAlexandre Belloni JAGUAR2_PIN(57), 353da801ab5SAlexandre Belloni JAGUAR2_PIN(58), 354da801ab5SAlexandre Belloni JAGUAR2_PIN(59), 355da801ab5SAlexandre Belloni JAGUAR2_PIN(60), 356da801ab5SAlexandre Belloni JAGUAR2_PIN(61), 357da801ab5SAlexandre Belloni JAGUAR2_PIN(62), 358da801ab5SAlexandre Belloni JAGUAR2_PIN(63), 359da801ab5SAlexandre Belloni }; 360da801ab5SAlexandre Belloni 361ce8dc094SAlexandre Belloni static int ocelot_get_functions_count(struct pinctrl_dev *pctldev) 362ce8dc094SAlexandre Belloni { 363ce8dc094SAlexandre Belloni return ARRAY_SIZE(ocelot_function_names); 364ce8dc094SAlexandre Belloni } 365ce8dc094SAlexandre Belloni 366ce8dc094SAlexandre Belloni static const char *ocelot_get_function_name(struct pinctrl_dev *pctldev, 367ce8dc094SAlexandre Belloni unsigned int function) 368ce8dc094SAlexandre Belloni { 369ce8dc094SAlexandre Belloni return ocelot_function_names[function]; 370ce8dc094SAlexandre Belloni } 371ce8dc094SAlexandre Belloni 372ce8dc094SAlexandre Belloni static int ocelot_get_function_groups(struct pinctrl_dev *pctldev, 373ce8dc094SAlexandre Belloni unsigned int function, 374ce8dc094SAlexandre Belloni const char *const **groups, 375ce8dc094SAlexandre Belloni unsigned *const num_groups) 376ce8dc094SAlexandre Belloni { 377ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 378ce8dc094SAlexandre Belloni 379ce8dc094SAlexandre Belloni *groups = info->func[function].groups; 380ce8dc094SAlexandre Belloni *num_groups = info->func[function].ngroups; 381ce8dc094SAlexandre Belloni 382ce8dc094SAlexandre Belloni return 0; 383ce8dc094SAlexandre Belloni } 384ce8dc094SAlexandre Belloni 385da801ab5SAlexandre Belloni static int ocelot_pin_function_idx(struct ocelot_pinctrl *info, 386da801ab5SAlexandre Belloni unsigned int pin, unsigned int function) 387ce8dc094SAlexandre Belloni { 388da801ab5SAlexandre Belloni struct ocelot_pin_caps *p = info->desc->pins[pin].drv_data; 389ce8dc094SAlexandre Belloni int i; 390ce8dc094SAlexandre Belloni 391ce8dc094SAlexandre Belloni for (i = 0; i < OCELOT_FUNC_PER_PIN; i++) { 392ce8dc094SAlexandre Belloni if (function == p->functions[i]) 393ce8dc094SAlexandre Belloni return i; 394ce8dc094SAlexandre Belloni } 395ce8dc094SAlexandre Belloni 396ce8dc094SAlexandre Belloni return -1; 397ce8dc094SAlexandre Belloni } 398ce8dc094SAlexandre Belloni 399da801ab5SAlexandre Belloni #define REG(r, info, p) ((r) * (info)->stride + (4 * ((p) / 32))) 400da801ab5SAlexandre Belloni 401ce8dc094SAlexandre Belloni static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev, 402ce8dc094SAlexandre Belloni unsigned int selector, unsigned int group) 403ce8dc094SAlexandre Belloni { 404ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 405da801ab5SAlexandre Belloni struct ocelot_pin_caps *pin = info->desc->pins[group].drv_data; 406da801ab5SAlexandre Belloni unsigned int p = pin->pin % 32; 407ce8dc094SAlexandre Belloni int f; 408ce8dc094SAlexandre Belloni 409da801ab5SAlexandre Belloni f = ocelot_pin_function_idx(info, group, selector); 410ce8dc094SAlexandre Belloni if (f < 0) 411ce8dc094SAlexandre Belloni return -EINVAL; 412ce8dc094SAlexandre Belloni 413ce8dc094SAlexandre Belloni /* 414ce8dc094SAlexandre Belloni * f is encoded on two bits. 415ce8dc094SAlexandre Belloni * bit 0 of f goes in BIT(pin) of ALT0, bit 1 of f goes in BIT(pin) of 416ce8dc094SAlexandre Belloni * ALT1 417ce8dc094SAlexandre Belloni * This is racy because both registers can't be updated at the same time 418ce8dc094SAlexandre Belloni * but it doesn't matter much for now. 419ce8dc094SAlexandre Belloni */ 420da801ab5SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT0, info, pin->pin), 421da801ab5SAlexandre Belloni BIT(p), f << p); 422da801ab5SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT1, info, pin->pin), 423da801ab5SAlexandre Belloni BIT(p), f << (p - 1)); 424ce8dc094SAlexandre Belloni 425ce8dc094SAlexandre Belloni return 0; 426ce8dc094SAlexandre Belloni } 427ce8dc094SAlexandre Belloni 428ce8dc094SAlexandre Belloni static int ocelot_gpio_set_direction(struct pinctrl_dev *pctldev, 429ce8dc094SAlexandre Belloni struct pinctrl_gpio_range *range, 430ce8dc094SAlexandre Belloni unsigned int pin, bool input) 431ce8dc094SAlexandre Belloni { 432ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 433da801ab5SAlexandre Belloni unsigned int p = pin % 32; 434ce8dc094SAlexandre Belloni 435da801ab5SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_OE, info, p), BIT(p), 436da801ab5SAlexandre Belloni input ? 0 : BIT(p)); 437ce8dc094SAlexandre Belloni 438ce8dc094SAlexandre Belloni return 0; 439ce8dc094SAlexandre Belloni } 440ce8dc094SAlexandre Belloni 441ce8dc094SAlexandre Belloni static int ocelot_gpio_request_enable(struct pinctrl_dev *pctldev, 442ce8dc094SAlexandre Belloni struct pinctrl_gpio_range *range, 443ce8dc094SAlexandre Belloni unsigned int offset) 444ce8dc094SAlexandre Belloni { 445ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 446da801ab5SAlexandre Belloni unsigned int p = offset % 32; 447ce8dc094SAlexandre Belloni 448da801ab5SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT0, info, offset), 449da801ab5SAlexandre Belloni BIT(p), 0); 450da801ab5SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT1, info, offset), 451da801ab5SAlexandre Belloni BIT(p), 0); 452ce8dc094SAlexandre Belloni 453ce8dc094SAlexandre Belloni return 0; 454ce8dc094SAlexandre Belloni } 455ce8dc094SAlexandre Belloni 456ce8dc094SAlexandre Belloni static const struct pinmux_ops ocelot_pmx_ops = { 457ce8dc094SAlexandre Belloni .get_functions_count = ocelot_get_functions_count, 458ce8dc094SAlexandre Belloni .get_function_name = ocelot_get_function_name, 459ce8dc094SAlexandre Belloni .get_function_groups = ocelot_get_function_groups, 460ce8dc094SAlexandre Belloni .set_mux = ocelot_pinmux_set_mux, 461ce8dc094SAlexandre Belloni .gpio_set_direction = ocelot_gpio_set_direction, 462ce8dc094SAlexandre Belloni .gpio_request_enable = ocelot_gpio_request_enable, 463ce8dc094SAlexandre Belloni }; 464ce8dc094SAlexandre Belloni 465ce8dc094SAlexandre Belloni static int ocelot_pctl_get_groups_count(struct pinctrl_dev *pctldev) 466ce8dc094SAlexandre Belloni { 467da801ab5SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 468da801ab5SAlexandre Belloni 469da801ab5SAlexandre Belloni return info->desc->npins; 470ce8dc094SAlexandre Belloni } 471ce8dc094SAlexandre Belloni 472ce8dc094SAlexandre Belloni static const char *ocelot_pctl_get_group_name(struct pinctrl_dev *pctldev, 473ce8dc094SAlexandre Belloni unsigned int group) 474ce8dc094SAlexandre Belloni { 475da801ab5SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 476da801ab5SAlexandre Belloni 477da801ab5SAlexandre Belloni return info->desc->pins[group].name; 478ce8dc094SAlexandre Belloni } 479ce8dc094SAlexandre Belloni 480ce8dc094SAlexandre Belloni static int ocelot_pctl_get_group_pins(struct pinctrl_dev *pctldev, 481ce8dc094SAlexandre Belloni unsigned int group, 482ce8dc094SAlexandre Belloni const unsigned int **pins, 483ce8dc094SAlexandre Belloni unsigned int *num_pins) 484ce8dc094SAlexandre Belloni { 485da801ab5SAlexandre Belloni struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 486da801ab5SAlexandre Belloni 487da801ab5SAlexandre Belloni *pins = &info->desc->pins[group].number; 488ce8dc094SAlexandre Belloni *num_pins = 1; 489ce8dc094SAlexandre Belloni 490ce8dc094SAlexandre Belloni return 0; 491ce8dc094SAlexandre Belloni } 492ce8dc094SAlexandre Belloni 493ce8dc094SAlexandre Belloni static const struct pinctrl_ops ocelot_pctl_ops = { 494ce8dc094SAlexandre Belloni .get_groups_count = ocelot_pctl_get_groups_count, 495ce8dc094SAlexandre Belloni .get_group_name = ocelot_pctl_get_group_name, 496ce8dc094SAlexandre Belloni .get_group_pins = ocelot_pctl_get_group_pins, 497ce8dc094SAlexandre Belloni .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 498ce8dc094SAlexandre Belloni .dt_free_map = pinconf_generic_dt_free_map, 499ce8dc094SAlexandre Belloni }; 500ce8dc094SAlexandre Belloni 501ce8dc094SAlexandre Belloni static struct pinctrl_desc ocelot_desc = { 502ce8dc094SAlexandre Belloni .name = "ocelot-pinctrl", 503ce8dc094SAlexandre Belloni .pins = ocelot_pins, 504ce8dc094SAlexandre Belloni .npins = ARRAY_SIZE(ocelot_pins), 505ce8dc094SAlexandre Belloni .pctlops = &ocelot_pctl_ops, 506ce8dc094SAlexandre Belloni .pmxops = &ocelot_pmx_ops, 507ce8dc094SAlexandre Belloni .owner = THIS_MODULE, 508ce8dc094SAlexandre Belloni }; 509ce8dc094SAlexandre Belloni 510da801ab5SAlexandre Belloni static struct pinctrl_desc jaguar2_desc = { 511da801ab5SAlexandre Belloni .name = "jaguar2-pinctrl", 512da801ab5SAlexandre Belloni .pins = jaguar2_pins, 513da801ab5SAlexandre Belloni .npins = ARRAY_SIZE(jaguar2_pins), 514da801ab5SAlexandre Belloni .pctlops = &ocelot_pctl_ops, 515da801ab5SAlexandre Belloni .pmxops = &ocelot_pmx_ops, 516da801ab5SAlexandre Belloni .owner = THIS_MODULE, 517da801ab5SAlexandre Belloni }; 518da801ab5SAlexandre Belloni 519ce8dc094SAlexandre Belloni static int ocelot_create_group_func_map(struct device *dev, 520ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info) 521ce8dc094SAlexandre Belloni { 522ce8dc094SAlexandre Belloni int f, npins, i; 523da801ab5SAlexandre Belloni u8 *pins = kcalloc(info->desc->npins, sizeof(u8), GFP_KERNEL); 524da801ab5SAlexandre Belloni 525da801ab5SAlexandre Belloni if (!pins) 526da801ab5SAlexandre Belloni return -ENOMEM; 527ce8dc094SAlexandre Belloni 528ce8dc094SAlexandre Belloni for (f = 0; f < FUNC_MAX; f++) { 529da801ab5SAlexandre Belloni for (npins = 0, i = 0; i < info->desc->npins; i++) { 530da801ab5SAlexandre Belloni if (ocelot_pin_function_idx(info, i, f) >= 0) 531ce8dc094SAlexandre Belloni pins[npins++] = i; 532ce8dc094SAlexandre Belloni } 533ce8dc094SAlexandre Belloni 534da801ab5SAlexandre Belloni if (!npins) 535da801ab5SAlexandre Belloni continue; 536da801ab5SAlexandre Belloni 537ce8dc094SAlexandre Belloni info->func[f].ngroups = npins; 538da801ab5SAlexandre Belloni info->func[f].groups = devm_kcalloc(dev, npins, sizeof(char *), 539ce8dc094SAlexandre Belloni GFP_KERNEL); 540da801ab5SAlexandre Belloni if (!info->func[f].groups) { 541da801ab5SAlexandre Belloni kfree(pins); 542ce8dc094SAlexandre Belloni return -ENOMEM; 543da801ab5SAlexandre Belloni } 544ce8dc094SAlexandre Belloni 545ce8dc094SAlexandre Belloni for (i = 0; i < npins; i++) 546da801ab5SAlexandre Belloni info->func[f].groups[i] = info->desc->pins[pins[i]].name; 547ce8dc094SAlexandre Belloni } 548ce8dc094SAlexandre Belloni 549da801ab5SAlexandre Belloni kfree(pins); 550da801ab5SAlexandre Belloni 551ce8dc094SAlexandre Belloni return 0; 552ce8dc094SAlexandre Belloni } 553ce8dc094SAlexandre Belloni 554ce8dc094SAlexandre Belloni static int ocelot_pinctrl_register(struct platform_device *pdev, 555ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info) 556ce8dc094SAlexandre Belloni { 557ce8dc094SAlexandre Belloni int ret; 558ce8dc094SAlexandre Belloni 559ce8dc094SAlexandre Belloni ret = ocelot_create_group_func_map(&pdev->dev, info); 560ce8dc094SAlexandre Belloni if (ret) { 561ce8dc094SAlexandre Belloni dev_err(&pdev->dev, "Unable to create group func map.\n"); 562ce8dc094SAlexandre Belloni return ret; 563ce8dc094SAlexandre Belloni } 564ce8dc094SAlexandre Belloni 565da801ab5SAlexandre Belloni info->pctl = devm_pinctrl_register(&pdev->dev, info->desc, info); 566ce8dc094SAlexandre Belloni if (IS_ERR(info->pctl)) { 567ce8dc094SAlexandre Belloni dev_err(&pdev->dev, "Failed to register pinctrl\n"); 568ce8dc094SAlexandre Belloni return PTR_ERR(info->pctl); 569ce8dc094SAlexandre Belloni } 570ce8dc094SAlexandre Belloni 571ce8dc094SAlexandre Belloni return 0; 572ce8dc094SAlexandre Belloni } 573ce8dc094SAlexandre Belloni 574ce8dc094SAlexandre Belloni static int ocelot_gpio_get(struct gpio_chip *chip, unsigned int offset) 575ce8dc094SAlexandre Belloni { 576ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = gpiochip_get_data(chip); 577ce8dc094SAlexandre Belloni unsigned int val; 578ce8dc094SAlexandre Belloni 579da801ab5SAlexandre Belloni regmap_read(info->map, REG(OCELOT_GPIO_IN, info, offset), &val); 580ce8dc094SAlexandre Belloni 581da801ab5SAlexandre Belloni return !!(val & BIT(offset % 32)); 582ce8dc094SAlexandre Belloni } 583ce8dc094SAlexandre Belloni 584ce8dc094SAlexandre Belloni static void ocelot_gpio_set(struct gpio_chip *chip, unsigned int offset, 585ce8dc094SAlexandre Belloni int value) 586ce8dc094SAlexandre Belloni { 587ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = gpiochip_get_data(chip); 588ce8dc094SAlexandre Belloni 589ce8dc094SAlexandre Belloni if (value) 590da801ab5SAlexandre Belloni regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset), 591da801ab5SAlexandre Belloni BIT(offset % 32)); 592ce8dc094SAlexandre Belloni else 593da801ab5SAlexandre Belloni regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset), 594da801ab5SAlexandre Belloni BIT(offset % 32)); 595ce8dc094SAlexandre Belloni } 596ce8dc094SAlexandre Belloni 597ce8dc094SAlexandre Belloni static int ocelot_gpio_get_direction(struct gpio_chip *chip, 598ce8dc094SAlexandre Belloni unsigned int offset) 599ce8dc094SAlexandre Belloni { 600ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = gpiochip_get_data(chip); 601ce8dc094SAlexandre Belloni unsigned int val; 602ce8dc094SAlexandre Belloni 603da801ab5SAlexandre Belloni regmap_read(info->map, REG(OCELOT_GPIO_OE, info, offset), &val); 604ce8dc094SAlexandre Belloni 605da801ab5SAlexandre Belloni return !(val & BIT(offset % 32)); 606ce8dc094SAlexandre Belloni } 607ce8dc094SAlexandre Belloni 608ce8dc094SAlexandre Belloni static int ocelot_gpio_direction_input(struct gpio_chip *chip, 609ce8dc094SAlexandre Belloni unsigned int offset) 610ce8dc094SAlexandre Belloni { 611ce8dc094SAlexandre Belloni return pinctrl_gpio_direction_input(chip->base + offset); 612ce8dc094SAlexandre Belloni } 613ce8dc094SAlexandre Belloni 614ce8dc094SAlexandre Belloni static int ocelot_gpio_direction_output(struct gpio_chip *chip, 615ce8dc094SAlexandre Belloni unsigned int offset, int value) 616ce8dc094SAlexandre Belloni { 617ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info = gpiochip_get_data(chip); 618da801ab5SAlexandre Belloni unsigned int pin = BIT(offset % 32); 619ce8dc094SAlexandre Belloni 620ce8dc094SAlexandre Belloni if (value) 621da801ab5SAlexandre Belloni regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset), 622da801ab5SAlexandre Belloni pin); 623ce8dc094SAlexandre Belloni else 624da801ab5SAlexandre Belloni regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset), 625da801ab5SAlexandre Belloni pin); 626ce8dc094SAlexandre Belloni 627ce8dc094SAlexandre Belloni return pinctrl_gpio_direction_output(chip->base + offset); 628ce8dc094SAlexandre Belloni } 629ce8dc094SAlexandre Belloni 630ce8dc094SAlexandre Belloni static const struct gpio_chip ocelot_gpiolib_chip = { 631ce8dc094SAlexandre Belloni .request = gpiochip_generic_request, 632ce8dc094SAlexandre Belloni .free = gpiochip_generic_free, 633ce8dc094SAlexandre Belloni .set = ocelot_gpio_set, 634ce8dc094SAlexandre Belloni .get = ocelot_gpio_get, 635ce8dc094SAlexandre Belloni .get_direction = ocelot_gpio_get_direction, 636ce8dc094SAlexandre Belloni .direction_input = ocelot_gpio_direction_input, 637ce8dc094SAlexandre Belloni .direction_output = ocelot_gpio_direction_output, 638ce8dc094SAlexandre Belloni .owner = THIS_MODULE, 639ce8dc094SAlexandre Belloni }; 640ce8dc094SAlexandre Belloni 641be36abb7SQuentin Schulz static void ocelot_irq_mask(struct irq_data *data) 642be36abb7SQuentin Schulz { 643be36abb7SQuentin Schulz struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 644be36abb7SQuentin Schulz struct ocelot_pinctrl *info = gpiochip_get_data(chip); 645be36abb7SQuentin Schulz unsigned int gpio = irqd_to_hwirq(data); 646be36abb7SQuentin Schulz 647da801ab5SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio), 648da801ab5SAlexandre Belloni BIT(gpio % 32), 0); 649be36abb7SQuentin Schulz } 650be36abb7SQuentin Schulz 651be36abb7SQuentin Schulz static void ocelot_irq_unmask(struct irq_data *data) 652be36abb7SQuentin Schulz { 653be36abb7SQuentin Schulz struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 654be36abb7SQuentin Schulz struct ocelot_pinctrl *info = gpiochip_get_data(chip); 655be36abb7SQuentin Schulz unsigned int gpio = irqd_to_hwirq(data); 656be36abb7SQuentin Schulz 657da801ab5SAlexandre Belloni regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio), 658da801ab5SAlexandre Belloni BIT(gpio % 32), BIT(gpio % 32)); 659be36abb7SQuentin Schulz } 660be36abb7SQuentin Schulz 661be36abb7SQuentin Schulz static void ocelot_irq_ack(struct irq_data *data) 662be36abb7SQuentin Schulz { 663be36abb7SQuentin Schulz struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 664be36abb7SQuentin Schulz struct ocelot_pinctrl *info = gpiochip_get_data(chip); 665be36abb7SQuentin Schulz unsigned int gpio = irqd_to_hwirq(data); 666be36abb7SQuentin Schulz 667da801ab5SAlexandre Belloni regmap_write_bits(info->map, REG(OCELOT_GPIO_INTR, info, gpio), 668da801ab5SAlexandre Belloni BIT(gpio % 32), BIT(gpio % 32)); 669be36abb7SQuentin Schulz } 670be36abb7SQuentin Schulz 671be36abb7SQuentin Schulz static int ocelot_irq_set_type(struct irq_data *data, unsigned int type); 672be36abb7SQuentin Schulz 673be36abb7SQuentin Schulz static struct irq_chip ocelot_eoi_irqchip = { 674be36abb7SQuentin Schulz .name = "gpio", 675be36abb7SQuentin Schulz .irq_mask = ocelot_irq_mask, 676be36abb7SQuentin Schulz .irq_eoi = ocelot_irq_ack, 677be36abb7SQuentin Schulz .irq_unmask = ocelot_irq_unmask, 678be36abb7SQuentin Schulz .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED, 679be36abb7SQuentin Schulz .irq_set_type = ocelot_irq_set_type, 680be36abb7SQuentin Schulz }; 681be36abb7SQuentin Schulz 682be36abb7SQuentin Schulz static struct irq_chip ocelot_irqchip = { 683be36abb7SQuentin Schulz .name = "gpio", 684be36abb7SQuentin Schulz .irq_mask = ocelot_irq_mask, 685be36abb7SQuentin Schulz .irq_ack = ocelot_irq_ack, 686be36abb7SQuentin Schulz .irq_unmask = ocelot_irq_unmask, 687be36abb7SQuentin Schulz .irq_set_type = ocelot_irq_set_type, 688be36abb7SQuentin Schulz }; 689be36abb7SQuentin Schulz 690be36abb7SQuentin Schulz static int ocelot_irq_set_type(struct irq_data *data, unsigned int type) 691be36abb7SQuentin Schulz { 692be36abb7SQuentin Schulz type &= IRQ_TYPE_SENSE_MASK; 693be36abb7SQuentin Schulz 694be36abb7SQuentin Schulz if (!(type & (IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_HIGH))) 695be36abb7SQuentin Schulz return -EINVAL; 696be36abb7SQuentin Schulz 697be36abb7SQuentin Schulz if (type & IRQ_TYPE_LEVEL_HIGH) 698be36abb7SQuentin Schulz irq_set_chip_handler_name_locked(data, &ocelot_eoi_irqchip, 699be36abb7SQuentin Schulz handle_fasteoi_irq, NULL); 700be36abb7SQuentin Schulz if (type & IRQ_TYPE_EDGE_BOTH) 701be36abb7SQuentin Schulz irq_set_chip_handler_name_locked(data, &ocelot_irqchip, 702be36abb7SQuentin Schulz handle_edge_irq, NULL); 703be36abb7SQuentin Schulz 704be36abb7SQuentin Schulz return 0; 705be36abb7SQuentin Schulz } 706be36abb7SQuentin Schulz 707be36abb7SQuentin Schulz static void ocelot_irq_handler(struct irq_desc *desc) 708be36abb7SQuentin Schulz { 709be36abb7SQuentin Schulz struct irq_chip *parent_chip = irq_desc_get_chip(desc); 710be36abb7SQuentin Schulz struct gpio_chip *chip = irq_desc_get_handler_data(desc); 711be36abb7SQuentin Schulz struct ocelot_pinctrl *info = gpiochip_get_data(chip); 712da801ab5SAlexandre Belloni unsigned int reg = 0, irq, i; 713be36abb7SQuentin Schulz unsigned long irqs; 714be36abb7SQuentin Schulz 715da801ab5SAlexandre Belloni for (i = 0; i < info->stride; i++) { 716da801ab5SAlexandre Belloni regmap_read(info->map, OCELOT_GPIO_INTR_IDENT + 4 * i, ®); 717be36abb7SQuentin Schulz if (!reg) 718da801ab5SAlexandre Belloni continue; 719be36abb7SQuentin Schulz 720be36abb7SQuentin Schulz chained_irq_enter(parent_chip, desc); 721be36abb7SQuentin Schulz 722be36abb7SQuentin Schulz irqs = reg; 723be36abb7SQuentin Schulz 724da801ab5SAlexandre Belloni for_each_set_bit(irq, &irqs, 725da801ab5SAlexandre Belloni min(32U, info->desc->npins - 32 * i)) 726da801ab5SAlexandre Belloni generic_handle_irq(irq_linear_revmap(chip->irq.domain, 727da801ab5SAlexandre Belloni irq + 32 * i)); 728be36abb7SQuentin Schulz 729be36abb7SQuentin Schulz chained_irq_exit(parent_chip, desc); 730be36abb7SQuentin Schulz } 731da801ab5SAlexandre Belloni } 732be36abb7SQuentin Schulz 733ce8dc094SAlexandre Belloni static int ocelot_gpiochip_register(struct platform_device *pdev, 734ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info) 735ce8dc094SAlexandre Belloni { 736ce8dc094SAlexandre Belloni struct gpio_chip *gc; 737be36abb7SQuentin Schulz int ret, irq; 738ce8dc094SAlexandre Belloni 739ce8dc094SAlexandre Belloni info->gpio_chip = ocelot_gpiolib_chip; 740ce8dc094SAlexandre Belloni 741ce8dc094SAlexandre Belloni gc = &info->gpio_chip; 742da801ab5SAlexandre Belloni gc->ngpio = info->desc->npins; 743ce8dc094SAlexandre Belloni gc->parent = &pdev->dev; 744ce8dc094SAlexandre Belloni gc->base = 0; 745ce8dc094SAlexandre Belloni gc->of_node = info->dev->of_node; 746ce8dc094SAlexandre Belloni gc->label = "ocelot-gpio"; 747ce8dc094SAlexandre Belloni 748ce8dc094SAlexandre Belloni ret = devm_gpiochip_add_data(&pdev->dev, gc, info); 749ce8dc094SAlexandre Belloni if (ret) 750ce8dc094SAlexandre Belloni return ret; 751ce8dc094SAlexandre Belloni 752be36abb7SQuentin Schulz irq = irq_of_parse_and_map(pdev->dev.of_node, 0); 753be36abb7SQuentin Schulz if (irq <= 0) 754be36abb7SQuentin Schulz return irq; 755be36abb7SQuentin Schulz 756be36abb7SQuentin Schulz ret = gpiochip_irqchip_add(gc, &ocelot_irqchip, 0, handle_edge_irq, 757be36abb7SQuentin Schulz IRQ_TYPE_NONE); 758be36abb7SQuentin Schulz if (ret) 759be36abb7SQuentin Schulz return ret; 760be36abb7SQuentin Schulz 761be36abb7SQuentin Schulz gpiochip_set_chained_irqchip(gc, &ocelot_irqchip, irq, 762be36abb7SQuentin Schulz ocelot_irq_handler); 763ce8dc094SAlexandre Belloni 764ce8dc094SAlexandre Belloni return 0; 765ce8dc094SAlexandre Belloni } 766ce8dc094SAlexandre Belloni 767ce8dc094SAlexandre Belloni static const struct of_device_id ocelot_pinctrl_of_match[] = { 768da801ab5SAlexandre Belloni { .compatible = "mscc,ocelot-pinctrl", .data = &ocelot_desc }, 769da801ab5SAlexandre Belloni { .compatible = "mscc,jaguar2-pinctrl", .data = &jaguar2_desc }, 770ce8dc094SAlexandre Belloni {}, 771ce8dc094SAlexandre Belloni }; 772ce8dc094SAlexandre Belloni 773ce3e7f0eSColin Ian King static int ocelot_pinctrl_probe(struct platform_device *pdev) 774ce8dc094SAlexandre Belloni { 775ce8dc094SAlexandre Belloni struct device *dev = &pdev->dev; 776ce8dc094SAlexandre Belloni struct ocelot_pinctrl *info; 777ce8dc094SAlexandre Belloni void __iomem *base; 778ce8dc094SAlexandre Belloni int ret; 779da801ab5SAlexandre Belloni struct regmap_config regmap_config = { 780da801ab5SAlexandre Belloni .reg_bits = 32, 781da801ab5SAlexandre Belloni .val_bits = 32, 782da801ab5SAlexandre Belloni .reg_stride = 4, 783da801ab5SAlexandre Belloni }; 784ce8dc094SAlexandre Belloni 785ce8dc094SAlexandre Belloni info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); 786ce8dc094SAlexandre Belloni if (!info) 787ce8dc094SAlexandre Belloni return -ENOMEM; 788ce8dc094SAlexandre Belloni 789da801ab5SAlexandre Belloni info->desc = (struct pinctrl_desc *)device_get_match_data(dev); 790da801ab5SAlexandre Belloni 791ce8dc094SAlexandre Belloni base = devm_ioremap_resource(dev, 792ce8dc094SAlexandre Belloni platform_get_resource(pdev, IORESOURCE_MEM, 0)); 793ce8dc094SAlexandre Belloni if (IS_ERR(base)) { 794ce8dc094SAlexandre Belloni dev_err(dev, "Failed to ioremap registers\n"); 795ce8dc094SAlexandre Belloni return PTR_ERR(base); 796ce8dc094SAlexandre Belloni } 797ce8dc094SAlexandre Belloni 798da801ab5SAlexandre Belloni info->stride = 1 + (info->desc->npins - 1) / 32; 799da801ab5SAlexandre Belloni regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4; 800da801ab5SAlexandre Belloni 801da801ab5SAlexandre Belloni info->map = devm_regmap_init_mmio(dev, base, ®map_config); 802ce8dc094SAlexandre Belloni if (IS_ERR(info->map)) { 803ce8dc094SAlexandre Belloni dev_err(dev, "Failed to create regmap\n"); 804ce8dc094SAlexandre Belloni return PTR_ERR(info->map); 805ce8dc094SAlexandre Belloni } 806ce8dc094SAlexandre Belloni dev_set_drvdata(dev, info->map); 807ce8dc094SAlexandre Belloni info->dev = dev; 808ce8dc094SAlexandre Belloni 809ce8dc094SAlexandre Belloni ret = ocelot_pinctrl_register(pdev, info); 810ce8dc094SAlexandre Belloni if (ret) 811ce8dc094SAlexandre Belloni return ret; 812ce8dc094SAlexandre Belloni 813ce8dc094SAlexandre Belloni ret = ocelot_gpiochip_register(pdev, info); 814ce8dc094SAlexandre Belloni if (ret) 815ce8dc094SAlexandre Belloni return ret; 816ce8dc094SAlexandre Belloni 817ce8dc094SAlexandre Belloni return 0; 818ce8dc094SAlexandre Belloni } 819ce8dc094SAlexandre Belloni 820ce8dc094SAlexandre Belloni static struct platform_driver ocelot_pinctrl_driver = { 821ce8dc094SAlexandre Belloni .driver = { 822ce8dc094SAlexandre Belloni .name = "pinctrl-ocelot", 823ce8dc094SAlexandre Belloni .of_match_table = of_match_ptr(ocelot_pinctrl_of_match), 824ce8dc094SAlexandre Belloni .suppress_bind_attrs = true, 825ce8dc094SAlexandre Belloni }, 826ce8dc094SAlexandre Belloni .probe = ocelot_pinctrl_probe, 827ce8dc094SAlexandre Belloni }; 828ce8dc094SAlexandre Belloni builtin_platform_driver(ocelot_pinctrl_driver); 829