static void mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin, int value, enum pin_config_param param) { unsigned int reg_addr, offset; unsigned int bit; int ret; /* * Due to some pins are irregular, their input enable and smt * control register are discontinuous, but they are mapping together. * So we need this special handle. */ if (pctl->devdata->spec_ies_smt_set) { ret = pctl->devdata->spec_ies_smt_set(mtk_get_regmap(pctl, pin), pin, pctl->devdata->port_align, value); if (!ret) return; } bit = BIT(pin & 0xf); if (param == PIN_CONFIG_INPUT_ENABLE) offset = pctl->devdata->ies_offset; else offset = pctl->devdata->smt_offset; if (value) reg_addr = SET_ADDR(mtk_get_port(pctl, pin) + offset, pctl); else reg_addr = CLR_ADDR(mtk_get_port(pctl, pin) + offset, pctl); regmap_write(mtk_get_regmap(pctl, pin), reg_addr, bit); }
static int mtk_pconf_set_driving(struct mtk_pinctrl *pctl, unsigned int pin, unsigned char driving) { const struct mtk_pin_drv_grp *pin_drv; unsigned int val; unsigned int bits, mask, shift; const struct mtk_drv_group_desc *drv_grp; if (pin >= pctl->devdata->npins) return -EINVAL; pin_drv = mtk_find_pin_drv_grp_by_pin(pctl, pin); if (!pin_drv || pin_drv->grp > pctl->devdata->n_grp_cls) return -EINVAL; drv_grp = pctl->devdata->grp_desc + pin_drv->grp; if (driving >= drv_grp->min_drv && driving <= drv_grp->max_drv && !(driving % drv_grp->step)) { val = driving / drv_grp->step - 1; bits = drv_grp->high_bit - drv_grp->low_bit + 1; mask = BIT(bits) - 1; shift = pin_drv->bit + drv_grp->low_bit; mask <<= shift; val <<= shift; return regmap_update_bits(mtk_get_regmap(pctl, pin), pin_drv->offset, mask, val); } return -EINVAL; }
static int mtk_pconf_set_pull_select(struct mtk_pinctrl *pctl, unsigned int pin, bool enable, bool isup, unsigned int arg) { unsigned int bit; unsigned int reg_pullen, reg_pullsel; int ret; /* Some pins' pull setting are very different, * they have separate pull up/down bit, R0 and R1 * resistor bit, so we need this special handle. */ if (pctl->devdata->spec_pull_set) { ret = pctl->devdata->spec_pull_set(mtk_get_regmap(pctl, pin), pin, pctl->devdata->port_align, isup, arg); if (!ret) return 0; } /* For generic pull config, default arg value should be 0 or 1. */ if (arg != 0 && arg != 1) { dev_err(pctl->dev, "invalid pull-up argument %d on pin %d .\n", arg, pin); return -EINVAL; } bit = BIT(pin & 0xf); if (enable) reg_pullen = SET_ADDR(mtk_get_port(pctl, pin) + pctl->devdata->pullen_offset, pctl); else reg_pullen = CLR_ADDR(mtk_get_port(pctl, pin) + pctl->devdata->pullen_offset, pctl); if (isup) reg_pullsel = SET_ADDR(mtk_get_port(pctl, pin) + pctl->devdata->pullsel_offset, pctl); else reg_pullsel = CLR_ADDR(mtk_get_port(pctl, pin) + pctl->devdata->pullsel_offset, pctl); regmap_write(mtk_get_regmap(pctl, pin), reg_pullen, bit); regmap_write(mtk_get_regmap(pctl, pin), reg_pullsel, bit); return 0; }
static int mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin, int value, enum pin_config_param arg) { unsigned int reg_addr, offset; unsigned int bit; /** * Due to some soc are not support ies/smt config, add this special * control to handle it. */ if (!pctl->devdata->spec_ies_smt_set && pctl->devdata->ies_offset == MTK_PINCTRL_NOT_SUPPORT && arg == PIN_CONFIG_INPUT_ENABLE) return -EINVAL; if (!pctl->devdata->spec_ies_smt_set && pctl->devdata->smt_offset == MTK_PINCTRL_NOT_SUPPORT && arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE) return -EINVAL; /* * Due to some pins are irregular, their input enable and smt * control register are discontinuous, so we need this special handle. */ if (pctl->devdata->spec_ies_smt_set) { return pctl->devdata->spec_ies_smt_set(mtk_get_regmap(pctl, pin), pin, pctl->devdata->port_align, value, arg); } bit = BIT(pin & 0xf); if (arg == PIN_CONFIG_INPUT_ENABLE) offset = pctl->devdata->ies_offset; else offset = pctl->devdata->smt_offset; if (value) reg_addr = SET_ADDR(mtk_get_port(pctl, pin) + offset, pctl); else reg_addr = CLR_ADDR(mtk_get_port(pctl, pin) + offset, pctl); regmap_write(mtk_get_regmap(pctl, pin), reg_addr, bit); return 0; }
static void mtk_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { unsigned int reg_addr; unsigned int bit; struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev); reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dout_offset; bit = BIT(offset & 0xf); if (value) reg_addr = SET_ADDR(reg_addr, pctl); else reg_addr = CLR_ADDR(reg_addr, pctl); regmap_write(mtk_get_regmap(pctl, offset), reg_addr, bit); }
static int mtk_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset, bool input) { unsigned int reg_addr; unsigned int bit; struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dir_offset; bit = BIT(offset & 0xf); if (input) /* Different SoC has different alignment offset. */ reg_addr = CLR_ADDR(reg_addr, pctl); else reg_addr = SET_ADDR(reg_addr, pctl); regmap_write(mtk_get_regmap(pctl, offset), reg_addr, bit); return 0; }