linux/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
<<
>>
Prefs
   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
  28struct uniphier_pinctrl_priv {
  29        struct pinctrl_dev *pctldev;
  30        struct regmap *regmap;
  31        struct uniphier_pinctrl_socdata *socdata;
  32};
  33
  34static 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
  41static 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
  49static 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
  63static 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
 110static 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
 121static 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
 171static 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
 226static 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
 245static 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
 280static 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
 355static 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
 411static 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
 435static 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
 478static 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
 498static 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
 505static 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
 512static 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
 520static 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
 533static 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        /* some pins need input-enabling */
 543        ret = uniphier_conf_pin_input_enable(pctldev,
 544                                             &pctldev->desc->pins[pin], 1);
 545        if (ret)
 546                return ret;
 547
 548        reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
 549        reg_end = reg + reg_stride;
 550        shift = pin * mux_bits % 32;
 551        mask = (1U << mux_bits) - 1;
 552
 553        /*
 554         * If reg_stride is greater than 4, the MSB of each pinsel shall be
 555         * stored in the offset+4.
 556         */
 557        for (; reg < reg_end; reg += 4) {
 558                ret = regmap_update_bits(priv->regmap, reg,
 559                                         mask << shift, muxval << shift);
 560                if (ret)
 561                        return ret;
 562                muxval >>= mux_bits;
 563        }
 564
 565        if (priv->socdata->load_pinctrl) {
 566                ret = regmap_write(priv->regmap,
 567                                   UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
 568                if (ret)
 569                        return ret;
 570        }
 571
 572        return 0;
 573}
 574
 575static int uniphier_pmx_set_mux(struct pinctrl_dev *pctldev,
 576                                unsigned func_selector,
 577                                unsigned group_selector)
 578{
 579        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
 580        const struct uniphier_pinctrl_group *grp =
 581                                        &priv->socdata->groups[group_selector];
 582        int i;
 583        int ret;
 584
 585        for (i = 0; i < grp->num_pins; i++) {
 586                ret = uniphier_pmx_set_one_mux(pctldev, grp->pins[i],
 587                                               grp->muxvals[i]);
 588                if (ret)
 589                        return ret;
 590        }
 591
 592        return 0;
 593}
 594
 595static int uniphier_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
 596                                            struct pinctrl_gpio_range *range,
 597                                            unsigned offset)
 598{
 599        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
 600        const struct uniphier_pinctrl_group *groups = priv->socdata->groups;
 601        int groups_count = priv->socdata->groups_count;
 602        enum uniphier_pinmux_gpio_range_type range_type;
 603        int i, j;
 604
 605        if (strstr(range->name, "irq"))
 606                range_type = UNIPHIER_PINMUX_GPIO_RANGE_IRQ;
 607        else
 608                range_type = UNIPHIER_PINMUX_GPIO_RANGE_PORT;
 609
 610        for (i = 0; i < groups_count; i++) {
 611                if (groups[i].range_type != range_type)
 612                        continue;
 613
 614                for (j = 0; j < groups[i].num_pins; j++)
 615                        if (groups[i].pins[j] == offset)
 616                                goto found;
 617        }
 618
 619        dev_err(pctldev->dev, "pin %u does not support GPIO\n", offset);
 620        return -EINVAL;
 621
 622found:
 623        return uniphier_pmx_set_one_mux(pctldev, offset, groups[i].muxvals[j]);
 624}
 625
 626static const struct pinmux_ops uniphier_pmxops = {
 627        .get_functions_count = uniphier_pmx_get_functions_count,
 628        .get_function_name = uniphier_pmx_get_function_name,
 629        .get_function_groups = uniphier_pmx_get_function_groups,
 630        .set_mux = uniphier_pmx_set_mux,
 631        .gpio_request_enable = uniphier_pmx_gpio_request_enable,
 632        .strict = true,
 633};
 634
 635int uniphier_pinctrl_probe(struct platform_device *pdev,
 636                           struct pinctrl_desc *desc,
 637                           struct uniphier_pinctrl_socdata *socdata)
 638{
 639        struct device *dev = &pdev->dev;
 640        struct uniphier_pinctrl_priv *priv;
 641
 642        if (!socdata ||
 643            !socdata->groups ||
 644            !socdata->groups_count ||
 645            !socdata->functions ||
 646            !socdata->functions_count ||
 647            !socdata->mux_bits ||
 648            !socdata->reg_stride) {
 649                dev_err(dev, "pinctrl socdata lacks necessary members\n");
 650                return -EINVAL;
 651        }
 652
 653        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 654        if (!priv)
 655                return -ENOMEM;
 656
 657        priv->regmap = syscon_node_to_regmap(dev->of_node);
 658        if (IS_ERR(priv->regmap)) {
 659                dev_err(dev, "failed to get regmap\n");
 660                return PTR_ERR(priv->regmap);
 661        }
 662
 663        priv->socdata = socdata;
 664        desc->pctlops = &uniphier_pctlops;
 665        desc->pmxops = &uniphier_pmxops;
 666        desc->confops = &uniphier_confops;
 667
 668        priv->pctldev = pinctrl_register(desc, dev, priv);
 669        if (IS_ERR(priv->pctldev)) {
 670                dev_err(dev, "failed to register UniPhier pinctrl driver\n");
 671                return PTR_ERR(priv->pctldev);
 672        }
 673
 674        platform_set_drvdata(pdev, priv);
 675
 676        return 0;
 677}
 678EXPORT_SYMBOL_GPL(uniphier_pinctrl_probe);
 679
 680int uniphier_pinctrl_remove(struct platform_device *pdev)
 681{
 682        struct uniphier_pinctrl_priv *priv = platform_get_drvdata(pdev);
 683
 684        pinctrl_unregister(priv->pctldev);
 685
 686        return 0;
 687}
 688EXPORT_SYMBOL_GPL(uniphier_pinctrl_remove);
 689