aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorTomasz Figa <t.figa@samsung.com>2014-07-02 11:40:59 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-07-11 08:08:36 -0400
commit18c28caa17d7127e0391e100a919d9f6c156e974 (patch)
tree4d2eb472ace97dd088aef0624a5a42ba01aae11e /drivers/pinctrl
parent0e9386752758b74fd42fda7cbdd6ccb5cb31033c (diff)
pinctrl: samsung: Decouple direction setting from pinctrl
This patch makes the pinctrl-samsung driver configure GPIO direction on its own, without using the pinctrl_gpio_direction_*() "helpers". The rationale behind this change is as follows: - pinctrl-samsung does not need translation from GPIO namespace to pinctrl namespace to handle GPIO operations - GPIO chip and offset therein are enough to calculate necessary offsets and bit masks in constant time, - the pinctrl_gpio_direction_*() functions do not do anything useful other than translating the pin into pinctrl namespace and calling the .gpio_set_direction() from pinmux_ops of the controller, - the undesirable side effect of using those helpers is losing the ability to change GPIO direction in atomic context, because they explicitly use a mutex for synchronization, Results of this patch are: - fixed warnings about scheduling while atomic in code that needs to set GPIO direction in atomic context (e.g. interrupt handler), - reduced overhead of bitbanging drivers that use gpio_direction_*(), e.g. i2c-gpio. Signed-off-by: Tomasz Figa <t.figa@samsung.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c99
1 files changed, 44 insertions, 55 deletions
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 089abde35d44..5740f93d658c 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -333,57 +333,12 @@ static int samsung_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
333 return 0; 333 return 0;
334} 334}
335 335
336/*
337 * The calls to gpio_direction_output() and gpio_direction_input()
338 * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
339 * function called from the gpiolib interface).
340 */
341static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
342 struct pinctrl_gpio_range *range, unsigned offset, bool input)
343{
344 struct samsung_pin_bank_type *type;
345 struct samsung_pin_bank *bank;
346 struct samsung_pinctrl_drv_data *drvdata;
347 void __iomem *reg;
348 u32 data, pin_offset, mask, shift;
349 unsigned long flags;
350
351 bank = gc_to_pin_bank(range->gc);
352 type = bank->type;
353 drvdata = pinctrl_dev_get_drvdata(pctldev);
354
355 pin_offset = offset - bank->pin_base;
356 reg = drvdata->virt_base + bank->pctl_offset +
357 type->reg_offset[PINCFG_TYPE_FUNC];
358
359 mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
360 shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
361 if (shift >= 32) {
362 /* Some banks have two config registers */
363 shift -= 32;
364 reg += 4;
365 }
366
367 spin_lock_irqsave(&bank->slock, flags);
368
369 data = readl(reg);
370 data &= ~(mask << shift);
371 if (!input)
372 data |= FUNC_OUTPUT << shift;
373 writel(data, reg);
374
375 spin_unlock_irqrestore(&bank->slock, flags);
376
377 return 0;
378}
379
380/* list of pinmux callbacks for the pinmux vertical in pinctrl core */ 336/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
381static const struct pinmux_ops samsung_pinmux_ops = { 337static const struct pinmux_ops samsung_pinmux_ops = {
382 .get_functions_count = samsung_get_functions_count, 338 .get_functions_count = samsung_get_functions_count,
383 .get_function_name = samsung_pinmux_get_fname, 339 .get_function_name = samsung_pinmux_get_fname,
384 .get_function_groups = samsung_pinmux_get_groups, 340 .get_function_groups = samsung_pinmux_get_groups,
385 .enable = samsung_pinmux_enable, 341 .enable = samsung_pinmux_enable,
386 .gpio_set_direction = samsung_pinmux_gpio_set_direction,
387}; 342};
388 343
389/* set or get the pin config settings for a specified pin */ 344/* set or get the pin config settings for a specified pin */
@@ -532,25 +487,59 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
532} 487}
533 488
534/* 489/*
535 * gpiolib gpio_direction_input callback function. The setting of the pin 490 * The calls to gpio_direction_output() and gpio_direction_input()
536 * mux function as 'gpio input' will be handled by the pinctrl susbsystem 491 * leads to this function call.
537 * interface.
538 */ 492 */
493static int samsung_gpio_set_direction(struct gpio_chip *gc,
494 unsigned offset, bool input)
495{
496 struct samsung_pin_bank_type *type;
497 struct samsung_pin_bank *bank;
498 struct samsung_pinctrl_drv_data *drvdata;
499 void __iomem *reg;
500 u32 data, mask, shift;
501 unsigned long flags;
502
503 bank = gc_to_pin_bank(gc);
504 type = bank->type;
505 drvdata = bank->drvdata;
506
507 reg = drvdata->virt_base + bank->pctl_offset +
508 type->reg_offset[PINCFG_TYPE_FUNC];
509
510 mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
511 shift = offset * type->fld_width[PINCFG_TYPE_FUNC];
512 if (shift >= 32) {
513 /* Some banks have two config registers */
514 shift -= 32;
515 reg += 4;
516 }
517
518 spin_lock_irqsave(&bank->slock, flags);
519
520 data = readl(reg);
521 data &= ~(mask << shift);
522 if (!input)
523 data |= FUNC_OUTPUT << shift;
524 writel(data, reg);
525
526 spin_unlock_irqrestore(&bank->slock, flags);
527
528 return 0;
529}
530
531/* gpiolib gpio_direction_input callback function. */
539static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset) 532static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
540{ 533{
541 return pinctrl_gpio_direction_input(gc->base + offset); 534 return samsung_gpio_set_direction(gc, offset, true);
542} 535}
543 536
544/* 537/* gpiolib gpio_direction_output callback function. */
545 * gpiolib gpio_direction_output callback function. The setting of the pin
546 * mux function as 'gpio output' will be handled by the pinctrl susbsystem
547 * interface.
548 */
549static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset, 538static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
550 int value) 539 int value)
551{ 540{
552 samsung_gpio_set(gc, offset, value); 541 samsung_gpio_set(gc, offset, value);
553 return pinctrl_gpio_direction_output(gc->base + offset); 542 return samsung_gpio_set_direction(gc, offset, false);
554} 543}
555 544
556/* 545/*