linux/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2018 MediaTek Inc.
   4 *
   5 * Author: Sean Wang <sean.wang@mediatek.com>
   6 *
   7 */
   8
   9#include <linux/device.h>
  10#include <linux/err.h>
  11#include <linux/gpio/driver.h>
  12#include <linux/platform_device.h>
  13#include <linux/io.h>
  14#include <linux/of_irq.h>
  15
  16#include "mtk-eint.h"
  17#include "pinctrl-mtk-common-v2.h"
  18
  19/**
  20 * struct mtk_drive_desc - the structure that holds the information
  21 *                          of the driving current
  22 * @min:        the minimum current of this group
  23 * @max:        the maximum current of this group
  24 * @step:       the step current of this group
  25 * @scal:       the weight factor
  26 *
  27 * formula: output = ((input) / step - 1) * scal
  28 */
  29struct mtk_drive_desc {
  30        u8 min;
  31        u8 max;
  32        u8 step;
  33        u8 scal;
  34};
  35
  36/* The groups of drive strength */
  37static const struct mtk_drive_desc mtk_drive[] = {
  38        [DRV_GRP0] = { 4, 16, 4, 1 },
  39        [DRV_GRP1] = { 4, 16, 4, 2 },
  40        [DRV_GRP2] = { 2, 8, 2, 1 },
  41        [DRV_GRP3] = { 2, 8, 2, 2 },
  42        [DRV_GRP4] = { 2, 16, 2, 1 },
  43};
  44
  45static void mtk_w32(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 val)
  46{
  47        writel_relaxed(val, pctl->base[i] + reg);
  48}
  49
  50static u32 mtk_r32(struct mtk_pinctrl *pctl, u8 i, u32 reg)
  51{
  52        return readl_relaxed(pctl->base[i] + reg);
  53}
  54
  55void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set)
  56{
  57        u32 val;
  58
  59        val = mtk_r32(pctl, i, reg);
  60        val &= ~mask;
  61        val |= set;
  62        mtk_w32(pctl, i, reg, val);
  63}
  64
  65static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
  66                                   const struct mtk_pin_desc *desc,
  67                                   int field, struct mtk_pin_field *pfd)
  68{
  69        const struct mtk_pin_field_calc *c, *e;
  70        const struct mtk_pin_reg_calc *rc;
  71        u32 bits;
  72
  73        if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
  74                rc = &hw->soc->reg_cal[field];
  75        } else {
  76                dev_dbg(hw->dev,
  77                        "Not support field %d for pin %d (%s)\n",
  78                        field, desc->number, desc->name);
  79                return -ENOTSUPP;
  80        }
  81
  82        c = rc->range;
  83        e = c + rc->nranges;
  84
  85        while (c < e) {
  86                if (desc->number >= c->s_pin && desc->number <= c->e_pin)
  87                        break;
  88                c++;
  89        }
  90
  91        if (c >= e) {
  92                dev_dbg(hw->dev, "Not support field %d for pin = %d (%s)\n",
  93                        field, desc->number, desc->name);
  94                return -ENOTSUPP;
  95        }
  96
  97        if (c->i_base > hw->nbase - 1) {
  98                dev_err(hw->dev,
  99                        "Invalid base for field %d for pin = %d (%s)\n",
 100                        field, desc->number, desc->name);
 101                return -EINVAL;
 102        }
 103
 104        /* Calculated bits as the overall offset the pin is located at,
 105         * if c->fixed is held, that determines the all the pins in the
 106         * range use the same field with the s_pin.
 107         */
 108        bits = c->fixed ? c->s_bit : c->s_bit +
 109               (desc->number - c->s_pin) * (c->x_bits);
 110
 111        /* Fill pfd from bits. For example 32-bit register applied is assumed
 112         * when c->sz_reg is equal to 32.
 113         */
 114        pfd->index = c->i_base;
 115        pfd->offset = c->s_addr + c->x_addrs * (bits / c->sz_reg);
 116        pfd->bitpos = bits % c->sz_reg;
 117        pfd->mask = (1 << c->x_bits) - 1;
 118
 119        /* pfd->next is used for indicating that bit wrapping-around happens
 120         * which requires the manipulation for bit 0 starting in the next
 121         * register to form the complete field read/write.
 122         */
 123        pfd->next = pfd->bitpos + c->x_bits > c->sz_reg ? c->x_addrs : 0;
 124
 125        return 0;
 126}
 127
 128static int mtk_hw_pin_field_get(struct mtk_pinctrl *hw,
 129                                const struct mtk_pin_desc *desc,
 130                                int field, struct mtk_pin_field *pfd)
 131{
 132        if (field < 0 || field >= PINCTRL_PIN_REG_MAX) {
 133                dev_err(hw->dev, "Invalid Field %d\n", field);
 134                return -EINVAL;
 135        }
 136
 137        return mtk_hw_pin_field_lookup(hw, desc, field, pfd);
 138}
 139
 140static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l)
 141{
 142        *l = 32 - pf->bitpos;
 143        *h = get_count_order(pf->mask) - *l;
 144}
 145
 146static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw,
 147                                     struct mtk_pin_field *pf, int value)
 148{
 149        int nbits_l, nbits_h;
 150
 151        mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
 152
 153        mtk_rmw(hw, pf->index, pf->offset, pf->mask << pf->bitpos,
 154                (value & pf->mask) << pf->bitpos);
 155
 156        mtk_rmw(hw, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1,
 157                (value & pf->mask) >> nbits_l);
 158}
 159
 160static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw,
 161                                    struct mtk_pin_field *pf, int *value)
 162{
 163        int nbits_l, nbits_h, h, l;
 164
 165        mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
 166
 167        l  = (mtk_r32(hw, pf->index, pf->offset)
 168              >> pf->bitpos) & (BIT(nbits_l) - 1);
 169        h  = (mtk_r32(hw, pf->index, pf->offset + pf->next))
 170              & (BIT(nbits_h) - 1);
 171
 172        *value = (h << nbits_l) | l;
 173}
 174
 175int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
 176                     int field, int value)
 177{
 178        struct mtk_pin_field pf;
 179        int err;
 180
 181        err = mtk_hw_pin_field_get(hw, desc, field, &pf);
 182        if (err)
 183                return err;
 184
 185        if (!pf.next)
 186                mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos,
 187                        (value & pf.mask) << pf.bitpos);
 188        else
 189                mtk_hw_write_cross_field(hw, &pf, value);
 190
 191        return 0;
 192}
 193
 194int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
 195                     int field, int *value)
 196{
 197        struct mtk_pin_field pf;
 198        int err;
 199
 200        err = mtk_hw_pin_field_get(hw, desc, field, &pf);
 201        if (err)
 202                return err;
 203
 204        if (!pf.next)
 205                *value = (mtk_r32(hw, pf.index, pf.offset)
 206                          >> pf.bitpos) & pf.mask;
 207        else
 208                mtk_hw_read_cross_field(hw, &pf, value);
 209
 210        return 0;
 211}
 212
 213static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, unsigned long eint_n)
 214{
 215        const struct mtk_pin_desc *desc;
 216        int i = 0;
 217
 218        desc = (const struct mtk_pin_desc *)hw->soc->pins;
 219
 220        while (i < hw->soc->npins) {
 221                if (desc[i].eint.eint_n == eint_n)
 222                        return desc[i].number;
 223                i++;
 224        }
 225
 226        return EINT_NA;
 227}
 228
 229static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n,
 230                             unsigned int *gpio_n,
 231                             struct gpio_chip **gpio_chip)
 232{
 233        struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
 234        const struct mtk_pin_desc *desc;
 235
 236        desc = (const struct mtk_pin_desc *)hw->soc->pins;
 237        *gpio_chip = &hw->chip;
 238
 239        /* Be greedy to guess first gpio_n is equal to eint_n */
 240        if (desc[eint_n].eint.eint_n == eint_n)
 241                *gpio_n = eint_n;
 242        else
 243                *gpio_n = mtk_xt_find_eint_num(hw, eint_n);
 244
 245        return *gpio_n == EINT_NA ? -EINVAL : 0;
 246}
 247
 248static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n)
 249{
 250        struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
 251        const struct mtk_pin_desc *desc;
 252        struct gpio_chip *gpio_chip;
 253        unsigned int gpio_n;
 254        int value, err;
 255
 256        err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
 257        if (err)
 258                return err;
 259
 260        desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
 261
 262        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
 263        if (err)
 264                return err;
 265
 266        return !!value;
 267}
 268
 269static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n)
 270{
 271        struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
 272        const struct mtk_pin_desc *desc;
 273        struct gpio_chip *gpio_chip;
 274        unsigned int gpio_n;
 275        int err;
 276
 277        err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
 278        if (err)
 279                return err;
 280
 281        desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
 282
 283        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
 284                               desc->eint.eint_m);
 285        if (err)
 286                return err;
 287
 288        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_INPUT);
 289        if (err)
 290                return err;
 291
 292        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, MTK_ENABLE);
 293        /* SMT is supposed to be supported by every real GPIO and doesn't
 294         * support virtual GPIOs, so the extra condition err != -ENOTSUPP
 295         * is just for adding EINT support to these virtual GPIOs. It should
 296         * add an extra flag in the pin descriptor when more pins with
 297         * distinctive characteristic come out.
 298         */
 299        if (err && err != -ENOTSUPP)
 300                return err;
 301
 302        return 0;
 303}
 304
 305static const struct mtk_eint_xt mtk_eint_xt = {
 306        .get_gpio_n = mtk_xt_get_gpio_n,
 307        .get_gpio_state = mtk_xt_get_gpio_state,
 308        .set_gpio_as_eint = mtk_xt_set_gpio_as_eint,
 309};
 310
 311int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
 312{
 313        struct device_node *np = pdev->dev.of_node;
 314        struct resource *res;
 315
 316        if (!IS_ENABLED(CONFIG_EINT_MTK))
 317                return 0;
 318
 319        if (!of_property_read_bool(np, "interrupt-controller"))
 320                return -ENODEV;
 321
 322        hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
 323        if (!hw->eint)
 324                return -ENOMEM;
 325
 326        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eint");
 327        if (!res) {
 328                dev_err(&pdev->dev, "Unable to get eint resource\n");
 329                return -ENODEV;
 330        }
 331
 332        hw->eint->base = devm_ioremap_resource(&pdev->dev, res);
 333        if (IS_ERR(hw->eint->base))
 334                return PTR_ERR(hw->eint->base);
 335
 336        hw->eint->irq = irq_of_parse_and_map(np, 0);
 337        if (!hw->eint->irq)
 338                return -EINVAL;
 339
 340        if (!hw->soc->eint_hw)
 341                return -ENODEV;
 342
 343        hw->eint->dev = &pdev->dev;
 344        hw->eint->hw = hw->soc->eint_hw;
 345        hw->eint->pctl = hw;
 346        hw->eint->gpio_xlate = &mtk_eint_xt;
 347
 348        return mtk_eint_do_init(hw->eint);
 349}
 350
 351/* Revision 0 */
 352int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw,
 353                                 const struct mtk_pin_desc *desc)
 354{
 355        int err;
 356
 357        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU,
 358                               MTK_DISABLE);
 359        if (err)
 360                return err;
 361
 362        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD,
 363                               MTK_DISABLE);
 364        if (err)
 365                return err;
 366
 367        return 0;
 368}
 369
 370int mtk_pinconf_bias_disable_get(struct mtk_pinctrl *hw,
 371                                 const struct mtk_pin_desc *desc, int *res)
 372{
 373        int v, v2;
 374        int err;
 375
 376        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &v);
 377        if (err)
 378                return err;
 379
 380        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &v2);
 381        if (err)
 382                return err;
 383
 384        if (v == MTK_ENABLE || v2 == MTK_ENABLE)
 385                return -EINVAL;
 386
 387        *res = 1;
 388
 389        return 0;
 390}
 391
 392int mtk_pinconf_bias_set(struct mtk_pinctrl *hw,
 393                         const struct mtk_pin_desc *desc, bool pullup)
 394{
 395        int err, arg;
 396
 397        arg = pullup ? 1 : 2;
 398
 399        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, arg & 1);
 400        if (err)
 401                return err;
 402
 403        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD,
 404                               !!(arg & 2));
 405        if (err)
 406                return err;
 407
 408        return 0;
 409}
 410
 411int mtk_pinconf_bias_get(struct mtk_pinctrl *hw,
 412                         const struct mtk_pin_desc *desc, bool pullup, int *res)
 413{
 414        int reg, err, v;
 415
 416        reg = pullup ? PINCTRL_PIN_REG_PU : PINCTRL_PIN_REG_PD;
 417
 418        err = mtk_hw_get_value(hw, desc, reg, &v);
 419        if (err)
 420                return err;
 421
 422        if (!v)
 423                return -EINVAL;
 424
 425        *res = 1;
 426
 427        return 0;
 428}
 429
 430/* Revision 1 */
 431int mtk_pinconf_bias_disable_set_rev1(struct mtk_pinctrl *hw,
 432                                      const struct mtk_pin_desc *desc)
 433{
 434        int err;
 435
 436        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN,
 437                               MTK_DISABLE);
 438        if (err)
 439                return err;
 440
 441        return 0;
 442}
 443
 444int mtk_pinconf_bias_disable_get_rev1(struct mtk_pinctrl *hw,
 445                                      const struct mtk_pin_desc *desc, int *res)
 446{
 447        int v, err;
 448
 449        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v);
 450        if (err)
 451                return err;
 452
 453        if (v == MTK_ENABLE)
 454                return -EINVAL;
 455
 456        *res = 1;
 457
 458        return 0;
 459}
 460
 461int mtk_pinconf_bias_set_rev1(struct mtk_pinctrl *hw,
 462                              const struct mtk_pin_desc *desc, bool pullup)
 463{
 464        int err, arg;
 465
 466        arg = pullup ? MTK_PULLUP : MTK_PULLDOWN;
 467
 468        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN,
 469                               MTK_ENABLE);
 470        if (err)
 471                return err;
 472
 473        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, arg);
 474        if (err)
 475                return err;
 476
 477        return 0;
 478}
 479
 480int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw,
 481                              const struct mtk_pin_desc *desc, bool pullup,
 482                              int *res)
 483{
 484        int err, v;
 485
 486        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v);
 487        if (err)
 488                return err;
 489
 490        if (v == MTK_DISABLE)
 491                return -EINVAL;
 492
 493        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, &v);
 494        if (err)
 495                return err;
 496
 497        if (pullup ^ (v == MTK_PULLUP))
 498                return -EINVAL;
 499
 500        *res = 1;
 501
 502        return 0;
 503}
 504
 505/* Revision 0 */
 506int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
 507                          const struct mtk_pin_desc *desc, u32 arg)
 508{
 509        const struct mtk_drive_desc *tb;
 510        int err = -ENOTSUPP;
 511
 512        tb = &mtk_drive[desc->drv_n];
 513        /* 4mA when (e8, e4) = (0, 0)
 514         * 8mA when (e8, e4) = (0, 1)
 515         * 12mA when (e8, e4) = (1, 0)
 516         * 16mA when (e8, e4) = (1, 1)
 517         */
 518        if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
 519                arg = (arg / tb->step - 1) * tb->scal;
 520                err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E4,
 521                                       arg & 0x1);
 522                if (err)
 523                        return err;
 524
 525                err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E8,
 526                                       (arg & 0x2) >> 1);
 527                if (err)
 528                        return err;
 529        }
 530
 531        return err;
 532}
 533
 534int mtk_pinconf_drive_get(struct mtk_pinctrl *hw,
 535                          const struct mtk_pin_desc *desc, int *val)
 536{
 537        const struct mtk_drive_desc *tb;
 538        int err, val1, val2;
 539
 540        tb = &mtk_drive[desc->drv_n];
 541
 542        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E4, &val1);
 543        if (err)
 544                return err;
 545
 546        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E8, &val2);
 547        if (err)
 548                return err;
 549
 550        /* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1)
 551         * 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1)
 552         */
 553        *val = (((val2 << 1) + val1) / tb->scal + 1) * tb->step;
 554
 555        return 0;
 556}
 557
 558/* Revision 1 */
 559int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw,
 560                               const struct mtk_pin_desc *desc, u32 arg)
 561{
 562        const struct mtk_drive_desc *tb;
 563        int err = -ENOTSUPP;
 564
 565        tb = &mtk_drive[desc->drv_n];
 566
 567        if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
 568                arg = (arg / tb->step - 1) * tb->scal;
 569
 570                err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV,
 571                                       arg);
 572                if (err)
 573                        return err;
 574        }
 575
 576        return err;
 577}
 578
 579int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw,
 580                               const struct mtk_pin_desc *desc, int *val)
 581{
 582        const struct mtk_drive_desc *tb;
 583        int err, val1;
 584
 585        tb = &mtk_drive[desc->drv_n];
 586
 587        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, &val1);
 588        if (err)
 589                return err;
 590
 591        *val = ((val1 & 0x7) / tb->scal + 1) * tb->step;
 592
 593        return 0;
 594}
 595
 596int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
 597                             const struct mtk_pin_desc *desc, bool pullup,
 598                             u32 arg)
 599{
 600        int err;
 601
 602        /* 10K off & 50K (75K) off, when (R0, R1) = (0, 0);
 603         * 10K off & 50K (75K) on, when (R0, R1) = (0, 1);
 604         * 10K on & 50K (75K) off, when (R0, R1) = (1, 0);
 605         * 10K on & 50K (75K) on, when (R0, R1) = (1, 1)
 606         */
 607        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, arg & 1);
 608        if (err)
 609                return 0;
 610
 611        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1,
 612                               !!(arg & 2));
 613        if (err)
 614                return 0;
 615
 616        arg = pullup ? 0 : 1;
 617
 618        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, arg);
 619
 620        /* If PUPD register is not supported for that pin, let's fallback to
 621         * general bias control.
 622         */
 623        if (err == -ENOTSUPP) {
 624                if (hw->soc->bias_set) {
 625                        err = hw->soc->bias_set(hw, desc, pullup);
 626                        if (err)
 627                                return err;
 628                } else {
 629                        return -ENOTSUPP;
 630                }
 631        }
 632
 633        return err;
 634}
 635
 636int mtk_pinconf_adv_pull_get(struct mtk_pinctrl *hw,
 637                             const struct mtk_pin_desc *desc, bool pullup,
 638                             u32 *val)
 639{
 640        u32 t, t2;
 641        int err;
 642
 643        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, &t);
 644
 645        /* If PUPD register is not supported for that pin, let's fallback to
 646         * general bias control.
 647         */
 648        if (err == -ENOTSUPP) {
 649                if (hw->soc->bias_get) {
 650                        err = hw->soc->bias_get(hw, desc, pullup, val);
 651                        if (err)
 652                                return err;
 653                } else {
 654                        return -ENOTSUPP;
 655                }
 656        } else {
 657                /* t == 0 supposes PULLUP for the customized PULL setup */
 658                if (err)
 659                        return err;
 660
 661                if (pullup ^ !t)
 662                        return -EINVAL;
 663        }
 664
 665        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &t);
 666        if (err)
 667                return err;
 668
 669        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &t2);
 670        if (err)
 671                return err;
 672
 673        *val = (t | t2 << 1) & 0x7;
 674
 675        return 0;
 676}
 677
 678int mtk_pinconf_adv_drive_set(struct mtk_pinctrl *hw,
 679                              const struct mtk_pin_desc *desc, u32 arg)
 680{
 681        int err;
 682        int en = arg & 1;
 683        int e0 = !!(arg & 2);
 684        int e1 = !!(arg & 4);
 685
 686        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV_EN, en);
 687        if (err)
 688                return err;
 689
 690        if (!en)
 691                return err;
 692
 693        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV_E0, e0);
 694        if (err)
 695                return err;
 696
 697        err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV_E1, e1);
 698        if (err)
 699                return err;
 700
 701        return err;
 702}
 703
 704int mtk_pinconf_adv_drive_get(struct mtk_pinctrl *hw,
 705                              const struct mtk_pin_desc *desc, u32 *val)
 706{
 707        u32 en, e0, e1;
 708        int err;
 709
 710        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV_EN, &en);
 711        if (err)
 712                return err;
 713
 714        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV_E0, &e0);
 715        if (err)
 716                return err;
 717
 718        err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV_E1, &e1);
 719        if (err)
 720                return err;
 721
 722        *val = (en | e0 << 1 | e1 << 2) & 0x7;
 723
 724        return 0;
 725}
 726