uboot/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2019 Rockchip Electronics Co., Ltd
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <dm/pinctrl.h>
   9#include <regmap.h>
  10#include <syscon.h>
  11#include <fdtdec.h>
  12
  13#include "pinctrl-rockchip.h"
  14
  15#define MAX_ROCKCHIP_PINS_ENTRIES       30
  16#define MAX_ROCKCHIP_GPIO_PER_BANK      32
  17#define RK_FUNC_GPIO                    0
  18
  19static int rockchip_verify_config(struct udevice *dev, u32 bank, u32 pin)
  20{
  21        struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
  22        struct rockchip_pin_ctrl *ctrl = priv->ctrl;
  23
  24        if (bank >= ctrl->nr_banks) {
  25                debug("pin conf bank %d >= nbanks %d\n", bank, ctrl->nr_banks);
  26                return -EINVAL;
  27        }
  28
  29        if (pin >= MAX_ROCKCHIP_GPIO_PER_BANK) {
  30                debug("pin conf pin %d >= %d\n", pin,
  31                      MAX_ROCKCHIP_GPIO_PER_BANK);
  32                return -EINVAL;
  33        }
  34
  35        return 0;
  36}
  37
  38void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin,
  39                               int *reg, u8 *bit, int *mask)
  40{
  41        struct rockchip_pinctrl_priv *priv = bank->priv;
  42        struct rockchip_pin_ctrl *ctrl = priv->ctrl;
  43        struct rockchip_mux_recalced_data *data;
  44        int i;
  45
  46        for (i = 0; i < ctrl->niomux_recalced; i++) {
  47                data = &ctrl->iomux_recalced[i];
  48                if (data->num == bank->bank_num &&
  49                    data->pin == pin)
  50                        break;
  51        }
  52
  53        if (i >= ctrl->niomux_recalced)
  54                return;
  55
  56        *reg = data->reg;
  57        *mask = data->mask;
  58        *bit = data->bit;
  59}
  60
  61bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
  62                            int mux, u32 *reg, u32 *value)
  63{
  64        struct rockchip_pinctrl_priv *priv = bank->priv;
  65        struct rockchip_pin_ctrl *ctrl = priv->ctrl;
  66        struct rockchip_mux_route_data *data;
  67        int i;
  68
  69        for (i = 0; i < ctrl->niomux_routes; i++) {
  70                data = &ctrl->iomux_routes[i];
  71                if (data->bank_num == bank->bank_num &&
  72                    data->pin == pin && data->func == mux)
  73                        break;
  74        }
  75
  76        if (i >= ctrl->niomux_routes)
  77                return false;
  78
  79        *reg = data->route_offset;
  80        *value = data->route_val;
  81
  82        return true;
  83}
  84
  85int rockchip_get_mux_data(int mux_type, int pin, u8 *bit, int *mask)
  86{
  87        int offset = 0;
  88
  89        if (mux_type & IOMUX_WIDTH_4BIT) {
  90                if ((pin % 8) >= 4)
  91                        offset = 0x4;
  92                *bit = (pin % 4) * 4;
  93                *mask = 0xf;
  94        } else if (mux_type & IOMUX_WIDTH_3BIT) {
  95                /*
  96                 * pin0 ~ pin4 are at first register, and
  97                 * pin5 ~ pin7 are at second register.
  98                 */
  99                if ((pin % 8) >= 5)
 100                        offset = 0x4;
 101                *bit = (pin % 8 % 5) * 3;
 102                *mask = 0x7;
 103        } else {
 104                *bit = (pin % 8) * 2;
 105                *mask = 0x3;
 106        }
 107
 108        return offset;
 109}
 110
 111static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
 112{
 113        struct rockchip_pinctrl_priv *priv = bank->priv;
 114        int iomux_num = (pin / 8);
 115        struct regmap *regmap;
 116        unsigned int val;
 117        int reg, ret, mask, mux_type;
 118        u8 bit;
 119
 120        if (iomux_num > 3)
 121                return -EINVAL;
 122
 123        if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
 124                debug("pin %d is unrouted\n", pin);
 125                return -EINVAL;
 126        }
 127
 128        if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
 129                return RK_FUNC_GPIO;
 130
 131        regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
 132                                ? priv->regmap_pmu : priv->regmap_base;
 133
 134        /* get basic quadrupel of mux registers and the correct reg inside */
 135        mux_type = bank->iomux[iomux_num].type;
 136        reg = bank->iomux[iomux_num].offset;
 137        reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
 138
 139        if (bank->recalced_mask & BIT(pin))
 140                rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
 141
 142        ret = regmap_read(regmap, reg, &val);
 143        if (ret)
 144                return ret;
 145
 146        return ((val >> bit) & mask);
 147}
 148
 149static int rockchip_pinctrl_get_gpio_mux(struct udevice *dev, int banknum,
 150                                         int index)
 151{       struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
 152        struct rockchip_pin_ctrl *ctrl = priv->ctrl;
 153
 154        return rockchip_get_mux(&ctrl->pin_banks[banknum], index);
 155}
 156
 157static int rockchip_verify_mux(struct rockchip_pin_bank *bank,
 158                               int pin, int mux)
 159{
 160        int iomux_num = (pin / 8);
 161
 162        if (iomux_num > 3)
 163                return -EINVAL;
 164
 165        if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
 166                debug("pin %d is unrouted\n", pin);
 167                return -EINVAL;
 168        }
 169
 170        if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) {
 171                if (mux != IOMUX_GPIO_ONLY) {
 172                        debug("pin %d only supports a gpio mux\n", pin);
 173                        return -ENOTSUPP;
 174                }
 175        }
 176
 177        return 0;
 178}
 179
 180/*
 181 * Set a new mux function for a pin.
 182 *
 183 * The register is divided into the upper and lower 16 bit. When changing
 184 * a value, the previous register value is not read and changed. Instead
 185 * it seems the changed bits are marked in the upper 16 bit, while the
 186 * changed value gets set in the same offset in the lower 16 bit.
 187 * All pin settings seem to be 2 bit wide in both the upper and lower
 188 * parts.
 189 * @bank: pin bank to change
 190 * @pin: pin to change
 191 * @mux: new mux function to set
 192 */
 193static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
 194{
 195        struct rockchip_pinctrl_priv *priv = bank->priv;
 196        struct rockchip_pin_ctrl *ctrl = priv->ctrl;
 197        int iomux_num = (pin / 8);
 198        int ret;
 199
 200        ret = rockchip_verify_mux(bank, pin, mux);
 201        if (ret < 0)
 202                return ret;
 203
 204        if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
 205                return 0;
 206
 207        debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
 208
 209        if (!ctrl->set_mux)
 210                return -ENOTSUPP;
 211
 212        ret = ctrl->set_mux(bank, pin, mux);
 213
 214        return ret;
 215}
 216
 217static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = {
 218        { 2, 4, 8, 12, -1, -1, -1, -1 },
 219        { 3, 6, 9, 12, -1, -1, -1, -1 },
 220        { 5, 10, 15, 20, -1, -1, -1, -1 },
 221        { 4, 6, 8, 10, 12, 14, 16, 18 },
 222        { 4, 7, 10, 13, 16, 19, 22, 26 }
 223};
 224
 225int rockchip_translate_drive_value(int type, int strength)
 226{
 227        int i, ret;
 228
 229        ret = -EINVAL;
 230        for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list[type]); i++) {
 231                if (rockchip_perpin_drv_list[type][i] == strength) {
 232                        ret = i;
 233                        break;
 234                } else if (rockchip_perpin_drv_list[type][i] < 0) {
 235                        ret = rockchip_perpin_drv_list[type][i];
 236                        break;
 237                }
 238        }
 239
 240        return ret;
 241}
 242
 243static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 244                                     int pin_num, int strength)
 245{
 246        struct rockchip_pinctrl_priv *priv = bank->priv;
 247        struct rockchip_pin_ctrl *ctrl = priv->ctrl;
 248
 249        debug("setting drive of GPIO%d-%d to %d\n", bank->bank_num,
 250              pin_num, strength);
 251
 252        if (!ctrl->set_drive)
 253                return -ENOTSUPP;
 254
 255        return ctrl->set_drive(bank, pin_num, strength);
 256}
 257
 258static int rockchip_pull_list[PULL_TYPE_MAX][4] = {
 259        {
 260                PIN_CONFIG_BIAS_DISABLE,
 261                PIN_CONFIG_BIAS_PULL_UP,
 262                PIN_CONFIG_BIAS_PULL_DOWN,
 263                PIN_CONFIG_BIAS_BUS_HOLD
 264        },
 265        {
 266                PIN_CONFIG_BIAS_DISABLE,
 267                PIN_CONFIG_BIAS_PULL_DOWN,
 268                PIN_CONFIG_BIAS_DISABLE,
 269                PIN_CONFIG_BIAS_PULL_UP
 270        },
 271};
 272
 273int rockchip_translate_pull_value(int type, int pull)
 274{
 275        int i, ret;
 276
 277        ret = -EINVAL;
 278        for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[type]);
 279                i++) {
 280                if (rockchip_pull_list[type][i] == pull) {
 281                        ret = i;
 282                        break;
 283                }
 284        }
 285
 286        return ret;
 287}
 288
 289static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 290                             int pin_num, int pull)
 291{
 292        struct rockchip_pinctrl_priv *priv = bank->priv;
 293        struct rockchip_pin_ctrl *ctrl = priv->ctrl;
 294
 295        debug("setting pull of GPIO%d-%d to %d\n", bank->bank_num,
 296              pin_num, pull);
 297
 298        if (!ctrl->set_pull)
 299                return -ENOTSUPP;
 300
 301        return ctrl->set_pull(bank, pin_num, pull);
 302}
 303
 304static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,
 305                                int pin_num, int enable)
 306{
 307        struct rockchip_pinctrl_priv *priv = bank->priv;
 308        struct rockchip_pin_ctrl *ctrl = priv->ctrl;
 309
 310        debug("setting input schmitt of GPIO%d-%d to %d\n", bank->bank_num,
 311              pin_num, enable);
 312
 313        if (!ctrl->set_schmitt)
 314                return -ENOTSUPP;
 315
 316        return ctrl->set_schmitt(bank, pin_num, enable);
 317}
 318
 319/* set the pin config settings for a specified pin */
 320static int rockchip_pinconf_set(struct rockchip_pin_bank *bank,
 321                                u32 pin, u32 param, u32 arg)
 322{
 323        int rc;
 324
 325        switch (param) {
 326        case PIN_CONFIG_BIAS_DISABLE:
 327        case PIN_CONFIG_BIAS_PULL_UP:
 328        case PIN_CONFIG_BIAS_PULL_DOWN:
 329        case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
 330        case PIN_CONFIG_BIAS_BUS_HOLD:
 331                rc = rockchip_set_pull(bank, pin, param);
 332                if (rc)
 333                        return rc;
 334                break;
 335
 336        case PIN_CONFIG_DRIVE_STRENGTH:
 337                rc = rockchip_set_drive_perpin(bank, pin, arg);
 338                if (rc < 0)
 339                        return rc;
 340                break;
 341
 342        case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
 343                rc = rockchip_set_schmitt(bank, pin, arg);
 344                if (rc < 0)
 345                        return rc;
 346                break;
 347
 348        default:
 349                break;
 350        }
 351
 352        return 0;
 353}
 354
 355static const struct pinconf_param rockchip_conf_params[] = {
 356        { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
 357        { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
 358        { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
 359        { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
 360        { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
 361        { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
 362        { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
 363        { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
 364};
 365
 366static int rockchip_pinconf_prop_name_to_param(const char *property,
 367                                               u32 *default_value)
 368{
 369        const struct pinconf_param *p, *end;
 370
 371        p = rockchip_conf_params;
 372        end = p + sizeof(rockchip_conf_params) / sizeof(struct pinconf_param);
 373
 374        /* See if this pctldev supports this parameter */
 375        for (; p < end; p++) {
 376                if (!strcmp(property, p->property)) {
 377                        *default_value = p->default_value;
 378                        return p->param;
 379                }
 380        }
 381
 382        *default_value = 0;
 383        return -EPERM;
 384}
 385
 386static int rockchip_pinctrl_set_state(struct udevice *dev,
 387                                      struct udevice *config)
 388{
 389        struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
 390        struct rockchip_pin_ctrl *ctrl = priv->ctrl;
 391        u32 cells[MAX_ROCKCHIP_PINS_ENTRIES * 4];
 392        u32 bank, pin, mux, conf, arg, default_val;
 393        int ret, count, i;
 394        const char *prop_name;
 395        const void *value;
 396        int prop_len, param;
 397        const u32 *data;
 398        ofnode node;
 399#ifdef CONFIG_OF_LIVE
 400        const struct device_node *np;
 401        struct property *pp;
 402#else
 403        int property_offset, pcfg_node;
 404        const void *blob = gd->fdt_blob;
 405#endif
 406        data = dev_read_prop(config, "rockchip,pins", &count);
 407        if (count < 0) {
 408                debug("%s: bad array size %d\n", __func__, count);
 409                return -EINVAL;
 410        }
 411
 412        count /= sizeof(u32);
 413        if (count > MAX_ROCKCHIP_PINS_ENTRIES * 4) {
 414                debug("%s: unsupported pins array count %d\n",
 415                      __func__, count);
 416                return -EINVAL;
 417        }
 418
 419        for (i = 0; i < count; i++)
 420                cells[i] = fdt32_to_cpu(data[i]);
 421
 422        for (i = 0; i < (count >> 2); i++) {
 423                bank = cells[4 * i + 0];
 424                pin = cells[4 * i + 1];
 425                mux = cells[4 * i + 2];
 426                conf = cells[4 * i + 3];
 427
 428                ret = rockchip_verify_config(dev, bank, pin);
 429                if (ret)
 430                        return ret;
 431
 432                ret = rockchip_set_mux(&ctrl->pin_banks[bank], pin, mux);
 433                if (ret)
 434                        return ret;
 435
 436                node = ofnode_get_by_phandle(conf);
 437                if (!ofnode_valid(node))
 438                        return -ENODEV;
 439#ifdef CONFIG_OF_LIVE
 440                np = ofnode_to_np(node);
 441                for (pp = np->properties; pp; pp = pp->next) {
 442                        prop_name = pp->name;
 443                        prop_len = pp->length;
 444                        value = pp->value;
 445#else
 446                pcfg_node = ofnode_to_offset(node);
 447                fdt_for_each_property_offset(property_offset, blob, pcfg_node) {
 448                        value = fdt_getprop_by_offset(blob, property_offset,
 449                                                      &prop_name, &prop_len);
 450                        if (!value)
 451                                return -ENOENT;
 452#endif
 453                        param = rockchip_pinconf_prop_name_to_param(prop_name,
 454                                                                    &default_val);
 455                        if (param < 0)
 456                                break;
 457
 458                        if (prop_len >= sizeof(fdt32_t))
 459                                arg = fdt32_to_cpu(*(fdt32_t *)value);
 460                        else
 461                                arg = default_val;
 462
 463                        ret = rockchip_pinconf_set(&ctrl->pin_banks[bank], pin,
 464                                                   param, arg);
 465                        if (ret) {
 466                                debug("%s: rockchip_pinconf_set fail: %d\n",
 467                                      __func__, ret);
 468                                return ret;
 469                        }
 470                }
 471        }
 472
 473        return 0;
 474}
 475
 476const struct pinctrl_ops rockchip_pinctrl_ops = {
 477        .set_state                      = rockchip_pinctrl_set_state,
 478        .get_gpio_mux                   = rockchip_pinctrl_get_gpio_mux,
 479};
 480
 481/* retrieve the soc specific data */
 482static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct udevice *dev)
 483{
 484        struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
 485        struct rockchip_pin_ctrl *ctrl =
 486                        (struct rockchip_pin_ctrl *)dev_get_driver_data(dev);
 487        struct rockchip_pin_bank *bank;
 488        int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j;
 489
 490        grf_offs = ctrl->grf_mux_offset;
 491        pmu_offs = ctrl->pmu_mux_offset;
 492        drv_pmu_offs = ctrl->pmu_drv_offset;
 493        drv_grf_offs = ctrl->grf_drv_offset;
 494        bank = ctrl->pin_banks;
 495
 496        for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
 497                int bank_pins = 0;
 498
 499                bank->priv = priv;
 500                bank->pin_base = ctrl->nr_pins;
 501                ctrl->nr_pins += bank->nr_pins;
 502
 503                /* calculate iomux and drv offsets */
 504                for (j = 0; j < 4; j++) {
 505                        struct rockchip_iomux *iom = &bank->iomux[j];
 506                        struct rockchip_drv *drv = &bank->drv[j];
 507                        int inc;
 508
 509                        if (bank_pins >= bank->nr_pins)
 510                                break;
 511
 512                        /* preset iomux offset value, set new start value */
 513                        if (iom->offset >= 0) {
 514                                if (iom->type & IOMUX_SOURCE_PMU)
 515                                        pmu_offs = iom->offset;
 516                                else
 517                                        grf_offs = iom->offset;
 518                        } else { /* set current iomux offset */
 519                                iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
 520                                                        pmu_offs : grf_offs;
 521                        }
 522
 523                        /* preset drv offset value, set new start value */
 524                        if (drv->offset >= 0) {
 525                                if (iom->type & IOMUX_SOURCE_PMU)
 526                                        drv_pmu_offs = drv->offset;
 527                                else
 528                                        drv_grf_offs = drv->offset;
 529                        } else { /* set current drv offset */
 530                                drv->offset = (iom->type & IOMUX_SOURCE_PMU) ?
 531                                                drv_pmu_offs : drv_grf_offs;
 532                        }
 533
 534                        debug("bank %d, iomux %d has iom_offset 0x%x drv_offset 0x%x\n",
 535                              i, j, iom->offset, drv->offset);
 536
 537                        /*
 538                         * Increase offset according to iomux width.
 539                         * 4bit iomux'es are spread over two registers.
 540                         */
 541                        inc = (iom->type & (IOMUX_WIDTH_4BIT |
 542                                            IOMUX_WIDTH_3BIT |
 543                                            IOMUX_8WIDTH_2BIT)) ? 8 : 4;
 544                        if (iom->type & IOMUX_SOURCE_PMU)
 545                                pmu_offs += inc;
 546                        else
 547                                grf_offs += inc;
 548
 549                        /*
 550                         * Increase offset according to drv width.
 551                         * 3bit drive-strenth'es are spread over two registers.
 552                         */
 553                        if ((drv->drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) ||
 554                            (drv->drv_type == DRV_TYPE_IO_3V3_ONLY))
 555                                inc = 8;
 556                        else
 557                                inc = 4;
 558
 559                        if (iom->type & IOMUX_SOURCE_PMU)
 560                                drv_pmu_offs += inc;
 561                        else
 562                                drv_grf_offs += inc;
 563
 564                        bank_pins += 8;
 565                }
 566
 567                /* calculate the per-bank recalced_mask */
 568                for (j = 0; j < ctrl->niomux_recalced; j++) {
 569                        int pin = 0;
 570
 571                        if (ctrl->iomux_recalced[j].num == bank->bank_num) {
 572                                pin = ctrl->iomux_recalced[j].pin;
 573                                bank->recalced_mask |= BIT(pin);
 574                        }
 575                }
 576
 577                /* calculate the per-bank route_mask */
 578                for (j = 0; j < ctrl->niomux_routes; j++) {
 579                        int pin = 0;
 580
 581                        if (ctrl->iomux_routes[j].bank_num == bank->bank_num) {
 582                                pin = ctrl->iomux_routes[j].pin;
 583                                bank->route_mask |= BIT(pin);
 584                        }
 585                }
 586        }
 587
 588        return ctrl;
 589}
 590
 591int rockchip_pinctrl_probe(struct udevice *dev)
 592{
 593        struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
 594        struct rockchip_pin_ctrl *ctrl;
 595        struct udevice *syscon;
 596        struct regmap *regmap;
 597        int ret = 0;
 598
 599        /* get rockchip grf syscon phandle */
 600        ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,grf",
 601                                           &syscon);
 602        if (ret) {
 603                debug("unable to find rockchip,grf syscon device (%d)\n", ret);
 604                return ret;
 605        }
 606
 607        /* get grf-reg base address */
 608        regmap = syscon_get_regmap(syscon);
 609        if (!regmap) {
 610                debug("unable to find rockchip grf regmap\n");
 611                return -ENODEV;
 612        }
 613        priv->regmap_base = regmap;
 614
 615        /* option: get pmu-reg base address */
 616        ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pmu",
 617                                           &syscon);
 618        if (!ret) {
 619                /* get pmugrf-reg base address */
 620                regmap = syscon_get_regmap(syscon);
 621                if (!regmap) {
 622                        debug("unable to find rockchip pmu regmap\n");
 623                        return -ENODEV;
 624                }
 625                priv->regmap_pmu = regmap;
 626        }
 627
 628        ctrl = rockchip_pinctrl_get_soc_data(dev);
 629        if (!ctrl) {
 630                debug("driver data not available\n");
 631                return -EINVAL;
 632        }
 633
 634        priv->ctrl = ctrl;
 635        return 0;
 636}
 637