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