aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume La Roque2019-06-04 13:53:07 +0200
committerNeil Armstrong2019-06-12 11:50:02 +0200
commit478c563b400e0ddf8438ac57e2ecc1cedd9d072a (patch)
tree3a783ecd9d0a916256d1e9d9118e5ec88d39c181
parent4c2eecf2441334bbeaa5091f39283fc6f4d56963 (diff)
pinctrl: meson: add support of drive-strength-microamp
drive-strength-microamp is a new feature needed for G12A SoC. the default DS setting after boot is usually 500uA and it is not enough for many functions. We need to be able to set the drive strength to reliably enable things like MMC, I2C, etc ... Signed-off-by: Guillaume La Roque <glaroque@baylibre.com> Tested-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c1
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.c45
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.h42
3 files changed, 74 insertions, 14 deletions
diff --git a/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c b/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c
index 10b070ea067..b5d74068c57 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 eb40a84ed12..f664d76b54e 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, &reg, &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 0882dfe713e..98010cdaf96 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -59,6 +59,16 @@ struct meson_reg_desc {
};
/**
+ * 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
*/
enum meson_reg_type {
@@ -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)