diff options
author | Jonas Aaberg <jonas.aberg@stericsson.com> | 2010-10-13 07:14:17 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2011-03-14 09:05:15 -0400 |
commit | 9c66ee6f55667c5f7e118135d3175b0100e160b9 (patch) | |
tree | 2324b4b8ac963526c266e4883be07d15e85ffd3e /arch/arm/plat-nomadik | |
parent | 33b744b35189baaa260f526cf117392095331843 (diff) |
plat-nomadik: pull-up/down settings for GPIO resume
Suspend/resume didn't take care of pull-up and pull-down
settings and writing back the DAT register at resume can
change pull up/down settings, depending on pin input value.
Output values are now also restored.
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch/arm/plat-nomadik')
-rw-r--r-- | arch/arm/plat-nomadik/Kconfig | 6 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/gpio.c | 78 |
2 files changed, 60 insertions, 24 deletions
diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig index 187f4e84bb22..ad25c963d437 100644 --- a/arch/arm/plat-nomadik/Kconfig +++ b/arch/arm/plat-nomadik/Kconfig | |||
@@ -25,4 +25,10 @@ config NOMADIK_GPIO | |||
25 | help | 25 | help |
26 | Support for the Nomadik GPIO controller. | 26 | Support for the Nomadik GPIO controller. |
27 | 27 | ||
28 | config NOMADIK_GPIO_PM | ||
29 | bool | ||
30 | depends on NOMADIK_GPIO && PM | ||
31 | help | ||
32 | Support PM for the Nomadik GPIO controller. | ||
33 | |||
28 | endif | 34 | endif |
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 971e5d3798e4..71682a87a878 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c | |||
@@ -30,11 +30,23 @@ | |||
30 | /* | 30 | /* |
31 | * The GPIO module in the Nomadik family of Systems-on-Chip is an | 31 | * The GPIO module in the Nomadik family of Systems-on-Chip is an |
32 | * AMBA device, managing 32 pins and alternate functions. The logic block | 32 | * AMBA device, managing 32 pins and alternate functions. The logic block |
33 | * is currently only used in the Nomadik. | 33 | * is currently used in the Nomadik and ux500. |
34 | * | 34 | * |
35 | * Symbols in this file are called "nmk_gpio" for "nomadik gpio" | 35 | * Symbols in this file are called "nmk_gpio" for "nomadik gpio" |
36 | */ | 36 | */ |
37 | 37 | ||
38 | static const u32 backup_regs[] = { | ||
39 | NMK_GPIO_PDIS, | ||
40 | NMK_GPIO_DIR, | ||
41 | NMK_GPIO_AFSLA, | ||
42 | NMK_GPIO_AFSLB, | ||
43 | NMK_GPIO_SLPC, | ||
44 | NMK_GPIO_RIMSC, | ||
45 | NMK_GPIO_FIMSC, | ||
46 | NMK_GPIO_RWIMSC, | ||
47 | NMK_GPIO_FWIMSC, | ||
48 | }; | ||
49 | |||
38 | struct nmk_gpio_chip { | 50 | struct nmk_gpio_chip { |
39 | struct gpio_chip chip; | 51 | struct gpio_chip chip; |
40 | void __iomem *addr; | 52 | void __iomem *addr; |
@@ -47,7 +59,9 @@ struct nmk_gpio_chip { | |||
47 | /* Keep track of configured edges */ | 59 | /* Keep track of configured edges */ |
48 | u32 edge_rising; | 60 | u32 edge_rising; |
49 | u32 edge_falling; | 61 | u32 edge_falling; |
50 | u32 backup[10]; | 62 | u32 backup[ARRAY_SIZE(backup_regs)]; |
63 | /* Bitmap, 1 = pull up, 0 = pull down */ | ||
64 | u32 pull; | ||
51 | }; | 65 | }; |
52 | 66 | ||
53 | static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, | 67 | static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, |
@@ -93,10 +107,13 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, | |||
93 | pdis &= ~bit; | 107 | pdis &= ~bit; |
94 | writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS); | 108 | writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS); |
95 | 109 | ||
96 | if (pull == NMK_GPIO_PULL_UP) | 110 | if (pull == NMK_GPIO_PULL_UP) { |
111 | nmk_chip->pull |= bit; | ||
97 | writel(bit, nmk_chip->addr + NMK_GPIO_DATS); | 112 | writel(bit, nmk_chip->addr + NMK_GPIO_DATS); |
98 | else if (pull == NMK_GPIO_PULL_DOWN) | 113 | } else if (pull == NMK_GPIO_PULL_DOWN) { |
114 | nmk_chip->pull &= ~bit; | ||
99 | writel(bit, nmk_chip->addr + NMK_GPIO_DATC); | 115 | writel(bit, nmk_chip->addr + NMK_GPIO_DATC); |
116 | } | ||
100 | } | 117 | } |
101 | 118 | ||
102 | static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, | 119 | static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, |
@@ -317,6 +334,15 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull) | |||
317 | } | 334 | } |
318 | 335 | ||
319 | /* Mode functions */ | 336 | /* Mode functions */ |
337 | /** | ||
338 | * nmk_gpio_set_mode() - set the mux mode of a gpio pin | ||
339 | * @gpio: pin number | ||
340 | * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A, | ||
341 | * NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C | ||
342 | * | ||
343 | * Sets the mode of the specified pin to one of the alternate functions or | ||
344 | * plain GPIO. | ||
345 | */ | ||
320 | int nmk_gpio_set_mode(int gpio, int gpio_mode) | 346 | int nmk_gpio_set_mode(int gpio, int gpio_mode) |
321 | { | 347 | { |
322 | struct nmk_gpio_chip *nmk_chip; | 348 | struct nmk_gpio_chip *nmk_chip; |
@@ -832,35 +858,39 @@ out: | |||
832 | return ret; | 858 | return ret; |
833 | } | 859 | } |
834 | 860 | ||
835 | #ifdef CONFIG_PM | 861 | #ifdef CONFIG_NOMADIK_GPIO_PM |
836 | static int nmk_gpio_pm(struct platform_device *dev, bool suspend) | 862 | static int nmk_gpio_pm(struct platform_device *dev, bool suspend) |
837 | { | 863 | { |
838 | struct nmk_gpio_chip *nmk_chip = platform_get_drvdata(dev); | 864 | struct nmk_gpio_chip *nmk_chip = platform_get_drvdata(dev); |
839 | int i; | 865 | int i; |
840 | static const unsigned int regs[] = { | 866 | u32 dir; |
841 | NMK_GPIO_DAT, | 867 | u32 dat; |
842 | NMK_GPIO_PDIS, | ||
843 | NMK_GPIO_DIR, | ||
844 | NMK_GPIO_AFSLA, | ||
845 | NMK_GPIO_AFSLB, | ||
846 | NMK_GPIO_SLPC, | ||
847 | NMK_GPIO_RIMSC, | ||
848 | NMK_GPIO_FIMSC, | ||
849 | NMK_GPIO_RWIMSC, | ||
850 | NMK_GPIO_FWIMSC, | ||
851 | }; | ||
852 | 868 | ||
853 | BUILD_BUG_ON(ARRAY_SIZE(nmk_chip->backup) != ARRAY_SIZE(regs)); | 869 | for (i = 0; i < ARRAY_SIZE(backup_regs); i++) { |
854 | |||
855 | /* XXX: is this sufficient? what about pull-up/down configuration? */ | ||
856 | |||
857 | for (i = 0; i < ARRAY_SIZE(regs); i++) { | ||
858 | if (suspend) | 870 | if (suspend) |
859 | nmk_chip->backup[i] = readl(nmk_chip->addr + regs[i]); | 871 | nmk_chip->backup[i] = readl(nmk_chip->addr + |
872 | backup_regs[i]); | ||
860 | else | 873 | else |
861 | writel(nmk_chip->backup[i], nmk_chip->addr + regs[i]); | 874 | writel(nmk_chip->backup[i], |
875 | nmk_chip->addr + backup_regs[i]); | ||
862 | } | 876 | } |
863 | 877 | ||
878 | if (!suspend) { | ||
879 | /* | ||
880 | * Restore pull-up and pull-down on inputs and | ||
881 | * outputs. | ||
882 | */ | ||
883 | dir = readl(nmk_chip->addr + NMK_GPIO_DIR); | ||
884 | dat = readl(nmk_chip->addr + NMK_GPIO_DAT); | ||
885 | |||
886 | writel((nmk_chip->pull & ~dir) | | ||
887 | (dat & dir), | ||
888 | nmk_chip->addr + NMK_GPIO_DATS); | ||
889 | |||
890 | writel((~nmk_chip->pull & ~dir) | | ||
891 | (~dat & dir), | ||
892 | nmk_chip->addr + NMK_GPIO_DATC); | ||
893 | } | ||
864 | return 0; | 894 | return 0; |
865 | } | 895 | } |
866 | 896 | ||