1105 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Pinctrl for Cirrus Logic Madera codecs4 *5 * Copyright (C) 2016-2018 Cirrus Logic6 */7 8#include <linux/err.h>9#include <linux/module.h>10#include <linux/platform_device.h>11#include <linux/property.h>12#include <linux/regmap.h>13#include <linux/seq_file.h>14#include <linux/slab.h>15 16#include <linux/pinctrl/machine.h>17#include <linux/pinctrl/pinconf-generic.h>18#include <linux/pinctrl/pinconf.h>19#include <linux/pinctrl/pinctrl.h>20#include <linux/pinctrl/pinmux.h>21 22#include <linux/mfd/madera/core.h>23#include <linux/mfd/madera/registers.h>24 25#include "../pinctrl-utils.h"26 27#include "pinctrl-madera.h"28 29/*30 * Use pin GPIO names for consistency31 * NOTE: IDs are zero-indexed for coding convenience32 */33static const struct pinctrl_pin_desc madera_pins[] = {34 PINCTRL_PIN(0, "gpio1"),35 PINCTRL_PIN(1, "gpio2"),36 PINCTRL_PIN(2, "gpio3"),37 PINCTRL_PIN(3, "gpio4"),38 PINCTRL_PIN(4, "gpio5"),39 PINCTRL_PIN(5, "gpio6"),40 PINCTRL_PIN(6, "gpio7"),41 PINCTRL_PIN(7, "gpio8"),42 PINCTRL_PIN(8, "gpio9"),43 PINCTRL_PIN(9, "gpio10"),44 PINCTRL_PIN(10, "gpio11"),45 PINCTRL_PIN(11, "gpio12"),46 PINCTRL_PIN(12, "gpio13"),47 PINCTRL_PIN(13, "gpio14"),48 PINCTRL_PIN(14, "gpio15"),49 PINCTRL_PIN(15, "gpio16"),50 PINCTRL_PIN(16, "gpio17"),51 PINCTRL_PIN(17, "gpio18"),52 PINCTRL_PIN(18, "gpio19"),53 PINCTRL_PIN(19, "gpio20"),54 PINCTRL_PIN(20, "gpio21"),55 PINCTRL_PIN(21, "gpio22"),56 PINCTRL_PIN(22, "gpio23"),57 PINCTRL_PIN(23, "gpio24"),58 PINCTRL_PIN(24, "gpio25"),59 PINCTRL_PIN(25, "gpio26"),60 PINCTRL_PIN(26, "gpio27"),61 PINCTRL_PIN(27, "gpio28"),62 PINCTRL_PIN(28, "gpio29"),63 PINCTRL_PIN(29, "gpio30"),64 PINCTRL_PIN(30, "gpio31"),65 PINCTRL_PIN(31, "gpio32"),66 PINCTRL_PIN(32, "gpio33"),67 PINCTRL_PIN(33, "gpio34"),68 PINCTRL_PIN(34, "gpio35"),69 PINCTRL_PIN(35, "gpio36"),70 PINCTRL_PIN(36, "gpio37"),71 PINCTRL_PIN(37, "gpio38"),72 PINCTRL_PIN(38, "gpio39"),73 PINCTRL_PIN(39, "gpio40"),74};75 76/*77 * All single-pin functions can be mapped to any GPIO, however pinmux applies78 * functions to pin groups and only those groups declared as supporting that79 * function. To make this work we must put each pin in its own dummy group so80 * that the functions can be described as applying to all pins.81 * Since these do not correspond to anything in the actual hardware - they are82 * merely an adaptation to pinctrl's view of the world - we use the same name83 * as the pin to avoid confusion when comparing with datasheet instructions84 */85static const char * const madera_pin_single_group_names[] = {86 "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",87 "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",88 "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",89 "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",90 "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",91 "gpio36", "gpio37", "gpio38", "gpio39", "gpio40",92};93 94/* set of pin numbers for single-pin groups, zero-indexed */95static const unsigned int madera_pin_single_group_pins[] = {96 0, 1, 2, 3, 4, 5, 6,97 7, 8, 9, 10, 11, 12, 13,98 14, 15, 16, 17, 18, 19, 20,99 21, 22, 23, 24, 25, 26, 27,100 28, 29, 30, 31, 32, 33, 34,101 35, 36, 37, 38, 39,102};103 104static const char * const madera_aif1_group_names[] = { "aif1" };105static const char * const madera_aif2_group_names[] = { "aif2" };106static const char * const madera_aif3_group_names[] = { "aif3" };107static const char * const madera_aif4_group_names[] = { "aif4" };108static const char * const madera_mif1_group_names[] = { "mif1" };109static const char * const madera_mif2_group_names[] = { "mif2" };110static const char * const madera_mif3_group_names[] = { "mif3" };111static const char * const madera_dmic3_group_names[] = { "dmic3" };112static const char * const madera_dmic4_group_names[] = { "dmic4" };113static const char * const madera_dmic5_group_names[] = { "dmic5" };114static const char * const madera_dmic6_group_names[] = { "dmic6" };115static const char * const madera_spk1_group_names[] = { "pdmspk1" };116static const char * const madera_spk2_group_names[] = { "pdmspk2" };117 118/*119 * alt-functions always apply to a single pin group, other functions always120 * apply to all pins121 */122static const struct {123 const char *name;124 const char * const *group_names;125 u32 func;126} madera_mux_funcs[] = {127 {128 .name = "aif1",129 .group_names = madera_aif1_group_names,130 .func = 0x000131 },132 {133 .name = "aif2",134 .group_names = madera_aif2_group_names,135 .func = 0x000136 },137 {138 .name = "aif3",139 .group_names = madera_aif3_group_names,140 .func = 0x000141 },142 {143 .name = "aif4",144 .group_names = madera_aif4_group_names,145 .func = 0x000146 },147 {148 .name = "mif1",149 .group_names = madera_mif1_group_names,150 .func = 0x000151 },152 {153 .name = "mif2",154 .group_names = madera_mif2_group_names,155 .func = 0x000156 },157 {158 .name = "mif3",159 .group_names = madera_mif3_group_names,160 .func = 0x000161 },162 {163 .name = "dmic3",164 .group_names = madera_dmic3_group_names,165 .func = 0x000166 },167 {168 .name = "dmic4",169 .group_names = madera_dmic4_group_names,170 .func = 0x000171 },172 {173 .name = "dmic5",174 .group_names = madera_dmic5_group_names,175 .func = 0x000176 },177 {178 .name = "dmic6",179 .group_names = madera_dmic6_group_names,180 .func = 0x000181 },182 {183 .name = "pdmspk1",184 .group_names = madera_spk1_group_names,185 .func = 0x000186 },187 {188 .name = "pdmspk2",189 .group_names = madera_spk2_group_names,190 .func = 0x000191 },192 {193 .name = "io",194 .group_names = madera_pin_single_group_names,195 .func = 0x001196 },197 {198 .name = "dsp-gpio",199 .group_names = madera_pin_single_group_names,200 .func = 0x002201 },202 {203 .name = "irq1",204 .group_names = madera_pin_single_group_names,205 .func = 0x003206 },207 {208 .name = "irq2",209 .group_names = madera_pin_single_group_names,210 .func = 0x004211 },212 {213 .name = "fll1-clk",214 .group_names = madera_pin_single_group_names,215 .func = 0x010216 },217 {218 .name = "fll2-clk",219 .group_names = madera_pin_single_group_names,220 .func = 0x011221 },222 {223 .name = "fll3-clk",224 .group_names = madera_pin_single_group_names,225 .func = 0x012226 },227 {228 .name = "fllao-clk",229 .group_names = madera_pin_single_group_names,230 .func = 0x013231 },232 {233 .name = "fll1-lock",234 .group_names = madera_pin_single_group_names,235 .func = 0x018236 },237 {238 .name = "fll2-lock",239 .group_names = madera_pin_single_group_names,240 .func = 0x019241 },242 {243 .name = "fll3-lock",244 .group_names = madera_pin_single_group_names,245 .func = 0x01a246 },247 {248 .name = "fllao-lock",249 .group_names = madera_pin_single_group_names,250 .func = 0x01b251 },252 {253 .name = "opclk",254 .group_names = madera_pin_single_group_names,255 .func = 0x040256 },257 {258 .name = "opclk-async",259 .group_names = madera_pin_single_group_names,260 .func = 0x041261 },262 {263 .name = "pwm1",264 .group_names = madera_pin_single_group_names,265 .func = 0x048266 },267 {268 .name = "pwm2",269 .group_names = madera_pin_single_group_names,270 .func = 0x049271 },272 {273 .name = "spdif",274 .group_names = madera_pin_single_group_names,275 .func = 0x04c276 },277 {278 .name = "asrc1-in1-lock",279 .group_names = madera_pin_single_group_names,280 .func = 0x088281 },282 {283 .name = "asrc1-in2-lock",284 .group_names = madera_pin_single_group_names,285 .func = 0x089286 },287 {288 .name = "asrc2-in1-lock",289 .group_names = madera_pin_single_group_names,290 .func = 0x08a291 },292 {293 .name = "asrc2-in2-lock",294 .group_names = madera_pin_single_group_names,295 .func = 0x08b296 },297 {298 .name = "spkl-short-circuit",299 .group_names = madera_pin_single_group_names,300 .func = 0x0b6301 },302 {303 .name = "spkr-short-circuit",304 .group_names = madera_pin_single_group_names,305 .func = 0x0b7306 },307 {308 .name = "spk-shutdown",309 .group_names = madera_pin_single_group_names,310 .func = 0x0e0311 },312 {313 .name = "spk-overheat-shutdown",314 .group_names = madera_pin_single_group_names,315 .func = 0x0e1316 },317 {318 .name = "spk-overheat-warn",319 .group_names = madera_pin_single_group_names,320 .func = 0x0e2321 },322 {323 .name = "timer1-sts",324 .group_names = madera_pin_single_group_names,325 .func = 0x140326 },327 {328 .name = "timer2-sts",329 .group_names = madera_pin_single_group_names,330 .func = 0x141331 },332 {333 .name = "timer3-sts",334 .group_names = madera_pin_single_group_names,335 .func = 0x142336 },337 {338 .name = "timer4-sts",339 .group_names = madera_pin_single_group_names,340 .func = 0x143341 },342 {343 .name = "timer5-sts",344 .group_names = madera_pin_single_group_names,345 .func = 0x144346 },347 {348 .name = "timer6-sts",349 .group_names = madera_pin_single_group_names,350 .func = 0x145351 },352 {353 .name = "timer7-sts",354 .group_names = madera_pin_single_group_names,355 .func = 0x146356 },357 {358 .name = "timer8-sts",359 .group_names = madera_pin_single_group_names,360 .func = 0x147361 },362 {363 .name = "log1-fifo-ne",364 .group_names = madera_pin_single_group_names,365 .func = 0x150366 },367 {368 .name = "log2-fifo-ne",369 .group_names = madera_pin_single_group_names,370 .func = 0x151371 },372 {373 .name = "log3-fifo-ne",374 .group_names = madera_pin_single_group_names,375 .func = 0x152376 },377 {378 .name = "log4-fifo-ne",379 .group_names = madera_pin_single_group_names,380 .func = 0x153381 },382 {383 .name = "log5-fifo-ne",384 .group_names = madera_pin_single_group_names,385 .func = 0x154386 },387 {388 .name = "log6-fifo-ne",389 .group_names = madera_pin_single_group_names,390 .func = 0x155391 },392 {393 .name = "log7-fifo-ne",394 .group_names = madera_pin_single_group_names,395 .func = 0x156396 },397 {398 .name = "log8-fifo-ne",399 .group_names = madera_pin_single_group_names,400 .func = 0x157401 },402 {403 .name = "aux-pdm-clk",404 .group_names = madera_pin_single_group_names,405 .func = 0x280406 },407 {408 .name = "aux-pdm-dat",409 .group_names = madera_pin_single_group_names,410 .func = 0x281411 },412};413 414static u16 madera_pin_make_drv_str(struct madera_pin_private *priv,415 unsigned int milliamps)416{417 switch (milliamps) {418 case 4:419 return 0;420 case 8:421 return 2 << MADERA_GP1_DRV_STR_SHIFT;422 default:423 break;424 }425 426 dev_warn(priv->dev, "%u mA not a valid drive strength", milliamps);427 428 return 0;429}430 431static unsigned int madera_pin_unmake_drv_str(struct madera_pin_private *priv,432 u16 regval)433{434 regval = (regval & MADERA_GP1_DRV_STR_MASK) >> MADERA_GP1_DRV_STR_SHIFT;435 436 switch (regval) {437 case 0:438 return 4;439 case 2:440 return 8;441 default:442 return 0;443 }444}445 446static int madera_get_groups_count(struct pinctrl_dev *pctldev)447{448 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);449 450 /* Number of alt function groups plus number of single-pin groups */451 return priv->chip->n_pin_groups + priv->chip->n_pins;452}453 454static const char *madera_get_group_name(struct pinctrl_dev *pctldev,455 unsigned int selector)456{457 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);458 459 if (selector < priv->chip->n_pin_groups)460 return priv->chip->pin_groups[selector].name;461 462 selector -= priv->chip->n_pin_groups;463 return madera_pin_single_group_names[selector];464}465 466static int madera_get_group_pins(struct pinctrl_dev *pctldev,467 unsigned int selector,468 const unsigned int **pins,469 unsigned int *num_pins)470{471 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);472 473 if (selector < priv->chip->n_pin_groups) {474 *pins = priv->chip->pin_groups[selector].pins;475 *num_pins = priv->chip->pin_groups[selector].n_pins;476 } else {477 /* return the dummy group for a single pin */478 selector -= priv->chip->n_pin_groups;479 *pins = &madera_pin_single_group_pins[selector];480 *num_pins = 1;481 }482 return 0;483}484 485static void madera_pin_dbg_show_fn(struct madera_pin_private *priv,486 struct seq_file *s,487 unsigned int pin, unsigned int fn)488{489 const struct madera_pin_chip *chip = priv->chip;490 int i, g_pin;491 492 if (fn != 0) {493 for (i = 0; i < ARRAY_SIZE(madera_mux_funcs); ++i) {494 if (madera_mux_funcs[i].func == fn) {495 seq_printf(s, " FN=%s",496 madera_mux_funcs[i].name);497 return;498 }499 }500 return; /* ignore unknown function values */501 }502 503 /* alt function */504 for (i = 0; i < chip->n_pin_groups; ++i) {505 for (g_pin = 0; g_pin < chip->pin_groups[i].n_pins; ++g_pin) {506 if (chip->pin_groups[i].pins[g_pin] == pin) {507 seq_printf(s, " FN=%s",508 chip->pin_groups[i].name);509 return;510 }511 }512 }513}514 515static void __maybe_unused madera_pin_dbg_show(struct pinctrl_dev *pctldev,516 struct seq_file *s,517 unsigned int pin)518{519 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);520 unsigned int conf[2];521 unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);522 unsigned int fn;523 int ret;524 525 ret = regmap_read(priv->madera->regmap, reg, &conf[0]);526 if (ret)527 return;528 529 ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);530 if (ret)531 return;532 533 seq_printf(s, "%04x:%04x", conf[0], conf[1]);534 535 fn = (conf[0] & MADERA_GP1_FN_MASK) >> MADERA_GP1_FN_SHIFT;536 madera_pin_dbg_show_fn(priv, s, pin, fn);537 538 /* State of direction bit is only relevant if function==1 */539 if (fn == 1) {540 if (conf[1] & MADERA_GP1_DIR_MASK)541 seq_puts(s, " IN");542 else543 seq_puts(s, " OUT");544 }545 546 if (conf[1] & MADERA_GP1_PU_MASK)547 seq_puts(s, " PU");548 549 if (conf[1] & MADERA_GP1_PD_MASK)550 seq_puts(s, " PD");551 552 if (conf[0] & MADERA_GP1_DB_MASK)553 seq_puts(s, " DB");554 555 if (conf[0] & MADERA_GP1_OP_CFG_MASK)556 seq_puts(s, " OD");557 else558 seq_puts(s, " CMOS");559 560 seq_printf(s, " DRV=%umA", madera_pin_unmake_drv_str(priv, conf[1]));561 562 if (conf[0] & MADERA_GP1_IP_CFG_MASK)563 seq_puts(s, " SCHMITT");564}565 566static const struct pinctrl_ops madera_pin_group_ops = {567 .get_groups_count = madera_get_groups_count,568 .get_group_name = madera_get_group_name,569 .get_group_pins = madera_get_group_pins,570#if IS_ENABLED(CONFIG_OF)571 .dt_node_to_map = pinconf_generic_dt_node_to_map_all,572 .dt_free_map = pinctrl_utils_free_map,573#endif574#if IS_ENABLED(CONFIG_DEBUG_FS)575 .pin_dbg_show = madera_pin_dbg_show,576#endif577};578 579static int madera_mux_get_funcs_count(struct pinctrl_dev *pctldev)580{581 return ARRAY_SIZE(madera_mux_funcs);582}583 584static const char *madera_mux_get_func_name(struct pinctrl_dev *pctldev,585 unsigned int selector)586{587 return madera_mux_funcs[selector].name;588}589 590static int madera_mux_get_groups(struct pinctrl_dev *pctldev,591 unsigned int selector,592 const char * const **groups,593 unsigned int * const num_groups)594{595 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);596 597 *groups = madera_mux_funcs[selector].group_names;598 599 if (madera_mux_funcs[selector].func == 0) {600 /* alt func always maps to a single group */601 *num_groups = 1;602 } else {603 /* other funcs map to all available gpio pins */604 *num_groups = priv->chip->n_pins;605 }606 607 return 0;608}609 610static int madera_mux_set_mux(struct pinctrl_dev *pctldev,611 unsigned int selector,612 unsigned int group)613{614 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);615 struct madera *madera = priv->madera;616 const struct madera_pin_groups *pin_group = priv->chip->pin_groups;617 unsigned int n_chip_groups = priv->chip->n_pin_groups;618 const char *func_name = madera_mux_funcs[selector].name;619 unsigned int reg;620 int i, ret = 0;621 622 dev_dbg(priv->dev, "%s selecting %u (%s) for group %u (%s)\n",623 __func__, selector, func_name, group,624 madera_get_group_name(pctldev, group));625 626 if (madera_mux_funcs[selector].func == 0) {627 /* alt func pin assignments are codec-specific */628 for (i = 0; i < n_chip_groups; ++i) {629 if (strcmp(func_name, pin_group->name) == 0)630 break;631 632 ++pin_group;633 }634 635 if (i == n_chip_groups)636 return -EINVAL;637 638 for (i = 0; i < pin_group->n_pins; ++i) {639 reg = MADERA_GPIO1_CTRL_1 + (2 * pin_group->pins[i]);640 641 dev_dbg(priv->dev, "%s setting 0x%x func bits to 0\n",642 __func__, reg);643 644 ret = regmap_update_bits(madera->regmap, reg,645 MADERA_GP1_FN_MASK, 0);646 if (ret)647 break;648 649 }650 } else {651 /*652 * for other funcs the group will be the gpio number and will653 * be offset by the number of chip-specific functions at the654 * start of the group list655 */656 group -= n_chip_groups;657 reg = MADERA_GPIO1_CTRL_1 + (2 * group);658 659 dev_dbg(priv->dev, "%s setting 0x%x func bits to 0x%x\n",660 __func__, reg, madera_mux_funcs[selector].func);661 662 ret = regmap_update_bits(madera->regmap,663 reg,664 MADERA_GP1_FN_MASK,665 madera_mux_funcs[selector].func);666 }667 668 if (ret)669 dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);670 671 return ret;672}673 674static int madera_gpio_set_direction(struct pinctrl_dev *pctldev,675 struct pinctrl_gpio_range *range,676 unsigned int offset,677 bool input)678{679 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);680 struct madera *madera = priv->madera;681 unsigned int reg = MADERA_GPIO1_CTRL_2 + (2 * offset);682 unsigned int val;683 int ret;684 685 if (input)686 val = MADERA_GP1_DIR;687 else688 val = 0;689 690 ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_DIR_MASK, val);691 if (ret)692 dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);693 694 return ret;695}696 697static int madera_gpio_request_enable(struct pinctrl_dev *pctldev,698 struct pinctrl_gpio_range *range,699 unsigned int offset)700{701 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);702 struct madera *madera = priv->madera;703 unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);704 int ret;705 706 /* put the pin into GPIO mode */707 ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);708 if (ret)709 dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);710 711 return ret;712}713 714static void madera_gpio_disable_free(struct pinctrl_dev *pctldev,715 struct pinctrl_gpio_range *range,716 unsigned int offset)717{718 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);719 struct madera *madera = priv->madera;720 unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);721 int ret;722 723 /* disable GPIO by setting to GPIO IN */724 madera_gpio_set_direction(pctldev, range, offset, true);725 726 ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);727 if (ret)728 dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);729}730 731static const struct pinmux_ops madera_pin_mux_ops = {732 .get_functions_count = madera_mux_get_funcs_count,733 .get_function_name = madera_mux_get_func_name,734 .get_function_groups = madera_mux_get_groups,735 .set_mux = madera_mux_set_mux,736 .gpio_request_enable = madera_gpio_request_enable,737 .gpio_disable_free = madera_gpio_disable_free,738 .gpio_set_direction = madera_gpio_set_direction,739 .strict = true, /* GPIO and other functions are exclusive */740};741 742static int madera_pin_conf_get(struct pinctrl_dev *pctldev, unsigned int pin,743 unsigned long *config)744{745 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);746 unsigned int param = pinconf_to_config_param(*config);747 unsigned int result = 0;748 unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);749 unsigned int conf[2];750 int ret;751 752 ret = regmap_read(priv->madera->regmap, reg, &conf[0]);753 if (!ret)754 ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);755 756 if (ret) {757 dev_err(priv->dev, "Failed to read GP%d conf (%d)\n",758 pin + 1, ret);759 return ret;760 }761 762 switch (param) {763 case PIN_CONFIG_BIAS_BUS_HOLD:764 conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;765 if (conf[1] == (MADERA_GP1_PU | MADERA_GP1_PD))766 result = 1;767 break;768 case PIN_CONFIG_BIAS_DISABLE:769 conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;770 if (!conf[1])771 result = 1;772 break;773 case PIN_CONFIG_BIAS_PULL_DOWN:774 conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;775 if (conf[1] == MADERA_GP1_PD_MASK)776 result = 1;777 break;778 case PIN_CONFIG_BIAS_PULL_UP:779 conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;780 if (conf[1] == MADERA_GP1_PU_MASK)781 result = 1;782 break;783 case PIN_CONFIG_DRIVE_OPEN_DRAIN:784 if (conf[0] & MADERA_GP1_OP_CFG_MASK)785 result = 1;786 break;787 case PIN_CONFIG_DRIVE_PUSH_PULL:788 if (!(conf[0] & MADERA_GP1_OP_CFG_MASK))789 result = 1;790 break;791 case PIN_CONFIG_DRIVE_STRENGTH:792 result = madera_pin_unmake_drv_str(priv, conf[1]);793 break;794 case PIN_CONFIG_INPUT_DEBOUNCE:795 if (conf[0] & MADERA_GP1_DB_MASK)796 result = 1;797 break;798 case PIN_CONFIG_INPUT_ENABLE:799 if (conf[0] & MADERA_GP1_DIR_MASK)800 result = 1;801 break;802 case PIN_CONFIG_INPUT_SCHMITT:803 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:804 if (conf[0] & MADERA_GP1_IP_CFG_MASK)805 result = 1;806 break;807 case PIN_CONFIG_OUTPUT:808 if ((conf[1] & MADERA_GP1_DIR_MASK) &&809 (conf[0] & MADERA_GP1_LVL_MASK))810 result = 1;811 break;812 default:813 return -ENOTSUPP;814 }815 816 *config = pinconf_to_config_packed(param, result);817 818 return 0;819}820 821static int madera_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin,822 unsigned long *configs, unsigned int num_configs)823{824 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);825 u16 conf[2] = {0, 0};826 u16 mask[2] = {0, 0};827 unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);828 unsigned int val;829 int ret;830 831 while (num_configs) {832 dev_dbg(priv->dev, "%s config 0x%lx\n", __func__, *configs);833 834 switch (pinconf_to_config_param(*configs)) {835 case PIN_CONFIG_BIAS_BUS_HOLD:836 mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;837 conf[1] |= MADERA_GP1_PU | MADERA_GP1_PD;838 break;839 case PIN_CONFIG_BIAS_DISABLE:840 mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;841 conf[1] &= ~(MADERA_GP1_PU | MADERA_GP1_PD);842 break;843 case PIN_CONFIG_BIAS_PULL_DOWN:844 mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;845 conf[1] |= MADERA_GP1_PD;846 conf[1] &= ~MADERA_GP1_PU;847 break;848 case PIN_CONFIG_BIAS_PULL_UP:849 mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;850 conf[1] |= MADERA_GP1_PU;851 conf[1] &= ~MADERA_GP1_PD;852 break;853 case PIN_CONFIG_DRIVE_OPEN_DRAIN:854 mask[0] |= MADERA_GP1_OP_CFG_MASK;855 conf[0] |= MADERA_GP1_OP_CFG;856 break;857 case PIN_CONFIG_DRIVE_PUSH_PULL:858 mask[0] |= MADERA_GP1_OP_CFG_MASK;859 conf[0] &= ~MADERA_GP1_OP_CFG;860 break;861 case PIN_CONFIG_DRIVE_STRENGTH:862 val = pinconf_to_config_argument(*configs);863 mask[1] |= MADERA_GP1_DRV_STR_MASK;864 conf[1] &= ~MADERA_GP1_DRV_STR_MASK;865 conf[1] |= madera_pin_make_drv_str(priv, val);866 break;867 case PIN_CONFIG_INPUT_DEBOUNCE:868 mask[0] |= MADERA_GP1_DB_MASK;869 870 /*871 * we can't configure debounce time per-pin so value872 * is just a flag873 */874 val = pinconf_to_config_argument(*configs);875 if (val)876 conf[0] |= MADERA_GP1_DB;877 else878 conf[0] &= ~MADERA_GP1_DB;879 break;880 case PIN_CONFIG_INPUT_ENABLE:881 val = pinconf_to_config_argument(*configs);882 mask[1] |= MADERA_GP1_DIR_MASK;883 if (val)884 conf[1] |= MADERA_GP1_DIR;885 else886 conf[1] &= ~MADERA_GP1_DIR;887 break;888 case PIN_CONFIG_INPUT_SCHMITT:889 val = pinconf_to_config_argument(*configs);890 mask[0] |= MADERA_GP1_IP_CFG;891 if (val)892 conf[0] |= MADERA_GP1_IP_CFG;893 else894 conf[0] &= ~MADERA_GP1_IP_CFG;895 896 mask[1] |= MADERA_GP1_DIR_MASK;897 conf[1] |= MADERA_GP1_DIR;898 break;899 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:900 mask[0] |= MADERA_GP1_IP_CFG;901 conf[0] |= MADERA_GP1_IP_CFG;902 mask[1] |= MADERA_GP1_DIR_MASK;903 conf[1] |= MADERA_GP1_DIR;904 break;905 case PIN_CONFIG_OUTPUT:906 val = pinconf_to_config_argument(*configs);907 mask[0] |= MADERA_GP1_LVL_MASK;908 if (val)909 conf[0] |= MADERA_GP1_LVL;910 else911 conf[0] &= ~MADERA_GP1_LVL;912 913 mask[1] |= MADERA_GP1_DIR_MASK;914 conf[1] &= ~MADERA_GP1_DIR;915 break;916 default:917 return -ENOTSUPP;918 }919 920 ++configs;921 --num_configs;922 }923 924 dev_dbg(priv->dev,925 "%s gpio%d 0x%x:0x%x 0x%x:0x%x\n",926 __func__, pin + 1, reg, conf[0], reg + 1, conf[1]);927 928 ret = regmap_update_bits(priv->madera->regmap, reg, mask[0], conf[0]);929 if (ret)930 goto err;931 932 ++reg;933 ret = regmap_update_bits(priv->madera->regmap, reg, mask[1], conf[1]);934 if (ret)935 goto err;936 937 return 0;938 939err:940 dev_err(priv->dev,941 "Failed to write GPIO%d conf (%d) reg 0x%x\n",942 pin + 1, ret, reg);943 944 return ret;945}946 947static int madera_pin_conf_group_set(struct pinctrl_dev *pctldev,948 unsigned int selector,949 unsigned long *configs,950 unsigned int num_configs)951{952 struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);953 const struct madera_pin_groups *pin_group;954 unsigned int n_groups = priv->chip->n_pin_groups;955 int i, ret;956 957 dev_dbg(priv->dev, "%s setting group %s\n", __func__,958 madera_get_group_name(pctldev, selector));959 960 if (selector >= n_groups) {961 /* group is a single pin, convert to pin number and set */962 return madera_pin_conf_set(pctldev,963 selector - n_groups,964 configs,965 num_configs);966 } else {967 pin_group = &priv->chip->pin_groups[selector];968 969 for (i = 0; i < pin_group->n_pins; ++i) {970 ret = madera_pin_conf_set(pctldev,971 pin_group->pins[i],972 configs,973 num_configs);974 if (ret)975 return ret;976 }977 }978 979 return 0;980}981 982static const struct pinconf_ops madera_pin_conf_ops = {983 .is_generic = true,984 .pin_config_get = madera_pin_conf_get,985 .pin_config_set = madera_pin_conf_set,986 .pin_config_group_set = madera_pin_conf_group_set,987};988 989static struct pinctrl_desc madera_pin_desc = {990 .name = "madera-pinctrl",991 .pins = madera_pins,992 .pctlops = &madera_pin_group_ops,993 .pmxops = &madera_pin_mux_ops,994 .confops = &madera_pin_conf_ops,995 .owner = THIS_MODULE,996};997 998static int madera_pin_probe(struct platform_device *pdev)999{1000 struct madera *madera = dev_get_drvdata(pdev->dev.parent);1001 const struct madera_pdata *pdata = &madera->pdata;1002 struct madera_pin_private *priv;1003 int ret;1004 1005 BUILD_BUG_ON(ARRAY_SIZE(madera_pin_single_group_names) !=1006 ARRAY_SIZE(madera_pin_single_group_pins));1007 1008 dev_dbg(&pdev->dev, "%s\n", __func__);1009 1010 device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));1011 1012 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);1013 if (!priv)1014 return -ENOMEM;1015 1016 priv->dev = &pdev->dev;1017 priv->madera = madera;1018 1019 switch (madera->type) {1020 case CS47L15:1021 if (IS_ENABLED(CONFIG_PINCTRL_CS47L15))1022 priv->chip = &cs47l15_pin_chip;1023 break;1024 case CS47L35:1025 if (IS_ENABLED(CONFIG_PINCTRL_CS47L35))1026 priv->chip = &cs47l35_pin_chip;1027 break;1028 case CS47L85:1029 case WM1840:1030 if (IS_ENABLED(CONFIG_PINCTRL_CS47L85))1031 priv->chip = &cs47l85_pin_chip;1032 break;1033 case CS47L90:1034 case CS47L91:1035 if (IS_ENABLED(CONFIG_PINCTRL_CS47L90))1036 priv->chip = &cs47l90_pin_chip;1037 break;1038 case CS42L92:1039 case CS47L92:1040 case CS47L93:1041 if (IS_ENABLED(CONFIG_PINCTRL_CS47L92))1042 priv->chip = &cs47l92_pin_chip;1043 break;1044 default:1045 break;1046 }1047 1048 if (!priv->chip)1049 return -ENODEV;1050 1051 madera_pin_desc.npins = priv->chip->n_pins;1052 1053 ret = devm_pinctrl_register_and_init(&pdev->dev,1054 &madera_pin_desc,1055 priv,1056 &priv->pctl);1057 if (ret) {1058 dev_err(priv->dev, "Failed pinctrl register (%d)\n", ret);1059 return ret;1060 }1061 1062 /* if the configuration is provided through pdata, apply it */1063 if (pdata->gpio_configs) {1064 ret = pinctrl_register_mappings(pdata->gpio_configs,1065 pdata->n_gpio_configs);1066 if (ret)1067 return dev_err_probe(priv->dev, ret,1068 "Failed to register pdata mappings\n");1069 }1070 1071 ret = pinctrl_enable(priv->pctl);1072 if (ret) {1073 dev_err(priv->dev, "Failed to enable pinctrl (%d)\n", ret);1074 return ret;1075 }1076 1077 platform_set_drvdata(pdev, priv);1078 1079 dev_dbg(priv->dev, "pinctrl probed ok\n");1080 1081 return 0;1082}1083 1084static void madera_pin_remove(struct platform_device *pdev)1085{1086 struct madera_pin_private *priv = platform_get_drvdata(pdev);1087 1088 if (priv->madera->pdata.gpio_configs)1089 pinctrl_unregister_mappings(priv->madera->pdata.gpio_configs);1090}1091 1092static struct platform_driver madera_pin_driver = {1093 .probe = madera_pin_probe,1094 .remove_new = madera_pin_remove,1095 .driver = {1096 .name = "madera-pinctrl",1097 },1098};1099 1100module_platform_driver(madera_pin_driver);1101 1102MODULE_DESCRIPTION("Madera pinctrl driver");1103MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");1104MODULE_LICENSE("GPL v2");1105