1a1a503a8SSean Wang // SPDX-License-Identifier: GPL-2.0 2a1a503a8SSean Wang /* 3a1a503a8SSean Wang * Copyright (C) 2018 MediaTek Inc. 4a1a503a8SSean Wang * 5a1a503a8SSean Wang * Author: Sean Wang <sean.wang@mediatek.com> 6a1a503a8SSean Wang * 7a1a503a8SSean Wang */ 8a1a503a8SSean Wang 9a1a503a8SSean Wang #include <linux/device.h> 10a1a503a8SSean Wang #include <linux/err.h> 11a1a503a8SSean Wang #include <linux/gpio.h> 12a1a503a8SSean Wang #include <linux/io.h> 13a1a503a8SSean Wang 14a1a503a8SSean Wang #include "pinctrl-mtk-common-v2.h" 15a1a503a8SSean Wang 16c2832197SSean Wang /** 17c2832197SSean Wang * struct mtk_drive_desc - the structure that holds the information 18c2832197SSean Wang * of the driving current 19c2832197SSean Wang * @min: the minimum current of this group 20c2832197SSean Wang * @max: the maximum current of this group 21c2832197SSean Wang * @step: the step current of this group 22c2832197SSean Wang * @scal: the weight factor 23c2832197SSean Wang * 24c2832197SSean Wang * formula: output = ((input) / step - 1) * scal 25c2832197SSean Wang */ 26c2832197SSean Wang struct mtk_drive_desc { 27c2832197SSean Wang u8 min; 28c2832197SSean Wang u8 max; 29c2832197SSean Wang u8 step; 30c2832197SSean Wang u8 scal; 31c2832197SSean Wang }; 32c2832197SSean Wang 33c2832197SSean Wang /* The groups of drive strength */ 34c2832197SSean Wang const struct mtk_drive_desc mtk_drive[] = { 35c2832197SSean Wang [DRV_GRP0] = { 4, 16, 4, 1 }, 36c2832197SSean Wang [DRV_GRP1] = { 4, 16, 4, 2 }, 37c2832197SSean Wang [DRV_GRP2] = { 2, 8, 2, 1 }, 38c2832197SSean Wang [DRV_GRP3] = { 2, 8, 2, 2 }, 39c2832197SSean Wang [DRV_GRP4] = { 2, 16, 2, 1 }, 40c2832197SSean Wang }; 41c2832197SSean Wang 42*2bc47dfeSSean Wang static void mtk_w32(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 val) 43a1a503a8SSean Wang { 44*2bc47dfeSSean Wang writel_relaxed(val, pctl->base[i] + reg); 45a1a503a8SSean Wang } 46a1a503a8SSean Wang 47*2bc47dfeSSean Wang static u32 mtk_r32(struct mtk_pinctrl *pctl, u8 i, u32 reg) 48a1a503a8SSean Wang { 49*2bc47dfeSSean Wang return readl_relaxed(pctl->base[i] + reg); 50a1a503a8SSean Wang } 51a1a503a8SSean Wang 52*2bc47dfeSSean Wang void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set) 53a1a503a8SSean Wang { 54a1a503a8SSean Wang u32 val; 55a1a503a8SSean Wang 56*2bc47dfeSSean Wang val = mtk_r32(pctl, i, reg); 57a1a503a8SSean Wang val &= ~mask; 58a1a503a8SSean Wang val |= set; 59*2bc47dfeSSean Wang mtk_w32(pctl, i, reg, val); 60a1a503a8SSean Wang } 61a1a503a8SSean Wang 62ea051eb3SSean Wang static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw, 63ea051eb3SSean Wang const struct mtk_pin_desc *desc, 64a1a503a8SSean Wang const struct mtk_pin_reg_calc *rc, 65a1a503a8SSean Wang struct mtk_pin_field *pfd) 66a1a503a8SSean Wang { 67a1a503a8SSean Wang const struct mtk_pin_field_calc *c, *e; 68a1a503a8SSean Wang u32 bits; 69a1a503a8SSean Wang 70a1a503a8SSean Wang c = rc->range; 71a1a503a8SSean Wang e = c + rc->nranges; 72a1a503a8SSean Wang 73a1a503a8SSean Wang while (c < e) { 74ea051eb3SSean Wang if (desc->number >= c->s_pin && desc->number <= c->e_pin) 75a1a503a8SSean Wang break; 76a1a503a8SSean Wang c++; 77a1a503a8SSean Wang } 78a1a503a8SSean Wang 79a1a503a8SSean Wang if (c >= e) { 80ea051eb3SSean Wang dev_err(hw->dev, "Out of range for pin = %d (%s)\n", 81ea051eb3SSean Wang desc->number, desc->name); 82a1a503a8SSean Wang return -EINVAL; 83a1a503a8SSean Wang } 84a1a503a8SSean Wang 85*2bc47dfeSSean Wang if (c->i_base > hw->nbase - 1) { 86*2bc47dfeSSean Wang dev_err(hw->dev, "Invalid base is found for pin = %d (%s)\n", 87*2bc47dfeSSean Wang desc->number, desc->name); 88*2bc47dfeSSean Wang return -EINVAL; 89*2bc47dfeSSean Wang } 90*2bc47dfeSSean Wang 91b906faf7SSean Wang /* Calculated bits as the overall offset the pin is located at, 92b906faf7SSean Wang * if c->fixed is held, that determines the all the pins in the 93b906faf7SSean Wang * range use the same field with the s_pin. 94b906faf7SSean Wang */ 95ea051eb3SSean Wang bits = c->fixed ? c->s_bit : c->s_bit + 96ea051eb3SSean Wang (desc->number - c->s_pin) * (c->x_bits); 97a1a503a8SSean Wang 98b906faf7SSean Wang /* Fill pfd from bits. For example 32-bit register applied is assumed 99b906faf7SSean Wang * when c->sz_reg is equal to 32. 100b906faf7SSean Wang */ 101*2bc47dfeSSean Wang pfd->index = c->i_base; 102b906faf7SSean Wang pfd->offset = c->s_addr + c->x_addrs * (bits / c->sz_reg); 103b906faf7SSean Wang pfd->bitpos = bits % c->sz_reg; 104a1a503a8SSean Wang pfd->mask = (1 << c->x_bits) - 1; 105a1a503a8SSean Wang 106a1a503a8SSean Wang /* pfd->next is used for indicating that bit wrapping-around happens 107a1a503a8SSean Wang * which requires the manipulation for bit 0 starting in the next 108a1a503a8SSean Wang * register to form the complete field read/write. 109a1a503a8SSean Wang */ 110b906faf7SSean Wang pfd->next = pfd->bitpos + c->x_bits > c->sz_reg ? c->x_addrs : 0; 111a1a503a8SSean Wang 112a1a503a8SSean Wang return 0; 113a1a503a8SSean Wang } 114a1a503a8SSean Wang 115ea051eb3SSean Wang static int mtk_hw_pin_field_get(struct mtk_pinctrl *hw, 116ea051eb3SSean Wang const struct mtk_pin_desc *desc, 117a1a503a8SSean Wang int field, struct mtk_pin_field *pfd) 118a1a503a8SSean Wang { 119a1a503a8SSean Wang const struct mtk_pin_reg_calc *rc; 120a1a503a8SSean Wang 121a1a503a8SSean Wang if (field < 0 || field >= PINCTRL_PIN_REG_MAX) { 122a1a503a8SSean Wang dev_err(hw->dev, "Invalid Field %d\n", field); 123a1a503a8SSean Wang return -EINVAL; 124a1a503a8SSean Wang } 125a1a503a8SSean Wang 126a1a503a8SSean Wang if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) { 127a1a503a8SSean Wang rc = &hw->soc->reg_cal[field]; 128a1a503a8SSean Wang } else { 129a1a503a8SSean Wang dev_err(hw->dev, "Undefined range for field %d\n", field); 130a1a503a8SSean Wang return -EINVAL; 131a1a503a8SSean Wang } 132a1a503a8SSean Wang 133ea051eb3SSean Wang return mtk_hw_pin_field_lookup(hw, desc, rc, pfd); 134a1a503a8SSean Wang } 135a1a503a8SSean Wang 136a1a503a8SSean Wang static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l) 137a1a503a8SSean Wang { 138a1a503a8SSean Wang *l = 32 - pf->bitpos; 139a1a503a8SSean Wang *h = get_count_order(pf->mask) - *l; 140a1a503a8SSean Wang } 141a1a503a8SSean Wang 142a1a503a8SSean Wang static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw, 143a1a503a8SSean Wang struct mtk_pin_field *pf, int value) 144a1a503a8SSean Wang { 145a1a503a8SSean Wang int nbits_l, nbits_h; 146a1a503a8SSean Wang 147a1a503a8SSean Wang mtk_hw_bits_part(pf, &nbits_h, &nbits_l); 148a1a503a8SSean Wang 149*2bc47dfeSSean Wang mtk_rmw(hw, pf->index, pf->offset, pf->mask << pf->bitpos, 150a1a503a8SSean Wang (value & pf->mask) << pf->bitpos); 151a1a503a8SSean Wang 152*2bc47dfeSSean Wang mtk_rmw(hw, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1, 153a1a503a8SSean Wang (value & pf->mask) >> nbits_l); 154a1a503a8SSean Wang } 155a1a503a8SSean Wang 156a1a503a8SSean Wang static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw, 157a1a503a8SSean Wang struct mtk_pin_field *pf, int *value) 158a1a503a8SSean Wang { 159a1a503a8SSean Wang int nbits_l, nbits_h, h, l; 160a1a503a8SSean Wang 161a1a503a8SSean Wang mtk_hw_bits_part(pf, &nbits_h, &nbits_l); 162a1a503a8SSean Wang 163*2bc47dfeSSean Wang l = (mtk_r32(hw, pf->index, pf->offset) 164*2bc47dfeSSean Wang >> pf->bitpos) & (BIT(nbits_l) - 1); 165*2bc47dfeSSean Wang h = (mtk_r32(hw, pf->index, pf->offset + pf->next)) 166*2bc47dfeSSean Wang & (BIT(nbits_h) - 1); 167a1a503a8SSean Wang 168a1a503a8SSean Wang *value = (h << nbits_l) | l; 169a1a503a8SSean Wang } 170a1a503a8SSean Wang 171ea051eb3SSean Wang int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, 172ea051eb3SSean Wang int field, int value) 173a1a503a8SSean Wang { 174a1a503a8SSean Wang struct mtk_pin_field pf; 175a1a503a8SSean Wang int err; 176a1a503a8SSean Wang 177ea051eb3SSean Wang err = mtk_hw_pin_field_get(hw, desc, field, &pf); 178a1a503a8SSean Wang if (err) 179a1a503a8SSean Wang return err; 180a1a503a8SSean Wang 181a1a503a8SSean Wang if (!pf.next) 182*2bc47dfeSSean Wang mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos, 183a1a503a8SSean Wang (value & pf.mask) << pf.bitpos); 184a1a503a8SSean Wang else 185a1a503a8SSean Wang mtk_hw_write_cross_field(hw, &pf, value); 186a1a503a8SSean Wang 187a1a503a8SSean Wang return 0; 188a1a503a8SSean Wang } 189a1a503a8SSean Wang 190ea051eb3SSean Wang int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, 191ea051eb3SSean Wang int field, int *value) 192a1a503a8SSean Wang { 193a1a503a8SSean Wang struct mtk_pin_field pf; 194a1a503a8SSean Wang int err; 195a1a503a8SSean Wang 196ea051eb3SSean Wang err = mtk_hw_pin_field_get(hw, desc, field, &pf); 197a1a503a8SSean Wang if (err) 198a1a503a8SSean Wang return err; 199a1a503a8SSean Wang 200a1a503a8SSean Wang if (!pf.next) 201*2bc47dfeSSean Wang *value = (mtk_r32(hw, pf.index, pf.offset) 202*2bc47dfeSSean Wang >> pf.bitpos) & pf.mask; 203a1a503a8SSean Wang else 204a1a503a8SSean Wang mtk_hw_read_cross_field(hw, &pf, value); 205a1a503a8SSean Wang 206a1a503a8SSean Wang return 0; 207a1a503a8SSean Wang } 208c2832197SSean Wang 2099afc305bSSean Wang /* Revision 0 */ 21085430152SSean Wang int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw, 21185430152SSean Wang const struct mtk_pin_desc *desc) 21285430152SSean Wang { 21385430152SSean Wang int err; 21485430152SSean Wang 215ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, 21685430152SSean Wang MTK_DISABLE); 21785430152SSean Wang if (err) 21885430152SSean Wang return err; 21985430152SSean Wang 220ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, 22185430152SSean Wang MTK_DISABLE); 22285430152SSean Wang if (err) 22385430152SSean Wang return err; 22485430152SSean Wang 22585430152SSean Wang return 0; 22685430152SSean Wang } 22785430152SSean Wang 22885430152SSean Wang int mtk_pinconf_bias_disable_get(struct mtk_pinctrl *hw, 22985430152SSean Wang const struct mtk_pin_desc *desc, int *res) 23085430152SSean Wang { 23185430152SSean Wang int v, v2; 23285430152SSean Wang int err; 23385430152SSean Wang 234ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &v); 23585430152SSean Wang if (err) 23685430152SSean Wang return err; 23785430152SSean Wang 238ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &v2); 23985430152SSean Wang if (err) 24085430152SSean Wang return err; 24185430152SSean Wang 24285430152SSean Wang if (v == MTK_ENABLE || v2 == MTK_ENABLE) 24385430152SSean Wang return -EINVAL; 24485430152SSean Wang 24585430152SSean Wang *res = 1; 24685430152SSean Wang 24785430152SSean Wang return 0; 24885430152SSean Wang } 24985430152SSean Wang 25085430152SSean Wang int mtk_pinconf_bias_set(struct mtk_pinctrl *hw, 25185430152SSean Wang const struct mtk_pin_desc *desc, bool pullup) 25285430152SSean Wang { 25385430152SSean Wang int err, arg; 25485430152SSean Wang 25585430152SSean Wang arg = pullup ? 1 : 2; 25685430152SSean Wang 257ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, arg & 1); 25885430152SSean Wang if (err) 25985430152SSean Wang return err; 26085430152SSean Wang 261ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, 26285430152SSean Wang !!(arg & 2)); 26385430152SSean Wang if (err) 26485430152SSean Wang return err; 26585430152SSean Wang 26685430152SSean Wang return 0; 26785430152SSean Wang } 26885430152SSean Wang 26985430152SSean Wang int mtk_pinconf_bias_get(struct mtk_pinctrl *hw, 27085430152SSean Wang const struct mtk_pin_desc *desc, bool pullup, int *res) 27185430152SSean Wang { 27285430152SSean Wang int reg, err, v; 27385430152SSean Wang 27485430152SSean Wang reg = pullup ? PINCTRL_PIN_REG_PU : PINCTRL_PIN_REG_PD; 27585430152SSean Wang 276ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, reg, &v); 27785430152SSean Wang if (err) 27885430152SSean Wang return err; 27985430152SSean Wang 28085430152SSean Wang if (!v) 28185430152SSean Wang return -EINVAL; 28285430152SSean Wang 28385430152SSean Wang *res = 1; 28485430152SSean Wang 28585430152SSean Wang return 0; 28685430152SSean Wang } 28785430152SSean Wang 2889afc305bSSean Wang /* Revision 1 */ 2899afc305bSSean Wang int mtk_pinconf_bias_disable_set_rev1(struct mtk_pinctrl *hw, 2909afc305bSSean Wang const struct mtk_pin_desc *desc) 2919afc305bSSean Wang { 2929afc305bSSean Wang int err; 2939afc305bSSean Wang 294ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN, 2959afc305bSSean Wang MTK_DISABLE); 2969afc305bSSean Wang if (err) 2979afc305bSSean Wang return err; 2989afc305bSSean Wang 2999afc305bSSean Wang return 0; 3009afc305bSSean Wang } 3019afc305bSSean Wang 3029afc305bSSean Wang int mtk_pinconf_bias_disable_get_rev1(struct mtk_pinctrl *hw, 3039afc305bSSean Wang const struct mtk_pin_desc *desc, int *res) 3049afc305bSSean Wang { 3059afc305bSSean Wang int v, err; 3069afc305bSSean Wang 307ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v); 3089afc305bSSean Wang if (err) 3099afc305bSSean Wang return err; 3109afc305bSSean Wang 3119afc305bSSean Wang if (v == MTK_ENABLE) 3129afc305bSSean Wang return -EINVAL; 3139afc305bSSean Wang 3149afc305bSSean Wang *res = 1; 3159afc305bSSean Wang 3169afc305bSSean Wang return 0; 3179afc305bSSean Wang } 3189afc305bSSean Wang 3199afc305bSSean Wang int mtk_pinconf_bias_set_rev1(struct mtk_pinctrl *hw, 3209afc305bSSean Wang const struct mtk_pin_desc *desc, bool pullup) 3219afc305bSSean Wang { 3229afc305bSSean Wang int err, arg; 3239afc305bSSean Wang 3249afc305bSSean Wang arg = pullup ? MTK_PULLUP : MTK_PULLDOWN; 3259afc305bSSean Wang 326ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN, 3279afc305bSSean Wang MTK_ENABLE); 3289afc305bSSean Wang if (err) 3299afc305bSSean Wang return err; 3309afc305bSSean Wang 331ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, arg); 3329afc305bSSean Wang if (err) 3339afc305bSSean Wang return err; 3349afc305bSSean Wang 3359afc305bSSean Wang return 0; 3369afc305bSSean Wang } 3379afc305bSSean Wang 3389afc305bSSean Wang int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw, 3399afc305bSSean Wang const struct mtk_pin_desc *desc, bool pullup, 3409afc305bSSean Wang int *res) 3419afc305bSSean Wang { 3429afc305bSSean Wang int err, v; 3439afc305bSSean Wang 344ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v); 3459afc305bSSean Wang if (err) 3469afc305bSSean Wang return err; 3479afc305bSSean Wang 3489afc305bSSean Wang if (v == MTK_DISABLE) 3499afc305bSSean Wang return -EINVAL; 3509afc305bSSean Wang 351ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, &v); 3529afc305bSSean Wang if (err) 3539afc305bSSean Wang return err; 3549afc305bSSean Wang 3559afc305bSSean Wang if (pullup ^ (v == MTK_PULLUP)) 3569afc305bSSean Wang return -EINVAL; 3579afc305bSSean Wang 3589afc305bSSean Wang *res = 1; 3599afc305bSSean Wang 3609afc305bSSean Wang return 0; 3619afc305bSSean Wang } 3629afc305bSSean Wang 363c2832197SSean Wang /* Revision 0 */ 364c2832197SSean Wang int mtk_pinconf_drive_set(struct mtk_pinctrl *hw, 365c2832197SSean Wang const struct mtk_pin_desc *desc, u32 arg) 366c2832197SSean Wang { 367c2832197SSean Wang const struct mtk_drive_desc *tb; 368c2832197SSean Wang int err = -ENOTSUPP; 369c2832197SSean Wang 370c2832197SSean Wang tb = &mtk_drive[desc->drv_n]; 371c2832197SSean Wang /* 4mA when (e8, e4) = (0, 0) 372c2832197SSean Wang * 8mA when (e8, e4) = (0, 1) 373c2832197SSean Wang * 12mA when (e8, e4) = (1, 0) 374c2832197SSean Wang * 16mA when (e8, e4) = (1, 1) 375c2832197SSean Wang */ 376c2832197SSean Wang if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) { 377c2832197SSean Wang arg = (arg / tb->step - 1) * tb->scal; 378ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E4, 379c2832197SSean Wang arg & 0x1); 380c2832197SSean Wang if (err) 381c2832197SSean Wang return err; 382c2832197SSean Wang 383ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E8, 384c2832197SSean Wang (arg & 0x2) >> 1); 385c2832197SSean Wang if (err) 386c2832197SSean Wang return err; 387c2832197SSean Wang } 388c2832197SSean Wang 389c2832197SSean Wang return err; 390c2832197SSean Wang } 391c2832197SSean Wang 392c2832197SSean Wang int mtk_pinconf_drive_get(struct mtk_pinctrl *hw, 393c2832197SSean Wang const struct mtk_pin_desc *desc, int *val) 394c2832197SSean Wang { 395c2832197SSean Wang const struct mtk_drive_desc *tb; 396c2832197SSean Wang int err, val1, val2; 397c2832197SSean Wang 398c2832197SSean Wang tb = &mtk_drive[desc->drv_n]; 399c2832197SSean Wang 400ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E4, &val1); 401c2832197SSean Wang if (err) 402c2832197SSean Wang return err; 403c2832197SSean Wang 404ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E8, &val2); 405c2832197SSean Wang if (err) 406c2832197SSean Wang return err; 407c2832197SSean Wang 408c2832197SSean Wang /* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1) 409c2832197SSean Wang * 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1) 410c2832197SSean Wang */ 411c2832197SSean Wang *val = (((val2 << 1) + val1) / tb->scal + 1) * tb->step; 412c2832197SSean Wang 413c2832197SSean Wang return 0; 414c2832197SSean Wang } 4153ad38a14SSean Wang 4163ad38a14SSean Wang /* Revision 1 */ 4173ad38a14SSean Wang int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw, 4183ad38a14SSean Wang const struct mtk_pin_desc *desc, u32 arg) 4193ad38a14SSean Wang { 4203ad38a14SSean Wang const struct mtk_drive_desc *tb; 4213ad38a14SSean Wang int err = -ENOTSUPP; 4223ad38a14SSean Wang 4233ad38a14SSean Wang tb = &mtk_drive[desc->drv_n]; 4243ad38a14SSean Wang 4253ad38a14SSean Wang if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) { 4263ad38a14SSean Wang arg = (arg / tb->step - 1) * tb->scal; 4273ad38a14SSean Wang 428ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV, 4293ad38a14SSean Wang arg); 4303ad38a14SSean Wang if (err) 4313ad38a14SSean Wang return err; 4323ad38a14SSean Wang } 4333ad38a14SSean Wang 4343ad38a14SSean Wang return err; 4353ad38a14SSean Wang } 4363ad38a14SSean Wang 4373ad38a14SSean Wang int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw, 4383ad38a14SSean Wang const struct mtk_pin_desc *desc, int *val) 4393ad38a14SSean Wang { 4403ad38a14SSean Wang const struct mtk_drive_desc *tb; 4413ad38a14SSean Wang int err, val1; 4423ad38a14SSean Wang 4433ad38a14SSean Wang tb = &mtk_drive[desc->drv_n]; 4443ad38a14SSean Wang 445ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, &val1); 4463ad38a14SSean Wang if (err) 4473ad38a14SSean Wang return err; 4483ad38a14SSean Wang 4493ad38a14SSean Wang *val = ((val1 & 0x7) / tb->scal + 1) * tb->step; 4503ad38a14SSean Wang 4513ad38a14SSean Wang return 0; 4523ad38a14SSean Wang } 4530d7ca772SSean Wang 4540d7ca772SSean Wang int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw, 4550d7ca772SSean Wang const struct mtk_pin_desc *desc, bool pullup, 4560d7ca772SSean Wang u32 arg) 4570d7ca772SSean Wang { 4580d7ca772SSean Wang int err; 4590d7ca772SSean Wang 4600d7ca772SSean Wang /* 10K off & 50K (75K) off, when (R0, R1) = (0, 0); 4610d7ca772SSean Wang * 10K off & 50K (75K) on, when (R0, R1) = (0, 1); 4620d7ca772SSean Wang * 10K on & 50K (75K) off, when (R0, R1) = (1, 0); 4630d7ca772SSean Wang * 10K on & 50K (75K) on, when (R0, R1) = (1, 1) 4640d7ca772SSean Wang */ 465ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, arg & 1); 4660d7ca772SSean Wang if (err) 4670d7ca772SSean Wang return 0; 4680d7ca772SSean Wang 469ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1, 4700d7ca772SSean Wang !!(arg & 2)); 4710d7ca772SSean Wang if (err) 4720d7ca772SSean Wang return 0; 4730d7ca772SSean Wang 4740d7ca772SSean Wang arg = pullup ? 0 : 1; 4750d7ca772SSean Wang 476ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, arg); 4770d7ca772SSean Wang 4780d7ca772SSean Wang return err; 4790d7ca772SSean Wang } 4800d7ca772SSean Wang 4810d7ca772SSean Wang int mtk_pinconf_adv_pull_get(struct mtk_pinctrl *hw, 4820d7ca772SSean Wang const struct mtk_pin_desc *desc, bool pullup, 4830d7ca772SSean Wang u32 *val) 4840d7ca772SSean Wang { 4850d7ca772SSean Wang u32 t, t2; 4860d7ca772SSean Wang int err; 4870d7ca772SSean Wang 488ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, &t); 4890d7ca772SSean Wang if (err) 4900d7ca772SSean Wang return err; 4910d7ca772SSean Wang 4920d7ca772SSean Wang /* t == 0 supposes PULLUP for the customized PULL setup */ 4930d7ca772SSean Wang if (pullup ^ !t) 4940d7ca772SSean Wang return -EINVAL; 4950d7ca772SSean Wang 496ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &t); 4970d7ca772SSean Wang if (err) 4980d7ca772SSean Wang return err; 4990d7ca772SSean Wang 500ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &t2); 5010d7ca772SSean Wang if (err) 5020d7ca772SSean Wang return err; 5030d7ca772SSean Wang 5040d7ca772SSean Wang *val = (t | t2 << 1) & 0x7; 5050d7ca772SSean Wang 5060d7ca772SSean Wang return 0; 5070d7ca772SSean Wang } 508