aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-nomadik/gpio.c
diff options
context:
space:
mode:
authorJonas Aaberg <jonas.aberg@stericsson.com>2010-10-13 07:14:17 -0400
committerLinus Walleij <linus.walleij@linaro.org>2011-03-14 09:05:15 -0400
commit9c66ee6f55667c5f7e118135d3175b0100e160b9 (patch)
tree2324b4b8ac963526c266e4883be07d15e85ffd3e /arch/arm/plat-nomadik/gpio.c
parent33b744b35189baaa260f526cf117392095331843 (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/gpio.c')
-rw-r--r--arch/arm/plat-nomadik/gpio.c78
1 files changed, 54 insertions, 24 deletions
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
38static 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
38struct nmk_gpio_chip { 50struct 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
53static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, 67static 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
102static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, 119static 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 */
320int nmk_gpio_set_mode(int gpio, int gpio_mode) 346int 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
836static int nmk_gpio_pm(struct platform_device *dev, bool suspend) 862static 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