diff --git a/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c b/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c index 10b070ea06..b5d74068c5 100644 --- a/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c +++ b/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c @@ -142,6 +142,7 @@ const struct pinconf_param meson_axg_pinconf_params[] = { { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, + { "drive-strength-microamp", PIN_CONFIG_DRIVE_STRENGTH_UA, 0 }, }; const struct pinctrl_ops meson_axg_pinctrl_ops = { diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index eb40a84ed1..f664d76b54 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c @@ -222,6 +222,47 @@ static int meson_pinconf_bias_set(struct udevice *dev, unsigned int pin, return 0; } +static int meson_pinconf_drive_strength_set(struct udevice *dev, + unsigned int pin, + unsigned int drive_strength_ua) +{ + struct meson_pinctrl *priv = dev_get_priv(dev); + unsigned int offset = pin - priv->data->pin_base; + unsigned int reg, bit; + unsigned int ds_val; + int ret; + + if (!priv->reg_ds) { + dev_err(dev, "drive-strength-microamp not supported\n"); + return -ENOTSUPP; + } + + ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_DS, ®, &bit); + if (ret) + return ret; + + bit = bit << 1; + + if (drive_strength_ua <= 500) { + ds_val = MESON_PINCONF_DRV_500UA; + } else if (drive_strength_ua <= 2500) { + ds_val = MESON_PINCONF_DRV_2500UA; + } else if (drive_strength_ua <= 3000) { + ds_val = MESON_PINCONF_DRV_3000UA; + } else if (drive_strength_ua <= 4000) { + ds_val = MESON_PINCONF_DRV_4000UA; + } else { + dev_warn(dev, + "pin %u: invalid drive-strength-microamp : %d , default to 4mA\n", + pin, drive_strength_ua); + ds_val = MESON_PINCONF_DRV_4000UA; + } + + clrsetbits_le32(priv->reg_ds + reg, 0x3 << bit, ds_val << bit); + + return 0; +} + int meson_pinconf_set(struct udevice *dev, unsigned int pin, unsigned int param, unsigned int arg) { @@ -233,7 +274,9 @@ int meson_pinconf_set(struct udevice *dev, unsigned int pin, case PIN_CONFIG_BIAS_PULL_DOWN: ret = meson_pinconf_bias_set(dev, pin, param); break; - + case PIN_CONFIG_DRIVE_STRENGTH_UA: + ret = meson_pinconf_drive_strength_set(dev, pin, arg); + break; default: dev_err(dev, "unsupported configuration parameter %u\n", param); return -EINVAL; diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h index 0882dfe713..98010cdaf9 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.h +++ b/drivers/pinctrl/meson/pinctrl-meson.h @@ -58,6 +58,16 @@ struct meson_reg_desc { unsigned int bit; }; +/** + * enum meson_pinconf_drv - value of drive-strength supported + */ +enum meson_pinconf_drv { + MESON_PINCONF_DRV_500UA, + MESON_PINCONF_DRV_2500UA, + MESON_PINCONF_DRV_3000UA, + MESON_PINCONF_DRV_4000UA, +}; + /** * enum meson_reg_type - type of registers encoded in @meson_reg_desc */ @@ -67,6 +77,7 @@ enum meson_reg_type { REG_DIR, REG_OUT, REG_IN, + REG_DS, NUM_REG, }; @@ -99,19 +110,24 @@ struct meson_bank { .num_groups = ARRAY_SIZE(fn ## _groups), \ } -#define BANK(n, f, l, per, peb, pr, pb, dr, db, or, ob, ir, ib) \ - { \ - .name = n, \ - .first = f, \ - .last = l, \ - .regs = { \ - [REG_PULLEN] = { per, peb }, \ - [REG_PULL] = { pr, pb }, \ - [REG_DIR] = { dr, db }, \ - [REG_OUT] = { or, ob }, \ - [REG_IN] = { ir, ib }, \ - }, \ - } +#define BANK_DS(n, f, l, per, peb, pr, pb, dr, db, or, ob, ir, ib, \ + dsr, dsb) \ + { \ + .name = n, \ + .first = f, \ + .last = l, \ + .regs = { \ + [REG_PULLEN] = {per, peb}, \ + [REG_PULL] = {pr, pb}, \ + [REG_DIR] = {dr, db}, \ + [REG_OUT] = { or, ob}, \ + [REG_IN] = {ir, ib}, \ + [REG_DS] = {dsr, dsb}, \ + }, \ + } + +#define BANK(n, f, l, per, peb, pr, pb, dr, db, or, ob, ir, ib) \ + BANK_DS(n, f, l, per, peb, pr, pb, dr, db, or, ob, ir, ib, 0, 0) #define MESON_PIN(x, b) PINCTRL_PIN(PIN(x, b), #x)