aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-29 19:54:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-29 19:54:29 -0400
commit7b55eab81ecbbd44e76ac14c67479b82807c261b (patch)
tree30b4ff18d3a8fbf6b1d396477fbd0ea4546f3e68
parentc476321533d3c6d018389a6309b3fc8731ac59be (diff)
parenta386267a2ceea33d76fa2b7f1c2e72a858fcb68e (diff)
Merge tag 'pinctrl-fixes-v3.10-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin-control fixes from Linus Walleij: - Six patches fixing up the suspend/resume and wakeup handling of the Samsung and Exynos drivers. - Errorpath fixes for four different drivers. All on the probe() errorpath. - Make the debugfs code for pin config take the right mutex. * tag 'pinctrl-fixes-v3.10-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: pinctrl: pinconf: take the right mutex pinctrl: sunxi: fix error return code in sunxi_pinctrl_probe() pinctrl: exynos: Handle suspend/resume of GPIO EINT registers pinctrl: samsung: Allow per-bank SoC-specific private data pinctrl: samsung: Add support for SoC-specific suspend/resume callbacks pinctrl: Don't override the error code in probe error handling ARM: EXYNOS: Fix EINT wake-up mask configuration when pinctrl is used pinctrl: exynos: Add support for set_irq_wake of wake-up EINTs pinctrl: samsung: fix suspend/resume functionality
-rw-r--r--arch/arm/mach-exynos/include/mach/pm-core.h14
-rw-r--r--drivers/pinctrl/pinconf.c4
-rw-r--r--drivers/pinctrl/pinctrl-coh901.c3
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c139
-rw-r--r--drivers/pinctrl/pinctrl-exynos.h1
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c154
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h9
-rw-r--r--drivers/pinctrl/pinctrl-sunxi.c7
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wmt.c3
9 files changed, 323 insertions, 11 deletions
diff --git a/arch/arm/mach-exynos/include/mach/pm-core.h b/arch/arm/mach-exynos/include/mach/pm-core.h
index 7dbbfec13ea5..296090e7f423 100644
--- a/arch/arm/mach-exynos/include/mach/pm-core.h
+++ b/arch/arm/mach-exynos/include/mach/pm-core.h
@@ -18,8 +18,15 @@
18#ifndef __ASM_ARCH_PM_CORE_H 18#ifndef __ASM_ARCH_PM_CORE_H
19#define __ASM_ARCH_PM_CORE_H __FILE__ 19#define __ASM_ARCH_PM_CORE_H __FILE__
20 20
21#include <linux/of.h>
21#include <mach/regs-pmu.h> 22#include <mach/regs-pmu.h>
22 23
24#ifdef CONFIG_PINCTRL_EXYNOS
25extern u32 exynos_get_eint_wake_mask(void);
26#else
27static inline u32 exynos_get_eint_wake_mask(void) { return 0xffffffff; }
28#endif
29
23static inline void s3c_pm_debug_init_uart(void) 30static inline void s3c_pm_debug_init_uart(void)
24{ 31{
25 /* nothing here yet */ 32 /* nothing here yet */
@@ -27,7 +34,12 @@ static inline void s3c_pm_debug_init_uart(void)
27 34
28static inline void s3c_pm_arch_prepare_irqs(void) 35static inline void s3c_pm_arch_prepare_irqs(void)
29{ 36{
30 __raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK); 37 u32 eintmask = s3c_irqwake_eintmask;
38
39 if (of_have_populated_dt())
40 eintmask = exynos_get_eint_wake_mask();
41
42 __raw_writel(eintmask, S5P_EINT_WAKEUP_MASK);
31 __raw_writel(s3c_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK); 43 __raw_writel(s3c_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
32} 44}
33 45
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index c67c37e23dd7..694c3ace4520 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -610,7 +610,7 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
610 bool found = false; 610 bool found = false;
611 unsigned long config; 611 unsigned long config;
612 612
613 mutex_lock(&pctldev->mutex); 613 mutex_lock(&pinctrl_maps_mutex);
614 614
615 /* Parse the pinctrl map and look for the elected pin/state */ 615 /* Parse the pinctrl map and look for the elected pin/state */
616 for_each_maps(maps_node, i, map) { 616 for_each_maps(maps_node, i, map) {
@@ -659,7 +659,7 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
659 confops->pin_config_config_dbg_show(pctldev, s, config); 659 confops->pin_config_config_dbg_show(pctldev, s, config);
660 660
661exit: 661exit:
662 mutex_unlock(&pctldev->mutex); 662 mutex_unlock(&pinctrl_maps_mutex);
663 663
664 return 0; 664 return 0;
665} 665}
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index a67af419f531..d6b41747d687 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -830,7 +830,8 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
830 return 0; 830 return 0;
831 831
832err_no_range: 832err_no_range:
833 err = gpiochip_remove(&gpio->chip); 833 if (gpiochip_remove(&gpio->chip))
834 dev_err(&pdev->dev, "failed to remove gpio chip\n");
834err_no_chip: 835err_no_chip:
835err_no_domain: 836err_no_domain:
836err_no_port: 837err_no_port:
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index ac742817ebce..2d76f66a2e0b 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -196,6 +196,12 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
196 return IRQ_HANDLED; 196 return IRQ_HANDLED;
197} 197}
198 198
199struct exynos_eint_gpio_save {
200 u32 eint_con;
201 u32 eint_fltcon0;
202 u32 eint_fltcon1;
203};
204
199/* 205/*
200 * exynos_eint_gpio_init() - setup handling of external gpio interrupts. 206 * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
201 * @d: driver data of samsung pinctrl driver. 207 * @d: driver data of samsung pinctrl driver.
@@ -204,8 +210,8 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
204{ 210{
205 struct samsung_pin_bank *bank; 211 struct samsung_pin_bank *bank;
206 struct device *dev = d->dev; 212 struct device *dev = d->dev;
207 unsigned int ret; 213 int ret;
208 unsigned int i; 214 int i;
209 215
210 if (!d->irq) { 216 if (!d->irq) {
211 dev_err(dev, "irq number not available\n"); 217 dev_err(dev, "irq number not available\n");
@@ -227,11 +233,29 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
227 bank->nr_pins, &exynos_gpio_irqd_ops, bank); 233 bank->nr_pins, &exynos_gpio_irqd_ops, bank);
228 if (!bank->irq_domain) { 234 if (!bank->irq_domain) {
229 dev_err(dev, "gpio irq domain add failed\n"); 235 dev_err(dev, "gpio irq domain add failed\n");
230 return -ENXIO; 236 ret = -ENXIO;
237 goto err_domains;
238 }
239
240 bank->soc_priv = devm_kzalloc(d->dev,
241 sizeof(struct exynos_eint_gpio_save), GFP_KERNEL);
242 if (!bank->soc_priv) {
243 irq_domain_remove(bank->irq_domain);
244 ret = -ENOMEM;
245 goto err_domains;
231 } 246 }
232 } 247 }
233 248
234 return 0; 249 return 0;
250
251err_domains:
252 for (--i, --bank; i >= 0; --i, --bank) {
253 if (bank->eint_type != EINT_TYPE_GPIO)
254 continue;
255 irq_domain_remove(bank->irq_domain);
256 }
257
258 return ret;
235} 259}
236 260
237static void exynos_wkup_irq_unmask(struct irq_data *irqd) 261static void exynos_wkup_irq_unmask(struct irq_data *irqd)
@@ -326,6 +350,28 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
326 return 0; 350 return 0;
327} 351}
328 352
353static u32 exynos_eint_wake_mask = 0xffffffff;
354
355u32 exynos_get_eint_wake_mask(void)
356{
357 return exynos_eint_wake_mask;
358}
359
360static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
361{
362 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
363 unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq);
364
365 pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq);
366
367 if (!on)
368 exynos_eint_wake_mask |= bit;
369 else
370 exynos_eint_wake_mask &= ~bit;
371
372 return 0;
373}
374
329/* 375/*
330 * irq_chip for wakeup interrupts 376 * irq_chip for wakeup interrupts
331 */ 377 */
@@ -335,6 +381,7 @@ static struct irq_chip exynos_wkup_irq_chip = {
335 .irq_mask = exynos_wkup_irq_mask, 381 .irq_mask = exynos_wkup_irq_mask,
336 .irq_ack = exynos_wkup_irq_ack, 382 .irq_ack = exynos_wkup_irq_ack,
337 .irq_set_type = exynos_wkup_irq_set_type, 383 .irq_set_type = exynos_wkup_irq_set_type,
384 .irq_set_wake = exynos_wkup_irq_set_wake,
338}; 385};
339 386
340/* interrupt handler for wakeup interrupts 0..15 */ 387/* interrupt handler for wakeup interrupts 0..15 */
@@ -505,6 +552,72 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
505 return 0; 552 return 0;
506} 553}
507 554
555static void exynos_pinctrl_suspend_bank(
556 struct samsung_pinctrl_drv_data *drvdata,
557 struct samsung_pin_bank *bank)
558{
559 struct exynos_eint_gpio_save *save = bank->soc_priv;
560 void __iomem *regs = drvdata->virt_base;
561
562 save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
563 + bank->eint_offset);
564 save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
565 + 2 * bank->eint_offset);
566 save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
567 + 2 * bank->eint_offset + 4);
568
569 pr_debug("%s: save con %#010x\n", bank->name, save->eint_con);
570 pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
571 pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
572}
573
574static void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
575{
576 struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
577 struct samsung_pin_bank *bank = ctrl->pin_banks;
578 int i;
579
580 for (i = 0; i < ctrl->nr_banks; ++i, ++bank)
581 if (bank->eint_type == EINT_TYPE_GPIO)
582 exynos_pinctrl_suspend_bank(drvdata, bank);
583}
584
585static void exynos_pinctrl_resume_bank(
586 struct samsung_pinctrl_drv_data *drvdata,
587 struct samsung_pin_bank *bank)
588{
589 struct exynos_eint_gpio_save *save = bank->soc_priv;
590 void __iomem *regs = drvdata->virt_base;
591
592 pr_debug("%s: con %#010x => %#010x\n", bank->name,
593 readl(regs + EXYNOS_GPIO_ECON_OFFSET
594 + bank->eint_offset), save->eint_con);
595 pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
596 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
597 + 2 * bank->eint_offset), save->eint_fltcon0);
598 pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
599 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
600 + 2 * bank->eint_offset + 4), save->eint_fltcon1);
601
602 writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
603 + bank->eint_offset);
604 writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
605 + 2 * bank->eint_offset);
606 writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
607 + 2 * bank->eint_offset + 4);
608}
609
610static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
611{
612 struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
613 struct samsung_pin_bank *bank = ctrl->pin_banks;
614 int i;
615
616 for (i = 0; i < ctrl->nr_banks; ++i, ++bank)
617 if (bank->eint_type == EINT_TYPE_GPIO)
618 exynos_pinctrl_resume_bank(drvdata, bank);
619}
620
508/* pin banks of exynos4210 pin-controller 0 */ 621/* pin banks of exynos4210 pin-controller 0 */
509static struct samsung_pin_bank exynos4210_pin_banks0[] = { 622static struct samsung_pin_bank exynos4210_pin_banks0[] = {
510 EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), 623 EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
@@ -568,6 +681,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
568 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, 681 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
569 .svc = EXYNOS_SVC_OFFSET, 682 .svc = EXYNOS_SVC_OFFSET,
570 .eint_gpio_init = exynos_eint_gpio_init, 683 .eint_gpio_init = exynos_eint_gpio_init,
684 .suspend = exynos_pinctrl_suspend,
685 .resume = exynos_pinctrl_resume,
571 .label = "exynos4210-gpio-ctrl0", 686 .label = "exynos4210-gpio-ctrl0",
572 }, { 687 }, {
573 /* pin-controller instance 1 data */ 688 /* pin-controller instance 1 data */
@@ -582,6 +697,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
582 .svc = EXYNOS_SVC_OFFSET, 697 .svc = EXYNOS_SVC_OFFSET,
583 .eint_gpio_init = exynos_eint_gpio_init, 698 .eint_gpio_init = exynos_eint_gpio_init,
584 .eint_wkup_init = exynos_eint_wkup_init, 699 .eint_wkup_init = exynos_eint_wkup_init,
700 .suspend = exynos_pinctrl_suspend,
701 .resume = exynos_pinctrl_resume,
585 .label = "exynos4210-gpio-ctrl1", 702 .label = "exynos4210-gpio-ctrl1",
586 }, { 703 }, {
587 /* pin-controller instance 2 data */ 704 /* pin-controller instance 2 data */
@@ -663,6 +780,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
663 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, 780 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
664 .svc = EXYNOS_SVC_OFFSET, 781 .svc = EXYNOS_SVC_OFFSET,
665 .eint_gpio_init = exynos_eint_gpio_init, 782 .eint_gpio_init = exynos_eint_gpio_init,
783 .suspend = exynos_pinctrl_suspend,
784 .resume = exynos_pinctrl_resume,
666 .label = "exynos4x12-gpio-ctrl0", 785 .label = "exynos4x12-gpio-ctrl0",
667 }, { 786 }, {
668 /* pin-controller instance 1 data */ 787 /* pin-controller instance 1 data */
@@ -677,6 +796,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
677 .svc = EXYNOS_SVC_OFFSET, 796 .svc = EXYNOS_SVC_OFFSET,
678 .eint_gpio_init = exynos_eint_gpio_init, 797 .eint_gpio_init = exynos_eint_gpio_init,
679 .eint_wkup_init = exynos_eint_wkup_init, 798 .eint_wkup_init = exynos_eint_wkup_init,
799 .suspend = exynos_pinctrl_suspend,
800 .resume = exynos_pinctrl_resume,
680 .label = "exynos4x12-gpio-ctrl1", 801 .label = "exynos4x12-gpio-ctrl1",
681 }, { 802 }, {
682 /* pin-controller instance 2 data */ 803 /* pin-controller instance 2 data */
@@ -687,6 +808,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
687 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, 808 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
688 .svc = EXYNOS_SVC_OFFSET, 809 .svc = EXYNOS_SVC_OFFSET,
689 .eint_gpio_init = exynos_eint_gpio_init, 810 .eint_gpio_init = exynos_eint_gpio_init,
811 .suspend = exynos_pinctrl_suspend,
812 .resume = exynos_pinctrl_resume,
690 .label = "exynos4x12-gpio-ctrl2", 813 .label = "exynos4x12-gpio-ctrl2",
691 }, { 814 }, {
692 /* pin-controller instance 3 data */ 815 /* pin-controller instance 3 data */
@@ -697,6 +820,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
697 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, 820 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
698 .svc = EXYNOS_SVC_OFFSET, 821 .svc = EXYNOS_SVC_OFFSET,
699 .eint_gpio_init = exynos_eint_gpio_init, 822 .eint_gpio_init = exynos_eint_gpio_init,
823 .suspend = exynos_pinctrl_suspend,
824 .resume = exynos_pinctrl_resume,
700 .label = "exynos4x12-gpio-ctrl3", 825 .label = "exynos4x12-gpio-ctrl3",
701 }, 826 },
702}; 827};
@@ -775,6 +900,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
775 .svc = EXYNOS_SVC_OFFSET, 900 .svc = EXYNOS_SVC_OFFSET,
776 .eint_gpio_init = exynos_eint_gpio_init, 901 .eint_gpio_init = exynos_eint_gpio_init,
777 .eint_wkup_init = exynos_eint_wkup_init, 902 .eint_wkup_init = exynos_eint_wkup_init,
903 .suspend = exynos_pinctrl_suspend,
904 .resume = exynos_pinctrl_resume,
778 .label = "exynos5250-gpio-ctrl0", 905 .label = "exynos5250-gpio-ctrl0",
779 }, { 906 }, {
780 /* pin-controller instance 1 data */ 907 /* pin-controller instance 1 data */
@@ -785,6 +912,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
785 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, 912 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
786 .svc = EXYNOS_SVC_OFFSET, 913 .svc = EXYNOS_SVC_OFFSET,
787 .eint_gpio_init = exynos_eint_gpio_init, 914 .eint_gpio_init = exynos_eint_gpio_init,
915 .suspend = exynos_pinctrl_suspend,
916 .resume = exynos_pinctrl_resume,
788 .label = "exynos5250-gpio-ctrl1", 917 .label = "exynos5250-gpio-ctrl1",
789 }, { 918 }, {
790 /* pin-controller instance 2 data */ 919 /* pin-controller instance 2 data */
@@ -795,6 +924,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
795 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, 924 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
796 .svc = EXYNOS_SVC_OFFSET, 925 .svc = EXYNOS_SVC_OFFSET,
797 .eint_gpio_init = exynos_eint_gpio_init, 926 .eint_gpio_init = exynos_eint_gpio_init,
927 .suspend = exynos_pinctrl_suspend,
928 .resume = exynos_pinctrl_resume,
798 .label = "exynos5250-gpio-ctrl2", 929 .label = "exynos5250-gpio-ctrl2",
799 }, { 930 }, {
800 /* pin-controller instance 3 data */ 931 /* pin-controller instance 3 data */
@@ -805,6 +936,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
805 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, 936 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
806 .svc = EXYNOS_SVC_OFFSET, 937 .svc = EXYNOS_SVC_OFFSET,
807 .eint_gpio_init = exynos_eint_gpio_init, 938 .eint_gpio_init = exynos_eint_gpio_init,
939 .suspend = exynos_pinctrl_suspend,
940 .resume = exynos_pinctrl_resume,
808 .label = "exynos5250-gpio-ctrl3", 941 .label = "exynos5250-gpio-ctrl3",
809 }, 942 },
810}; 943};
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
index 9b1f77a5bf0f..3c91c357792f 100644
--- a/drivers/pinctrl/pinctrl-exynos.h
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -19,6 +19,7 @@
19 19
20/* External GPIO and wakeup interrupt related definitions */ 20/* External GPIO and wakeup interrupt related definitions */
21#define EXYNOS_GPIO_ECON_OFFSET 0x700 21#define EXYNOS_GPIO_ECON_OFFSET 0x700
22#define EXYNOS_GPIO_EFLTCON_OFFSET 0x800
22#define EXYNOS_GPIO_EMASK_OFFSET 0x900 23#define EXYNOS_GPIO_EMASK_OFFSET 0x900
23#define EXYNOS_GPIO_EPEND_OFFSET 0xA00 24#define EXYNOS_GPIO_EPEND_OFFSET 0xA00
24#define EXYNOS_WKUP_ECON_OFFSET 0xE00 25#define EXYNOS_WKUP_ECON_OFFSET 0xE00
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 055d0162098b..63ac22e89678 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -28,6 +28,7 @@
28#include <linux/gpio.h> 28#include <linux/gpio.h>
29#include <linux/irqdomain.h> 29#include <linux/irqdomain.h>
30#include <linux/spinlock.h> 30#include <linux/spinlock.h>
31#include <linux/syscore_ops.h>
31 32
32#include "core.h" 33#include "core.h"
33#include "pinctrl-samsung.h" 34#include "pinctrl-samsung.h"
@@ -48,6 +49,9 @@ static struct pin_config {
48 { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN }, 49 { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
49}; 50};
50 51
52/* Global list of devices (struct samsung_pinctrl_drv_data) */
53LIST_HEAD(drvdata_list);
54
51static unsigned int pin_base; 55static unsigned int pin_base;
52 56
53static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc) 57static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
@@ -956,9 +960,151 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
956 ctrl->eint_wkup_init(drvdata); 960 ctrl->eint_wkup_init(drvdata);
957 961
958 platform_set_drvdata(pdev, drvdata); 962 platform_set_drvdata(pdev, drvdata);
963
964 /* Add to the global list */
965 list_add_tail(&drvdata->node, &drvdata_list);
966
959 return 0; 967 return 0;
960} 968}
961 969
970#ifdef CONFIG_PM
971
972/**
973 * samsung_pinctrl_suspend_dev - save pinctrl state for suspend for a device
974 *
975 * Save data for all banks handled by this device.
976 */
977static void samsung_pinctrl_suspend_dev(
978 struct samsung_pinctrl_drv_data *drvdata)
979{
980 struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
981 void __iomem *virt_base = drvdata->virt_base;
982 int i;
983
984 for (i = 0; i < ctrl->nr_banks; i++) {
985 struct samsung_pin_bank *bank = &ctrl->pin_banks[i];
986 void __iomem *reg = virt_base + bank->pctl_offset;
987
988 u8 *offs = bank->type->reg_offset;
989 u8 *widths = bank->type->fld_width;
990 enum pincfg_type type;
991
992 /* Registers without a powerdown config aren't lost */
993 if (!widths[PINCFG_TYPE_CON_PDN])
994 continue;
995
996 for (type = 0; type < PINCFG_TYPE_NUM; type++)
997 if (widths[type])
998 bank->pm_save[type] = readl(reg + offs[type]);
999
1000 if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) {
1001 /* Some banks have two config registers */
1002 bank->pm_save[PINCFG_TYPE_NUM] =
1003 readl(reg + offs[PINCFG_TYPE_FUNC] + 4);
1004 pr_debug("Save %s @ %p (con %#010x %08x)\n",
1005 bank->name, reg,
1006 bank->pm_save[PINCFG_TYPE_FUNC],
1007 bank->pm_save[PINCFG_TYPE_NUM]);
1008 } else {
1009 pr_debug("Save %s @ %p (con %#010x)\n", bank->name,
1010 reg, bank->pm_save[PINCFG_TYPE_FUNC]);
1011 }
1012 }
1013
1014 if (ctrl->suspend)
1015 ctrl->suspend(drvdata);
1016}
1017
1018/**
1019 * samsung_pinctrl_resume_dev - restore pinctrl state from suspend for a device
1020 *
1021 * Restore one of the banks that was saved during suspend.
1022 *
1023 * We don't bother doing anything complicated to avoid glitching lines since
1024 * we're called before pad retention is turned off.
1025 */
1026static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
1027{
1028 struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
1029 void __iomem *virt_base = drvdata->virt_base;
1030 int i;
1031
1032 if (ctrl->resume)
1033 ctrl->resume(drvdata);
1034
1035 for (i = 0; i < ctrl->nr_banks; i++) {
1036 struct samsung_pin_bank *bank = &ctrl->pin_banks[i];
1037 void __iomem *reg = virt_base + bank->pctl_offset;
1038
1039 u8 *offs = bank->type->reg_offset;
1040 u8 *widths = bank->type->fld_width;
1041 enum pincfg_type type;
1042
1043 /* Registers without a powerdown config aren't lost */
1044 if (!widths[PINCFG_TYPE_CON_PDN])
1045 continue;
1046
1047 if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) {
1048 /* Some banks have two config registers */
1049 pr_debug("%s @ %p (con %#010x %08x => %#010x %08x)\n",
1050 bank->name, reg,
1051 readl(reg + offs[PINCFG_TYPE_FUNC]),
1052 readl(reg + offs[PINCFG_TYPE_FUNC] + 4),
1053 bank->pm_save[PINCFG_TYPE_FUNC],
1054 bank->pm_save[PINCFG_TYPE_NUM]);
1055 writel(bank->pm_save[PINCFG_TYPE_NUM],
1056 reg + offs[PINCFG_TYPE_FUNC] + 4);
1057 } else {
1058 pr_debug("%s @ %p (con %#010x => %#010x)\n", bank->name,
1059 reg, readl(reg + offs[PINCFG_TYPE_FUNC]),
1060 bank->pm_save[PINCFG_TYPE_FUNC]);
1061 }
1062 for (type = 0; type < PINCFG_TYPE_NUM; type++)
1063 if (widths[type])
1064 writel(bank->pm_save[type], reg + offs[type]);
1065 }
1066}
1067
1068/**
1069 * samsung_pinctrl_suspend - save pinctrl state for suspend
1070 *
1071 * Save data for all banks across all devices.
1072 */
1073static int samsung_pinctrl_suspend(void)
1074{
1075 struct samsung_pinctrl_drv_data *drvdata;
1076
1077 list_for_each_entry(drvdata, &drvdata_list, node) {
1078 samsung_pinctrl_suspend_dev(drvdata);
1079 }
1080
1081 return 0;
1082}
1083
1084/**
1085 * samsung_pinctrl_resume - restore pinctrl state for suspend
1086 *
1087 * Restore data for all banks across all devices.
1088 */
1089static void samsung_pinctrl_resume(void)
1090{
1091 struct samsung_pinctrl_drv_data *drvdata;
1092
1093 list_for_each_entry_reverse(drvdata, &drvdata_list, node) {
1094 samsung_pinctrl_resume_dev(drvdata);
1095 }
1096}
1097
1098#else
1099#define samsung_pinctrl_suspend NULL
1100#define samsung_pinctrl_resume NULL
1101#endif
1102
1103static struct syscore_ops samsung_pinctrl_syscore_ops = {
1104 .suspend = samsung_pinctrl_suspend,
1105 .resume = samsung_pinctrl_resume,
1106};
1107
962static const struct of_device_id samsung_pinctrl_dt_match[] = { 1108static const struct of_device_id samsung_pinctrl_dt_match[] = {
963#ifdef CONFIG_PINCTRL_EXYNOS 1109#ifdef CONFIG_PINCTRL_EXYNOS
964 { .compatible = "samsung,exynos4210-pinctrl", 1110 { .compatible = "samsung,exynos4210-pinctrl",
@@ -987,6 +1133,14 @@ static struct platform_driver samsung_pinctrl_driver = {
987 1133
988static int __init samsung_pinctrl_drv_register(void) 1134static int __init samsung_pinctrl_drv_register(void)
989{ 1135{
1136 /*
1137 * Register syscore ops for save/restore of registers across suspend.
1138 * It's important to ensure that this driver is running at an earlier
1139 * initcall level than any arch-specific init calls that install syscore
1140 * ops that turn off pad retention (like exynos_pm_resume).
1141 */
1142 register_syscore_ops(&samsung_pinctrl_syscore_ops);
1143
990 return platform_driver_register(&samsung_pinctrl_driver); 1144 return platform_driver_register(&samsung_pinctrl_driver);
991} 1145}
992postcore_initcall(samsung_pinctrl_drv_register); 1146postcore_initcall(samsung_pinctrl_drv_register);
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index 7c7f9ebcd05b..26d3519240c9 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -127,6 +127,7 @@ struct samsung_pin_bank_type {
127 * @gpio_chip: GPIO chip of the bank. 127 * @gpio_chip: GPIO chip of the bank.
128 * @grange: linux gpio pin range supported by this bank. 128 * @grange: linux gpio pin range supported by this bank.
129 * @slock: spinlock protecting bank registers 129 * @slock: spinlock protecting bank registers
130 * @pm_save: saved register values during suspend
130 */ 131 */
131struct samsung_pin_bank { 132struct samsung_pin_bank {
132 struct samsung_pin_bank_type *type; 133 struct samsung_pin_bank_type *type;
@@ -138,12 +139,15 @@ struct samsung_pin_bank {
138 u32 eint_mask; 139 u32 eint_mask;
139 u32 eint_offset; 140 u32 eint_offset;
140 char *name; 141 char *name;
142 void *soc_priv;
141 struct device_node *of_node; 143 struct device_node *of_node;
142 struct samsung_pinctrl_drv_data *drvdata; 144 struct samsung_pinctrl_drv_data *drvdata;
143 struct irq_domain *irq_domain; 145 struct irq_domain *irq_domain;
144 struct gpio_chip gpio_chip; 146 struct gpio_chip gpio_chip;
145 struct pinctrl_gpio_range grange; 147 struct pinctrl_gpio_range grange;
146 spinlock_t slock; 148 spinlock_t slock;
149
150 u32 pm_save[PINCFG_TYPE_NUM + 1]; /* +1 to handle double CON registers*/
147}; 151};
148 152
149/** 153/**
@@ -184,11 +188,15 @@ struct samsung_pin_ctrl {
184 188
185 int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *); 189 int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
186 int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *); 190 int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
191 void (*suspend)(struct samsung_pinctrl_drv_data *);
192 void (*resume)(struct samsung_pinctrl_drv_data *);
193
187 char *label; 194 char *label;
188}; 195};
189 196
190/** 197/**
191 * struct samsung_pinctrl_drv_data: wrapper for holding driver data together. 198 * struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
199 * @node: global list node
192 * @virt_base: register base address of the controller. 200 * @virt_base: register base address of the controller.
193 * @dev: device instance representing the controller. 201 * @dev: device instance representing the controller.
194 * @irq: interrpt number used by the controller to notify gpio interrupts. 202 * @irq: interrpt number used by the controller to notify gpio interrupts.
@@ -201,6 +209,7 @@ struct samsung_pin_ctrl {
201 * @nr_function: number of such pin functions. 209 * @nr_function: number of such pin functions.
202 */ 210 */
203struct samsung_pinctrl_drv_data { 211struct samsung_pinctrl_drv_data {
212 struct list_head node;
204 void __iomem *virt_base; 213 void __iomem *virt_base;
205 struct device *dev; 214 struct device *dev;
206 int irq; 215 int irq;
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index c52fc2c08732..b7d8c890514c 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -1990,8 +1990,10 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
1990 } 1990 }
1991 1991
1992 clk = devm_clk_get(&pdev->dev, NULL); 1992 clk = devm_clk_get(&pdev->dev, NULL);
1993 if (IS_ERR(clk)) 1993 if (IS_ERR(clk)) {
1994 ret = PTR_ERR(clk);
1994 goto gpiochip_error; 1995 goto gpiochip_error;
1996 }
1995 1997
1996 clk_prepare_enable(clk); 1998 clk_prepare_enable(clk);
1997 1999
@@ -2000,7 +2002,8 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
2000 return 0; 2002 return 0;
2001 2003
2002gpiochip_error: 2004gpiochip_error:
2003 ret = gpiochip_remove(pctl->chip); 2005 if (gpiochip_remove(pctl->chip))
2006 dev_err(&pdev->dev, "failed to remove gpio chip\n");
2004pinctrl_error: 2007pinctrl_error:
2005 pinctrl_unregister(pctl->pctl_dev); 2008 pinctrl_unregister(pctl->pctl_dev);
2006 return ret; 2009 return ret;
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c
index ab63104e8dc9..70d986e04afb 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wmt.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c
@@ -609,8 +609,7 @@ int wmt_pinctrl_probe(struct platform_device *pdev,
609 return 0; 609 return 0;
610 610
611fail_range: 611fail_range:
612 err = gpiochip_remove(&data->gpio_chip); 612 if (gpiochip_remove(&data->gpio_chip))
613 if (err)
614 dev_err(&pdev->dev, "failed to remove gpio chip\n"); 613 dev_err(&pdev->dev, "failed to remove gpio chip\n");
615fail_gpio: 614fail_gpio:
616 pinctrl_unregister(data->pctl_dev); 615 pinctrl_unregister(data->pctl_dev);