diff options
author | Jerome Brunet <jbrunet@baylibre.com> | 2019-05-16 11:13:39 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2019-05-24 07:49:32 -0400 |
commit | b22a7f85443e579367dfc2d7f4cb6aa863c3a709 (patch) | |
tree | aa61635273dd93517d74a1b92ac12b644af1b03e /drivers/pinctrl/meson | |
parent | 1254db248fce4e2cf05a01c1c8df3b79745424c0 (diff) |
pinctrl: meson: add output support in pinconf
Add pinconf support for PIN_CONFIG_OUTPUT_ENABLE and PIN_CONFIG_OUTPUT
in the meson pinctrl driver.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/meson')
-rw-r--r-- | drivers/pinctrl/meson/pinctrl-meson.c | 182 |
1 files changed, 127 insertions, 55 deletions
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index 33b4b141baac..410eb7559016 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c | |||
@@ -174,6 +174,88 @@ int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector, | |||
174 | return 0; | 174 | return 0; |
175 | } | 175 | } |
176 | 176 | ||
177 | static int meson_pinconf_set_gpio_bit(struct meson_pinctrl *pc, | ||
178 | unsigned int pin, | ||
179 | unsigned int reg_type, | ||
180 | bool arg) | ||
181 | { | ||
182 | struct meson_bank *bank; | ||
183 | unsigned int reg, bit; | ||
184 | int ret; | ||
185 | |||
186 | ret = meson_get_bank(pc, pin, &bank); | ||
187 | if (ret) | ||
188 | return ret; | ||
189 | |||
190 | meson_calc_reg_and_bit(bank, pin, reg_type, ®, &bit); | ||
191 | return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), | ||
192 | arg ? BIT(bit) : 0); | ||
193 | } | ||
194 | |||
195 | static int meson_pinconf_get_gpio_bit(struct meson_pinctrl *pc, | ||
196 | unsigned int pin, | ||
197 | unsigned int reg_type) | ||
198 | { | ||
199 | struct meson_bank *bank; | ||
200 | unsigned int reg, bit, val; | ||
201 | int ret; | ||
202 | |||
203 | ret = meson_get_bank(pc, pin, &bank); | ||
204 | if (ret) | ||
205 | return ret; | ||
206 | |||
207 | meson_calc_reg_and_bit(bank, pin, reg_type, ®, &bit); | ||
208 | ret = regmap_read(pc->reg_gpio, reg, &val); | ||
209 | if (ret) | ||
210 | return ret; | ||
211 | |||
212 | return BIT(bit) & val ? 1 : 0; | ||
213 | } | ||
214 | |||
215 | static int meson_pinconf_set_output(struct meson_pinctrl *pc, | ||
216 | unsigned int pin, | ||
217 | bool out) | ||
218 | { | ||
219 | return meson_pinconf_set_gpio_bit(pc, pin, REG_DIR, !out); | ||
220 | } | ||
221 | |||
222 | static int meson_pinconf_get_output(struct meson_pinctrl *pc, | ||
223 | unsigned int pin) | ||
224 | { | ||
225 | int ret = meson_pinconf_get_gpio_bit(pc, pin, REG_DIR); | ||
226 | |||
227 | if (ret < 0) | ||
228 | return ret; | ||
229 | |||
230 | return !ret; | ||
231 | } | ||
232 | |||
233 | static int meson_pinconf_set_drive(struct meson_pinctrl *pc, | ||
234 | unsigned int pin, | ||
235 | bool high) | ||
236 | { | ||
237 | return meson_pinconf_set_gpio_bit(pc, pin, REG_OUT, high); | ||
238 | } | ||
239 | |||
240 | static int meson_pinconf_get_drive(struct meson_pinctrl *pc, | ||
241 | unsigned int pin) | ||
242 | { | ||
243 | return meson_pinconf_get_gpio_bit(pc, pin, REG_OUT); | ||
244 | } | ||
245 | |||
246 | static int meson_pinconf_set_output_drive(struct meson_pinctrl *pc, | ||
247 | unsigned int pin, | ||
248 | bool high) | ||
249 | { | ||
250 | int ret; | ||
251 | |||
252 | ret = meson_pinconf_set_output(pc, pin, true); | ||
253 | if (ret) | ||
254 | return ret; | ||
255 | |||
256 | return meson_pinconf_set_drive(pc, pin, high); | ||
257 | } | ||
258 | |||
177 | static int meson_pinconf_disable_bias(struct meson_pinctrl *pc, | 259 | static int meson_pinconf_disable_bias(struct meson_pinctrl *pc, |
178 | unsigned int pin) | 260 | unsigned int pin) |
179 | { | 261 | { |
@@ -267,39 +349,48 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin, | |||
267 | { | 349 | { |
268 | struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); | 350 | struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); |
269 | enum pin_config_param param; | 351 | enum pin_config_param param; |
270 | unsigned int drive_strength_ua; | 352 | unsigned int arg = 0; |
271 | int i, ret; | 353 | int i, ret; |
272 | 354 | ||
273 | for (i = 0; i < num_configs; i++) { | 355 | for (i = 0; i < num_configs; i++) { |
274 | param = pinconf_to_config_param(configs[i]); | 356 | param = pinconf_to_config_param(configs[i]); |
275 | 357 | ||
276 | switch (param) { | 358 | switch (param) { |
359 | case PIN_CONFIG_DRIVE_STRENGTH_UA: | ||
360 | case PIN_CONFIG_OUTPUT_ENABLE: | ||
361 | case PIN_CONFIG_OUTPUT: | ||
362 | arg = pinconf_to_config_argument(configs[i]); | ||
363 | break; | ||
364 | |||
365 | default: | ||
366 | break; | ||
367 | } | ||
368 | |||
369 | switch (param) { | ||
277 | case PIN_CONFIG_BIAS_DISABLE: | 370 | case PIN_CONFIG_BIAS_DISABLE: |
278 | ret = meson_pinconf_disable_bias(pc, pin); | 371 | ret = meson_pinconf_disable_bias(pc, pin); |
279 | if (ret) | ||
280 | return ret; | ||
281 | break; | 372 | break; |
282 | case PIN_CONFIG_BIAS_PULL_UP: | 373 | case PIN_CONFIG_BIAS_PULL_UP: |
283 | ret = meson_pinconf_enable_bias(pc, pin, true); | 374 | ret = meson_pinconf_enable_bias(pc, pin, true); |
284 | if (ret) | ||
285 | return ret; | ||
286 | break; | 375 | break; |
287 | case PIN_CONFIG_BIAS_PULL_DOWN: | 376 | case PIN_CONFIG_BIAS_PULL_DOWN: |
288 | ret = meson_pinconf_enable_bias(pc, pin, false); | 377 | ret = meson_pinconf_enable_bias(pc, pin, false); |
289 | if (ret) | ||
290 | return ret; | ||
291 | break; | 378 | break; |
292 | case PIN_CONFIG_DRIVE_STRENGTH_UA: | 379 | case PIN_CONFIG_DRIVE_STRENGTH_UA: |
293 | drive_strength_ua = | 380 | ret = meson_pinconf_set_drive_strength(pc, pin, arg); |
294 | pinconf_to_config_argument(configs[i]); | 381 | break; |
295 | ret = meson_pinconf_set_drive_strength | 382 | case PIN_CONFIG_OUTPUT_ENABLE: |
296 | (pc, pin, drive_strength_ua); | 383 | ret = meson_pinconf_set_output(pc, pin, arg); |
297 | if (ret) | 384 | break; |
298 | return ret; | 385 | case PIN_CONFIG_OUTPUT: |
386 | ret = meson_pinconf_set_output_drive(pc, pin, arg); | ||
299 | break; | 387 | break; |
300 | default: | 388 | default: |
301 | return -ENOTSUPP; | 389 | ret = -ENOTSUPP; |
302 | } | 390 | } |
391 | |||
392 | if (ret) | ||
393 | return ret; | ||
303 | } | 394 | } |
304 | 395 | ||
305 | return 0; | 396 | return 0; |
@@ -403,6 +494,24 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin, | |||
403 | if (ret) | 494 | if (ret) |
404 | return ret; | 495 | return ret; |
405 | break; | 496 | break; |
497 | case PIN_CONFIG_OUTPUT_ENABLE: | ||
498 | ret = meson_pinconf_get_output(pc, pin); | ||
499 | if (ret <= 0) | ||
500 | return -EINVAL; | ||
501 | arg = 1; | ||
502 | break; | ||
503 | case PIN_CONFIG_OUTPUT: | ||
504 | ret = meson_pinconf_get_output(pc, pin); | ||
505 | if (ret <= 0) | ||
506 | return -EINVAL; | ||
507 | |||
508 | ret = meson_pinconf_get_drive(pc, pin); | ||
509 | if (ret < 0) | ||
510 | return -EINVAL; | ||
511 | |||
512 | arg = ret; | ||
513 | break; | ||
514 | |||
406 | default: | 515 | default: |
407 | return -ENOTSUPP; | 516 | return -ENOTSUPP; |
408 | } | 517 | } |
@@ -447,56 +556,19 @@ static const struct pinconf_ops meson_pinconf_ops = { | |||
447 | 556 | ||
448 | static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) | 557 | static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) |
449 | { | 558 | { |
450 | struct meson_pinctrl *pc = gpiochip_get_data(chip); | 559 | return meson_pinconf_set_output(gpiochip_get_data(chip), gpio, false); |
451 | unsigned int reg, bit; | ||
452 | struct meson_bank *bank; | ||
453 | int ret; | ||
454 | |||
455 | ret = meson_get_bank(pc, gpio, &bank); | ||
456 | if (ret) | ||
457 | return ret; | ||
458 | |||
459 | meson_calc_reg_and_bit(bank, gpio, REG_DIR, ®, &bit); | ||
460 | |||
461 | return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), BIT(bit)); | ||
462 | } | 560 | } |
463 | 561 | ||
464 | static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, | 562 | static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, |
465 | int value) | 563 | int value) |
466 | { | 564 | { |
467 | struct meson_pinctrl *pc = gpiochip_get_data(chip); | 565 | return meson_pinconf_set_output_drive(gpiochip_get_data(chip), |
468 | unsigned int reg, bit; | 566 | gpio, value); |
469 | struct meson_bank *bank; | ||
470 | int ret; | ||
471 | |||
472 | ret = meson_get_bank(pc, gpio, &bank); | ||
473 | if (ret) | ||
474 | return ret; | ||
475 | |||
476 | meson_calc_reg_and_bit(bank, gpio, REG_DIR, ®, &bit); | ||
477 | ret = regmap_update_bits(pc->reg_gpio, reg, BIT(bit), 0); | ||
478 | if (ret) | ||
479 | return ret; | ||
480 | |||
481 | meson_calc_reg_and_bit(bank, gpio, REG_OUT, ®, &bit); | ||
482 | return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), | ||
483 | value ? BIT(bit) : 0); | ||
484 | } | 567 | } |
485 | 568 | ||
486 | static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) | 569 | static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) |
487 | { | 570 | { |
488 | struct meson_pinctrl *pc = gpiochip_get_data(chip); | 571 | meson_pinconf_set_drive(gpiochip_get_data(chip), gpio, value); |
489 | unsigned int reg, bit; | ||
490 | struct meson_bank *bank; | ||
491 | int ret; | ||
492 | |||
493 | ret = meson_get_bank(pc, gpio, &bank); | ||
494 | if (ret) | ||
495 | return; | ||
496 | |||
497 | meson_calc_reg_and_bit(bank, gpio, REG_OUT, ®, &bit); | ||
498 | regmap_update_bits(pc->reg_gpio, reg, BIT(bit), | ||
499 | value ? BIT(bit) : 0); | ||
500 | } | 572 | } |
501 | 573 | ||
502 | static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio) | 574 | static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio) |