diff options
Diffstat (limited to 'arch/arm/plat-nomadik')
-rw-r--r-- | arch/arm/plat-nomadik/gpio.c | 316 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/gpio.h | 15 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/mtu.h | 6 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/pincfg.h | 72 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/timer.c | 14 |
5 files changed, 365 insertions, 58 deletions
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 5a6ef252c38b..977c8f9a07a2 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | 25 | ||
26 | #include <plat/pincfg.h> | ||
26 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
27 | #include <mach/gpio.h> | 28 | #include <mach/gpio.h> |
28 | 29 | ||
@@ -46,28 +47,217 @@ struct nmk_gpio_chip { | |||
46 | u32 edge_falling; | 47 | u32 edge_falling; |
47 | }; | 48 | }; |
48 | 49 | ||
50 | static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, | ||
51 | unsigned offset, int gpio_mode) | ||
52 | { | ||
53 | u32 bit = 1 << offset; | ||
54 | u32 afunc, bfunc; | ||
55 | |||
56 | afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; | ||
57 | bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; | ||
58 | if (gpio_mode & NMK_GPIO_ALT_A) | ||
59 | afunc |= bit; | ||
60 | if (gpio_mode & NMK_GPIO_ALT_B) | ||
61 | bfunc |= bit; | ||
62 | writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); | ||
63 | writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); | ||
64 | } | ||
65 | |||
66 | static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip, | ||
67 | unsigned offset, enum nmk_gpio_slpm mode) | ||
68 | { | ||
69 | u32 bit = 1 << offset; | ||
70 | u32 slpm; | ||
71 | |||
72 | slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC); | ||
73 | if (mode == NMK_GPIO_SLPM_NOCHANGE) | ||
74 | slpm |= bit; | ||
75 | else | ||
76 | slpm &= ~bit; | ||
77 | writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC); | ||
78 | } | ||
79 | |||
80 | static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, | ||
81 | unsigned offset, enum nmk_gpio_pull pull) | ||
82 | { | ||
83 | u32 bit = 1 << offset; | ||
84 | u32 pdis; | ||
85 | |||
86 | pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS); | ||
87 | if (pull == NMK_GPIO_PULL_NONE) | ||
88 | pdis |= bit; | ||
89 | else | ||
90 | pdis &= ~bit; | ||
91 | writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS); | ||
92 | |||
93 | if (pull == NMK_GPIO_PULL_UP) | ||
94 | writel(bit, nmk_chip->addr + NMK_GPIO_DATS); | ||
95 | else if (pull == NMK_GPIO_PULL_DOWN) | ||
96 | writel(bit, nmk_chip->addr + NMK_GPIO_DATC); | ||
97 | } | ||
98 | |||
99 | static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, | ||
100 | unsigned offset) | ||
101 | { | ||
102 | writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); | ||
103 | } | ||
104 | |||
105 | static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, | ||
106 | pin_cfg_t cfg) | ||
107 | { | ||
108 | static const char *afnames[] = { | ||
109 | [NMK_GPIO_ALT_GPIO] = "GPIO", | ||
110 | [NMK_GPIO_ALT_A] = "A", | ||
111 | [NMK_GPIO_ALT_B] = "B", | ||
112 | [NMK_GPIO_ALT_C] = "C" | ||
113 | }; | ||
114 | static const char *pullnames[] = { | ||
115 | [NMK_GPIO_PULL_NONE] = "none", | ||
116 | [NMK_GPIO_PULL_UP] = "up", | ||
117 | [NMK_GPIO_PULL_DOWN] = "down", | ||
118 | [3] /* illegal */ = "??" | ||
119 | }; | ||
120 | static const char *slpmnames[] = { | ||
121 | [NMK_GPIO_SLPM_INPUT] = "input", | ||
122 | [NMK_GPIO_SLPM_NOCHANGE] = "no-change", | ||
123 | }; | ||
124 | |||
125 | int pin = PIN_NUM(cfg); | ||
126 | int pull = PIN_PULL(cfg); | ||
127 | int af = PIN_ALT(cfg); | ||
128 | int slpm = PIN_SLPM(cfg); | ||
129 | |||
130 | dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s\n", | ||
131 | pin, afnames[af], pullnames[pull], slpmnames[slpm]); | ||
132 | |||
133 | __nmk_gpio_make_input(nmk_chip, offset); | ||
134 | __nmk_gpio_set_pull(nmk_chip, offset, pull); | ||
135 | __nmk_gpio_set_slpm(nmk_chip, offset, slpm); | ||
136 | __nmk_gpio_set_mode(nmk_chip, offset, af); | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * nmk_config_pin - configure a pin's mux attributes | ||
141 | * @cfg: pin confguration | ||
142 | * | ||
143 | * Configures a pin's mode (alternate function or GPIO), its pull up status, | ||
144 | * and its sleep mode based on the specified configuration. The @cfg is | ||
145 | * usually one of the SoC specific macros defined in mach/<soc>-pins.h. These | ||
146 | * are constructed using, and can be further enhanced with, the macros in | ||
147 | * plat/pincfg.h. | ||
148 | * | ||
149 | * If a pin's mode is set to GPIO, it is configured as an input to avoid | ||
150 | * side-effects. The gpio can be manipulated later using standard GPIO API | ||
151 | * calls. | ||
152 | */ | ||
153 | int nmk_config_pin(pin_cfg_t cfg) | ||
154 | { | ||
155 | struct nmk_gpio_chip *nmk_chip; | ||
156 | int gpio = PIN_NUM(cfg); | ||
157 | unsigned long flags; | ||
158 | |||
159 | nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); | ||
160 | if (!nmk_chip) | ||
161 | return -EINVAL; | ||
162 | |||
163 | spin_lock_irqsave(&nmk_chip->lock, flags); | ||
164 | __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg); | ||
165 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | EXPORT_SYMBOL(nmk_config_pin); | ||
170 | |||
171 | /** | ||
172 | * nmk_config_pins - configure several pins at once | ||
173 | * @cfgs: array of pin configurations | ||
174 | * @num: number of elments in the array | ||
175 | * | ||
176 | * Configures several pins using nmk_config_pin(). Refer to that function for | ||
177 | * further information. | ||
178 | */ | ||
179 | int nmk_config_pins(pin_cfg_t *cfgs, int num) | ||
180 | { | ||
181 | int ret = 0; | ||
182 | int i; | ||
183 | |||
184 | for (i = 0; i < num; i++) { | ||
185 | int ret = nmk_config_pin(cfgs[i]); | ||
186 | if (ret) | ||
187 | break; | ||
188 | } | ||
189 | |||
190 | return ret; | ||
191 | } | ||
192 | EXPORT_SYMBOL(nmk_config_pins); | ||
193 | |||
194 | /** | ||
195 | * nmk_gpio_set_slpm() - configure the sleep mode of a pin | ||
196 | * @gpio: pin number | ||
197 | * @mode: NMK_GPIO_SLPM_INPUT or NMK_GPIO_SLPM_NOCHANGE, | ||
198 | * | ||
199 | * Sets the sleep mode of a pin. If @mode is NMK_GPIO_SLPM_INPUT, the pin is | ||
200 | * changed to an input (with pullup/down enabled) in sleep and deep sleep. If | ||
201 | * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was | ||
202 | * configured even when in sleep and deep sleep. | ||
203 | */ | ||
204 | int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) | ||
205 | { | ||
206 | struct nmk_gpio_chip *nmk_chip; | ||
207 | unsigned long flags; | ||
208 | |||
209 | nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); | ||
210 | if (!nmk_chip) | ||
211 | return -EINVAL; | ||
212 | |||
213 | spin_lock_irqsave(&nmk_chip->lock, flags); | ||
214 | __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode); | ||
215 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * nmk_gpio_set_pull() - enable/disable pull up/down on a gpio | ||
222 | * @gpio: pin number | ||
223 | * @pull: one of NMK_GPIO_PULL_DOWN, NMK_GPIO_PULL_UP, and NMK_GPIO_PULL_NONE | ||
224 | * | ||
225 | * Enables/disables pull up/down on a specified pin. This only takes effect if | ||
226 | * the pin is configured as an input (either explicitly or by the alternate | ||
227 | * function). | ||
228 | * | ||
229 | * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is | ||
230 | * configured as an input. Otherwise, due to the way the controller registers | ||
231 | * work, this function will change the value output on the pin. | ||
232 | */ | ||
233 | int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull) | ||
234 | { | ||
235 | struct nmk_gpio_chip *nmk_chip; | ||
236 | unsigned long flags; | ||
237 | |||
238 | nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); | ||
239 | if (!nmk_chip) | ||
240 | return -EINVAL; | ||
241 | |||
242 | spin_lock_irqsave(&nmk_chip->lock, flags); | ||
243 | __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull); | ||
244 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
49 | /* Mode functions */ | 249 | /* Mode functions */ |
50 | int nmk_gpio_set_mode(int gpio, int gpio_mode) | 250 | int nmk_gpio_set_mode(int gpio, int gpio_mode) |
51 | { | 251 | { |
52 | struct nmk_gpio_chip *nmk_chip; | 252 | struct nmk_gpio_chip *nmk_chip; |
53 | unsigned long flags; | 253 | unsigned long flags; |
54 | u32 afunc, bfunc, bit; | ||
55 | 254 | ||
56 | nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); | 255 | nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); |
57 | if (!nmk_chip) | 256 | if (!nmk_chip) |
58 | return -EINVAL; | 257 | return -EINVAL; |
59 | 258 | ||
60 | bit = 1 << (gpio - nmk_chip->chip.base); | ||
61 | |||
62 | spin_lock_irqsave(&nmk_chip->lock, flags); | 259 | spin_lock_irqsave(&nmk_chip->lock, flags); |
63 | afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; | 260 | __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode); |
64 | bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; | ||
65 | if (gpio_mode & NMK_GPIO_ALT_A) | ||
66 | afunc |= bit; | ||
67 | if (gpio_mode & NMK_GPIO_ALT_B) | ||
68 | bfunc |= bit; | ||
69 | writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); | ||
70 | writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); | ||
71 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 261 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
72 | 262 | ||
73 | return 0; | 263 | return 0; |
@@ -111,32 +301,41 @@ static void nmk_gpio_irq_ack(unsigned int irq) | |||
111 | writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); | 301 | writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); |
112 | } | 302 | } |
113 | 303 | ||
304 | enum nmk_gpio_irq_type { | ||
305 | NORMAL, | ||
306 | WAKE, | ||
307 | }; | ||
308 | |||
114 | static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, | 309 | static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, |
115 | int gpio, bool enable) | 310 | int gpio, enum nmk_gpio_irq_type which, |
311 | bool enable) | ||
116 | { | 312 | { |
313 | u32 rimsc = which == WAKE ? NMK_GPIO_RWIMSC : NMK_GPIO_RIMSC; | ||
314 | u32 fimsc = which == WAKE ? NMK_GPIO_FWIMSC : NMK_GPIO_FIMSC; | ||
117 | u32 bitmask = nmk_gpio_get_bitmask(gpio); | 315 | u32 bitmask = nmk_gpio_get_bitmask(gpio); |
118 | u32 reg; | 316 | u32 reg; |
119 | 317 | ||
120 | /* we must individually set/clear the two edges */ | 318 | /* we must individually set/clear the two edges */ |
121 | if (nmk_chip->edge_rising & bitmask) { | 319 | if (nmk_chip->edge_rising & bitmask) { |
122 | reg = readl(nmk_chip->addr + NMK_GPIO_RIMSC); | 320 | reg = readl(nmk_chip->addr + rimsc); |
123 | if (enable) | 321 | if (enable) |
124 | reg |= bitmask; | 322 | reg |= bitmask; |
125 | else | 323 | else |
126 | reg &= ~bitmask; | 324 | reg &= ~bitmask; |
127 | writel(reg, nmk_chip->addr + NMK_GPIO_RIMSC); | 325 | writel(reg, nmk_chip->addr + rimsc); |
128 | } | 326 | } |
129 | if (nmk_chip->edge_falling & bitmask) { | 327 | if (nmk_chip->edge_falling & bitmask) { |
130 | reg = readl(nmk_chip->addr + NMK_GPIO_FIMSC); | 328 | reg = readl(nmk_chip->addr + fimsc); |
131 | if (enable) | 329 | if (enable) |
132 | reg |= bitmask; | 330 | reg |= bitmask; |
133 | else | 331 | else |
134 | reg &= ~bitmask; | 332 | reg &= ~bitmask; |
135 | writel(reg, nmk_chip->addr + NMK_GPIO_FIMSC); | 333 | writel(reg, nmk_chip->addr + fimsc); |
136 | } | 334 | } |
137 | } | 335 | } |
138 | 336 | ||
139 | static void nmk_gpio_irq_modify(unsigned int irq, bool enable) | 337 | static int nmk_gpio_irq_modify(unsigned int irq, enum nmk_gpio_irq_type which, |
338 | bool enable) | ||
140 | { | 339 | { |
141 | int gpio; | 340 | int gpio; |
142 | struct nmk_gpio_chip *nmk_chip; | 341 | struct nmk_gpio_chip *nmk_chip; |
@@ -147,26 +346,35 @@ static void nmk_gpio_irq_modify(unsigned int irq, bool enable) | |||
147 | nmk_chip = get_irq_chip_data(irq); | 346 | nmk_chip = get_irq_chip_data(irq); |
148 | bitmask = nmk_gpio_get_bitmask(gpio); | 347 | bitmask = nmk_gpio_get_bitmask(gpio); |
149 | if (!nmk_chip) | 348 | if (!nmk_chip) |
150 | return; | 349 | return -EINVAL; |
151 | 350 | ||
152 | spin_lock_irqsave(&nmk_chip->lock, flags); | 351 | spin_lock_irqsave(&nmk_chip->lock, flags); |
153 | __nmk_gpio_irq_modify(nmk_chip, gpio, enable); | 352 | __nmk_gpio_irq_modify(nmk_chip, gpio, which, enable); |
154 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 353 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
354 | |||
355 | return 0; | ||
155 | } | 356 | } |
156 | 357 | ||
157 | static void nmk_gpio_irq_mask(unsigned int irq) | 358 | static void nmk_gpio_irq_mask(unsigned int irq) |
158 | { | 359 | { |
159 | nmk_gpio_irq_modify(irq, false); | 360 | nmk_gpio_irq_modify(irq, NORMAL, false); |
160 | }; | 361 | } |
161 | 362 | ||
162 | static void nmk_gpio_irq_unmask(unsigned int irq) | 363 | static void nmk_gpio_irq_unmask(unsigned int irq) |
163 | { | 364 | { |
164 | nmk_gpio_irq_modify(irq, true); | 365 | nmk_gpio_irq_modify(irq, NORMAL, true); |
366 | } | ||
367 | |||
368 | static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on) | ||
369 | { | ||
370 | return nmk_gpio_irq_modify(irq, WAKE, on); | ||
165 | } | 371 | } |
166 | 372 | ||
167 | static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) | 373 | static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) |
168 | { | 374 | { |
169 | bool enabled = !(irq_to_desc(irq)->status & IRQ_DISABLED); | 375 | struct irq_desc *desc = irq_to_desc(irq); |
376 | bool enabled = !(desc->status & IRQ_DISABLED); | ||
377 | bool wake = desc->wake_depth; | ||
170 | int gpio; | 378 | int gpio; |
171 | struct nmk_gpio_chip *nmk_chip; | 379 | struct nmk_gpio_chip *nmk_chip; |
172 | unsigned long flags; | 380 | unsigned long flags; |
@@ -186,7 +394,10 @@ static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) | |||
186 | spin_lock_irqsave(&nmk_chip->lock, flags); | 394 | spin_lock_irqsave(&nmk_chip->lock, flags); |
187 | 395 | ||
188 | if (enabled) | 396 | if (enabled) |
189 | __nmk_gpio_irq_modify(nmk_chip, gpio, false); | 397 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); |
398 | |||
399 | if (wake) | ||
400 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); | ||
190 | 401 | ||
191 | nmk_chip->edge_rising &= ~bitmask; | 402 | nmk_chip->edge_rising &= ~bitmask; |
192 | if (type & IRQ_TYPE_EDGE_RISING) | 403 | if (type & IRQ_TYPE_EDGE_RISING) |
@@ -197,7 +408,10 @@ static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) | |||
197 | nmk_chip->edge_falling |= bitmask; | 408 | nmk_chip->edge_falling |= bitmask; |
198 | 409 | ||
199 | if (enabled) | 410 | if (enabled) |
200 | __nmk_gpio_irq_modify(nmk_chip, gpio, true); | 411 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); |
412 | |||
413 | if (wake) | ||
414 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); | ||
201 | 415 | ||
202 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 416 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
203 | 417 | ||
@@ -210,6 +424,7 @@ static struct irq_chip nmk_gpio_irq_chip = { | |||
210 | .mask = nmk_gpio_irq_mask, | 424 | .mask = nmk_gpio_irq_mask, |
211 | .unmask = nmk_gpio_irq_unmask, | 425 | .unmask = nmk_gpio_irq_unmask, |
212 | .set_type = nmk_gpio_irq_set_type, | 426 | .set_type = nmk_gpio_irq_set_type, |
427 | .set_wake = nmk_gpio_irq_set_wake, | ||
213 | }; | 428 | }; |
214 | 429 | ||
215 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 430 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) |
@@ -266,16 +481,6 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) | |||
266 | return 0; | 481 | return 0; |
267 | } | 482 | } |
268 | 483 | ||
269 | static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, | ||
270 | int val) | ||
271 | { | ||
272 | struct nmk_gpio_chip *nmk_chip = | ||
273 | container_of(chip, struct nmk_gpio_chip, chip); | ||
274 | |||
275 | writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) | 484 | static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) |
280 | { | 485 | { |
281 | struct nmk_gpio_chip *nmk_chip = | 486 | struct nmk_gpio_chip *nmk_chip = |
@@ -298,12 +503,33 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, | |||
298 | writel(bit, nmk_chip->addr + NMK_GPIO_DATC); | 503 | writel(bit, nmk_chip->addr + NMK_GPIO_DATC); |
299 | } | 504 | } |
300 | 505 | ||
506 | static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, | ||
507 | int val) | ||
508 | { | ||
509 | struct nmk_gpio_chip *nmk_chip = | ||
510 | container_of(chip, struct nmk_gpio_chip, chip); | ||
511 | |||
512 | writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); | ||
513 | nmk_gpio_set_output(chip, offset, val); | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
519 | { | ||
520 | struct nmk_gpio_chip *nmk_chip = | ||
521 | container_of(chip, struct nmk_gpio_chip, chip); | ||
522 | |||
523 | return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset; | ||
524 | } | ||
525 | |||
301 | /* This structure is replicated for each GPIO block allocated at probe time */ | 526 | /* This structure is replicated for each GPIO block allocated at probe time */ |
302 | static struct gpio_chip nmk_gpio_template = { | 527 | static struct gpio_chip nmk_gpio_template = { |
303 | .direction_input = nmk_gpio_make_input, | 528 | .direction_input = nmk_gpio_make_input, |
304 | .get = nmk_gpio_get_input, | 529 | .get = nmk_gpio_get_input, |
305 | .direction_output = nmk_gpio_make_output, | 530 | .direction_output = nmk_gpio_make_output, |
306 | .set = nmk_gpio_set_output, | 531 | .set = nmk_gpio_set_output, |
532 | .to_irq = nmk_gpio_to_irq, | ||
307 | .ngpio = NMK_GPIO_PER_CHIP, | 533 | .ngpio = NMK_GPIO_PER_CHIP, |
308 | .can_sleep = 0, | 534 | .can_sleep = 0, |
309 | }; | 535 | }; |
@@ -393,30 +619,12 @@ out: | |||
393 | return ret; | 619 | return ret; |
394 | } | 620 | } |
395 | 621 | ||
396 | static int __exit nmk_gpio_remove(struct platform_device *dev) | ||
397 | { | ||
398 | struct nmk_gpio_chip *nmk_chip; | ||
399 | struct resource *res; | ||
400 | |||
401 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
402 | |||
403 | nmk_chip = platform_get_drvdata(dev); | ||
404 | gpiochip_remove(&nmk_chip->chip); | ||
405 | clk_disable(nmk_chip->clk); | ||
406 | clk_put(nmk_chip->clk); | ||
407 | kfree(nmk_chip); | ||
408 | release_mem_region(res->start, resource_size(res)); | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | |||
413 | static struct platform_driver nmk_gpio_driver = { | 622 | static struct platform_driver nmk_gpio_driver = { |
414 | .driver = { | 623 | .driver = { |
415 | .owner = THIS_MODULE, | 624 | .owner = THIS_MODULE, |
416 | .name = "gpio", | 625 | .name = "gpio", |
417 | }, | 626 | }, |
418 | .probe = nmk_gpio_probe, | 627 | .probe = nmk_gpio_probe, |
419 | .remove = __exit_p(nmk_gpio_remove), | ||
420 | .suspend = NULL, /* to be done */ | 628 | .suspend = NULL, /* to be done */ |
421 | .resume = NULL, | 629 | .resume = NULL, |
422 | }; | 630 | }; |
@@ -426,7 +634,7 @@ static int __init nmk_gpio_init(void) | |||
426 | return platform_driver_register(&nmk_gpio_driver); | 634 | return platform_driver_register(&nmk_gpio_driver); |
427 | } | 635 | } |
428 | 636 | ||
429 | arch_initcall(nmk_gpio_init); | 637 | core_initcall(nmk_gpio_init); |
430 | 638 | ||
431 | MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); | 639 | MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); |
432 | MODULE_DESCRIPTION("Nomadik GPIO Driver"); | 640 | MODULE_DESCRIPTION("Nomadik GPIO Driver"); |
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index 4200811249ca..aba355101f49 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h | |||
@@ -55,6 +55,21 @@ | |||
55 | #define NMK_GPIO_ALT_B 2 | 55 | #define NMK_GPIO_ALT_B 2 |
56 | #define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) | 56 | #define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) |
57 | 57 | ||
58 | /* Pull up/down values */ | ||
59 | enum nmk_gpio_pull { | ||
60 | NMK_GPIO_PULL_NONE, | ||
61 | NMK_GPIO_PULL_UP, | ||
62 | NMK_GPIO_PULL_DOWN, | ||
63 | }; | ||
64 | |||
65 | /* Sleep mode */ | ||
66 | enum nmk_gpio_slpm { | ||
67 | NMK_GPIO_SLPM_INPUT, | ||
68 | NMK_GPIO_SLPM_NOCHANGE, | ||
69 | }; | ||
70 | |||
71 | extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode); | ||
72 | extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull); | ||
58 | extern int nmk_gpio_set_mode(int gpio, int gpio_mode); | 73 | extern int nmk_gpio_set_mode(int gpio, int gpio_mode); |
59 | extern int nmk_gpio_get_mode(int gpio); | 74 | extern int nmk_gpio_get_mode(int gpio); |
60 | 75 | ||
diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/arch/arm/plat-nomadik/include/plat/mtu.h index 42c907258b14..65704a3d4241 100644 --- a/arch/arm/plat-nomadik/include/plat/mtu.h +++ b/arch/arm/plat-nomadik/include/plat/mtu.h | |||
@@ -1,6 +1,12 @@ | |||
1 | #ifndef __PLAT_MTU_H | 1 | #ifndef __PLAT_MTU_H |
2 | #define __PLAT_MTU_H | 2 | #define __PLAT_MTU_H |
3 | 3 | ||
4 | /* | ||
5 | * Guaranteed runtime conversion range in seconds for | ||
6 | * the clocksource and clockevent. | ||
7 | */ | ||
8 | #define MTU_MIN_RANGE 4 | ||
9 | |||
4 | /* should be set by the platform code */ | 10 | /* should be set by the platform code */ |
5 | extern void __iomem *mtu_base; | 11 | extern void __iomem *mtu_base; |
6 | 12 | ||
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h new file mode 100644 index 000000000000..7eed11c1038d --- /dev/null +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | * | ||
7 | * Based on arch/arm/mach-pxa/include/mach/mfp.h: | ||
8 | * Copyright (C) 2007 Marvell International Ltd. | ||
9 | * eric miao <eric.miao@marvell.com> | ||
10 | */ | ||
11 | |||
12 | #ifndef __PLAT_PINCFG_H | ||
13 | #define __PLAT_PINCFG_H | ||
14 | |||
15 | /* | ||
16 | * pin configurations are represented by 32-bit integers: | ||
17 | * | ||
18 | * bit 0.. 8 - Pin Number (512 Pins Maximum) | ||
19 | * bit 9..10 - Alternate Function Selection | ||
20 | * bit 11..12 - Pull up/down state | ||
21 | * bit 13 - Sleep mode behaviour | ||
22 | * | ||
23 | * to facilitate the definition, the following macros are provided | ||
24 | * | ||
25 | * PIN_CFG_DEFAULT - default config (0): | ||
26 | * pull up/down = disabled | ||
27 | * sleep mode = input | ||
28 | * | ||
29 | * PIN_CFG - default config with alternate function | ||
30 | * PIN_CFG_PULL - default config with alternate function and pull up/down | ||
31 | */ | ||
32 | |||
33 | typedef unsigned long pin_cfg_t; | ||
34 | |||
35 | #define PIN_NUM_MASK 0x1ff | ||
36 | #define PIN_NUM(x) ((x) & PIN_NUM_MASK) | ||
37 | |||
38 | #define PIN_ALT_SHIFT 9 | ||
39 | #define PIN_ALT_MASK (0x3 << PIN_ALT_SHIFT) | ||
40 | #define PIN_ALT(x) (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT) | ||
41 | #define PIN_GPIO (NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT) | ||
42 | #define PIN_ALT_A (NMK_GPIO_ALT_A << PIN_ALT_SHIFT) | ||
43 | #define PIN_ALT_B (NMK_GPIO_ALT_B << PIN_ALT_SHIFT) | ||
44 | #define PIN_ALT_C (NMK_GPIO_ALT_C << PIN_ALT_SHIFT) | ||
45 | |||
46 | #define PIN_PULL_SHIFT 11 | ||
47 | #define PIN_PULL_MASK (0x3 << PIN_PULL_SHIFT) | ||
48 | #define PIN_PULL(x) (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT) | ||
49 | #define PIN_PULL_NONE (NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT) | ||
50 | #define PIN_PULL_UP (NMK_GPIO_PULL_UP << PIN_PULL_SHIFT) | ||
51 | #define PIN_PULL_DOWN (NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT) | ||
52 | |||
53 | #define PIN_SLPM_SHIFT 13 | ||
54 | #define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) | ||
55 | #define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) | ||
56 | #define PIN_SLPM_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) | ||
57 | #define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) | ||
58 | |||
59 | #define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) | ||
60 | |||
61 | #define PIN_CFG(num, alt) \ | ||
62 | (PIN_CFG_DEFAULT |\ | ||
63 | (PIN_NUM(num) | PIN_##alt)) | ||
64 | |||
65 | #define PIN_CFG_PULL(num, alt, pull) \ | ||
66 | ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\ | ||
67 | (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull)) | ||
68 | |||
69 | extern int nmk_config_pin(pin_cfg_t cfg); | ||
70 | extern int nmk_config_pins(pin_cfg_t *cfgs, int num); | ||
71 | |||
72 | #endif | ||
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index 08aaa4a7f65f..ea3ca86c5283 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c | |||
@@ -42,7 +42,6 @@ static struct clocksource nmdk_clksrc = { | |||
42 | .rating = 200, | 42 | .rating = 200, |
43 | .read = nmdk_read_timer_dummy, | 43 | .read = nmdk_read_timer_dummy, |
44 | .mask = CLOCKSOURCE_MASK(32), | 44 | .mask = CLOCKSOURCE_MASK(32), |
45 | .shift = 20, | ||
46 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 45 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
47 | }; | 46 | }; |
48 | 47 | ||
@@ -82,6 +81,12 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode, | |||
82 | case CLOCK_EVT_MODE_UNUSED: | 81 | case CLOCK_EVT_MODE_UNUSED: |
83 | /* disable irq */ | 82 | /* disable irq */ |
84 | writel(0, mtu_base + MTU_IMSC); | 83 | writel(0, mtu_base + MTU_IMSC); |
84 | /* disable timer */ | ||
85 | cr = readl(mtu_base + MTU_CR(1)); | ||
86 | cr &= ~MTU_CRn_ENA; | ||
87 | writel(cr, mtu_base + MTU_CR(1)); | ||
88 | /* load some high default value */ | ||
89 | writel(0xffffffff, mtu_base + MTU_LR(1)); | ||
85 | break; | 90 | break; |
86 | case CLOCK_EVT_MODE_RESUME: | 91 | case CLOCK_EVT_MODE_RESUME: |
87 | break; | 92 | break; |
@@ -98,7 +103,6 @@ static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev) | |||
98 | static struct clock_event_device nmdk_clkevt = { | 103 | static struct clock_event_device nmdk_clkevt = { |
99 | .name = "mtu_1", | 104 | .name = "mtu_1", |
100 | .features = CLOCK_EVT_FEAT_ONESHOT, | 105 | .features = CLOCK_EVT_FEAT_ONESHOT, |
101 | .shift = 32, | ||
102 | .rating = 200, | 106 | .rating = 200, |
103 | .set_mode = nmdk_clkevt_mode, | 107 | .set_mode = nmdk_clkevt_mode, |
104 | .set_next_event = nmdk_clkevt_next, | 108 | .set_next_event = nmdk_clkevt_next, |
@@ -151,6 +155,7 @@ void __init nmdk_timer_init(void) | |||
151 | } else { | 155 | } else { |
152 | cr |= MTU_CRn_PRESCALE_1; | 156 | cr |= MTU_CRn_PRESCALE_1; |
153 | } | 157 | } |
158 | clocksource_calc_mult_shift(&nmdk_clksrc, rate, MTU_MIN_RANGE); | ||
154 | 159 | ||
155 | /* Timer 0 is the free running clocksource */ | 160 | /* Timer 0 is the free running clocksource */ |
156 | writel(cr, mtu_base + MTU_CR(0)); | 161 | writel(cr, mtu_base + MTU_CR(0)); |
@@ -158,7 +163,6 @@ void __init nmdk_timer_init(void) | |||
158 | writel(0, mtu_base + MTU_BGLR(0)); | 163 | writel(0, mtu_base + MTU_BGLR(0)); |
159 | writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); | 164 | writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); |
160 | 165 | ||
161 | nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift); | ||
162 | /* Now the scheduling clock is ready */ | 166 | /* Now the scheduling clock is ready */ |
163 | nmdk_clksrc.read = nmdk_read_timer; | 167 | nmdk_clksrc.read = nmdk_read_timer; |
164 | 168 | ||
@@ -175,8 +179,10 @@ void __init nmdk_timer_init(void) | |||
175 | } else { | 179 | } else { |
176 | cr |= MTU_CRn_PRESCALE_1; | 180 | cr |= MTU_CRn_PRESCALE_1; |
177 | } | 181 | } |
182 | clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); | ||
183 | |||
178 | writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */ | 184 | writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */ |
179 | nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift); | 185 | |
180 | nmdk_clkevt.max_delta_ns = | 186 | nmdk_clkevt.max_delta_ns = |
181 | clockevent_delta2ns(0xffffffff, &nmdk_clkevt); | 187 | clockevent_delta2ns(0xffffffff, &nmdk_clkevt); |
182 | nmdk_clkevt.min_delta_ns = | 188 | nmdk_clkevt.min_delta_ns = |