Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

pinctrl: add polarfire soc mssio pinctrl driver

On Polarfire SoC, the Bank 2 and Bank 4 IOs connected to the
Multiprocessor Subsystem (MSS) are controlled by IOMUX_CRs 1 through 6,
which determine what function in routed to them, and
MSSIO_BANK#_IO_CFG_CRs, which determine the configuration of each pin.

Add a driver for this pin controller, including several custom
properties that reflect aspects of the MSS's configuration.

Reuse the Kconfig option for iomux0, since controlling MSSIOs without
iomux0 routing a function to the MSSIOs in question is pointless, and
routing a function to the MSSIOs is equally unhelpful if none of them
are configured to make use of that function.

Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>

authored by

Conor Dooley and committed by
Linus Walleij
488d704e 6b324d19

+741 -3
+3 -3
drivers/pinctrl/microchip/Kconfig
··· 9 9 This selects the pinctrl driver for gpio2 on pic64gx. 10 10 11 11 config PINCTRL_POLARFIRE_SOC 12 - bool "Polarfire SoC pinctrl driver" 12 + bool "Polarfire SoC pinctrl drivers" 13 13 depends on ARCH_MICROCHIP || COMPILE_TEST 14 14 depends on OF 15 - select GENERIC_PINCONF 15 + select GENERIC_PINCTRL 16 16 help 17 - This selects the pinctrl driver for Microchip Polarfire SoC. 17 + This selects the pinctrl drivers for Microchip Polarfire SoC.
+1
drivers/pinctrl/microchip/Makefile
··· 2 2 3 3 obj-$(CONFIG_PINCTRL_PIC64GX) += pinctrl-pic64gx-gpio2.o 4 4 obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) += pinctrl-mpfs-iomux0.o 5 + obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) += pinctrl-mpfs-mssio.o
+737
drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/bitfield.h> 4 + #include <linux/module.h> 5 + #include <linux/mfd/syscon.h> 6 + #include <linux/mod_devicetable.h> 7 + #include <linux/of.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/regmap.h> 10 + #include <linux/seq_file.h> 11 + 12 + #include <linux/pinctrl/pinconf-generic.h> 13 + #include <linux/pinctrl/pinconf.h> 14 + #include <linux/pinctrl/pinctrl.h> 15 + #include <linux/pinctrl/pinmux.h> 16 + 17 + #include "../core.h" 18 + #include "../pinctrl-utils.h" 19 + #include "../pinconf.h" 20 + #include "../pinmux.h" 21 + 22 + #define MPFS_PINCTRL_PAD_MUX_MASK GENMASK(3, 0) 23 + 24 + #define MPFS_PINCTRL_IOCFG_MASK GENMASK(14, 0) 25 + #define MPFS_PINCTRL_IBUFMD_MASK GENMASK(2, 0) 26 + #define MPFS_PINCTRL_DRV_MASK GENMASK(6, 3) 27 + #define MPFS_PINCTRL_CLAMP BIT(7) 28 + #define MPFS_PINCTRL_ENHYST BIT(8) 29 + #define MPFS_PINCTRL_LOCKDN BIT(9) 30 + #define MPFS_PINCTRL_WPD BIT(10) 31 + #define MPFS_PINCTRL_WPU BIT(11) 32 + #define MPFS_PINCTRL_PULL_MASK GENMASK(11, 10) 33 + #define MPFS_PINCTRL_LP_PERSIST_EN BIT(12) 34 + #define MPFS_PINCTRL_LP_BYPASS_EN BIT(13) 35 + 36 + #define MPFS_PINCTRL_MSSIO_BANK2_CFG_CR 0x1c4 37 + #define MPFS_PINCTRL_MSSIO_BANK4_CFG_CR 0x1c8 38 + #define MPFS_PINCTRL_BANK_VOLTAGE_MASK GENMASK(19, 16) 39 + 40 + #define MPFS_PINCTRL_IOCFG01_REG 0x234 41 + 42 + #define MPFS_PINCTRL_INTER_BANK_GAP 0x4 43 + 44 + #define MPFS_PINCTRL_BANK2_START 14 45 + 46 + #define MPFS_PINCTRL_LOCKDOWN (PIN_CONFIG_END + 1) 47 + #define MPFS_PINCTRL_CLAMP_DIODE (PIN_CONFIG_END + 2) 48 + #define MPFS_PINCTRL_IBUFMD (PIN_CONFIG_END + 3) 49 + 50 + struct mpfs_pinctrl_mux_config { 51 + u8 pin; 52 + u8 function; 53 + }; 54 + 55 + struct mpfs_pinctrl { 56 + struct pinctrl_dev *pctrl; 57 + struct device *dev; 58 + struct regmap *regmap; 59 + struct regmap *sysreg_regmap; 60 + struct mutex mutex; 61 + struct pinctrl_desc desc; 62 + }; 63 + 64 + struct mpfs_pinctrl_drive_strength { 65 + u8 ma; 66 + u8 val; 67 + }; 68 + 69 + struct mpfs_pinctrl_bank_voltage { 70 + u32 uv; 71 + u8 val; 72 + }; 73 + 74 + static struct mpfs_pinctrl_drive_strength mpfs_pinctrl_drive_strengths[8] = { 75 + { .ma = 2, .val = 2 }, 76 + { .ma = 4, .val = 3 }, 77 + { .ma = 6, .val = 4 }, 78 + { .ma = 8, .val = 5 }, 79 + { .ma = 10, .val = 6 }, 80 + { .ma = 12, .val = 7 }, 81 + { .ma = 16, .val = 10 }, 82 + { .ma = 20, .val = 12 }, 83 + }; 84 + static struct mpfs_pinctrl_bank_voltage mpfs_pinctrl_bank_voltages[8] = { 85 + { .uv = 1200000, .val = 0 }, 86 + { .uv = 1500000, .val = 2 }, 87 + { .uv = 1800000, .val = 4 }, 88 + { .uv = 2500000, .val = 6 }, 89 + { .uv = 3300000, .val = 8 }, 90 + { .uv = 0, .val = 0x3f }, // pin unused 91 + }; 92 + 93 + static int mpfs_pinctrl_get_drive_strength_ma(u32 drive_strength) 94 + { 95 + size_t num = ARRAY_SIZE(mpfs_pinctrl_drive_strengths); 96 + 97 + for (int i = 0; i < num; i++) 98 + if (drive_strength == mpfs_pinctrl_drive_strengths[i].val) 99 + return mpfs_pinctrl_drive_strengths[i].ma; 100 + 101 + return -EINVAL; 102 + } 103 + 104 + static int mpfs_pinctrl_get_drive_strength_val(u32 drive_strength_ma) 105 + { 106 + size_t num = ARRAY_SIZE(mpfs_pinctrl_drive_strengths); 107 + 108 + if (!drive_strength_ma) 109 + return -EINVAL; 110 + 111 + for (int i = 0; i < num; i++) 112 + if (drive_strength_ma <= mpfs_pinctrl_drive_strengths[i].ma) 113 + return mpfs_pinctrl_drive_strengths[i].val; 114 + 115 + return mpfs_pinctrl_drive_strengths[num - 1].val; 116 + } 117 + 118 + static int mpfs_pinctrl_get_bank_voltage_uv(u32 bank_voltage) 119 + { 120 + size_t num = ARRAY_SIZE(mpfs_pinctrl_bank_voltages); 121 + 122 + for (int i = 0; i < num; i++) 123 + if (bank_voltage == mpfs_pinctrl_bank_voltages[i].val) 124 + return mpfs_pinctrl_bank_voltages[i].uv; 125 + 126 + return -EINVAL; 127 + } 128 + 129 + static int mpfs_pinctrl_get_bank_voltage_val(u32 bank_voltage_uv) 130 + { 131 + size_t num = ARRAY_SIZE(mpfs_pinctrl_bank_voltages); 132 + 133 + for (int i = 0; i < num; i++) 134 + if (bank_voltage_uv <= mpfs_pinctrl_bank_voltages[i].uv) 135 + return mpfs_pinctrl_bank_voltages[i].val; 136 + 137 + return -EINVAL; 138 + } 139 + 140 + static u32 mpfs_pinctrl_pin_to_bank_voltage(struct mpfs_pinctrl *pctrl, unsigned int pin) 141 + { 142 + u32 bank_voltage, val; 143 + 144 + if (pin < MPFS_PINCTRL_BANK2_START) 145 + regmap_read(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK4_CFG_CR, &val); 146 + else 147 + regmap_read(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK2_CFG_CR, &val); 148 + 149 + bank_voltage = FIELD_GET(MPFS_PINCTRL_BANK_VOLTAGE_MASK, val); 150 + 151 + return mpfs_pinctrl_get_bank_voltage_uv(bank_voltage); 152 + } 153 + 154 + static void mpfs_pinctrl_set_bank_voltage(struct mpfs_pinctrl *pctrl, unsigned int pin, 155 + u32 bank_voltage) 156 + { 157 + u32 val = FIELD_PREP(MPFS_PINCTRL_BANK_VOLTAGE_MASK, bank_voltage); 158 + 159 + if (pin < MPFS_PINCTRL_BANK2_START) 160 + regmap_assign_bits(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK4_CFG_CR, 161 + MPFS_PINCTRL_BANK_VOLTAGE_MASK, val); 162 + else 163 + regmap_assign_bits(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK2_CFG_CR, 164 + MPFS_PINCTRL_BANK_VOLTAGE_MASK, val); 165 + } 166 + 167 + static char *mpfs_pinctrl_function_names[] = { 168 + "sd", 169 + "emmc", 170 + "qspi", 171 + "spi", 172 + "usb", 173 + "uart", 174 + "i2c", 175 + "can", 176 + "mdio", 177 + "misc", 178 + "reserved", 179 + "gpio", 180 + "fabric test", 181 + "tied-low", 182 + "tied-high", 183 + "tristate" 184 + }; 185 + 186 + static int mpfs_pinctrl_function_map(const char *function) 187 + { 188 + size_t num = ARRAY_SIZE(mpfs_pinctrl_function_names); 189 + 190 + for (int i = 0; i < num; i++) 191 + if (!strcmp(function, mpfs_pinctrl_function_names[i])) 192 + return i; 193 + 194 + return -EINVAL; 195 + } 196 + 197 + static const struct pinconf_generic_params mpfs_pinctrl_custom_bindings[] = { 198 + { "microchip,clamp-diode", MPFS_PINCTRL_CLAMP_DIODE, 1 }, 199 + { "microchip,ibufmd", MPFS_PINCTRL_IBUFMD, 0x0 }, 200 + }; 201 + 202 + static int mpfs_pinctrl_pin_to_iomux_offset(unsigned int pin) 203 + { 204 + int offset; 205 + 206 + switch (pin) { 207 + case 0 ... 7: 208 + offset = pin * 4; 209 + break; 210 + case 8 ... 13: 211 + offset = (pin - 8) * 4; 212 + break; 213 + case 14 ... 21: 214 + offset = (pin - 14) * 4; 215 + break; 216 + case 22 ... 29: 217 + offset = (pin - 22) * 4; 218 + break; 219 + case 30 ... 37: 220 + offset = (pin - 30) * 4; 221 + break; 222 + default: 223 + offset = -EINVAL; 224 + } 225 + 226 + return offset; 227 + } 228 + 229 + static int mpfs_pinctrl_pin_to_iomux_reg(unsigned int pin) 230 + { 231 + int reg; 232 + 233 + switch (pin) { 234 + case 0 ... 7: 235 + reg = 0x204; 236 + break; 237 + case 8 ... 13: 238 + reg = 0x208; 239 + break; 240 + case 14 ... 21: 241 + reg = 0x20c; 242 + break; 243 + case 22 ... 29: 244 + reg = 0x210; 245 + break; 246 + case 30 ... 37: 247 + reg = 0x214; 248 + break; 249 + default: 250 + reg = -EINVAL; 251 + } 252 + 253 + return reg; 254 + } 255 + 256 + static int mpfs_pinctrl_pin_to_iocfg_reg(unsigned int pin) 257 + { 258 + u32 reg = MPFS_PINCTRL_IOCFG01_REG; 259 + 260 + if (pin >= MPFS_PINCTRL_BANK2_START) 261 + reg += MPFS_PINCTRL_INTER_BANK_GAP; 262 + 263 + // 2 pins per 32-bit register 264 + reg += (pin / 2) * 0x4; 265 + 266 + return reg; 267 + } 268 + 269 + static int mpfs_pinctrl_pin_to_iocfg_offset(unsigned int pin) 270 + { 271 + return 16 * (pin % 2); 272 + } 273 + 274 + static void mpfs_pinctrl_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq, 275 + unsigned int pin) 276 + { 277 + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 278 + u32 func; 279 + int reg, offset; 280 + 281 + reg = mpfs_pinctrl_pin_to_iomux_reg(pin); 282 + offset = mpfs_pinctrl_pin_to_iomux_offset(pin); 283 + 284 + seq_printf(seq, "reg: %x, offset: %u ", reg, offset); 285 + seq_printf(seq, "pin: %u ", pin); 286 + 287 + if (reg < 0 || offset < 0) 288 + return; 289 + 290 + regmap_read(pctrl->regmap, reg, &func); 291 + func = (func >> offset) & MPFS_PINCTRL_PAD_MUX_MASK; 292 + seq_printf(seq, "func: %s (%x)\n", mpfs_pinctrl_function_names[func], func); 293 + } 294 + 295 + static const struct pinctrl_ops mpfs_pinctrl_ops = { 296 + .get_groups_count = pinctrl_generic_get_group_count, 297 + .get_group_name = pinctrl_generic_get_group_name, 298 + .get_group_pins = pinctrl_generic_get_group_pins, 299 + .pin_dbg_show = mpfs_pinctrl_dbg_show, 300 + .dt_node_to_map = pinctrl_generic_pins_function_dt_node_to_map, 301 + .dt_free_map = pinctrl_utils_free_map, 302 + }; 303 + 304 + static int mpfs_pinctrl_set_pin_func(struct mpfs_pinctrl *pctrl, u8 pin, u8 function) 305 + { 306 + struct device *dev = pctrl->dev; 307 + int reg, offset; 308 + u32 func, mask; 309 + 310 + reg = mpfs_pinctrl_pin_to_iomux_reg(pin); 311 + offset = mpfs_pinctrl_pin_to_iomux_offset(pin); 312 + 313 + func = function << offset; 314 + mask = MPFS_PINCTRL_PAD_MUX_MASK << offset; 315 + 316 + dev_dbg(dev, "Setting pin %u. reg: %x offset %u func %x\n", pin, reg, offset, func); 317 + 318 + if (reg < 0 || offset < 0) 319 + return -EINVAL; 320 + 321 + regmap_update_bits(pctrl->regmap, reg, mask, func); 322 + 323 + return 0; 324 + } 325 + 326 + static int mpfs_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev, unsigned int fsel, 327 + unsigned int gsel) 328 + { 329 + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 330 + const struct group_desc *group; 331 + const char **functions; 332 + 333 + group = pinctrl_generic_get_group(pctrl_dev, gsel); 334 + if (!group) 335 + return -EINVAL; 336 + 337 + functions = group->data; 338 + 339 + for (int i = 0; i < group->grp.npins; i++) { 340 + int function; 341 + 342 + function = mpfs_pinctrl_function_map(functions[i]); 343 + if (function < 0) { 344 + dev_err(pctrl->dev, "invalid function %s\n", functions[i]); 345 + return function; 346 + } 347 + 348 + mpfs_pinctrl_set_pin_func(pctrl, group->grp.pins[i], function); 349 + } 350 + 351 + return 0; 352 + } 353 + 354 + static const struct pinmux_ops mpfs_pinctrl_pinmux_ops = { 355 + .get_functions_count = pinmux_generic_get_function_count, 356 + .get_function_name = pinmux_generic_get_function_name, 357 + .get_function_groups = pinmux_generic_get_function_groups, 358 + .set_mux = mpfs_pinctrl_set_mux, 359 + }; 360 + 361 + static int mpfs_pinctrl_pinconf_get(struct pinctrl_dev *pctrl_dev, unsigned int pin, 362 + unsigned long *config) 363 + { 364 + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 365 + int param = pinconf_to_config_param(*config); 366 + int reg = mpfs_pinctrl_pin_to_iocfg_reg(pin); 367 + int val; 368 + u32 arg; 369 + u8 str; 370 + 371 + regmap_read(pctrl->regmap, reg, &val); 372 + 373 + val = val >> mpfs_pinctrl_pin_to_iocfg_offset(pin); 374 + val = val & MPFS_PINCTRL_IOCFG_MASK; 375 + 376 + switch (param) { 377 + case PIN_CONFIG_BIAS_BUS_HOLD: 378 + if (!(val & MPFS_PINCTRL_WPD)) 379 + return -EINVAL; 380 + 381 + if (!(val & MPFS_PINCTRL_WPU)) 382 + return -EINVAL; 383 + 384 + arg = 1; 385 + break; 386 + case PIN_CONFIG_BIAS_PULL_DOWN: 387 + if (!(val & MPFS_PINCTRL_WPD)) 388 + return -EINVAL; 389 + 390 + if (val & MPFS_PINCTRL_WPU) 391 + return -EINVAL; 392 + 393 + arg = 1; 394 + break; 395 + case PIN_CONFIG_BIAS_PULL_UP: 396 + if (!(val & MPFS_PINCTRL_WPU)) 397 + return -EINVAL; 398 + 399 + if (val & MPFS_PINCTRL_WPD) 400 + return -EINVAL; 401 + 402 + arg = 1; 403 + break; 404 + case PIN_CONFIG_BIAS_DISABLE: 405 + if (val & MPFS_PINCTRL_PULL_MASK) 406 + return -EINVAL; 407 + 408 + arg = 1; 409 + break; 410 + case PIN_CONFIG_DRIVE_STRENGTH: 411 + str = FIELD_GET(MPFS_PINCTRL_DRV_MASK, val); 412 + if (!str) 413 + return -EINVAL; 414 + 415 + arg = mpfs_pinctrl_get_drive_strength_ma(str); 416 + break; 417 + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 418 + if (!FIELD_GET(MPFS_PINCTRL_ENHYST, val)) 419 + return -EINVAL; 420 + 421 + arg = 1; 422 + break; 423 + case PIN_CONFIG_PERSIST_STATE: 424 + if (!FIELD_GET(MPFS_PINCTRL_LP_PERSIST_EN, val)) 425 + return -EINVAL; 426 + 427 + arg = 1; 428 + break; 429 + case PIN_CONFIG_MODE_LOW_POWER: 430 + if (!FIELD_GET(MPFS_PINCTRL_LP_BYPASS_EN, val)) 431 + return -EINVAL; 432 + 433 + arg = 1; 434 + break; 435 + case PIN_CONFIG_POWER_SOURCE: 436 + arg = mpfs_pinctrl_pin_to_bank_voltage(pctrl, pin); 437 + break; 438 + case MPFS_PINCTRL_CLAMP_DIODE: 439 + if (!FIELD_GET(MPFS_PINCTRL_CLAMP, val)) 440 + return -EINVAL; 441 + 442 + arg = 1; 443 + break; 444 + case MPFS_PINCTRL_LOCKDOWN: 445 + /* 446 + * Lockdown is a read-only configuration, it'll get set if the 447 + * tamper unit triggers global lockdown and lockdown has been 448 + * set in the MSS Configurator for the bank a pin belongs to. 449 + */ 450 + if (!FIELD_GET(MPFS_PINCTRL_LOCKDN, val)) 451 + return -EINVAL; 452 + 453 + arg = 1; 454 + break; 455 + case MPFS_PINCTRL_IBUFMD: 456 + arg = FIELD_GET(MPFS_PINCTRL_IBUFMD_MASK, val); 457 + break; 458 + default: 459 + return -ENOTSUPP; 460 + } 461 + 462 + *config = pinconf_to_config_packed(param, arg); 463 + 464 + return 0; 465 + } 466 + 467 + static int mpfs_pinctrl_pinconf_generate_config(struct mpfs_pinctrl *pctrl, unsigned int pin, 468 + unsigned long *configs, unsigned int num_configs, 469 + u32 *value, u32 *bank_voltage) 470 + { 471 + u32 val = 0; 472 + 473 + for (int i = 0; i < num_configs; i++) { 474 + int param, tmp; 475 + u32 arg; 476 + 477 + param = pinconf_to_config_param(configs[i]); 478 + arg = pinconf_to_config_argument(configs[i]); 479 + 480 + switch (param) { 481 + case PIN_CONFIG_BIAS_BUS_HOLD: 482 + val |= MPFS_PINCTRL_PULL_MASK; 483 + break; 484 + case PIN_CONFIG_BIAS_PULL_DOWN: 485 + val &= ~MPFS_PINCTRL_PULL_MASK; 486 + val |= MPFS_PINCTRL_WPD; 487 + break; 488 + case PIN_CONFIG_BIAS_PULL_UP: 489 + val &= ~MPFS_PINCTRL_PULL_MASK; 490 + val |= MPFS_PINCTRL_WPU; 491 + break; 492 + case PIN_CONFIG_BIAS_DISABLE: 493 + val &= ~MPFS_PINCTRL_PULL_MASK; 494 + break; 495 + case PIN_CONFIG_DRIVE_STRENGTH: 496 + tmp = mpfs_pinctrl_get_drive_strength_val(arg); 497 + if (tmp < 0) 498 + return tmp; 499 + 500 + val |= FIELD_PREP(MPFS_PINCTRL_DRV_MASK, tmp); 501 + break; 502 + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 503 + if (!arg) 504 + break; 505 + val |= MPFS_PINCTRL_ENHYST; 506 + break; 507 + case PIN_CONFIG_PERSIST_STATE: 508 + val |= MPFS_PINCTRL_LP_PERSIST_EN; 509 + break; 510 + case PIN_CONFIG_MODE_LOW_POWER: 511 + if (arg) 512 + val |= MPFS_PINCTRL_LP_BYPASS_EN; 513 + break; 514 + case PIN_CONFIG_POWER_SOURCE: 515 + tmp = mpfs_pinctrl_get_bank_voltage_val(arg); 516 + if (tmp < 0) 517 + return tmp; 518 + 519 + *bank_voltage = tmp; 520 + break; 521 + case MPFS_PINCTRL_CLAMP_DIODE: 522 + val |= MPFS_PINCTRL_CLAMP; 523 + break; 524 + case MPFS_PINCTRL_IBUFMD: 525 + val |= FIELD_PREP(MPFS_PINCTRL_IBUFMD_MASK, arg); 526 + break; 527 + default: 528 + dev_err(pctrl->dev, "config %u not supported\n", param); 529 + return -ENOTSUPP; 530 + } 531 + } 532 + 533 + *value = val; 534 + return 0; 535 + } 536 + 537 + static int mpfs_pinctrl_pin_set_config(struct mpfs_pinctrl *pctrl, unsigned int pin, u32 config) 538 + { 539 + int reg = mpfs_pinctrl_pin_to_iocfg_reg(pin); 540 + int offset = mpfs_pinctrl_pin_to_iocfg_offset(pin); 541 + u32 val, mask; 542 + 543 + mask = MPFS_PINCTRL_IOCFG_MASK << offset; 544 + val = config << offset; 545 + 546 + regmap_update_bits(pctrl->regmap, reg, mask, val); 547 + 548 + return 0; 549 + } 550 + 551 + static int mpfs_pinctrl_pinconf_set(struct pinctrl_dev *pctrl_dev, unsigned int pin, 552 + unsigned long *configs, unsigned int num_configs) 553 + { 554 + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 555 + u32 val, bank_voltage = 0; 556 + int ret; 557 + 558 + ret = mpfs_pinctrl_pinconf_generate_config(pctrl, pin, configs, num_configs, &val, 559 + &bank_voltage); 560 + if (ret) 561 + return ret; 562 + 563 + ret = mpfs_pinctrl_pin_set_config(pctrl, pin, val); 564 + if (ret) 565 + return ret; 566 + 567 + if (bank_voltage) 568 + mpfs_pinctrl_set_bank_voltage(pctrl, pin, bank_voltage); 569 + 570 + return 0; 571 + } 572 + 573 + static int mpfs_pinctrl_pinconf_group_set(struct pinctrl_dev *pctrl_dev, unsigned int gsel, 574 + unsigned long *configs, unsigned int num_configs) 575 + { 576 + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 577 + const struct group_desc *group; 578 + unsigned int pin; 579 + u32 val, bank_voltage = 0; 580 + int ret; 581 + 582 + group = pinctrl_generic_get_group(pctrl_dev, gsel); 583 + if (!group) 584 + return -EINVAL; 585 + 586 + /* 587 + * Assume that the first pin in a group is representative, as the mss 588 + * configurator doesn't allow splitting a function between two banks. 589 + */ 590 + pin = group->grp.pins[0]; 591 + 592 + ret = mpfs_pinctrl_pinconf_generate_config(pctrl, pin, configs, num_configs, &val, 593 + &bank_voltage); 594 + if (ret) 595 + return ret; 596 + 597 + for (int i = 0; i < group->grp.npins; i++) 598 + mpfs_pinctrl_pin_set_config(pctrl, group->grp.pins[i], val); 599 + 600 + if (bank_voltage) 601 + mpfs_pinctrl_set_bank_voltage(pctrl, group->grp.pins[0], bank_voltage); 602 + 603 + return 0; 604 + } 605 + 606 + static void mpfs_pinctrl_pinconf_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq, 607 + unsigned int pin) 608 + { 609 + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 610 + u32 val; 611 + int reg, offset; 612 + 613 + reg = mpfs_pinctrl_pin_to_iocfg_reg(pin); 614 + offset = mpfs_pinctrl_pin_to_iocfg_offset(pin); 615 + 616 + seq_printf(seq, "pin: %u ", pin); 617 + seq_printf(seq, "reg: %x offset: %u ", reg, offset); 618 + 619 + if (reg < 0 || offset < 0) 620 + return; 621 + 622 + regmap_read(pctrl->regmap, reg, &val); 623 + val = (val & (MPFS_PINCTRL_IOCFG_MASK << offset)) >> offset; 624 + seq_printf(seq, "val: %x\n", val); 625 + } 626 + 627 + static const struct pinconf_ops mpfs_pinctrl_pinconf_ops = { 628 + .pin_config_get = mpfs_pinctrl_pinconf_get, 629 + .pin_config_set = mpfs_pinctrl_pinconf_set, 630 + .pin_config_group_set = mpfs_pinctrl_pinconf_group_set, 631 + .pin_config_dbg_show = mpfs_pinctrl_pinconf_dbg_show, 632 + .is_generic = true, 633 + }; 634 + 635 + static const struct pinctrl_pin_desc mpfs_pinctrl_pins[] = { 636 + PINCTRL_PIN(0, "bank 4 0"), 637 + PINCTRL_PIN(1, "bank 4 1"), 638 + PINCTRL_PIN(2, "bank 4 2"), 639 + PINCTRL_PIN(3, "bank 4 3"), 640 + PINCTRL_PIN(4, "bank 4 4"), 641 + PINCTRL_PIN(5, "bank 4 5"), 642 + PINCTRL_PIN(6, "bank 4 6"), 643 + PINCTRL_PIN(7, "bank 4 7"), 644 + PINCTRL_PIN(8, "bank 4 8"), 645 + PINCTRL_PIN(9, "bank 4 9"), 646 + PINCTRL_PIN(10, "bank 4 10"), 647 + PINCTRL_PIN(11, "bank 4 11"), 648 + PINCTRL_PIN(12, "bank 4 12"), 649 + PINCTRL_PIN(13, "bank 4 13"), 650 + 651 + PINCTRL_PIN(14, "bank 2 0"), 652 + PINCTRL_PIN(15, "bank 2 1"), 653 + PINCTRL_PIN(16, "bank 2 2"), 654 + PINCTRL_PIN(17, "bank 2 3"), 655 + PINCTRL_PIN(18, "bank 2 4"), 656 + PINCTRL_PIN(19, "bank 2 5"), 657 + PINCTRL_PIN(20, "bank 2 6"), 658 + PINCTRL_PIN(21, "bank 2 7"), 659 + PINCTRL_PIN(22, "bank 2 8"), 660 + PINCTRL_PIN(23, "bank 2 9"), 661 + PINCTRL_PIN(24, "bank 2 10"), 662 + PINCTRL_PIN(25, "bank 2 11"), 663 + PINCTRL_PIN(26, "bank 2 12"), 664 + PINCTRL_PIN(27, "bank 2 13"), 665 + PINCTRL_PIN(28, "bank 2 14"), 666 + PINCTRL_PIN(29, "bank 2 15"), 667 + PINCTRL_PIN(30, "bank 2 16"), 668 + PINCTRL_PIN(31, "bank 2 17"), 669 + PINCTRL_PIN(32, "bank 2 18"), 670 + PINCTRL_PIN(33, "bank 2 19"), 671 + PINCTRL_PIN(34, "bank 2 20"), 672 + PINCTRL_PIN(35, "bank 2 21"), 673 + PINCTRL_PIN(36, "bank 2 22"), 674 + PINCTRL_PIN(37, "bank 2 23"), 675 + }; 676 + 677 + static int mpfs_pinctrl_probe(struct platform_device *pdev) 678 + { 679 + struct device *dev = &pdev->dev; 680 + struct mpfs_pinctrl *pctrl; 681 + int ret; 682 + 683 + pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); 684 + if (!pctrl) 685 + return -ENOMEM; 686 + 687 + pctrl->regmap = device_node_to_regmap(pdev->dev.parent->of_node); 688 + if (IS_ERR(pctrl->regmap)) 689 + dev_err_probe(dev, PTR_ERR(pctrl->regmap), "Failed to find syscon regmap\n"); 690 + 691 + pctrl->sysreg_regmap = syscon_regmap_lookup_by_compatible("microchip,mpfs-sysreg-scb"); 692 + if (IS_ERR(pctrl->sysreg_regmap)) 693 + return PTR_ERR(pctrl->sysreg_regmap); 694 + 695 + pctrl->desc.name = dev_name(dev); 696 + pctrl->desc.pins = mpfs_pinctrl_pins; 697 + pctrl->desc.npins = ARRAY_SIZE(mpfs_pinctrl_pins); 698 + pctrl->desc.pctlops = &mpfs_pinctrl_ops; 699 + pctrl->desc.pmxops = &mpfs_pinctrl_pinmux_ops; 700 + pctrl->desc.confops = &mpfs_pinctrl_pinconf_ops; 701 + pctrl->desc.owner = THIS_MODULE; 702 + pctrl->desc.num_custom_params = ARRAY_SIZE(mpfs_pinctrl_custom_bindings); 703 + pctrl->desc.custom_params = mpfs_pinctrl_custom_bindings; 704 + 705 + pctrl->dev = dev; 706 + 707 + ret = devm_mutex_init(dev, &pctrl->mutex); 708 + if (ret) 709 + return ret; 710 + 711 + platform_set_drvdata(pdev, pctrl); 712 + 713 + pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl); 714 + if (IS_ERR(pctrl->pctrl)) 715 + return PTR_ERR(pctrl->pctrl); 716 + 717 + return 0; 718 + } 719 + 720 + static const struct of_device_id mpfs_pinctrl_of_match[] = { 721 + { .compatible = "microchip,mpfs-pinctrl-mssio" }, 722 + { } 723 + }; 724 + MODULE_DEVICE_TABLE(of, mpfs_pinctrl_of_match); 725 + 726 + static struct platform_driver mpfs_pinctrl_driver = { 727 + .driver = { 728 + .name = "mpfs-pinctrl", 729 + .of_match_table = mpfs_pinctrl_of_match, 730 + }, 731 + .probe = mpfs_pinctrl_probe, 732 + }; 733 + module_platform_driver(mpfs_pinctrl_driver); 734 + 735 + MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>"); 736 + MODULE_DESCRIPTION("Polarfire SoC mssio pinctrl driver"); 737 + MODULE_LICENSE("GPL");