diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-02-19 11:25:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-02-19 11:25:40 -0500 |
commit | 409ee136f28f71cbec518cfc85a379a508ccbaa0 (patch) | |
tree | 5392d24a7971b532c266d2331358fc320e2b53ea | |
parent | 9001b8e4f08dd7ae8429214979bd7783160932c5 (diff) | |
parent | d9ff0eb9ca4b00ce2fbf9ede1e99681f05c0bc91 (diff) |
Merge tag 'pinctrl-v4.5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull Pin control fixes from Linus Walleij:
"Pin control fixes for the v4.5 series, all are individual driver
fixes:
- Fix the PXA2xx driver to export its init function so we do not
break modular compiles.
- Hide unused functions in the Nomadik driver.
- Fix up direction control in the Mediatek driver.
- Toggle the sunxi GPIO lines to input when you read them on the H3
GPIO controller, lest you only get garbage.
- Fix up the number of settings in the MVEBU driver.
- Fix a serious SMP race condition in the Samsung driver"
* tag 'pinctrl-v4.5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
pinctrl: samsung: fix SMP race condition
pinctrl: mvebu: fix num_settings in mpp group assignment
pinctrl: sunxi: H3 requires irq_read_needs_mux
pinctrl: mediatek: fix direction control issue
pinctrl: nomadik: hide unused functions
pinctrl: pxa: export pxa2xx_pinctrl_init()
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 | ||||
-rw-r--r-- | drivers/pinctrl/mvebu/pinctrl-mvebu.c | 9 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-abx500.c | 5 | ||||
-rw-r--r-- | drivers/pinctrl/pxa/pinctrl-pxa2xx.c | 1 | ||||
-rw-r--r-- | drivers/pinctrl/samsung/pinctrl-samsung.c | 48 | ||||
-rw-r--r-- | drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 1 |
6 files changed, 48 insertions, 18 deletions
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 16d48a4ed225..e96e86d2e745 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c | |||
@@ -347,6 +347,7 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev, | |||
347 | ret = mtk_pconf_set_pull_select(pctl, pin, true, false, arg); | 347 | ret = mtk_pconf_set_pull_select(pctl, pin, true, false, arg); |
348 | break; | 348 | break; |
349 | case PIN_CONFIG_INPUT_ENABLE: | 349 | case PIN_CONFIG_INPUT_ENABLE: |
350 | mtk_pmx_gpio_set_direction(pctldev, NULL, pin, true); | ||
350 | ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param); | 351 | ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param); |
351 | break; | 352 | break; |
352 | case PIN_CONFIG_OUTPUT: | 353 | case PIN_CONFIG_OUTPUT: |
@@ -354,6 +355,7 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev, | |||
354 | ret = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false); | 355 | ret = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false); |
355 | break; | 356 | break; |
356 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: | 357 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
358 | mtk_pmx_gpio_set_direction(pctldev, NULL, pin, true); | ||
357 | ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param); | 359 | ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param); |
358 | break; | 360 | break; |
359 | case PIN_CONFIG_DRIVE_STRENGTH: | 361 | case PIN_CONFIG_DRIVE_STRENGTH: |
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index e4d473811bb3..3ef798fac81b 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c | |||
@@ -666,16 +666,19 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) | |||
666 | struct mvebu_mpp_ctrl_setting *set = &mode->settings[0]; | 666 | struct mvebu_mpp_ctrl_setting *set = &mode->settings[0]; |
667 | struct mvebu_pinctrl_group *grp; | 667 | struct mvebu_pinctrl_group *grp; |
668 | unsigned num_settings; | 668 | unsigned num_settings; |
669 | unsigned supp_settings; | ||
669 | 670 | ||
670 | for (num_settings = 0; ; set++) { | 671 | for (num_settings = 0, supp_settings = 0; ; set++) { |
671 | if (!set->name) | 672 | if (!set->name) |
672 | break; | 673 | break; |
673 | 674 | ||
675 | num_settings++; | ||
676 | |||
674 | /* skip unsupported settings for this variant */ | 677 | /* skip unsupported settings for this variant */ |
675 | if (pctl->variant && !(pctl->variant & set->variant)) | 678 | if (pctl->variant && !(pctl->variant & set->variant)) |
676 | continue; | 679 | continue; |
677 | 680 | ||
678 | num_settings++; | 681 | supp_settings++; |
679 | 682 | ||
680 | /* find gpio/gpo/gpi settings */ | 683 | /* find gpio/gpo/gpi settings */ |
681 | if (strcmp(set->name, "gpio") == 0) | 684 | if (strcmp(set->name, "gpio") == 0) |
@@ -688,7 +691,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) | |||
688 | } | 691 | } |
689 | 692 | ||
690 | /* skip modes with no settings for this variant */ | 693 | /* skip modes with no settings for this variant */ |
691 | if (!num_settings) | 694 | if (!supp_settings) |
692 | continue; | 695 | continue; |
693 | 696 | ||
694 | grp = mvebu_pinctrl_find_group_by_pid(pctl, mode->pid); | 697 | grp = mvebu_pinctrl_find_group_by_pid(pctl, mode->pid); |
diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 085e60106ec2..1f7469c9857d 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c | |||
@@ -191,6 +191,7 @@ static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | |||
191 | dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret); | 191 | dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret); |
192 | } | 192 | } |
193 | 193 | ||
194 | #ifdef CONFIG_DEBUG_FS | ||
194 | static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset, | 195 | static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset, |
195 | enum abx500_gpio_pull_updown *pull_updown) | 196 | enum abx500_gpio_pull_updown *pull_updown) |
196 | { | 197 | { |
@@ -226,6 +227,7 @@ out: | |||
226 | 227 | ||
227 | return ret; | 228 | return ret; |
228 | } | 229 | } |
230 | #endif | ||
229 | 231 | ||
230 | static int abx500_set_pull_updown(struct abx500_pinctrl *pct, | 232 | static int abx500_set_pull_updown(struct abx500_pinctrl *pct, |
231 | int offset, enum abx500_gpio_pull_updown val) | 233 | int offset, enum abx500_gpio_pull_updown val) |
@@ -468,6 +470,7 @@ out: | |||
468 | return ret; | 470 | return ret; |
469 | } | 471 | } |
470 | 472 | ||
473 | #ifdef CONFIG_DEBUG_FS | ||
471 | static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, | 474 | static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, |
472 | unsigned gpio) | 475 | unsigned gpio) |
473 | { | 476 | { |
@@ -553,8 +556,6 @@ out: | |||
553 | return ret; | 556 | return ret; |
554 | } | 557 | } |
555 | 558 | ||
556 | #ifdef CONFIG_DEBUG_FS | ||
557 | |||
558 | #include <linux/seq_file.h> | 559 | #include <linux/seq_file.h> |
559 | 560 | ||
560 | static void abx500_gpio_dbg_show_one(struct seq_file *s, | 561 | static void abx500_gpio_dbg_show_one(struct seq_file *s, |
diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c index d90e205cf809..216f227c6009 100644 --- a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c +++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c | |||
@@ -426,6 +426,7 @@ int pxa2xx_pinctrl_init(struct platform_device *pdev, | |||
426 | 426 | ||
427 | return 0; | 427 | return 0; |
428 | } | 428 | } |
429 | EXPORT_SYMBOL(pxa2xx_pinctrl_init); | ||
429 | 430 | ||
430 | int pxa2xx_pinctrl_exit(struct platform_device *pdev) | 431 | int pxa2xx_pinctrl_exit(struct platform_device *pdev) |
431 | { | 432 | { |
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index f67b1e958589..5cc97f85db02 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c | |||
@@ -514,25 +514,35 @@ static const struct pinconf_ops samsung_pinconf_ops = { | |||
514 | .pin_config_group_set = samsung_pinconf_group_set, | 514 | .pin_config_group_set = samsung_pinconf_group_set, |
515 | }; | 515 | }; |
516 | 516 | ||
517 | /* gpiolib gpio_set callback function */ | 517 | /* |
518 | static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | 518 | * The samsung_gpio_set_vlaue() should be called with "bank->slock" held |
519 | * to avoid race condition. | ||
520 | */ | ||
521 | static void samsung_gpio_set_value(struct gpio_chip *gc, | ||
522 | unsigned offset, int value) | ||
519 | { | 523 | { |
520 | struct samsung_pin_bank *bank = gpiochip_get_data(gc); | 524 | struct samsung_pin_bank *bank = gpiochip_get_data(gc); |
521 | const struct samsung_pin_bank_type *type = bank->type; | 525 | const struct samsung_pin_bank_type *type = bank->type; |
522 | unsigned long flags; | ||
523 | void __iomem *reg; | 526 | void __iomem *reg; |
524 | u32 data; | 527 | u32 data; |
525 | 528 | ||
526 | reg = bank->drvdata->virt_base + bank->pctl_offset; | 529 | reg = bank->drvdata->virt_base + bank->pctl_offset; |
527 | 530 | ||
528 | spin_lock_irqsave(&bank->slock, flags); | ||
529 | |||
530 | data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); | 531 | data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); |
531 | data &= ~(1 << offset); | 532 | data &= ~(1 << offset); |
532 | if (value) | 533 | if (value) |
533 | data |= 1 << offset; | 534 | data |= 1 << offset; |
534 | writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]); | 535 | writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]); |
536 | } | ||
537 | |||
538 | /* gpiolib gpio_set callback function */ | ||
539 | static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | ||
540 | { | ||
541 | struct samsung_pin_bank *bank = gpiochip_get_data(gc); | ||
542 | unsigned long flags; | ||
535 | 543 | ||
544 | spin_lock_irqsave(&bank->slock, flags); | ||
545 | samsung_gpio_set_value(gc, offset, value); | ||
536 | spin_unlock_irqrestore(&bank->slock, flags); | 546 | spin_unlock_irqrestore(&bank->slock, flags); |
537 | } | 547 | } |
538 | 548 | ||
@@ -553,6 +563,8 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) | |||
553 | } | 563 | } |
554 | 564 | ||
555 | /* | 565 | /* |
566 | * The samsung_gpio_set_direction() should be called with "bank->slock" held | ||
567 | * to avoid race condition. | ||
556 | * The calls to gpio_direction_output() and gpio_direction_input() | 568 | * The calls to gpio_direction_output() and gpio_direction_input() |
557 | * leads to this function call. | 569 | * leads to this function call. |
558 | */ | 570 | */ |
@@ -564,7 +576,6 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc, | |||
564 | struct samsung_pinctrl_drv_data *drvdata; | 576 | struct samsung_pinctrl_drv_data *drvdata; |
565 | void __iomem *reg; | 577 | void __iomem *reg; |
566 | u32 data, mask, shift; | 578 | u32 data, mask, shift; |
567 | unsigned long flags; | ||
568 | 579 | ||
569 | bank = gpiochip_get_data(gc); | 580 | bank = gpiochip_get_data(gc); |
570 | type = bank->type; | 581 | type = bank->type; |
@@ -581,31 +592,42 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc, | |||
581 | reg += 4; | 592 | reg += 4; |
582 | } | 593 | } |
583 | 594 | ||
584 | spin_lock_irqsave(&bank->slock, flags); | ||
585 | |||
586 | data = readl(reg); | 595 | data = readl(reg); |
587 | data &= ~(mask << shift); | 596 | data &= ~(mask << shift); |
588 | if (!input) | 597 | if (!input) |
589 | data |= FUNC_OUTPUT << shift; | 598 | data |= FUNC_OUTPUT << shift; |
590 | writel(data, reg); | 599 | writel(data, reg); |
591 | 600 | ||
592 | spin_unlock_irqrestore(&bank->slock, flags); | ||
593 | |||
594 | return 0; | 601 | return 0; |
595 | } | 602 | } |
596 | 603 | ||
597 | /* gpiolib gpio_direction_input callback function. */ | 604 | /* gpiolib gpio_direction_input callback function. */ |
598 | static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset) | 605 | static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset) |
599 | { | 606 | { |
600 | return samsung_gpio_set_direction(gc, offset, true); | 607 | struct samsung_pin_bank *bank = gpiochip_get_data(gc); |
608 | unsigned long flags; | ||
609 | int ret; | ||
610 | |||
611 | spin_lock_irqsave(&bank->slock, flags); | ||
612 | ret = samsung_gpio_set_direction(gc, offset, true); | ||
613 | spin_unlock_irqrestore(&bank->slock, flags); | ||
614 | return ret; | ||
601 | } | 615 | } |
602 | 616 | ||
603 | /* gpiolib gpio_direction_output callback function. */ | 617 | /* gpiolib gpio_direction_output callback function. */ |
604 | static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset, | 618 | static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset, |
605 | int value) | 619 | int value) |
606 | { | 620 | { |
607 | samsung_gpio_set(gc, offset, value); | 621 | struct samsung_pin_bank *bank = gpiochip_get_data(gc); |
608 | return samsung_gpio_set_direction(gc, offset, false); | 622 | unsigned long flags; |
623 | int ret; | ||
624 | |||
625 | spin_lock_irqsave(&bank->slock, flags); | ||
626 | samsung_gpio_set_value(gc, offset, value); | ||
627 | ret = samsung_gpio_set_direction(gc, offset, false); | ||
628 | spin_unlock_irqrestore(&bank->slock, flags); | ||
629 | |||
630 | return ret; | ||
609 | } | 631 | } |
610 | 632 | ||
611 | /* | 633 | /* |
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c index 77d4cf047cee..11760bbe9d51 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | |||
@@ -492,6 +492,7 @@ static const struct sunxi_pinctrl_desc sun8i_h3_pinctrl_data = { | |||
492 | .pins = sun8i_h3_pins, | 492 | .pins = sun8i_h3_pins, |
493 | .npins = ARRAY_SIZE(sun8i_h3_pins), | 493 | .npins = ARRAY_SIZE(sun8i_h3_pins), |
494 | .irq_banks = 2, | 494 | .irq_banks = 2, |
495 | .irq_read_needs_mux = true | ||
495 | }; | 496 | }; |
496 | 497 | ||
497 | static int sun8i_h3_pinctrl_probe(struct platform_device *pdev) | 498 | static int sun8i_h3_pinctrl_probe(struct platform_device *pdev) |