1 /* 2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #include <linux/export.h> 16 #include <linux/mfd/syscon.h> 17 #include <linux/pinctrl/pinconf.h> 18 #include <linux/pinctrl/pinconf-generic.h> 19 #include <linux/pinctrl/pinctrl.h> 20 #include <linux/pinctrl/pinmux.h> 21 #include <linux/platform_device.h> 22 #include <linux/regmap.h> 23 24 #include "../core.h" 25 #include "../pinctrl-utils.h" 26 #include "pinctrl-uniphier.h" 27 28 struct uniphier_pinctrl_priv { 29 struct pinctrl_dev *pctldev; 30 struct regmap *regmap; 31 struct uniphier_pinctrl_socdata *socdata; 32 }; 33 34 static int uniphier_pctl_get_groups_count(struct pinctrl_dev *pctldev) 35 { 36 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 37 38 return priv->socdata->groups_count; 39 } 40 41 static const char *uniphier_pctl_get_group_name(struct pinctrl_dev *pctldev, 42 unsigned selector) 43 { 44 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 45 46 return priv->socdata->groups[selector].name; 47 } 48 49 static int uniphier_pctl_get_group_pins(struct pinctrl_dev *pctldev, 50 unsigned selector, 51 const unsigned **pins, 52 unsigned *num_pins) 53 { 54 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 55 56 *pins = priv->socdata->groups[selector].pins; 57 *num_pins = priv->socdata->groups[selector].num_pins; 58 59 return 0; 60 } 61 62 #ifdef CONFIG_DEBUG_FS 63 static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, 64 struct seq_file *s, unsigned offset) 65 { 66 const struct pinctrl_pin_desc *pin = &pctldev->desc->pins[offset]; 67 const char *pull_dir, *drv_str; 68 69 switch (uniphier_pin_get_pull_dir(pin->drv_data)) { 70 case UNIPHIER_PIN_PULL_UP: 71 pull_dir = "UP"; 72 break; 73 case UNIPHIER_PIN_PULL_DOWN: 74 pull_dir = "DOWN"; 75 break; 76 case UNIPHIER_PIN_PULL_NONE: 77 pull_dir = "NONE"; 78 break; 79 default: 80 BUG(); 81 } 82 83 switch (uniphier_pin_get_drv_str(pin->drv_data)) { 84 case UNIPHIER_PIN_DRV_4_8: 85 drv_str = "4/8(mA)"; 86 break; 87 case UNIPHIER_PIN_DRV_8_12_16_20: 88 drv_str = "8/12/16/20(mA)"; 89 break; 90 case UNIPHIER_PIN_DRV_FIXED_4: 91 drv_str = "4(mA)"; 92 break; 93 case UNIPHIER_PIN_DRV_FIXED_5: 94 drv_str = "5(mA)"; 95 break; 96 case UNIPHIER_PIN_DRV_FIXED_8: 97 drv_str = "8(mA)"; 98 break; 99 case UNIPHIER_PIN_DRV_NONE: 100 drv_str = "NONE"; 101 break; 102 default: 103 BUG(); 104 } 105 106 seq_printf(s, " PULL_DIR=%s DRV_STR=%s", pull_dir, drv_str); 107 } 108 #endif 109 110 static const struct pinctrl_ops uniphier_pctlops = { 111 .get_groups_count = uniphier_pctl_get_groups_count, 112 .get_group_name = uniphier_pctl_get_group_name, 113 .get_group_pins = uniphier_pctl_get_group_pins, 114 #ifdef CONFIG_DEBUG_FS 115 .pin_dbg_show = uniphier_pctl_pin_dbg_show, 116 #endif 117 .dt_node_to_map = pinconf_generic_dt_node_to_map_all, 118 .dt_free_map = pinctrl_utils_dt_free_map, 119 }; 120 121 static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev, 122 const struct pinctrl_pin_desc *pin, 123 enum pin_config_param param) 124 { 125 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 126 enum uniphier_pin_pull_dir pull_dir = 127 uniphier_pin_get_pull_dir(pin->drv_data); 128 unsigned int pupdctrl, reg, shift, val; 129 unsigned int expected = 1; 130 int ret; 131 132 switch (param) { 133 case PIN_CONFIG_BIAS_DISABLE: 134 if (pull_dir == UNIPHIER_PIN_PULL_NONE) 135 return 0; 136 if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED || 137 pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) 138 return -EINVAL; 139 expected = 0; 140 break; 141 case PIN_CONFIG_BIAS_PULL_UP: 142 if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED) 143 return 0; 144 if (pull_dir != UNIPHIER_PIN_PULL_UP) 145 return -EINVAL; 146 break; 147 case PIN_CONFIG_BIAS_PULL_DOWN: 148 if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) 149 return 0; 150 if (pull_dir != UNIPHIER_PIN_PULL_DOWN) 151 return -EINVAL; 152 break; 153 default: 154 BUG(); 155 } 156 157 pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data); 158 159 reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4; 160 shift = pupdctrl % 32; 161 162 ret = regmap_read(priv->regmap, reg, &val); 163 if (ret) 164 return ret; 165 166 val = (val >> shift) & 1; 167 168 return (val == expected) ? 0 : -EINVAL; 169 } 170 171 static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev, 172 const struct pinctrl_pin_desc *pin, 173 u16 *strength) 174 { 175 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 176 enum uniphier_pin_drv_str drv_str = 177 uniphier_pin_get_drv_str(pin->drv_data); 178 const unsigned int strength_4_8[] = {4, 8}; 179 const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20}; 180 const unsigned int *supported_strength; 181 unsigned int drvctrl, reg, shift, mask, width, val; 182 int ret; 183 184 switch (drv_str) { 185 case UNIPHIER_PIN_DRV_4_8: 186 supported_strength = strength_4_8; 187 width = 1; 188 break; 189 case UNIPHIER_PIN_DRV_8_12_16_20: 190 supported_strength = strength_8_12_16_20; 191 width = 2; 192 break; 193 case UNIPHIER_PIN_DRV_FIXED_4: 194 *strength = 4; 195 return 0; 196 case UNIPHIER_PIN_DRV_FIXED_5: 197 *strength = 5; 198 return 0; 199 case UNIPHIER_PIN_DRV_FIXED_8: 200 *strength = 8; 201 return 0; 202 default: 203 /* drive strength control is not supported for this pin */ 204 return -EINVAL; 205 } 206 207 drvctrl = uniphier_pin_get_drvctrl(pin->drv_data); 208 drvctrl *= width; 209 210 reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE : 211 UNIPHIER_PINCTRL_DRVCTRL_BASE; 212 213 reg += drvctrl / 32 * 4; 214 shift = drvctrl % 32; 215 mask = (1U << width) - 1; 216 217 ret = regmap_read(priv->regmap, reg, &val); 218 if (ret) 219 return ret; 220 221 *strength = supported_strength[(val >> shift) & mask]; 222 223 return 0; 224 } 225 226 static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev, 227 const struct pinctrl_pin_desc *pin) 228 { 229 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 230 unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data); 231 unsigned int val; 232 int ret; 233 234 if (iectrl == UNIPHIER_PIN_IECTRL_NONE) 235 /* This pin is always input-enabled. */ 236 return 0; 237 238 ret = regmap_read(priv->regmap, UNIPHIER_PINCTRL_IECTRL, &val); 239 if (ret) 240 return ret; 241 242 return val & BIT(iectrl) ? 0 : -EINVAL; 243 } 244 245 static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev, 246 unsigned pin, 247 unsigned long *configs) 248 { 249 const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin]; 250 enum pin_config_param param = pinconf_to_config_param(*configs); 251 bool has_arg = false; 252 u16 arg; 253 int ret; 254 255 switch (param) { 256 case PIN_CONFIG_BIAS_DISABLE: 257 case PIN_CONFIG_BIAS_PULL_UP: 258 case PIN_CONFIG_BIAS_PULL_DOWN: 259 ret = uniphier_conf_pin_bias_get(pctldev, pin_desc, param); 260 break; 261 case PIN_CONFIG_DRIVE_STRENGTH: 262 ret = uniphier_conf_pin_drive_get(pctldev, pin_desc, &arg); 263 has_arg = true; 264 break; 265 case PIN_CONFIG_INPUT_ENABLE: 266 ret = uniphier_conf_pin_input_enable_get(pctldev, pin_desc); 267 break; 268 default: 269 /* unsupported parameter */ 270 ret = -EINVAL; 271 break; 272 } 273 274 if (ret == 0 && has_arg) 275 *configs = pinconf_to_config_packed(param, arg); 276 277 return ret; 278 } 279 280 static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev, 281 const struct pinctrl_pin_desc *pin, 282 enum pin_config_param param, 283 u16 arg) 284 { 285 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 286 enum uniphier_pin_pull_dir pull_dir = 287 uniphier_pin_get_pull_dir(pin->drv_data); 288 unsigned int pupdctrl, reg, shift; 289 unsigned int val = 1; 290 291 switch (param) { 292 case PIN_CONFIG_BIAS_DISABLE: 293 if (pull_dir == UNIPHIER_PIN_PULL_NONE) 294 return 0; 295 if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED || 296 pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) { 297 dev_err(pctldev->dev, 298 "can not disable pull register for pin %u (%s)\n", 299 pin->number, pin->name); 300 return -EINVAL; 301 } 302 val = 0; 303 break; 304 case PIN_CONFIG_BIAS_PULL_UP: 305 if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED && arg != 0) 306 return 0; 307 if (pull_dir != UNIPHIER_PIN_PULL_UP) { 308 dev_err(pctldev->dev, 309 "pull-up is unsupported for pin %u (%s)\n", 310 pin->number, pin->name); 311 return -EINVAL; 312 } 313 if (arg == 0) { 314 dev_err(pctldev->dev, "pull-up can not be total\n"); 315 return -EINVAL; 316 } 317 break; 318 case PIN_CONFIG_BIAS_PULL_DOWN: 319 if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED && arg != 0) 320 return 0; 321 if (pull_dir != UNIPHIER_PIN_PULL_DOWN) { 322 dev_err(pctldev->dev, 323 "pull-down is unsupported for pin %u (%s)\n", 324 pin->number, pin->name); 325 return -EINVAL; 326 } 327 if (arg == 0) { 328 dev_err(pctldev->dev, "pull-down can not be total\n"); 329 return -EINVAL; 330 } 331 break; 332 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 333 if (pull_dir == UNIPHIER_PIN_PULL_NONE) { 334 dev_err(pctldev->dev, 335 "pull-up/down is unsupported for pin %u (%s)\n", 336 pin->number, pin->name); 337 return -EINVAL; 338 } 339 340 if (arg == 0) 341 return 0; /* configuration ingored */ 342 break; 343 default: 344 BUG(); 345 } 346 347 pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data); 348 349 reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4; 350 shift = pupdctrl % 32; 351 352 return regmap_update_bits(priv->regmap, reg, 1 << shift, val << shift); 353 } 354 355 static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev, 356 const struct pinctrl_pin_desc *pin, 357 u16 strength) 358 { 359 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 360 enum uniphier_pin_drv_str drv_str = 361 uniphier_pin_get_drv_str(pin->drv_data); 362 const unsigned int strength_4_8[] = {4, 8, -1}; 363 const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20, -1}; 364 const unsigned int *supported_strength; 365 unsigned int drvctrl, reg, shift, mask, width, val; 366 367 switch (drv_str) { 368 case UNIPHIER_PIN_DRV_4_8: 369 supported_strength = strength_4_8; 370 width = 1; 371 break; 372 case UNIPHIER_PIN_DRV_8_12_16_20: 373 supported_strength = strength_8_12_16_20; 374 width = 2; 375 break; 376 default: 377 dev_err(pctldev->dev, 378 "cannot change drive strength for pin %u (%s)\n", 379 pin->number, pin->name); 380 return -EINVAL; 381 } 382 383 for (val = 0; supported_strength[val] > 0; val++) { 384 if (supported_strength[val] > strength) 385 break; 386 } 387 388 if (val == 0) { 389 dev_err(pctldev->dev, 390 "unsupported drive strength %u mA for pin %u (%s)\n", 391 strength, pin->number, pin->name); 392 return -EINVAL; 393 } 394 395 val--; 396 397 drvctrl = uniphier_pin_get_drvctrl(pin->drv_data); 398 drvctrl *= width; 399 400 reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE : 401 UNIPHIER_PINCTRL_DRVCTRL_BASE; 402 403 reg += drvctrl / 32 * 4; 404 shift = drvctrl % 32; 405 mask = (1U << width) - 1; 406 407 return regmap_update_bits(priv->regmap, reg, 408 mask << shift, val << shift); 409 } 410 411 static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev, 412 const struct pinctrl_pin_desc *pin, 413 u16 enable) 414 { 415 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 416 unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data); 417 418 if (enable == 0) { 419 /* 420 * Multiple pins share one input enable, so per-pin disabling 421 * is impossible. 422 */ 423 dev_err(pctldev->dev, "unable to disable input\n"); 424 return -EINVAL; 425 } 426 427 if (iectrl == UNIPHIER_PIN_IECTRL_NONE) 428 /* This pin is always input-enabled. nothing to do. */ 429 return 0; 430 431 return regmap_update_bits(priv->regmap, UNIPHIER_PINCTRL_IECTRL, 432 BIT(iectrl), BIT(iectrl)); 433 } 434 435 static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev, 436 unsigned pin, 437 unsigned long *configs, 438 unsigned num_configs) 439 { 440 const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin]; 441 int i, ret; 442 443 for (i = 0; i < num_configs; i++) { 444 enum pin_config_param param = 445 pinconf_to_config_param(configs[i]); 446 u16 arg = pinconf_to_config_argument(configs[i]); 447 448 switch (param) { 449 case PIN_CONFIG_BIAS_DISABLE: 450 case PIN_CONFIG_BIAS_PULL_UP: 451 case PIN_CONFIG_BIAS_PULL_DOWN: 452 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 453 ret = uniphier_conf_pin_bias_set(pctldev, pin_desc, 454 param, arg); 455 break; 456 case PIN_CONFIG_DRIVE_STRENGTH: 457 ret = uniphier_conf_pin_drive_set(pctldev, pin_desc, 458 arg); 459 break; 460 case PIN_CONFIG_INPUT_ENABLE: 461 ret = uniphier_conf_pin_input_enable(pctldev, 462 pin_desc, arg); 463 break; 464 default: 465 dev_err(pctldev->dev, 466 "unsupported configuration parameter %u\n", 467 param); 468 return -EINVAL; 469 } 470 471 if (ret) 472 return ret; 473 } 474 475 return 0; 476 } 477 478 static int uniphier_conf_pin_config_group_set(struct pinctrl_dev *pctldev, 479 unsigned selector, 480 unsigned long *configs, 481 unsigned num_configs) 482 { 483 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 484 const unsigned *pins = priv->socdata->groups[selector].pins; 485 unsigned num_pins = priv->socdata->groups[selector].num_pins; 486 int i, ret; 487 488 for (i = 0; i < num_pins; i++) { 489 ret = uniphier_conf_pin_config_set(pctldev, pins[i], 490 configs, num_configs); 491 if (ret) 492 return ret; 493 } 494 495 return 0; 496 } 497 498 static const struct pinconf_ops uniphier_confops = { 499 .is_generic = true, 500 .pin_config_get = uniphier_conf_pin_config_get, 501 .pin_config_set = uniphier_conf_pin_config_set, 502 .pin_config_group_set = uniphier_conf_pin_config_group_set, 503 }; 504 505 static int uniphier_pmx_get_functions_count(struct pinctrl_dev *pctldev) 506 { 507 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 508 509 return priv->socdata->functions_count; 510 } 511 512 static const char *uniphier_pmx_get_function_name(struct pinctrl_dev *pctldev, 513 unsigned selector) 514 { 515 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 516 517 return priv->socdata->functions[selector].name; 518 } 519 520 static int uniphier_pmx_get_function_groups(struct pinctrl_dev *pctldev, 521 unsigned selector, 522 const char * const **groups, 523 unsigned *num_groups) 524 { 525 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 526 527 *groups = priv->socdata->functions[selector].groups; 528 *num_groups = priv->socdata->functions[selector].num_groups; 529 530 return 0; 531 } 532 533 static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin, 534 unsigned muxval) 535 { 536 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 537 unsigned mux_bits = priv->socdata->mux_bits; 538 unsigned reg_stride = priv->socdata->reg_stride; 539 unsigned reg, reg_end, shift, mask; 540 int ret; 541 542 reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride; 543 reg_end = reg + reg_stride; 544 shift = pin * mux_bits % 32; 545 mask = (1U << mux_bits) - 1; 546 547 /* 548 * If reg_stride is greater than 4, the MSB of each pinsel shall be 549 * stored in the offset+4. 550 */ 551 for (; reg < reg_end; reg += 4) { 552 ret = regmap_update_bits(priv->regmap, reg, 553 mask << shift, muxval << shift); 554 if (ret) 555 return ret; 556 muxval >>= mux_bits; 557 } 558 559 if (priv->socdata->load_pinctrl) { 560 ret = regmap_write(priv->regmap, 561 UNIPHIER_PINCTRL_LOAD_PINMUX, 1); 562 if (ret) 563 return ret; 564 } 565 566 /* some pins need input-enabling */ 567 return uniphier_conf_pin_input_enable(pctldev, 568 &pctldev->desc->pins[pin], 1); 569 } 570 571 static int uniphier_pmx_set_mux(struct pinctrl_dev *pctldev, 572 unsigned func_selector, 573 unsigned group_selector) 574 { 575 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 576 const struct uniphier_pinctrl_group *grp = 577 &priv->socdata->groups[group_selector]; 578 int i; 579 int ret; 580 581 for (i = 0; i < grp->num_pins; i++) { 582 ret = uniphier_pmx_set_one_mux(pctldev, grp->pins[i], 583 grp->muxvals[i]); 584 if (ret) 585 return ret; 586 } 587 588 return 0; 589 } 590 591 static int uniphier_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, 592 struct pinctrl_gpio_range *range, 593 unsigned offset) 594 { 595 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 596 const struct uniphier_pinctrl_group *groups = priv->socdata->groups; 597 int groups_count = priv->socdata->groups_count; 598 enum uniphier_pinmux_gpio_range_type range_type; 599 int i, j; 600 601 if (strstr(range->name, "irq")) 602 range_type = UNIPHIER_PINMUX_GPIO_RANGE_IRQ; 603 else 604 range_type = UNIPHIER_PINMUX_GPIO_RANGE_PORT; 605 606 for (i = 0; i < groups_count; i++) { 607 if (groups[i].range_type != range_type) 608 continue; 609 610 for (j = 0; j < groups[i].num_pins; j++) 611 if (groups[i].pins[j] == offset) 612 goto found; 613 } 614 615 dev_err(pctldev->dev, "pin %u does not support GPIO\n", offset); 616 return -EINVAL; 617 618 found: 619 return uniphier_pmx_set_one_mux(pctldev, offset, groups[i].muxvals[j]); 620 } 621 622 static const struct pinmux_ops uniphier_pmxops = { 623 .get_functions_count = uniphier_pmx_get_functions_count, 624 .get_function_name = uniphier_pmx_get_function_name, 625 .get_function_groups = uniphier_pmx_get_function_groups, 626 .set_mux = uniphier_pmx_set_mux, 627 .gpio_request_enable = uniphier_pmx_gpio_request_enable, 628 .strict = true, 629 }; 630 631 int uniphier_pinctrl_probe(struct platform_device *pdev, 632 struct pinctrl_desc *desc, 633 struct uniphier_pinctrl_socdata *socdata) 634 { 635 struct device *dev = &pdev->dev; 636 struct uniphier_pinctrl_priv *priv; 637 638 if (!socdata || 639 !socdata->groups || 640 !socdata->groups_count || 641 !socdata->functions || 642 !socdata->functions_count || 643 !socdata->mux_bits || 644 !socdata->reg_stride) { 645 dev_err(dev, "pinctrl socdata lacks necessary members\n"); 646 return -EINVAL; 647 } 648 649 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 650 if (!priv) 651 return -ENOMEM; 652 653 priv->regmap = syscon_node_to_regmap(dev->of_node); 654 if (IS_ERR(priv->regmap)) { 655 dev_err(dev, "failed to get regmap\n"); 656 return PTR_ERR(priv->regmap); 657 } 658 659 priv->socdata = socdata; 660 desc->pctlops = &uniphier_pctlops; 661 desc->pmxops = &uniphier_pmxops; 662 desc->confops = &uniphier_confops; 663 664 priv->pctldev = pinctrl_register(desc, dev, priv); 665 if (IS_ERR(priv->pctldev)) { 666 dev_err(dev, "failed to register UniPhier pinctrl driver\n"); 667 return PTR_ERR(priv->pctldev); 668 } 669 670 platform_set_drvdata(pdev, priv); 671 672 return 0; 673 } 674 EXPORT_SYMBOL_GPL(uniphier_pinctrl_probe); 675 676 int uniphier_pinctrl_remove(struct platform_device *pdev) 677 { 678 struct uniphier_pinctrl_priv *priv = platform_get_drvdata(pdev); 679 680 pinctrl_unregister(priv->pctldev); 681 682 return 0; 683 } 684 EXPORT_SYMBOL_GPL(uniphier_pinctrl_remove); 685