diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/plat-nomadik | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/arm/plat-nomadik')
-rw-r--r-- | arch/arm/plat-nomadik/Kconfig | 7 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/gpio.c | 643 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/gpio.h | 11 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/i2c.h | 8 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/pincfg.h | 80 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/ske.h | 50 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/ste_dma40.h | 165 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/timer.c | 60 |
9 files changed, 239 insertions, 786 deletions
diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig index 5da3f97c537b..ce659015535e 100644 --- a/arch/arm/plat-nomadik/Kconfig +++ b/arch/arm/plat-nomadik/Kconfig | |||
@@ -5,6 +5,7 @@ | |||
5 | config PLAT_NOMADIK | 5 | config PLAT_NOMADIK |
6 | bool | 6 | bool |
7 | depends on ARCH_NOMADIK || ARCH_U8500 | 7 | depends on ARCH_NOMADIK || ARCH_U8500 |
8 | select CLKSRC_MMIO | ||
8 | default y | 9 | default y |
9 | help | 10 | help |
10 | Common platform code for Nomadik and other ST-Ericsson | 11 | Common platform code for Nomadik and other ST-Ericsson |
@@ -14,14 +15,10 @@ if PLAT_NOMADIK | |||
14 | 15 | ||
15 | config HAS_MTU | 16 | config HAS_MTU |
16 | bool | 17 | bool |
18 | select HAVE_SCHED_CLOCK | ||
17 | help | 19 | help |
18 | Support for Multi Timer Unit. MTU provides access | 20 | Support for Multi Timer Unit. MTU provides access |
19 | to multiple interrupt generating programmable | 21 | to multiple interrupt generating programmable |
20 | 32-bit free running decrementing counters. | 22 | 32-bit free running decrementing counters. |
21 | 23 | ||
22 | config NOMADIK_GPIO | ||
23 | bool | ||
24 | help | ||
25 | Support for the Nomadik GPIO controller. | ||
26 | |||
27 | endif | 24 | endif |
diff --git a/arch/arm/plat-nomadik/Makefile b/arch/arm/plat-nomadik/Makefile index c33547361bd7..37c7cdd0f8f0 100644 --- a/arch/arm/plat-nomadik/Makefile +++ b/arch/arm/plat-nomadik/Makefile | |||
@@ -3,4 +3,3 @@ | |||
3 | # Licensed under GPLv2 | 3 | # Licensed under GPLv2 |
4 | 4 | ||
5 | obj-$(CONFIG_HAS_MTU) += timer.o | 5 | obj-$(CONFIG_HAS_MTU) += timer.o |
6 | obj-$(CONFIG_NOMADIK_GPIO) += gpio.o | ||
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c deleted file mode 100644 index 977c8f9a07a2..000000000000 --- a/arch/arm/plat-nomadik/gpio.c +++ /dev/null | |||
@@ -1,643 +0,0 @@ | |||
1 | /* | ||
2 | * Generic GPIO driver for logic cells found in the Nomadik SoC | ||
3 | * | ||
4 | * Copyright (C) 2008,2009 STMicroelectronics | ||
5 | * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> | ||
6 | * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/irq.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #include <plat/pincfg.h> | ||
27 | #include <mach/hardware.h> | ||
28 | #include <mach/gpio.h> | ||
29 | |||
30 | /* | ||
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 | ||
33 | * is currently only used in the Nomadik. | ||
34 | * | ||
35 | * Symbols in this file are called "nmk_gpio" for "nomadik gpio" | ||
36 | */ | ||
37 | |||
38 | #define NMK_GPIO_PER_CHIP 32 | ||
39 | struct nmk_gpio_chip { | ||
40 | struct gpio_chip chip; | ||
41 | void __iomem *addr; | ||
42 | struct clk *clk; | ||
43 | unsigned int parent_irq; | ||
44 | spinlock_t lock; | ||
45 | /* Keep track of configured edges */ | ||
46 | u32 edge_rising; | ||
47 | u32 edge_falling; | ||
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 | |||
249 | /* Mode functions */ | ||
250 | int nmk_gpio_set_mode(int gpio, int gpio_mode) | ||
251 | { | ||
252 | struct nmk_gpio_chip *nmk_chip; | ||
253 | unsigned long flags; | ||
254 | |||
255 | nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); | ||
256 | if (!nmk_chip) | ||
257 | return -EINVAL; | ||
258 | |||
259 | spin_lock_irqsave(&nmk_chip->lock, flags); | ||
260 | __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode); | ||
261 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | EXPORT_SYMBOL(nmk_gpio_set_mode); | ||
266 | |||
267 | int nmk_gpio_get_mode(int gpio) | ||
268 | { | ||
269 | struct nmk_gpio_chip *nmk_chip; | ||
270 | u32 afunc, bfunc, bit; | ||
271 | |||
272 | nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); | ||
273 | if (!nmk_chip) | ||
274 | return -EINVAL; | ||
275 | |||
276 | bit = 1 << (gpio - nmk_chip->chip.base); | ||
277 | |||
278 | afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; | ||
279 | bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; | ||
280 | |||
281 | return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); | ||
282 | } | ||
283 | EXPORT_SYMBOL(nmk_gpio_get_mode); | ||
284 | |||
285 | |||
286 | /* IRQ functions */ | ||
287 | static inline int nmk_gpio_get_bitmask(int gpio) | ||
288 | { | ||
289 | return 1 << (gpio % 32); | ||
290 | } | ||
291 | |||
292 | static void nmk_gpio_irq_ack(unsigned int irq) | ||
293 | { | ||
294 | int gpio; | ||
295 | struct nmk_gpio_chip *nmk_chip; | ||
296 | |||
297 | gpio = NOMADIK_IRQ_TO_GPIO(irq); | ||
298 | nmk_chip = get_irq_chip_data(irq); | ||
299 | if (!nmk_chip) | ||
300 | return; | ||
301 | writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); | ||
302 | } | ||
303 | |||
304 | enum nmk_gpio_irq_type { | ||
305 | NORMAL, | ||
306 | WAKE, | ||
307 | }; | ||
308 | |||
309 | static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, | ||
310 | int gpio, enum nmk_gpio_irq_type which, | ||
311 | bool enable) | ||
312 | { | ||
313 | u32 rimsc = which == WAKE ? NMK_GPIO_RWIMSC : NMK_GPIO_RIMSC; | ||
314 | u32 fimsc = which == WAKE ? NMK_GPIO_FWIMSC : NMK_GPIO_FIMSC; | ||
315 | u32 bitmask = nmk_gpio_get_bitmask(gpio); | ||
316 | u32 reg; | ||
317 | |||
318 | /* we must individually set/clear the two edges */ | ||
319 | if (nmk_chip->edge_rising & bitmask) { | ||
320 | reg = readl(nmk_chip->addr + rimsc); | ||
321 | if (enable) | ||
322 | reg |= bitmask; | ||
323 | else | ||
324 | reg &= ~bitmask; | ||
325 | writel(reg, nmk_chip->addr + rimsc); | ||
326 | } | ||
327 | if (nmk_chip->edge_falling & bitmask) { | ||
328 | reg = readl(nmk_chip->addr + fimsc); | ||
329 | if (enable) | ||
330 | reg |= bitmask; | ||
331 | else | ||
332 | reg &= ~bitmask; | ||
333 | writel(reg, nmk_chip->addr + fimsc); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | static int nmk_gpio_irq_modify(unsigned int irq, enum nmk_gpio_irq_type which, | ||
338 | bool enable) | ||
339 | { | ||
340 | int gpio; | ||
341 | struct nmk_gpio_chip *nmk_chip; | ||
342 | unsigned long flags; | ||
343 | u32 bitmask; | ||
344 | |||
345 | gpio = NOMADIK_IRQ_TO_GPIO(irq); | ||
346 | nmk_chip = get_irq_chip_data(irq); | ||
347 | bitmask = nmk_gpio_get_bitmask(gpio); | ||
348 | if (!nmk_chip) | ||
349 | return -EINVAL; | ||
350 | |||
351 | spin_lock_irqsave(&nmk_chip->lock, flags); | ||
352 | __nmk_gpio_irq_modify(nmk_chip, gpio, which, enable); | ||
353 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static void nmk_gpio_irq_mask(unsigned int irq) | ||
359 | { | ||
360 | nmk_gpio_irq_modify(irq, NORMAL, false); | ||
361 | } | ||
362 | |||
363 | static void nmk_gpio_irq_unmask(unsigned int irq) | ||
364 | { | ||
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); | ||
371 | } | ||
372 | |||
373 | static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) | ||
374 | { | ||
375 | struct irq_desc *desc = irq_to_desc(irq); | ||
376 | bool enabled = !(desc->status & IRQ_DISABLED); | ||
377 | bool wake = desc->wake_depth; | ||
378 | int gpio; | ||
379 | struct nmk_gpio_chip *nmk_chip; | ||
380 | unsigned long flags; | ||
381 | u32 bitmask; | ||
382 | |||
383 | gpio = NOMADIK_IRQ_TO_GPIO(irq); | ||
384 | nmk_chip = get_irq_chip_data(irq); | ||
385 | bitmask = nmk_gpio_get_bitmask(gpio); | ||
386 | if (!nmk_chip) | ||
387 | return -EINVAL; | ||
388 | |||
389 | if (type & IRQ_TYPE_LEVEL_HIGH) | ||
390 | return -EINVAL; | ||
391 | if (type & IRQ_TYPE_LEVEL_LOW) | ||
392 | return -EINVAL; | ||
393 | |||
394 | spin_lock_irqsave(&nmk_chip->lock, flags); | ||
395 | |||
396 | if (enabled) | ||
397 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); | ||
398 | |||
399 | if (wake) | ||
400 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); | ||
401 | |||
402 | nmk_chip->edge_rising &= ~bitmask; | ||
403 | if (type & IRQ_TYPE_EDGE_RISING) | ||
404 | nmk_chip->edge_rising |= bitmask; | ||
405 | |||
406 | nmk_chip->edge_falling &= ~bitmask; | ||
407 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
408 | nmk_chip->edge_falling |= bitmask; | ||
409 | |||
410 | if (enabled) | ||
411 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); | ||
412 | |||
413 | if (wake) | ||
414 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); | ||
415 | |||
416 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static struct irq_chip nmk_gpio_irq_chip = { | ||
422 | .name = "Nomadik-GPIO", | ||
423 | .ack = nmk_gpio_irq_ack, | ||
424 | .mask = nmk_gpio_irq_mask, | ||
425 | .unmask = nmk_gpio_irq_unmask, | ||
426 | .set_type = nmk_gpio_irq_set_type, | ||
427 | .set_wake = nmk_gpio_irq_set_wake, | ||
428 | }; | ||
429 | |||
430 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
431 | { | ||
432 | struct nmk_gpio_chip *nmk_chip; | ||
433 | struct irq_chip *host_chip = get_irq_chip(irq); | ||
434 | unsigned int gpio_irq; | ||
435 | u32 pending; | ||
436 | unsigned int first_irq; | ||
437 | |||
438 | if (host_chip->mask_ack) | ||
439 | host_chip->mask_ack(irq); | ||
440 | else { | ||
441 | host_chip->mask(irq); | ||
442 | if (host_chip->ack) | ||
443 | host_chip->ack(irq); | ||
444 | } | ||
445 | |||
446 | nmk_chip = get_irq_data(irq); | ||
447 | first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); | ||
448 | while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) { | ||
449 | gpio_irq = first_irq + __ffs(pending); | ||
450 | generic_handle_irq(gpio_irq); | ||
451 | } | ||
452 | |||
453 | host_chip->unmask(irq); | ||
454 | } | ||
455 | |||
456 | static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) | ||
457 | { | ||
458 | unsigned int first_irq; | ||
459 | int i; | ||
460 | |||
461 | first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); | ||
462 | for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) { | ||
463 | set_irq_chip(i, &nmk_gpio_irq_chip); | ||
464 | set_irq_handler(i, handle_edge_irq); | ||
465 | set_irq_flags(i, IRQF_VALID); | ||
466 | set_irq_chip_data(i, nmk_chip); | ||
467 | set_irq_type(i, IRQ_TYPE_EDGE_FALLING); | ||
468 | } | ||
469 | set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); | ||
470 | set_irq_data(nmk_chip->parent_irq, nmk_chip); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | /* I/O Functions */ | ||
475 | static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) | ||
476 | { | ||
477 | struct nmk_gpio_chip *nmk_chip = | ||
478 | container_of(chip, struct nmk_gpio_chip, chip); | ||
479 | |||
480 | writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) | ||
485 | { | ||
486 | struct nmk_gpio_chip *nmk_chip = | ||
487 | container_of(chip, struct nmk_gpio_chip, chip); | ||
488 | u32 bit = 1 << offset; | ||
489 | |||
490 | return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; | ||
491 | } | ||
492 | |||
493 | static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, | ||
494 | int val) | ||
495 | { | ||
496 | struct nmk_gpio_chip *nmk_chip = | ||
497 | container_of(chip, struct nmk_gpio_chip, chip); | ||
498 | u32 bit = 1 << offset; | ||
499 | |||
500 | if (val) | ||
501 | writel(bit, nmk_chip->addr + NMK_GPIO_DATS); | ||
502 | else | ||
503 | writel(bit, nmk_chip->addr + NMK_GPIO_DATC); | ||
504 | } | ||
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 | |||
526 | /* This structure is replicated for each GPIO block allocated at probe time */ | ||
527 | static struct gpio_chip nmk_gpio_template = { | ||
528 | .direction_input = nmk_gpio_make_input, | ||
529 | .get = nmk_gpio_get_input, | ||
530 | .direction_output = nmk_gpio_make_output, | ||
531 | .set = nmk_gpio_set_output, | ||
532 | .to_irq = nmk_gpio_to_irq, | ||
533 | .ngpio = NMK_GPIO_PER_CHIP, | ||
534 | .can_sleep = 0, | ||
535 | }; | ||
536 | |||
537 | static int __init nmk_gpio_probe(struct platform_device *dev) | ||
538 | { | ||
539 | struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; | ||
540 | struct nmk_gpio_chip *nmk_chip; | ||
541 | struct gpio_chip *chip; | ||
542 | struct resource *res; | ||
543 | struct clk *clk; | ||
544 | int irq; | ||
545 | int ret; | ||
546 | |||
547 | if (!pdata) | ||
548 | return -ENODEV; | ||
549 | |||
550 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
551 | if (!res) { | ||
552 | ret = -ENOENT; | ||
553 | goto out; | ||
554 | } | ||
555 | |||
556 | irq = platform_get_irq(dev, 0); | ||
557 | if (irq < 0) { | ||
558 | ret = irq; | ||
559 | goto out; | ||
560 | } | ||
561 | |||
562 | if (request_mem_region(res->start, resource_size(res), | ||
563 | dev_name(&dev->dev)) == NULL) { | ||
564 | ret = -EBUSY; | ||
565 | goto out; | ||
566 | } | ||
567 | |||
568 | clk = clk_get(&dev->dev, NULL); | ||
569 | if (IS_ERR(clk)) { | ||
570 | ret = PTR_ERR(clk); | ||
571 | goto out_release; | ||
572 | } | ||
573 | |||
574 | clk_enable(clk); | ||
575 | |||
576 | nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); | ||
577 | if (!nmk_chip) { | ||
578 | ret = -ENOMEM; | ||
579 | goto out_clk; | ||
580 | } | ||
581 | /* | ||
582 | * The virt address in nmk_chip->addr is in the nomadik register space, | ||
583 | * so we can simply convert the resource address, without remapping | ||
584 | */ | ||
585 | nmk_chip->clk = clk; | ||
586 | nmk_chip->addr = io_p2v(res->start); | ||
587 | nmk_chip->chip = nmk_gpio_template; | ||
588 | nmk_chip->parent_irq = irq; | ||
589 | spin_lock_init(&nmk_chip->lock); | ||
590 | |||
591 | chip = &nmk_chip->chip; | ||
592 | chip->base = pdata->first_gpio; | ||
593 | chip->label = pdata->name; | ||
594 | chip->dev = &dev->dev; | ||
595 | chip->owner = THIS_MODULE; | ||
596 | |||
597 | ret = gpiochip_add(&nmk_chip->chip); | ||
598 | if (ret) | ||
599 | goto out_free; | ||
600 | |||
601 | platform_set_drvdata(dev, nmk_chip); | ||
602 | |||
603 | nmk_gpio_init_irq(nmk_chip); | ||
604 | |||
605 | dev_info(&dev->dev, "Bits %i-%i at address %p\n", | ||
606 | nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr); | ||
607 | return 0; | ||
608 | |||
609 | out_free: | ||
610 | kfree(nmk_chip); | ||
611 | out_clk: | ||
612 | clk_disable(clk); | ||
613 | clk_put(clk); | ||
614 | out_release: | ||
615 | release_mem_region(res->start, resource_size(res)); | ||
616 | out: | ||
617 | dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, | ||
618 | pdata->first_gpio, pdata->first_gpio+31); | ||
619 | return ret; | ||
620 | } | ||
621 | |||
622 | static struct platform_driver nmk_gpio_driver = { | ||
623 | .driver = { | ||
624 | .owner = THIS_MODULE, | ||
625 | .name = "gpio", | ||
626 | }, | ||
627 | .probe = nmk_gpio_probe, | ||
628 | .suspend = NULL, /* to be done */ | ||
629 | .resume = NULL, | ||
630 | }; | ||
631 | |||
632 | static int __init nmk_gpio_init(void) | ||
633 | { | ||
634 | return platform_driver_register(&nmk_gpio_driver); | ||
635 | } | ||
636 | |||
637 | core_initcall(nmk_gpio_init); | ||
638 | |||
639 | MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); | ||
640 | MODULE_DESCRIPTION("Nomadik GPIO Driver"); | ||
641 | MODULE_LICENSE("GPL"); | ||
642 | |||
643 | |||
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index aba355101f49..d5d7e651269c 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h | |||
@@ -65,7 +65,9 @@ enum nmk_gpio_pull { | |||
65 | /* Sleep mode */ | 65 | /* Sleep mode */ |
66 | enum nmk_gpio_slpm { | 66 | enum nmk_gpio_slpm { |
67 | NMK_GPIO_SLPM_INPUT, | 67 | NMK_GPIO_SLPM_INPUT, |
68 | NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT, | ||
68 | NMK_GPIO_SLPM_NOCHANGE, | 69 | NMK_GPIO_SLPM_NOCHANGE, |
70 | NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, | ||
69 | }; | 71 | }; |
70 | 72 | ||
71 | extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode); | 73 | extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode); |
@@ -73,6 +75,11 @@ extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull); | |||
73 | extern int nmk_gpio_set_mode(int gpio, int gpio_mode); | 75 | extern int nmk_gpio_set_mode(int gpio, int gpio_mode); |
74 | extern int nmk_gpio_get_mode(int gpio); | 76 | extern int nmk_gpio_get_mode(int gpio); |
75 | 77 | ||
78 | extern void nmk_gpio_wakeups_suspend(void); | ||
79 | extern void nmk_gpio_wakeups_resume(void); | ||
80 | |||
81 | extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up); | ||
82 | |||
76 | /* | 83 | /* |
77 | * Platform data to register a block: only the initial gpio/irq number. | 84 | * Platform data to register a block: only the initial gpio/irq number. |
78 | */ | 85 | */ |
@@ -80,6 +87,10 @@ struct nmk_gpio_platform_data { | |||
80 | char *name; | 87 | char *name; |
81 | int first_gpio; | 88 | int first_gpio; |
82 | int first_irq; | 89 | int first_irq; |
90 | int num_gpio; | ||
91 | u32 (*get_secondary_status)(unsigned int bank); | ||
92 | void (*set_ioforce)(bool enable); | ||
93 | bool supports_sleepmode; | ||
83 | }; | 94 | }; |
84 | 95 | ||
85 | #endif /* __ASM_PLAT_GPIO_H */ | 96 | #endif /* __ASM_PLAT_GPIO_H */ |
diff --git a/arch/arm/plat-nomadik/include/plat/i2c.h b/arch/arm/plat-nomadik/include/plat/i2c.h index 1621db67a53d..8ba70ffc31ec 100644 --- a/arch/arm/plat-nomadik/include/plat/i2c.h +++ b/arch/arm/plat-nomadik/include/plat/i2c.h | |||
@@ -11,8 +11,8 @@ | |||
11 | enum i2c_freq_mode { | 11 | enum i2c_freq_mode { |
12 | I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */ | 12 | I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */ |
13 | I2C_FREQ_MODE_FAST, /* up to 400 Kb/s */ | 13 | I2C_FREQ_MODE_FAST, /* up to 400 Kb/s */ |
14 | I2C_FREQ_MODE_HIGH_SPEED, /* up to 3.4 Mb/s */ | ||
14 | I2C_FREQ_MODE_FAST_PLUS, /* up to 1 Mb/s */ | 15 | I2C_FREQ_MODE_FAST_PLUS, /* up to 1 Mb/s */ |
15 | I2C_FREQ_MODE_HIGH_SPEED /* up to 3.4 Mb/s */ | ||
16 | }; | 16 | }; |
17 | 17 | ||
18 | /** | 18 | /** |
@@ -24,13 +24,15 @@ enum i2c_freq_mode { | |||
24 | * to the values of 14, 6, 2 for a 48 MHz i2c clk | 24 | * to the values of 14, 6, 2 for a 48 MHz i2c clk |
25 | * @tft: Tx FIFO Threshold in bytes | 25 | * @tft: Tx FIFO Threshold in bytes |
26 | * @rft: Rx FIFO Threshold in bytes | 26 | * @rft: Rx FIFO Threshold in bytes |
27 | * @timeout Slave response timeout(ms) | ||
27 | * @sm: speed mode | 28 | * @sm: speed mode |
28 | */ | 29 | */ |
29 | struct nmk_i2c_controller { | 30 | struct nmk_i2c_controller { |
30 | unsigned long clk_freq; | 31 | unsigned long clk_freq; |
31 | unsigned short slsu; | 32 | unsigned short slsu; |
32 | unsigned char tft; | 33 | unsigned char tft; |
33 | unsigned char rft; | 34 | unsigned char rft; |
35 | int timeout; | ||
34 | enum i2c_freq_mode sm; | 36 | enum i2c_freq_mode sm; |
35 | }; | 37 | }; |
36 | 38 | ||
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 7eed11c1038d..05a3936ae6d1 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h | |||
@@ -19,12 +19,22 @@ | |||
19 | * bit 9..10 - Alternate Function Selection | 19 | * bit 9..10 - Alternate Function Selection |
20 | * bit 11..12 - Pull up/down state | 20 | * bit 11..12 - Pull up/down state |
21 | * bit 13 - Sleep mode behaviour | 21 | * bit 13 - Sleep mode behaviour |
22 | * bit 14 - Direction | ||
23 | * bit 15 - Value (if output) | ||
24 | * bit 16..18 - SLPM pull up/down state | ||
25 | * bit 19..20 - SLPM direction | ||
26 | * bit 21..22 - SLPM Value (if output) | ||
22 | * | 27 | * |
23 | * to facilitate the definition, the following macros are provided | 28 | * to facilitate the definition, the following macros are provided |
24 | * | 29 | * |
25 | * PIN_CFG_DEFAULT - default config (0): | 30 | * PIN_CFG_DEFAULT - default config (0): |
26 | * pull up/down = disabled | 31 | * pull up/down = disabled |
27 | * sleep mode = input | 32 | * sleep mode = input/wakeup |
33 | * direction = input | ||
34 | * value = low | ||
35 | * SLPM direction = same as normal | ||
36 | * SLPM pull = same as normal | ||
37 | * SLPM value = same as normal | ||
28 | * | 38 | * |
29 | * PIN_CFG - default config with alternate function | 39 | * PIN_CFG - default config with alternate function |
30 | * PIN_CFG_PULL - default config with alternate function and pull up/down | 40 | * PIN_CFG_PULL - default config with alternate function and pull up/down |
@@ -53,20 +63,82 @@ typedef unsigned long pin_cfg_t; | |||
53 | #define PIN_SLPM_SHIFT 13 | 63 | #define PIN_SLPM_SHIFT 13 |
54 | #define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) | 64 | #define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) |
55 | #define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) | 65 | #define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) |
56 | #define PIN_SLPM_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) | 66 | #define PIN_SLPM_MAKE_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) |
57 | #define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) | 67 | #define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) |
68 | /* These two replace the above in DB8500v2+ */ | ||
69 | #define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) | ||
70 | #define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) | ||
58 | 71 | ||
59 | #define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) | 72 | #define PIN_DIR_SHIFT 14 |
73 | #define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) | ||
74 | #define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT) | ||
75 | #define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT) | ||
76 | #define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT) | ||
77 | |||
78 | #define PIN_VAL_SHIFT 15 | ||
79 | #define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT) | ||
80 | #define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT) | ||
81 | #define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) | ||
82 | #define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) | ||
83 | |||
84 | #define PIN_SLPM_PULL_SHIFT 16 | ||
85 | #define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT) | ||
86 | #define PIN_SLPM_PULL(x) \ | ||
87 | (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT) | ||
88 | #define PIN_SLPM_PULL_NONE \ | ||
89 | ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT) | ||
90 | #define PIN_SLPM_PULL_UP \ | ||
91 | ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT) | ||
92 | #define PIN_SLPM_PULL_DOWN \ | ||
93 | ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT) | ||
94 | |||
95 | #define PIN_SLPM_DIR_SHIFT 19 | ||
96 | #define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT) | ||
97 | #define PIN_SLPM_DIR(x) \ | ||
98 | (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT) | ||
99 | #define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT) | ||
100 | #define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT) | ||
101 | |||
102 | #define PIN_SLPM_VAL_SHIFT 21 | ||
103 | #define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT) | ||
104 | #define PIN_SLPM_VAL(x) \ | ||
105 | (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT) | ||
106 | #define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) | ||
107 | #define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) | ||
108 | |||
109 | /* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ | ||
110 | #define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) | ||
111 | #define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) | ||
112 | #define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE) | ||
113 | #define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) | ||
114 | #define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) | ||
115 | |||
116 | #define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN) | ||
117 | #define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP) | ||
118 | #define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE) | ||
119 | #define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW) | ||
120 | #define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH) | ||
121 | |||
122 | #define PIN_CFG_DEFAULT (0) | ||
60 | 123 | ||
61 | #define PIN_CFG(num, alt) \ | 124 | #define PIN_CFG(num, alt) \ |
62 | (PIN_CFG_DEFAULT |\ | 125 | (PIN_CFG_DEFAULT |\ |
63 | (PIN_NUM(num) | PIN_##alt)) | 126 | (PIN_NUM(num) | PIN_##alt)) |
64 | 127 | ||
128 | #define PIN_CFG_INPUT(num, alt, pull) \ | ||
129 | (PIN_CFG_DEFAULT |\ | ||
130 | (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull)) | ||
131 | |||
132 | #define PIN_CFG_OUTPUT(num, alt, val) \ | ||
133 | (PIN_CFG_DEFAULT |\ | ||
134 | (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val)) | ||
135 | |||
65 | #define PIN_CFG_PULL(num, alt, pull) \ | 136 | #define PIN_CFG_PULL(num, alt, pull) \ |
66 | ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\ | 137 | ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\ |
67 | (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull)) | 138 | (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull)) |
68 | 139 | ||
69 | extern int nmk_config_pin(pin_cfg_t cfg); | 140 | extern int nmk_config_pin(pin_cfg_t cfg, bool sleep); |
70 | extern int nmk_config_pins(pin_cfg_t *cfgs, int num); | 141 | extern int nmk_config_pins(pin_cfg_t *cfgs, int num); |
142 | extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num); | ||
71 | 143 | ||
72 | #endif | 144 | #endif |
diff --git a/arch/arm/plat-nomadik/include/plat/ske.h b/arch/arm/plat-nomadik/include/plat/ske.h new file mode 100644 index 000000000000..31382fbc07dc --- /dev/null +++ b/arch/arm/plat-nomadik/include/plat/ske.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com> | ||
6 | * | ||
7 | * ux500 Scroll key and Keypad Encoder (SKE) header | ||
8 | */ | ||
9 | |||
10 | #ifndef __SKE_H | ||
11 | #define __SKE_H | ||
12 | |||
13 | #include <linux/input/matrix_keypad.h> | ||
14 | |||
15 | /* register definitions for SKE peripheral */ | ||
16 | #define SKE_CR 0x00 | ||
17 | #define SKE_VAL0 0x04 | ||
18 | #define SKE_VAL1 0x08 | ||
19 | #define SKE_DBCR 0x0C | ||
20 | #define SKE_IMSC 0x10 | ||
21 | #define SKE_RIS 0x14 | ||
22 | #define SKE_MIS 0x18 | ||
23 | #define SKE_ICR 0x1C | ||
24 | |||
25 | /* | ||
26 | * Keypad module | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * struct keypad_platform_data - structure for platform specific data | ||
31 | * @init: pointer to keypad init function | ||
32 | * @exit: pointer to keypad deinitialisation function | ||
33 | * @keymap_data: matrix scan code table for keycodes | ||
34 | * @krow: maximum number of rows | ||
35 | * @kcol: maximum number of columns | ||
36 | * @debounce_ms: platform specific debounce time | ||
37 | * @no_autorepeat: flag for auto repetition | ||
38 | * @wakeup_enable: allow waking up the system | ||
39 | */ | ||
40 | struct ske_keypad_platform_data { | ||
41 | int (*init)(void); | ||
42 | int (*exit)(void); | ||
43 | const struct matrix_keymap_data *keymap_data; | ||
44 | u8 krow; | ||
45 | u8 kcol; | ||
46 | u8 debounce_ms; | ||
47 | bool no_autorepeat; | ||
48 | bool wakeup_enable; | ||
49 | }; | ||
50 | #endif /*__SKE_KPD_H*/ | ||
diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 5fbde4b8dc12..c44886062f8e 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h | |||
@@ -1,10 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/plat-nomadik/include/plat/ste_dma40.h | 2 | * Copyright (C) ST-Ericsson SA 2007-2010 |
3 | * | 3 | * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson |
4 | * Copyright (C) ST-Ericsson 2007-2010 | 4 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson |
5 | * License terms: GNU General Public License (GPL) version 2 | 5 | * License terms: GNU General Public License (GPL) version 2 |
6 | * Author: Per Friden <per.friden@stericsson.com> | ||
7 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> | ||
8 | */ | 6 | */ |
9 | 7 | ||
10 | 8 | ||
@@ -14,43 +12,33 @@ | |||
14 | #include <linux/dmaengine.h> | 12 | #include <linux/dmaengine.h> |
15 | #include <linux/workqueue.h> | 13 | #include <linux/workqueue.h> |
16 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
17 | #include <linux/dmaengine.h> | 15 | |
16 | /* | ||
17 | * Maxium size for a single dma descriptor | ||
18 | * Size is limited to 16 bits. | ||
19 | * Size is in the units of addr-widths (1,2,4,8 bytes) | ||
20 | * Larger transfers will be split up to multiple linked desc | ||
21 | */ | ||
22 | #define STEDMA40_MAX_SEG_SIZE 0xFFFF | ||
18 | 23 | ||
19 | /* dev types for memcpy */ | 24 | /* dev types for memcpy */ |
20 | #define STEDMA40_DEV_DST_MEMORY (-1) | 25 | #define STEDMA40_DEV_DST_MEMORY (-1) |
21 | #define STEDMA40_DEV_SRC_MEMORY (-1) | 26 | #define STEDMA40_DEV_SRC_MEMORY (-1) |
22 | 27 | ||
23 | /* | 28 | enum stedma40_mode { |
24 | * Description of bitfields of channel_type variable is available in | 29 | STEDMA40_MODE_LOGICAL = 0, |
25 | * the info structure. | 30 | STEDMA40_MODE_PHYSICAL, |
26 | */ | 31 | STEDMA40_MODE_OPERATION, |
32 | }; | ||
27 | 33 | ||
28 | /* Priority */ | 34 | enum stedma40_mode_opt { |
29 | #define STEDMA40_INFO_PRIO_TYPE_POS 2 | 35 | STEDMA40_PCHAN_BASIC_MODE = 0, |
30 | #define STEDMA40_HIGH_PRIORITY_CHANNEL (0x1 << STEDMA40_INFO_PRIO_TYPE_POS) | 36 | STEDMA40_LCHAN_SRC_LOG_DST_LOG = 0, |
31 | #define STEDMA40_LOW_PRIORITY_CHANNEL (0x2 << STEDMA40_INFO_PRIO_TYPE_POS) | 37 | STEDMA40_PCHAN_MODULO_MODE, |
32 | 38 | STEDMA40_PCHAN_DOUBLE_DST_MODE, | |
33 | /* Mode */ | 39 | STEDMA40_LCHAN_SRC_PHY_DST_LOG, |
34 | #define STEDMA40_INFO_CH_MODE_TYPE_POS 6 | 40 | STEDMA40_LCHAN_SRC_LOG_DST_PHY, |
35 | #define STEDMA40_CHANNEL_IN_PHY_MODE (0x1 << STEDMA40_INFO_CH_MODE_TYPE_POS) | 41 | }; |
36 | #define STEDMA40_CHANNEL_IN_LOG_MODE (0x2 << STEDMA40_INFO_CH_MODE_TYPE_POS) | ||
37 | #define STEDMA40_CHANNEL_IN_OPER_MODE (0x3 << STEDMA40_INFO_CH_MODE_TYPE_POS) | ||
38 | |||
39 | /* Mode options */ | ||
40 | #define STEDMA40_INFO_CH_MODE_OPT_POS 8 | ||
41 | #define STEDMA40_PCHAN_BASIC_MODE (0x1 << STEDMA40_INFO_CH_MODE_OPT_POS) | ||
42 | #define STEDMA40_PCHAN_MODULO_MODE (0x2 << STEDMA40_INFO_CH_MODE_OPT_POS) | ||
43 | #define STEDMA40_PCHAN_DOUBLE_DST_MODE (0x3 << STEDMA40_INFO_CH_MODE_OPT_POS) | ||
44 | #define STEDMA40_LCHAN_SRC_PHY_DST_LOG (0x1 << STEDMA40_INFO_CH_MODE_OPT_POS) | ||
45 | #define STEDMA40_LCHAN_SRC_LOG_DST_PHS (0x2 << STEDMA40_INFO_CH_MODE_OPT_POS) | ||
46 | #define STEDMA40_LCHAN_SRC_LOG_DST_LOG (0x3 << STEDMA40_INFO_CH_MODE_OPT_POS) | ||
47 | |||
48 | /* Interrupt */ | ||
49 | #define STEDMA40_INFO_TIM_POS 10 | ||
50 | #define STEDMA40_NO_TIM_FOR_LINK (0x0 << STEDMA40_INFO_TIM_POS) | ||
51 | #define STEDMA40_TIM_FOR_LINK (0x1 << STEDMA40_INFO_TIM_POS) | ||
52 | |||
53 | /* End of channel_type configuration */ | ||
54 | 42 | ||
55 | #define STEDMA40_ESIZE_8_BIT 0x0 | 43 | #define STEDMA40_ESIZE_8_BIT 0x0 |
56 | #define STEDMA40_ESIZE_16_BIT 0x1 | 44 | #define STEDMA40_ESIZE_16_BIT 0x1 |
@@ -73,16 +61,14 @@ | |||
73 | #define STEDMA40_PSIZE_LOG_8 STEDMA40_PSIZE_PHY_8 | 61 | #define STEDMA40_PSIZE_LOG_8 STEDMA40_PSIZE_PHY_8 |
74 | #define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16 | 62 | #define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16 |
75 | 63 | ||
64 | /* Maximum number of possible physical channels */ | ||
65 | #define STEDMA40_MAX_PHYS 32 | ||
66 | |||
76 | enum stedma40_flow_ctrl { | 67 | enum stedma40_flow_ctrl { |
77 | STEDMA40_NO_FLOW_CTRL, | 68 | STEDMA40_NO_FLOW_CTRL, |
78 | STEDMA40_FLOW_CTRL, | 69 | STEDMA40_FLOW_CTRL, |
79 | }; | 70 | }; |
80 | 71 | ||
81 | enum stedma40_endianess { | ||
82 | STEDMA40_LITTLE_ENDIAN, | ||
83 | STEDMA40_BIG_ENDIAN | ||
84 | }; | ||
85 | |||
86 | enum stedma40_periph_data_width { | 72 | enum stedma40_periph_data_width { |
87 | STEDMA40_BYTE_WIDTH = STEDMA40_ESIZE_8_BIT, | 73 | STEDMA40_BYTE_WIDTH = STEDMA40_ESIZE_8_BIT, |
88 | STEDMA40_HALFWORD_WIDTH = STEDMA40_ESIZE_16_BIT, | 74 | STEDMA40_HALFWORD_WIDTH = STEDMA40_ESIZE_16_BIT, |
@@ -90,15 +76,8 @@ enum stedma40_periph_data_width { | |||
90 | STEDMA40_DOUBLEWORD_WIDTH = STEDMA40_ESIZE_64_BIT | 76 | STEDMA40_DOUBLEWORD_WIDTH = STEDMA40_ESIZE_64_BIT |
91 | }; | 77 | }; |
92 | 78 | ||
93 | struct stedma40_half_channel_info { | ||
94 | enum stedma40_endianess endianess; | ||
95 | enum stedma40_periph_data_width data_width; | ||
96 | int psize; | ||
97 | enum stedma40_flow_ctrl flow_ctrl; | ||
98 | }; | ||
99 | |||
100 | enum stedma40_xfer_dir { | 79 | enum stedma40_xfer_dir { |
101 | STEDMA40_MEM_TO_MEM, | 80 | STEDMA40_MEM_TO_MEM = 1, |
102 | STEDMA40_MEM_TO_PERIPH, | 81 | STEDMA40_MEM_TO_PERIPH, |
103 | STEDMA40_PERIPH_TO_MEM, | 82 | STEDMA40_PERIPH_TO_MEM, |
104 | STEDMA40_PERIPH_TO_PERIPH | 83 | STEDMA40_PERIPH_TO_PERIPH |
@@ -106,18 +85,33 @@ enum stedma40_xfer_dir { | |||
106 | 85 | ||
107 | 86 | ||
108 | /** | 87 | /** |
88 | * struct stedma40_chan_cfg - dst/src channel configuration | ||
89 | * | ||
90 | * @big_endian: true if the src/dst should be read as big endian | ||
91 | * @data_width: Data width of the src/dst hardware | ||
92 | * @p_size: Burst size | ||
93 | * @flow_ctrl: Flow control on/off. | ||
94 | */ | ||
95 | struct stedma40_half_channel_info { | ||
96 | bool big_endian; | ||
97 | enum stedma40_periph_data_width data_width; | ||
98 | int psize; | ||
99 | enum stedma40_flow_ctrl flow_ctrl; | ||
100 | }; | ||
101 | |||
102 | /** | ||
109 | * struct stedma40_chan_cfg - Structure to be filled by client drivers. | 103 | * struct stedma40_chan_cfg - Structure to be filled by client drivers. |
110 | * | 104 | * |
111 | * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH | 105 | * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH |
112 | * @channel_type: priority, mode, mode options and interrupt configuration. | 106 | * @high_priority: true if high-priority |
107 | * @realtime: true if realtime mode is to be enabled. Only available on DMA40 | ||
108 | * version 3+, i.e DB8500v2+ | ||
109 | * @mode: channel mode: physical, logical, or operation | ||
110 | * @mode_opt: options for the chosen channel mode | ||
113 | * @src_dev_type: Src device type | 111 | * @src_dev_type: Src device type |
114 | * @dst_dev_type: Dst device type | 112 | * @dst_dev_type: Dst device type |
115 | * @src_info: Parameters for dst half channel | 113 | * @src_info: Parameters for dst half channel |
116 | * @dst_info: Parameters for dst half channel | 114 | * @dst_info: Parameters for dst half channel |
117 | * @pre_transfer_data: Data to be passed on to the pre_transfer() function. | ||
118 | * @pre_transfer: Callback used if needed before preparation of transfer. | ||
119 | * Only called if device is set. size of bytes to transfer | ||
120 | * (in case of multiple element transfer size is size of the first element). | ||
121 | * | 115 | * |
122 | * | 116 | * |
123 | * This structure has to be filled by the client drivers. | 117 | * This structure has to be filled by the client drivers. |
@@ -126,15 +120,14 @@ enum stedma40_xfer_dir { | |||
126 | */ | 120 | */ |
127 | struct stedma40_chan_cfg { | 121 | struct stedma40_chan_cfg { |
128 | enum stedma40_xfer_dir dir; | 122 | enum stedma40_xfer_dir dir; |
129 | unsigned int channel_type; | 123 | bool high_priority; |
124 | bool realtime; | ||
125 | enum stedma40_mode mode; | ||
126 | enum stedma40_mode_opt mode_opt; | ||
130 | int src_dev_type; | 127 | int src_dev_type; |
131 | int dst_dev_type; | 128 | int dst_dev_type; |
132 | struct stedma40_half_channel_info src_info; | 129 | struct stedma40_half_channel_info src_info; |
133 | struct stedma40_half_channel_info dst_info; | 130 | struct stedma40_half_channel_info dst_info; |
134 | void *pre_transfer_data; | ||
135 | int (*pre_transfer) (struct dma_chan *chan, | ||
136 | void *data, | ||
137 | int size); | ||
138 | }; | 131 | }; |
139 | 132 | ||
140 | /** | 133 | /** |
@@ -147,7 +140,6 @@ struct stedma40_chan_cfg { | |||
147 | * @memcpy_len: length of memcpy | 140 | * @memcpy_len: length of memcpy |
148 | * @memcpy_conf_phy: default configuration of physical channel memcpy | 141 | * @memcpy_conf_phy: default configuration of physical channel memcpy |
149 | * @memcpy_conf_log: default configuration of logical channel memcpy | 142 | * @memcpy_conf_log: default configuration of logical channel memcpy |
150 | * @llis_per_log: number of max linked list items per logical channel | ||
151 | * @disabled_channels: A vector, ending with -1, that marks physical channels | 143 | * @disabled_channels: A vector, ending with -1, that marks physical channels |
152 | * that are for different reasons not available for the driver. | 144 | * that are for different reasons not available for the driver. |
153 | */ | 145 | */ |
@@ -159,23 +151,10 @@ struct stedma40_platform_data { | |||
159 | u32 memcpy_len; | 151 | u32 memcpy_len; |
160 | struct stedma40_chan_cfg *memcpy_conf_phy; | 152 | struct stedma40_chan_cfg *memcpy_conf_phy; |
161 | struct stedma40_chan_cfg *memcpy_conf_log; | 153 | struct stedma40_chan_cfg *memcpy_conf_log; |
162 | unsigned int llis_per_log; | 154 | int disabled_channels[STEDMA40_MAX_PHYS]; |
163 | int disabled_channels[8]; | ||
164 | }; | 155 | }; |
165 | 156 | ||
166 | /** | 157 | #ifdef CONFIG_STE_DMA40 |
167 | * setdma40_set_psize() - Used for changing the package size of an | ||
168 | * already configured dma channel. | ||
169 | * | ||
170 | * @chan: dmaengine handle | ||
171 | * @src_psize: new package side for src. (STEDMA40_PSIZE*) | ||
172 | * @src_psize: new package side for dst. (STEDMA40_PSIZE*) | ||
173 | * | ||
174 | * returns 0 on ok, otherwise negative error number. | ||
175 | */ | ||
176 | int stedma40_set_psize(struct dma_chan *chan, | ||
177 | int src_psize, | ||
178 | int dst_psize); | ||
179 | 158 | ||
180 | /** | 159 | /** |
181 | * stedma40_filter() - Provides stedma40_chan_cfg to the | 160 | * stedma40_filter() - Provides stedma40_chan_cfg to the |
@@ -193,25 +172,6 @@ int stedma40_set_psize(struct dma_chan *chan, | |||
193 | bool stedma40_filter(struct dma_chan *chan, void *data); | 172 | bool stedma40_filter(struct dma_chan *chan, void *data); |
194 | 173 | ||
195 | /** | 174 | /** |
196 | * stedma40_memcpy_sg() - extension of the dma framework, memcpy to/from | ||
197 | * scattergatter lists. | ||
198 | * | ||
199 | * @chan: dmaengine handle | ||
200 | * @sgl_dst: Destination scatter list | ||
201 | * @sgl_src: Source scatter list | ||
202 | * @sgl_len: The length of each scatterlist. Both lists must be of equal length | ||
203 | * and each element must match the corresponding element in the other scatter | ||
204 | * list. | ||
205 | * @flags: is actually enum dma_ctrl_flags. See dmaengine.h | ||
206 | */ | ||
207 | |||
208 | struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, | ||
209 | struct scatterlist *sgl_dst, | ||
210 | struct scatterlist *sgl_src, | ||
211 | unsigned int sgl_len, | ||
212 | unsigned long flags); | ||
213 | |||
214 | /** | ||
215 | * stedma40_slave_mem() - Transfers a raw data buffer to or from a slave | 175 | * stedma40_slave_mem() - Transfers a raw data buffer to or from a slave |
216 | * (=device) | 176 | * (=device) |
217 | * | 177 | * |
@@ -238,4 +198,21 @@ dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, | |||
238 | direction, flags); | 198 | direction, flags); |
239 | } | 199 | } |
240 | 200 | ||
201 | #else | ||
202 | static inline bool stedma40_filter(struct dma_chan *chan, void *data) | ||
203 | { | ||
204 | return false; | ||
205 | } | ||
206 | |||
207 | static inline struct | ||
208 | dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, | ||
209 | dma_addr_t addr, | ||
210 | unsigned int size, | ||
211 | enum dma_data_direction direction, | ||
212 | unsigned long flags) | ||
213 | { | ||
214 | return NULL; | ||
215 | } | ||
216 | #endif | ||
217 | |||
241 | #endif | 218 | #endif |
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index aedf9c1d645e..ef74e157a9d5 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 STMicroelectronics | 4 | * Copyright (C) 2008 STMicroelectronics |
5 | * Copyright (C) 2010 Alessandro Rubini | 5 | * Copyright (C) 2010 Alessandro Rubini |
6 | * Copyright (C) 2010 Linus Walleij for ST-Ericsson | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2, as | 9 | * it under the terms of the GNU General Public License version 2, as |
@@ -16,48 +17,36 @@ | |||
16 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
17 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
18 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/sched.h> | ||
19 | #include <asm/mach/time.h> | 21 | #include <asm/mach/time.h> |
22 | #include <asm/sched_clock.h> | ||
20 | 23 | ||
21 | #include <plat/mtu.h> | 24 | #include <plat/mtu.h> |
22 | 25 | ||
23 | void __iomem *mtu_base; /* ssigned by machine code */ | 26 | void __iomem *mtu_base; /* Assigned by machine code */ |
24 | 27 | ||
25 | /* | 28 | /* |
26 | * Kernel assumes that sched_clock can be called early | 29 | * Override the global weak sched_clock symbol with this |
27 | * but the MTU may not yet be initialized. | 30 | * local implementation which uses the clocksource to get some |
31 | * better resolution when scheduling the kernel. | ||
28 | */ | 32 | */ |
29 | static cycle_t nmdk_read_timer_dummy(struct clocksource *cs) | 33 | static DEFINE_CLOCK_DATA(cd); |
30 | { | ||
31 | return 0; | ||
32 | } | ||
33 | 34 | ||
34 | /* clocksource: MTU decrements, so we negate the value being read. */ | 35 | unsigned long long notrace sched_clock(void) |
35 | static cycle_t nmdk_read_timer(struct clocksource *cs) | ||
36 | { | 36 | { |
37 | return -readl(mtu_base + MTU_VAL(0)); | 37 | u32 cyc; |
38 | } | ||
39 | 38 | ||
40 | static struct clocksource nmdk_clksrc = { | 39 | if (unlikely(!mtu_base)) |
41 | .name = "mtu_0", | 40 | return 0; |
42 | .rating = 200, | ||
43 | .read = nmdk_read_timer_dummy, | ||
44 | .mask = CLOCKSOURCE_MASK(32), | ||
45 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
46 | }; | ||
47 | 41 | ||
48 | /* | 42 | cyc = -readl(mtu_base + MTU_VAL(0)); |
49 | * Override the global weak sched_clock symbol with this | 43 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); |
50 | * local implementation which uses the clocksource to get some | 44 | } |
51 | * better resolution when scheduling the kernel. We accept that | 45 | |
52 | * this wraps around for now, since it is just a relative time | 46 | static void notrace nomadik_update_sched_clock(void) |
53 | * stamp. (Inspired by OMAP implementation.) | ||
54 | */ | ||
55 | unsigned long long notrace sched_clock(void) | ||
56 | { | 47 | { |
57 | return clocksource_cyc2ns(nmdk_clksrc.read( | 48 | u32 cyc = -readl(mtu_base + MTU_VAL(0)); |
58 | &nmdk_clksrc), | 49 | update_sched_clock(&cd, cyc, (u32)~0); |
59 | nmdk_clksrc.mult, | ||
60 | nmdk_clksrc.shift); | ||
61 | } | 50 | } |
62 | 51 | ||
63 | /* Clockevent device: use one-shot mode */ | 52 | /* Clockevent device: use one-shot mode */ |
@@ -153,7 +142,6 @@ void __init nmdk_timer_init(void) | |||
153 | } else { | 142 | } else { |
154 | cr |= MTU_CRn_PRESCALE_1; | 143 | cr |= MTU_CRn_PRESCALE_1; |
155 | } | 144 | } |
156 | clocksource_calc_mult_shift(&nmdk_clksrc, rate, MTU_MIN_RANGE); | ||
157 | 145 | ||
158 | /* Timer 0 is the free running clocksource */ | 146 | /* Timer 0 is the free running clocksource */ |
159 | writel(cr, mtu_base + MTU_CR(0)); | 147 | writel(cr, mtu_base + MTU_CR(0)); |
@@ -161,12 +149,12 @@ void __init nmdk_timer_init(void) | |||
161 | writel(0, mtu_base + MTU_BGLR(0)); | 149 | writel(0, mtu_base + MTU_BGLR(0)); |
162 | writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); | 150 | writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); |
163 | 151 | ||
164 | /* Now the scheduling clock is ready */ | 152 | if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", |
165 | nmdk_clksrc.read = nmdk_read_timer; | 153 | rate, 200, 32, clocksource_mmio_readl_down)) |
166 | |||
167 | if (clocksource_register(&nmdk_clksrc)) | ||
168 | pr_err("timer: failed to initialize clock source %s\n", | 154 | pr_err("timer: failed to initialize clock source %s\n", |
169 | nmdk_clksrc.name); | 155 | "mtu_0"); |
156 | |||
157 | init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate); | ||
170 | 158 | ||
171 | /* Timer 1 is used for events */ | 159 | /* Timer 1 is used for events */ |
172 | 160 | ||