summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/meson
diff options
context:
space:
mode:
authorGuillaume La Roque <glaroque@baylibre.com>2019-05-14 04:26:51 -0400
committerLinus Walleij <linus.walleij@linaro.org>2019-05-23 03:24:46 -0400
commit6ea3e3bbef3705225bb675a8c57af58420c23f81 (patch)
tree03f98695e86c3f56d5f2a6f36216fa468fba48c1 /drivers/pinctrl/meson
parent9959d9a747fddfd9e1a37f2e3fc60cbc956aad3a (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> Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Tested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/meson')
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.c99
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.h18
2 files changed, 116 insertions, 1 deletions
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 8ea5c1527064..33b4b141baac 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -220,11 +220,54 @@ static int meson_pinconf_enable_bias(struct meson_pinctrl *pc, unsigned int pin,
220 return 0; 220 return 0;
221} 221}
222 222
223static int meson_pinconf_set_drive_strength(struct meson_pinctrl *pc,
224 unsigned int pin,
225 u16 drive_strength_ua)
226{
227 struct meson_bank *bank;
228 unsigned int reg, bit, ds_val;
229 int ret;
230
231 if (!pc->reg_ds) {
232 dev_err(pc->dev, "drive-strength not supported\n");
233 return -ENOTSUPP;
234 }
235
236 ret = meson_get_bank(pc, pin, &bank);
237 if (ret)
238 return ret;
239
240 meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit);
241 bit = bit << 1;
242
243 if (drive_strength_ua <= 500) {
244 ds_val = MESON_PINCONF_DRV_500UA;
245 } else if (drive_strength_ua <= 2500) {
246 ds_val = MESON_PINCONF_DRV_2500UA;
247 } else if (drive_strength_ua <= 3000) {
248 ds_val = MESON_PINCONF_DRV_3000UA;
249 } else if (drive_strength_ua <= 4000) {
250 ds_val = MESON_PINCONF_DRV_4000UA;
251 } else {
252 dev_warn_once(pc->dev,
253 "pin %u: invalid drive-strength : %d , default to 4mA\n",
254 pin, drive_strength_ua);
255 ds_val = MESON_PINCONF_DRV_4000UA;
256 }
257
258 ret = regmap_update_bits(pc->reg_ds, reg, 0x3 << bit, ds_val << bit);
259 if (ret)
260 return ret;
261
262 return 0;
263}
264
223static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin, 265static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
224 unsigned long *configs, unsigned num_configs) 266 unsigned long *configs, unsigned num_configs)
225{ 267{
226 struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 268 struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
227 enum pin_config_param param; 269 enum pin_config_param param;
270 unsigned int drive_strength_ua;
228 int i, ret; 271 int i, ret;
229 272
230 for (i = 0; i < num_configs; i++) { 273 for (i = 0; i < num_configs; i++) {
@@ -246,6 +289,14 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
246 if (ret) 289 if (ret)
247 return ret; 290 return ret;
248 break; 291 break;
292 case PIN_CONFIG_DRIVE_STRENGTH_UA:
293 drive_strength_ua =
294 pinconf_to_config_argument(configs[i]);
295 ret = meson_pinconf_set_drive_strength
296 (pc, pin, drive_strength_ua);
297 if (ret)
298 return ret;
299 break;
249 default: 300 default:
250 return -ENOTSUPP; 301 return -ENOTSUPP;
251 } 302 }
@@ -288,12 +339,55 @@ static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
288 return conf; 339 return conf;
289} 340}
290 341
342static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
343 unsigned int pin,
344 u16 *drive_strength_ua)
345{
346 struct meson_bank *bank;
347 unsigned int reg, bit;
348 unsigned int val;
349 int ret;
350
351 if (!pc->reg_ds)
352 return -ENOTSUPP;
353
354 ret = meson_get_bank(pc, pin, &bank);
355 if (ret)
356 return ret;
357
358 meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit);
359
360 ret = regmap_read(pc->reg_ds, reg, &val);
361 if (ret)
362 return ret;
363
364 switch ((val >> bit) & 0x3) {
365 case MESON_PINCONF_DRV_500UA:
366 *drive_strength_ua = 500;
367 break;
368 case MESON_PINCONF_DRV_2500UA:
369 *drive_strength_ua = 2500;
370 break;
371 case MESON_PINCONF_DRV_3000UA:
372 *drive_strength_ua = 3000;
373 break;
374 case MESON_PINCONF_DRV_4000UA:
375 *drive_strength_ua = 4000;
376 break;
377 default:
378 return -EINVAL;
379 }
380
381 return 0;
382}
383
291static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin, 384static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
292 unsigned long *config) 385 unsigned long *config)
293{ 386{
294 struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 387 struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
295 enum pin_config_param param = pinconf_to_config_param(*config); 388 enum pin_config_param param = pinconf_to_config_param(*config);
296 u16 arg; 389 u16 arg;
390 int ret;
297 391
298 switch (param) { 392 switch (param) {
299 case PIN_CONFIG_BIAS_DISABLE: 393 case PIN_CONFIG_BIAS_DISABLE:
@@ -304,6 +398,11 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
304 else 398 else
305 return -EINVAL; 399 return -EINVAL;
306 break; 400 break;
401 case PIN_CONFIG_DRIVE_STRENGTH_UA:
402 ret = meson_pinconf_get_drive_strength(pc, pin, &arg);
403 if (ret)
404 return ret;
405 break;
307 default: 406 default:
308 return -ENOTSUPP; 407 return -ENOTSUPP;
309 } 408 }
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index 5eaab925f427..cd955fb7c2ce 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -71,10 +71,21 @@ enum meson_reg_type {
71 REG_DIR, 71 REG_DIR,
72 REG_OUT, 72 REG_OUT,
73 REG_IN, 73 REG_IN,
74 REG_DS,
74 NUM_REG, 75 NUM_REG,
75}; 76};
76 77
77/** 78/**
79 * enum meson_pinconf_drv - value of drive-strength supported
80 */
81enum meson_pinconf_drv {
82 MESON_PINCONF_DRV_500UA,
83 MESON_PINCONF_DRV_2500UA,
84 MESON_PINCONF_DRV_3000UA,
85 MESON_PINCONF_DRV_4000UA,
86};
87
88/**
78 * struct meson bank 89 * struct meson bank
79 * 90 *
80 * @name: bank name 91 * @name: bank name
@@ -132,7 +143,8 @@ struct meson_pinctrl {
132 .num_groups = ARRAY_SIZE(fn ## _groups), \ 143 .num_groups = ARRAY_SIZE(fn ## _groups), \
133 } 144 }
134 145
135#define BANK(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib) \ 146#define BANK_DS(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib, \
147 dsr, dsb) \
136 { \ 148 { \
137 .name = n, \ 149 .name = n, \
138 .first = f, \ 150 .first = f, \
@@ -145,9 +157,13 @@ struct meson_pinctrl {
145 [REG_DIR] = { dr, db }, \ 157 [REG_DIR] = { dr, db }, \
146 [REG_OUT] = { or, ob }, \ 158 [REG_OUT] = { or, ob }, \
147 [REG_IN] = { ir, ib }, \ 159 [REG_IN] = { ir, ib }, \
160 [REG_DS] = { dsr, dsb }, \
148 }, \ 161 }, \
149 } 162 }
150 163
164#define BANK(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib) \
165 BANK_DS(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib, 0, 0)
166
151#define MESON_PIN(x) PINCTRL_PIN(x, #x) 167#define MESON_PIN(x) PINCTRL_PIN(x, #x)
152 168
153/* Common pmx functions */ 169/* Common pmx functions */