diff options
Diffstat (limited to 'arch/arm/plat-samsung')
-rw-r--r-- | arch/arm/plat-samsung/gpio-config.c | 111 | ||||
-rw-r--r-- | arch/arm/plat-samsung/gpio.c | 15 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h | 58 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/gpio-cfg.h | 11 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/gpio-core.h | 17 | ||||
-rw-r--r-- | arch/arm/plat-samsung/pm-gpio.c | 4 |
6 files changed, 201 insertions, 15 deletions
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index 44a84e896546..a76eef533392 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* linux/arch/arm/plat-s3c/gpio-config.c | 1 | /* linux/arch/arm/plat-s3c/gpio-config.c |
2 | * | 2 | * |
3 | * Copyright 2008 Openmoko, Inc. | 3 | * Copyright 2008 Openmoko, Inc. |
4 | * Copyright 2008 Simtec Electronics | 4 | * Copyright 2008-2010 Simtec Electronics |
5 | * Ben Dooks <ben@simtec.co.uk> | 5 | * Ben Dooks <ben@simtec.co.uk> |
6 | * http://armlinux.simtec.co.uk/ | 6 | * http://armlinux.simtec.co.uk/ |
7 | * | 7 | * |
@@ -33,14 +33,34 @@ int s3c_gpio_cfgpin(unsigned int pin, unsigned int config) | |||
33 | 33 | ||
34 | offset = pin - chip->chip.base; | 34 | offset = pin - chip->chip.base; |
35 | 35 | ||
36 | local_irq_save(flags); | 36 | s3c_gpio_lock(chip, flags); |
37 | ret = s3c_gpio_do_setcfg(chip, offset, config); | 37 | ret = s3c_gpio_do_setcfg(chip, offset, config); |
38 | local_irq_restore(flags); | 38 | s3c_gpio_unlock(chip, flags); |
39 | 39 | ||
40 | return ret; | 40 | return ret; |
41 | } | 41 | } |
42 | EXPORT_SYMBOL(s3c_gpio_cfgpin); | 42 | EXPORT_SYMBOL(s3c_gpio_cfgpin); |
43 | 43 | ||
44 | unsigned s3c_gpio_getcfg(unsigned int pin) | ||
45 | { | ||
46 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
47 | unsigned long flags; | ||
48 | unsigned ret = 0; | ||
49 | int offset; | ||
50 | |||
51 | if (chip) { | ||
52 | offset = pin - chip->chip.base; | ||
53 | |||
54 | s3c_gpio_lock(chip, flags); | ||
55 | ret = s3c_gpio_do_getcfg(chip, offset); | ||
56 | s3c_gpio_unlock(chip, flags); | ||
57 | } | ||
58 | |||
59 | return ret; | ||
60 | } | ||
61 | EXPORT_SYMBOL(s3c_gpio_getcfg); | ||
62 | |||
63 | |||
44 | int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) | 64 | int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) |
45 | { | 65 | { |
46 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | 66 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); |
@@ -52,17 +72,17 @@ int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) | |||
52 | 72 | ||
53 | offset = pin - chip->chip.base; | 73 | offset = pin - chip->chip.base; |
54 | 74 | ||
55 | local_irq_save(flags); | 75 | s3c_gpio_lock(chip, flags); |
56 | ret = s3c_gpio_do_setpull(chip, offset, pull); | 76 | ret = s3c_gpio_do_setpull(chip, offset, pull); |
57 | local_irq_restore(flags); | 77 | s3c_gpio_unlock(chip, flags); |
58 | 78 | ||
59 | return ret; | 79 | return ret; |
60 | } | 80 | } |
61 | EXPORT_SYMBOL(s3c_gpio_setpull); | 81 | EXPORT_SYMBOL(s3c_gpio_setpull); |
62 | 82 | ||
63 | #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX | 83 | #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX |
64 | int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip, | 84 | int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, |
65 | unsigned int off, unsigned int cfg) | 85 | unsigned int off, unsigned int cfg) |
66 | { | 86 | { |
67 | void __iomem *reg = chip->base; | 87 | void __iomem *reg = chip->base; |
68 | unsigned int shift = off; | 88 | unsigned int shift = off; |
@@ -87,6 +107,19 @@ int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip, | |||
87 | return 0; | 107 | return 0; |
88 | } | 108 | } |
89 | 109 | ||
110 | unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip, | ||
111 | unsigned int off) | ||
112 | { | ||
113 | u32 con; | ||
114 | |||
115 | con = __raw_readl(chip->base); | ||
116 | con >>= off; | ||
117 | con &= 1; | ||
118 | con++; | ||
119 | |||
120 | return S3C_GPIO_SFN(con); | ||
121 | } | ||
122 | |||
90 | int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, | 123 | int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, |
91 | unsigned int off, unsigned int cfg) | 124 | unsigned int off, unsigned int cfg) |
92 | { | 125 | { |
@@ -109,6 +142,19 @@ int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, | |||
109 | 142 | ||
110 | return 0; | 143 | return 0; |
111 | } | 144 | } |
145 | |||
146 | unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip, | ||
147 | unsigned int off) | ||
148 | { | ||
149 | u32 con; | ||
150 | |||
151 | con = __raw_readl(chip->base); | ||
152 | con >>= off * 2; | ||
153 | con &= 3; | ||
154 | |||
155 | /* this conversion works for IN and OUT as well as special mode */ | ||
156 | return S3C_GPIO_SPECIAL(con); | ||
157 | } | ||
112 | #endif | 158 | #endif |
113 | 159 | ||
114 | #ifdef CONFIG_S3C_GPIO_CFG_S3C64XX | 160 | #ifdef CONFIG_S3C_GPIO_CFG_S3C64XX |
@@ -134,6 +180,25 @@ int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | |||
134 | 180 | ||
135 | return 0; | 181 | return 0; |
136 | } | 182 | } |
183 | |||
184 | unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | ||
185 | unsigned int off) | ||
186 | { | ||
187 | void __iomem *reg = chip->base; | ||
188 | unsigned int shift = (off & 7) * 4; | ||
189 | u32 con; | ||
190 | |||
191 | if (off < 8 && chip->chip.ngpio > 8) | ||
192 | reg -= 4; | ||
193 | |||
194 | con = __raw_readl(reg); | ||
195 | con >>= shift; | ||
196 | con &= 0xf; | ||
197 | |||
198 | /* this conversion works for IN and OUT as well as special mode */ | ||
199 | return S3C_GPIO_SPECIAL(con); | ||
200 | } | ||
201 | |||
137 | #endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */ | 202 | #endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */ |
138 | 203 | ||
139 | #ifdef CONFIG_S3C_GPIO_PULL_UPDOWN | 204 | #ifdef CONFIG_S3C_GPIO_PULL_UPDOWN |
@@ -164,3 +229,35 @@ s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, | |||
164 | return (__force s3c_gpio_pull_t)pup; | 229 | return (__force s3c_gpio_pull_t)pup; |
165 | } | 230 | } |
166 | #endif | 231 | #endif |
232 | |||
233 | #ifdef CONFIG_S3C_GPIO_PULL_UP | ||
234 | int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip, | ||
235 | unsigned int off, s3c_gpio_pull_t pull) | ||
236 | { | ||
237 | void __iomem *reg = chip->base + 0x08; | ||
238 | u32 pup = __raw_readl(reg); | ||
239 | |||
240 | pup = __raw_readl(reg); | ||
241 | |||
242 | if (pup == S3C_GPIO_PULL_UP) | ||
243 | pup &= ~(1 << off); | ||
244 | else if (pup == S3C_GPIO_PULL_NONE) | ||
245 | pup |= (1 << off); | ||
246 | else | ||
247 | return -EINVAL; | ||
248 | |||
249 | __raw_writel(pup, reg); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, | ||
254 | unsigned int off) | ||
255 | { | ||
256 | void __iomem *reg = chip->base + 0x08; | ||
257 | u32 pup = __raw_readl(reg); | ||
258 | |||
259 | pup &= (1 << off); | ||
260 | return pup ? S3C_GPIO_PULL_NONE : S3C_GPIO_PULL_UP; | ||
261 | } | ||
262 | #endif /* CONFIG_S3C_GPIO_PULL_UP */ | ||
263 | |||
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c index 28d2ab8a08db..b83a83351cea 100644 --- a/arch/arm/plat-samsung/gpio.c +++ b/arch/arm/plat-samsung/gpio.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
18 | #include <linux/spinlock.h> | ||
18 | 19 | ||
19 | #include <plat/gpio-core.h> | 20 | #include <plat/gpio-core.h> |
20 | 21 | ||
@@ -52,14 +53,14 @@ static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset) | |||
52 | unsigned long flags; | 53 | unsigned long flags; |
53 | unsigned long con; | 54 | unsigned long con; |
54 | 55 | ||
55 | local_irq_save(flags); | 56 | s3c_gpio_lock(ourchip, flags); |
56 | 57 | ||
57 | con = __raw_readl(base + 0x00); | 58 | con = __raw_readl(base + 0x00); |
58 | con &= ~(3 << (offset * 2)); | 59 | con &= ~(3 << (offset * 2)); |
59 | 60 | ||
60 | __raw_writel(con, base + 0x00); | 61 | __raw_writel(con, base + 0x00); |
61 | 62 | ||
62 | local_irq_restore(flags); | 63 | s3c_gpio_unlock(ourchip, flags); |
63 | return 0; | 64 | return 0; |
64 | } | 65 | } |
65 | 66 | ||
@@ -72,7 +73,7 @@ static int s3c_gpiolib_output(struct gpio_chip *chip, | |||
72 | unsigned long dat; | 73 | unsigned long dat; |
73 | unsigned long con; | 74 | unsigned long con; |
74 | 75 | ||
75 | local_irq_save(flags); | 76 | s3c_gpio_lock(ourchip, flags); |
76 | 77 | ||
77 | dat = __raw_readl(base + 0x04); | 78 | dat = __raw_readl(base + 0x04); |
78 | dat &= ~(1 << offset); | 79 | dat &= ~(1 << offset); |
@@ -87,7 +88,7 @@ static int s3c_gpiolib_output(struct gpio_chip *chip, | |||
87 | __raw_writel(con, base + 0x00); | 88 | __raw_writel(con, base + 0x00); |
88 | __raw_writel(dat, base + 0x04); | 89 | __raw_writel(dat, base + 0x04); |
89 | 90 | ||
90 | local_irq_restore(flags); | 91 | s3c_gpio_unlock(ourchip, flags); |
91 | return 0; | 92 | return 0; |
92 | } | 93 | } |
93 | 94 | ||
@@ -99,7 +100,7 @@ static void s3c_gpiolib_set(struct gpio_chip *chip, | |||
99 | unsigned long flags; | 100 | unsigned long flags; |
100 | unsigned long dat; | 101 | unsigned long dat; |
101 | 102 | ||
102 | local_irq_save(flags); | 103 | s3c_gpio_lock(ourchip, flags); |
103 | 104 | ||
104 | dat = __raw_readl(base + 0x04); | 105 | dat = __raw_readl(base + 0x04); |
105 | dat &= ~(1 << offset); | 106 | dat &= ~(1 << offset); |
@@ -107,7 +108,7 @@ static void s3c_gpiolib_set(struct gpio_chip *chip, | |||
107 | dat |= 1 << offset; | 108 | dat |= 1 << offset; |
108 | __raw_writel(dat, base + 0x04); | 109 | __raw_writel(dat, base + 0x04); |
109 | 110 | ||
110 | local_irq_restore(flags); | 111 | s3c_gpio_unlock(ourchip, flags); |
111 | } | 112 | } |
112 | 113 | ||
113 | static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset) | 114 | static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset) |
@@ -131,6 +132,8 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) | |||
131 | BUG_ON(!gc->label); | 132 | BUG_ON(!gc->label); |
132 | BUG_ON(!gc->ngpio); | 133 | BUG_ON(!gc->ngpio); |
133 | 134 | ||
135 | spin_lock_init(&chip->lock); | ||
136 | |||
134 | if (!gc->direction_input) | 137 | if (!gc->direction_input) |
135 | gc->direction_input = s3c_gpiolib_input; | 138 | gc->direction_input = s3c_gpiolib_input; |
136 | if (!gc->direction_output) | 139 | if (!gc->direction_output) |
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h index dda19da037ad..3e21c75feefa 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h | |||
@@ -30,6 +30,12 @@ static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip, | |||
30 | return (chip->config->set_config)(chip, off, config); | 30 | return (chip->config->set_config)(chip, off, config); |
31 | } | 31 | } |
32 | 32 | ||
33 | static inline unsigned s3c_gpio_do_getcfg(struct s3c_gpio_chip *chip, | ||
34 | unsigned int off) | ||
35 | { | ||
36 | return (chip->config->get_config)(chip, off); | ||
37 | } | ||
38 | |||
33 | static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip, | 39 | static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip, |
34 | unsigned int off, s3c_gpio_pull_t pull) | 40 | unsigned int off, s3c_gpio_pull_t pull) |
35 | { | 41 | { |
@@ -53,6 +59,18 @@ extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, | |||
53 | unsigned int off, unsigned int cfg); | 59 | unsigned int off, unsigned int cfg); |
54 | 60 | ||
55 | /** | 61 | /** |
62 | * s3c_gpio_getcfg_s3c24xx - S3C24XX style GPIO configuration read. | ||
63 | * @chip: The gpio chip that is being configured. | ||
64 | * @off: The offset for the GPIO being configured. | ||
65 | * | ||
66 | * The reverse of s3c_gpio_setcfg_s3c24xx(). Will return a value whicg | ||
67 | * could be directly passed back to s3c_gpio_setcfg_s3c24xx(), from the | ||
68 | * S3C_GPIO_SPECIAL() macro. | ||
69 | */ | ||
70 | unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip, | ||
71 | unsigned int off); | ||
72 | |||
73 | /** | ||
56 | * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A) | 74 | * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A) |
57 | * @chip: The gpio chip that is being configured. | 75 | * @chip: The gpio chip that is being configured. |
58 | * @off: The offset for the GPIO being configured. | 76 | * @off: The offset for the GPIO being configured. |
@@ -65,6 +83,21 @@ extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, | |||
65 | extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, | 83 | extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, |
66 | unsigned int off, unsigned int cfg); | 84 | unsigned int off, unsigned int cfg); |
67 | 85 | ||
86 | |||
87 | /** | ||
88 | * s3c_gpio_getcfg_s3c24xx_a - S3C24XX style GPIO configuration read (Bank A) | ||
89 | * @chip: The gpio chip that is being configured. | ||
90 | * @off: The offset for the GPIO being configured. | ||
91 | * | ||
92 | * The reverse of s3c_gpio_setcfg_s3c24xx_a() turning an GPIO into a usable | ||
93 | * GPIO configuration value. | ||
94 | * | ||
95 | * @sa s3c_gpio_getcfg_s3c24xx | ||
96 | * @sa s3c_gpio_getcfg_s3c64xx_4bit | ||
97 | */ | ||
98 | extern unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip, | ||
99 | unsigned int off); | ||
100 | |||
68 | /** | 101 | /** |
69 | * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config. | 102 | * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config. |
70 | * @chip: The gpio chip that is being configured. | 103 | * @chip: The gpio chip that is being configured. |
@@ -85,6 +118,20 @@ extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | |||
85 | unsigned int off, unsigned int cfg); | 118 | unsigned int off, unsigned int cfg); |
86 | 119 | ||
87 | 120 | ||
121 | /** | ||
122 | * s3c_gpio_getcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config read. | ||
123 | * @chip: The gpio chip that is being configured. | ||
124 | * @off: The offset for the GPIO being configured. | ||
125 | * | ||
126 | * The reverse of s3c_gpio_setcfg_s3c64xx_4bit(), turning a gpio configuration | ||
127 | * register setting into a value the software can use, such as could be passed | ||
128 | * to s3c_gpio_setcfg_s3c64xx_4bit(). | ||
129 | * | ||
130 | * @sa s3c_gpio_getcfg_s3c24xx | ||
131 | */ | ||
132 | extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | ||
133 | unsigned int off); | ||
134 | |||
88 | /* Pull-{up,down} resistor controls. | 135 | /* Pull-{up,down} resistor controls. |
89 | * | 136 | * |
90 | * S3C2410,S3C2440,S3C24A0 = Pull-UP, | 137 | * S3C2410,S3C2440,S3C24A0 = Pull-UP, |
@@ -146,6 +193,17 @@ extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, | |||
146 | unsigned int off); | 193 | unsigned int off); |
147 | 194 | ||
148 | /** | 195 | /** |
196 | * s3c_gpio_getpull_1up() - Get configuration for choice of up or none | ||
197 | * @chip: The gpio chip that the GPIO pin belongs to | ||
198 | * @off: The offset to the pin to get the configuration of. | ||
199 | * | ||
200 | * This helper function reads the state of the pull-up resistor for the | ||
201 | * given GPIO in the same case as s3c_gpio_setpull_1up. | ||
202 | */ | ||
203 | extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, | ||
204 | unsigned int off); | ||
205 | |||
206 | /** | ||
149 | * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443. | 207 | * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443. |
150 | * @chip: The gpio chip that is being configured. | 208 | * @chip: The gpio chip that is being configured. |
151 | * @off: The offset for the GPIO being configured. | 209 | * @off: The offset for the GPIO being configured. |
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index 29cd6a86cade..8d01e853df39 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h | |||
@@ -77,6 +77,17 @@ struct s3c_gpio_cfg { | |||
77 | */ | 77 | */ |
78 | extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to); | 78 | extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to); |
79 | 79 | ||
80 | /** | ||
81 | * s3c_gpio_getcfg - Read the current function for a GPIO pin | ||
82 | * @pin: The pin to read the configuration value for. | ||
83 | * | ||
84 | * Read the configuration state of the given @pin, returning a value that | ||
85 | * could be passed back to s3c_gpio_cfgpin(). | ||
86 | * | ||
87 | * @sa s3c_gpio_cfgpin | ||
88 | */ | ||
89 | extern unsigned s3c_gpio_getcfg(unsigned int pin); | ||
90 | |||
80 | /* Define values for the pull-{up,down} available for each gpio pin. | 91 | /* Define values for the pull-{up,down} available for each gpio pin. |
81 | * | 92 | * |
82 | * These values control the state of the weak pull-{up,down} resistors | 93 | * These values control the state of the weak pull-{up,down} resistors |
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index 49ff406a7066..f3a68d1a07b9 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h | |||
@@ -44,16 +44,26 @@ struct s3c_gpio_cfg; | |||
44 | * @chip: The chip structure to be exported via gpiolib. | 44 | * @chip: The chip structure to be exported via gpiolib. |
45 | * @base: The base pointer to the gpio configuration registers. | 45 | * @base: The base pointer to the gpio configuration registers. |
46 | * @config: special function and pull-resistor control information. | 46 | * @config: special function and pull-resistor control information. |
47 | * @lock: Lock for exclusive access to this gpio bank. | ||
47 | * @pm_save: Save information for suspend/resume support. | 48 | * @pm_save: Save information for suspend/resume support. |
48 | * | 49 | * |
49 | * This wrapper provides the necessary information for the Samsung | 50 | * This wrapper provides the necessary information for the Samsung |
50 | * specific gpios being registered with gpiolib. | 51 | * specific gpios being registered with gpiolib. |
52 | * | ||
53 | * The lock protects each gpio bank from multiple access of the shared | ||
54 | * configuration registers, or from reading of data whilst another thread | ||
55 | * is writing to the register set. | ||
56 | * | ||
57 | * Each chip has its own lock to avoid any contention between different | ||
58 | * CPU cores trying to get one lock for different GPIO banks, where each | ||
59 | * bank of GPIO has its own register space and configuration registers. | ||
51 | */ | 60 | */ |
52 | struct s3c_gpio_chip { | 61 | struct s3c_gpio_chip { |
53 | struct gpio_chip chip; | 62 | struct gpio_chip chip; |
54 | struct s3c_gpio_cfg *config; | 63 | struct s3c_gpio_cfg *config; |
55 | struct s3c_gpio_pm *pm; | 64 | struct s3c_gpio_pm *pm; |
56 | void __iomem *base; | 65 | void __iomem *base; |
66 | spinlock_t lock; | ||
57 | #ifdef CONFIG_PM | 67 | #ifdef CONFIG_PM |
58 | u32 pm_save[4]; | 68 | u32 pm_save[4]; |
59 | #endif | 69 | #endif |
@@ -108,6 +118,9 @@ extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip, | |||
108 | extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip); | 118 | extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip); |
109 | extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip); | 119 | extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip); |
110 | 120 | ||
121 | /* exported for core SoC support to change */ | ||
122 | extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default; | ||
123 | |||
111 | #ifdef CONFIG_S3C_GPIO_TRACK | 124 | #ifdef CONFIG_S3C_GPIO_TRACK |
112 | extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; | 125 | extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; |
113 | 126 | ||
@@ -135,3 +148,7 @@ extern struct s3c_gpio_pm s3c_gpio_pm_4bit; | |||
135 | #define __gpio_pm(x) NULL | 148 | #define __gpio_pm(x) NULL |
136 | 149 | ||
137 | #endif /* CONFIG_PM */ | 150 | #endif /* CONFIG_PM */ |
151 | |||
152 | /* locking wrappers to deal with multiple access to the same gpio bank */ | ||
153 | #define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) | ||
154 | #define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl) | ||
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c index 69a4c7f02e25..d50ab9d2af53 100644 --- a/arch/arm/plat-samsung/pm-gpio.c +++ b/arch/arm/plat-samsung/pm-gpio.c | |||
@@ -329,7 +329,7 @@ void s3c_pm_save_gpios(void) | |||
329 | struct s3c_gpio_chip *ourchip; | 329 | struct s3c_gpio_chip *ourchip; |
330 | unsigned int gpio_nr; | 330 | unsigned int gpio_nr; |
331 | 331 | ||
332 | for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) { | 332 | for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) { |
333 | ourchip = s3c_gpiolib_getchip(gpio_nr); | 333 | ourchip = s3c_gpiolib_getchip(gpio_nr); |
334 | if (!ourchip) | 334 | if (!ourchip) |
335 | continue; | 335 | continue; |
@@ -367,7 +367,7 @@ void s3c_pm_restore_gpios(void) | |||
367 | struct s3c_gpio_chip *ourchip; | 367 | struct s3c_gpio_chip *ourchip; |
368 | unsigned int gpio_nr; | 368 | unsigned int gpio_nr; |
369 | 369 | ||
370 | for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) { | 370 | for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) { |
371 | ourchip = s3c_gpiolib_getchip(gpio_nr); | 371 | ourchip = s3c_gpiolib_getchip(gpio_nr); |
372 | if (!ourchip) | 372 | if (!ourchip) |
373 | continue; | 373 | continue; |