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