@@ -1304,28 +1304,28 @@ static struct meson_pmx_func meson_g12a_aobus_functions[] = {
};
static struct meson_bank meson_g12a_periphs_banks[] = {
- /* name first last irq pullen pull dir out in */
- BANK("Z", GPIOZ_0, GPIOZ_15, 12, 27,
- 4, 0, 4, 0, 12, 0, 13, 0, 14, 0),
- BANK("H", GPIOH_0, GPIOH_8, 28, 36,
- 3, 0, 3, 0, 9, 0, 10, 0, 11, 0),
- BANK("BOOT", BOOT_0, BOOT_15, 37, 52,
- 0, 0, 0, 0, 0, 0, 1, 0, 2, 0),
- BANK("C", GPIOC_0, GPIOC_7, 53, 60,
- 1, 0, 1, 0, 3, 0, 4, 0, 5, 0),
- BANK("A", GPIOA_0, GPIOA_15, 61, 76,
- 5, 0, 5, 0, 16, 0, 17, 0, 18, 0),
- BANK("X", GPIOX_0, GPIOX_19, 77, 96,
- 2, 0, 2, 0, 6, 0, 7, 0, 8, 0),
+ /* name first last irq pullen pull dir out in ds */
+ BANK_DS("Z", GPIOZ_0, GPIOZ_15, 12, 27,
+ 4, 0, 4, 0, 12, 0, 13, 0, 14, 0, 5, 0),
+ BANK_DS("H", GPIOH_0, GPIOH_8, 28, 36,
+ 3, 0, 3, 0, 9, 0, 10, 0, 11, 0, 4, 0),
+ BANK_DS("BOOT", BOOT_0, BOOT_15, 37, 52,
+ 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0),
+ BANK_DS("C", GPIOC_0, GPIOC_7, 53, 60,
+ 1, 0, 1, 0, 3, 0, 4, 0, 5, 0, 1, 0),
+ BANK_DS("A", GPIOA_0, GPIOA_15, 61, 76,
+ 5, 0, 5, 0, 16, 0, 17, 0, 18, 0, 6, 0),
+ BANK_DS("X", GPIOX_0, GPIOX_19, 77, 96,
+ 2, 0, 2, 0, 6, 0, 7, 0, 8, 0, 2, 0),
};
static struct meson_bank meson_g12a_aobus_banks[] = {
- /* name first last irq pullen pull dir out in */
- BANK("AO", GPIOAO_0, GPIOAO_11, 0, 11,
- 3, 0, 2, 0, 0, 0, 4, 0, 1, 0),
+ /* name first last irq pullen pull dir out in ds */
+ BANK_DS("AO", GPIOAO_0, GPIOAO_11, 0, 11, 3, 0, 2, 0, 0, 0, 4, 0, 1, 0,
+ 0, 0),
/* GPIOE actually located in the AO bank */
- BANK("E", GPIOE_0, GPIOE_2, 97, 99,
- 3, 16, 2, 16, 0, 16, 4, 16, 1, 16),
+ BANK_DS("E", GPIOE_0, GPIOE_2, 97, 99, 3, 16, 2, 16, 0, 16, 4, 16, 1,
+ 16, 1, 0),
};
static struct meson_pmx_bank meson_g12a_periphs_pmx_banks[] = {
@@ -174,65 +174,108 @@ int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector,
return 0;
}
-static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
- unsigned long *configs, unsigned num_configs)
+static int meson_pinconf_set_bias(struct meson_pinctrl *pc, unsigned int pin,
+ enum pin_config_param conf)
+{
+ struct meson_bank *bank;
+ unsigned int reg, bit, val = 0;
+ int ret;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, REG_PULLEN, ®, &bit);
+
+ if (conf == PIN_CONFIG_BIAS_DISABLE) {
+ ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), 0);
+ if (ret)
+ return ret;
+ } else {
+ meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit);
+ if (conf == PIN_CONFIG_BIAS_PULL_UP)
+ val = BIT(bit);
+
+ ret = regmap_update_bits(pc->reg_pull, reg, BIT(bit), val);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, REG_PULLEN, ®, &bit);
+ ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit),
+ BIT(bit));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int meson_pinconf_set_drive_strength(struct meson_pinctrl *pc,
+ unsigned int pin, u16 arg)
{
- struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
struct meson_bank *bank;
- enum pin_config_param param;
unsigned int reg, bit;
- int i, ret;
+ unsigned int ds_val;
+ int ret;
+
+ if (!pc->reg_ds) {
+ dev_err(pc->dev, "drive-strength not supported\n");
+ return -ENOTSUPP;
+ }
ret = meson_get_bank(pc, pin, &bank);
if (ret)
return ret;
+ meson_calc_reg_and_bit(bank, pin, REG_DS, ®, &bit);
+ bit = bit << 1;
+
+ if (arg <= 500) {
+ ds_val = MESON_PINCONF_DRV_500UA;
+ } else if (arg <= 2500) {
+ ds_val = MESON_PINCONF_DRV_2500UA;
+ } else if (arg <= 3000) {
+ ds_val = MESON_PINCONF_DRV_3000UA;
+ } else if (arg <= 4000) {
+ ds_val = MESON_PINCONF_DRV_4000UA;
+ } else {
+ dev_warn_once(pc->dev,
+ "pin %u: invalid drive-strength : %d , default to 4mA\n",
+ pin, arg);
+ ds_val = MESON_PINCONF_DRV_4000UA;
+ }
+
+ ret = regmap_update_bits(pc->reg_ds, reg, 0x3 << bit, ds_val << bit);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
+ unsigned long *configs, unsigned num_configs)
+{
+ struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
+ enum pin_config_param param;
+ unsigned int arg;
+ int i, ret;
+
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
- dev_dbg(pc->dev, "pin %u: disable bias\n", pin);
-
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN, ®,
- &bit);
- ret = regmap_update_bits(pc->reg_pullen, reg,
- BIT(bit), 0);
- if (ret)
- return ret;
- break;
case PIN_CONFIG_BIAS_PULL_UP:
- dev_dbg(pc->dev, "pin %u: enable pull-up\n", pin);
-
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
- ®, &bit);
- ret = regmap_update_bits(pc->reg_pullen, reg,
- BIT(bit), BIT(bit));
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit);
- ret = regmap_update_bits(pc->reg_pull, reg,
- BIT(bit), BIT(bit));
- if (ret)
- return ret;
- break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- dev_dbg(pc->dev, "pin %u: enable pull-down\n", pin);
-
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
- ®, &bit);
- ret = regmap_update_bits(pc->reg_pullen, reg,
- BIT(bit), BIT(bit));
+ ret = meson_pinconf_set_bias(pc, pin, param);
if (ret)
return ret;
-
- meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit);
- ret = regmap_update_bits(pc->reg_pull, reg,
- BIT(bit), 0);
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ arg = pinconf_to_config_argument(configs[i]);
+ ret = meson_pinconf_set_drive_strength(pc, pin, arg);
if (ret)
return ret;
- break;
default:
return -ENOTSUPP;
}
@@ -275,12 +318,51 @@ static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
return conf;
}
+static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
+ unsigned int pin, u16 *arg)
+{
+ struct meson_bank *bank;
+ unsigned int reg, bit;
+ unsigned int val;
+ int ret;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, REG_DS, ®, &bit);
+
+ ret = regmap_read(pc->reg_ds, reg, &val);
+ if (ret)
+ return ret;
+
+ switch ((val >> bit) & 0x3) {
+ case MESON_PINCONF_DRV_500UA:
+ *arg = 500;
+ break;
+ case MESON_PINCONF_DRV_2500UA:
+ *arg = 2500;
+ break;
+ case MESON_PINCONF_DRV_3000UA:
+ *arg = 3000;
+ break;
+ case MESON_PINCONF_DRV_4000UA:
+ *arg = 4000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
unsigned long *config)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
enum pin_config_param param = pinconf_to_config_param(*config);
u16 arg;
+ int ret;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
@@ -291,6 +373,10 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
else
return -EINVAL;
break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ ret = meson_pinconf_get_drive_strength(pc, pin, &arg);
+ if (ret)
+ return ret;
default:
return -ENOTSUPP;
}
@@ -71,9 +71,20 @@ enum meson_reg_type {
REG_DIR,
REG_OUT,
REG_IN,
+ REG_DS,
NUM_REG,
};
+/**
+ * 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,
+};
+
/**
* struct meson bank
*
@@ -132,7 +143,8 @@ struct meson_pinctrl {
.num_groups = ARRAY_SIZE(fn ## _groups), \
}
-#define BANK(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib) \
+#define BANK_DS(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib, \
+ dsr, dsb) \
{ \
.name = n, \
.first = f, \
@@ -145,8 +157,12 @@ struct meson_pinctrl {
[REG_DIR] = { dr, db }, \
[REG_OUT] = { or, ob }, \
[REG_IN] = { ir, ib }, \
+ [REG_DS] = { dsr, dsb }, \
}, \
- }
+ }
+
+#define BANK(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib) \
+ BANK_DS(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib, 0, 0)
#define MESON_PIN(x) PINCTRL_PIN(x, #x)