diff options
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/Kconfig | 4 | ||||
-rw-r--r-- | arch/arm/plat-omap/Makefile | 6 | ||||
-rw-r--r-- | arch/arm/plat-omap/clock.c | 67 | ||||
-rw-r--r-- | arch/arm/plat-omap/devices.c | 143 | ||||
-rw-r--r-- | arch/arm/plat-omap/dma.c | 6 | ||||
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 26 | ||||
-rw-r--r-- | arch/arm/plat-omap/fb.c | 80 | ||||
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 86 | ||||
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 345 | ||||
-rw-r--r-- | arch/arm/plat-omap/ocpi.c | 3 | ||||
-rw-r--r-- | arch/arm/plat-omap/pm.c | 1 | ||||
-rw-r--r-- | arch/arm/plat-omap/sleep.S | 452 | ||||
-rw-r--r-- | arch/arm/plat-omap/sram.c | 143 | ||||
-rw-r--r-- | arch/arm/plat-omap/timer32k.c | 325 |
14 files changed, 1104 insertions, 583 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 0887bb2a2551..ec49495e651e 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
@@ -70,13 +70,13 @@ config OMAP_MPU_TIMER | |||
70 | 70 | ||
71 | config OMAP_32K_TIMER | 71 | config OMAP_32K_TIMER |
72 | bool "Use 32KHz timer" | 72 | bool "Use 32KHz timer" |
73 | depends on ARCH_OMAP16XX | 73 | depends on ARCH_OMAP16XX || ARCH_OMAP24XX |
74 | help | 74 | help |
75 | Select this option if you want to enable the OMAP 32KHz timer. | 75 | Select this option if you want to enable the OMAP 32KHz timer. |
76 | This timer saves power compared to the OMAP_MPU_TIMER, and has | 76 | This timer saves power compared to the OMAP_MPU_TIMER, and has |
77 | support for no tick during idle. The 32KHz timer provides less | 77 | support for no tick during idle. The 32KHz timer provides less |
78 | intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is | 78 | intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is |
79 | currently only available for OMAP-16xx. | 79 | currently only available for OMAP16XX and 24XX. |
80 | 80 | ||
81 | endchoice | 81 | endchoice |
82 | 82 | ||
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 9ccf1943fc94..2896b4546411 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile | |||
@@ -3,16 +3,16 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Common support | 5 | # Common support |
6 | obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o | 6 | obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o |
7 | obj-m := | 7 | obj-m := |
8 | obj-n := | 8 | obj-n := |
9 | obj- := | 9 | obj- := |
10 | 10 | ||
11 | obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o | ||
12 | |||
11 | # OCPI interconnect support for 1710, 1610 and 5912 | 13 | # OCPI interconnect support for 1710, 1610 and 5912 |
12 | obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o | 14 | obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o |
13 | 15 | ||
14 | # Power Management | ||
15 | obj-$(CONFIG_PM) += pm.o sleep.o | ||
16 | 16 | ||
17 | obj-$(CONFIG_CPU_FREQ) += cpu-omap.o | 17 | obj-$(CONFIG_CPU_FREQ) += cpu-omap.o |
18 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o | 18 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o |
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 3c2bfc0efdaf..06485c193ee3 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/platform_device.h> | ||
24 | 25 | ||
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
26 | #include <asm/semaphore.h> | 27 | #include <asm/semaphore.h> |
@@ -37,17 +38,37 @@ static struct clk_functions *arch_clock; | |||
37 | * Standard clock functions defined in include/linux/clk.h | 38 | * Standard clock functions defined in include/linux/clk.h |
38 | *-------------------------------------------------------------------------*/ | 39 | *-------------------------------------------------------------------------*/ |
39 | 40 | ||
41 | /* | ||
42 | * Returns a clock. Note that we first try to use device id on the bus | ||
43 | * and clock name. If this fails, we try to use clock name only. | ||
44 | */ | ||
40 | struct clk * clk_get(struct device *dev, const char *id) | 45 | struct clk * clk_get(struct device *dev, const char *id) |
41 | { | 46 | { |
42 | struct clk *p, *clk = ERR_PTR(-ENOENT); | 47 | struct clk *p, *clk = ERR_PTR(-ENOENT); |
48 | int idno; | ||
49 | |||
50 | if (dev == NULL || dev->bus != &platform_bus_type) | ||
51 | idno = -1; | ||
52 | else | ||
53 | idno = to_platform_device(dev)->id; | ||
43 | 54 | ||
44 | mutex_lock(&clocks_mutex); | 55 | mutex_lock(&clocks_mutex); |
56 | |||
57 | list_for_each_entry(p, &clocks, node) { | ||
58 | if (p->id == idno && | ||
59 | strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | ||
60 | clk = p; | ||
61 | break; | ||
62 | } | ||
63 | } | ||
64 | |||
45 | list_for_each_entry(p, &clocks, node) { | 65 | list_for_each_entry(p, &clocks, node) { |
46 | if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | 66 | if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { |
47 | clk = p; | 67 | clk = p; |
48 | break; | 68 | break; |
49 | } | 69 | } |
50 | } | 70 | } |
71 | |||
51 | mutex_unlock(&clocks_mutex); | 72 | mutex_unlock(&clocks_mutex); |
52 | 73 | ||
53 | return clk; | 74 | return clk; |
@@ -59,6 +80,9 @@ int clk_enable(struct clk *clk) | |||
59 | unsigned long flags; | 80 | unsigned long flags; |
60 | int ret = 0; | 81 | int ret = 0; |
61 | 82 | ||
83 | if (clk == NULL || IS_ERR(clk)) | ||
84 | return -EINVAL; | ||
85 | |||
62 | spin_lock_irqsave(&clockfw_lock, flags); | 86 | spin_lock_irqsave(&clockfw_lock, flags); |
63 | if (arch_clock->clk_enable) | 87 | if (arch_clock->clk_enable) |
64 | ret = arch_clock->clk_enable(clk); | 88 | ret = arch_clock->clk_enable(clk); |
@@ -72,6 +96,9 @@ void clk_disable(struct clk *clk) | |||
72 | { | 96 | { |
73 | unsigned long flags; | 97 | unsigned long flags; |
74 | 98 | ||
99 | if (clk == NULL || IS_ERR(clk)) | ||
100 | return; | ||
101 | |||
75 | spin_lock_irqsave(&clockfw_lock, flags); | 102 | spin_lock_irqsave(&clockfw_lock, flags); |
76 | if (arch_clock->clk_disable) | 103 | if (arch_clock->clk_disable) |
77 | arch_clock->clk_disable(clk); | 104 | arch_clock->clk_disable(clk); |
@@ -84,6 +111,9 @@ int clk_get_usecount(struct clk *clk) | |||
84 | unsigned long flags; | 111 | unsigned long flags; |
85 | int ret = 0; | 112 | int ret = 0; |
86 | 113 | ||
114 | if (clk == NULL || IS_ERR(clk)) | ||
115 | return 0; | ||
116 | |||
87 | spin_lock_irqsave(&clockfw_lock, flags); | 117 | spin_lock_irqsave(&clockfw_lock, flags); |
88 | ret = clk->usecount; | 118 | ret = clk->usecount; |
89 | spin_unlock_irqrestore(&clockfw_lock, flags); | 119 | spin_unlock_irqrestore(&clockfw_lock, flags); |
@@ -97,6 +127,9 @@ unsigned long clk_get_rate(struct clk *clk) | |||
97 | unsigned long flags; | 127 | unsigned long flags; |
98 | unsigned long ret = 0; | 128 | unsigned long ret = 0; |
99 | 129 | ||
130 | if (clk == NULL || IS_ERR(clk)) | ||
131 | return 0; | ||
132 | |||
100 | spin_lock_irqsave(&clockfw_lock, flags); | 133 | spin_lock_irqsave(&clockfw_lock, flags); |
101 | ret = clk->rate; | 134 | ret = clk->rate; |
102 | spin_unlock_irqrestore(&clockfw_lock, flags); | 135 | spin_unlock_irqrestore(&clockfw_lock, flags); |
@@ -121,6 +154,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
121 | unsigned long flags; | 154 | unsigned long flags; |
122 | long ret = 0; | 155 | long ret = 0; |
123 | 156 | ||
157 | if (clk == NULL || IS_ERR(clk)) | ||
158 | return ret; | ||
159 | |||
124 | spin_lock_irqsave(&clockfw_lock, flags); | 160 | spin_lock_irqsave(&clockfw_lock, flags); |
125 | if (arch_clock->clk_round_rate) | 161 | if (arch_clock->clk_round_rate) |
126 | ret = arch_clock->clk_round_rate(clk, rate); | 162 | ret = arch_clock->clk_round_rate(clk, rate); |
@@ -133,7 +169,10 @@ EXPORT_SYMBOL(clk_round_rate); | |||
133 | int clk_set_rate(struct clk *clk, unsigned long rate) | 169 | int clk_set_rate(struct clk *clk, unsigned long rate) |
134 | { | 170 | { |
135 | unsigned long flags; | 171 | unsigned long flags; |
136 | int ret = 0; | 172 | int ret = -EINVAL; |
173 | |||
174 | if (clk == NULL || IS_ERR(clk)) | ||
175 | return ret; | ||
137 | 176 | ||
138 | spin_lock_irqsave(&clockfw_lock, flags); | 177 | spin_lock_irqsave(&clockfw_lock, flags); |
139 | if (arch_clock->clk_set_rate) | 178 | if (arch_clock->clk_set_rate) |
@@ -147,7 +186,10 @@ EXPORT_SYMBOL(clk_set_rate); | |||
147 | int clk_set_parent(struct clk *clk, struct clk *parent) | 186 | int clk_set_parent(struct clk *clk, struct clk *parent) |
148 | { | 187 | { |
149 | unsigned long flags; | 188 | unsigned long flags; |
150 | int ret = 0; | 189 | int ret = -EINVAL; |
190 | |||
191 | if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent)) | ||
192 | return ret; | ||
151 | 193 | ||
152 | spin_lock_irqsave(&clockfw_lock, flags); | 194 | spin_lock_irqsave(&clockfw_lock, flags); |
153 | if (arch_clock->clk_set_parent) | 195 | if (arch_clock->clk_set_parent) |
@@ -163,6 +205,9 @@ struct clk *clk_get_parent(struct clk *clk) | |||
163 | unsigned long flags; | 205 | unsigned long flags; |
164 | struct clk * ret = NULL; | 206 | struct clk * ret = NULL; |
165 | 207 | ||
208 | if (clk == NULL || IS_ERR(clk)) | ||
209 | return ret; | ||
210 | |||
166 | spin_lock_irqsave(&clockfw_lock, flags); | 211 | spin_lock_irqsave(&clockfw_lock, flags); |
167 | if (arch_clock->clk_get_parent) | 212 | if (arch_clock->clk_get_parent) |
168 | ret = arch_clock->clk_get_parent(clk); | 213 | ret = arch_clock->clk_get_parent(clk); |
@@ -199,6 +244,9 @@ __setup("mpurate=", omap_clk_setup); | |||
199 | /* Used for clocks that always have same value as the parent clock */ | 244 | /* Used for clocks that always have same value as the parent clock */ |
200 | void followparent_recalc(struct clk *clk) | 245 | void followparent_recalc(struct clk *clk) |
201 | { | 246 | { |
247 | if (clk == NULL || IS_ERR(clk)) | ||
248 | return; | ||
249 | |||
202 | clk->rate = clk->parent->rate; | 250 | clk->rate = clk->parent->rate; |
203 | } | 251 | } |
204 | 252 | ||
@@ -207,6 +255,9 @@ void propagate_rate(struct clk * tclk) | |||
207 | { | 255 | { |
208 | struct clk *clkp; | 256 | struct clk *clkp; |
209 | 257 | ||
258 | if (tclk == NULL || IS_ERR(tclk)) | ||
259 | return; | ||
260 | |||
210 | list_for_each_entry(clkp, &clocks, node) { | 261 | list_for_each_entry(clkp, &clocks, node) { |
211 | if (likely(clkp->parent != tclk)) | 262 | if (likely(clkp->parent != tclk)) |
212 | continue; | 263 | continue; |
@@ -217,6 +268,9 @@ void propagate_rate(struct clk * tclk) | |||
217 | 268 | ||
218 | int clk_register(struct clk *clk) | 269 | int clk_register(struct clk *clk) |
219 | { | 270 | { |
271 | if (clk == NULL || IS_ERR(clk)) | ||
272 | return -EINVAL; | ||
273 | |||
220 | mutex_lock(&clocks_mutex); | 274 | mutex_lock(&clocks_mutex); |
221 | list_add(&clk->node, &clocks); | 275 | list_add(&clk->node, &clocks); |
222 | if (clk->init) | 276 | if (clk->init) |
@@ -229,6 +283,9 @@ EXPORT_SYMBOL(clk_register); | |||
229 | 283 | ||
230 | void clk_unregister(struct clk *clk) | 284 | void clk_unregister(struct clk *clk) |
231 | { | 285 | { |
286 | if (clk == NULL || IS_ERR(clk)) | ||
287 | return; | ||
288 | |||
232 | mutex_lock(&clocks_mutex); | 289 | mutex_lock(&clocks_mutex); |
233 | list_del(&clk->node); | 290 | list_del(&clk->node); |
234 | mutex_unlock(&clocks_mutex); | 291 | mutex_unlock(&clocks_mutex); |
@@ -239,6 +296,9 @@ void clk_deny_idle(struct clk *clk) | |||
239 | { | 296 | { |
240 | unsigned long flags; | 297 | unsigned long flags; |
241 | 298 | ||
299 | if (clk == NULL || IS_ERR(clk)) | ||
300 | return; | ||
301 | |||
242 | spin_lock_irqsave(&clockfw_lock, flags); | 302 | spin_lock_irqsave(&clockfw_lock, flags); |
243 | if (arch_clock->clk_deny_idle) | 303 | if (arch_clock->clk_deny_idle) |
244 | arch_clock->clk_deny_idle(clk); | 304 | arch_clock->clk_deny_idle(clk); |
@@ -250,6 +310,9 @@ void clk_allow_idle(struct clk *clk) | |||
250 | { | 310 | { |
251 | unsigned long flags; | 311 | unsigned long flags; |
252 | 312 | ||
313 | if (clk == NULL || IS_ERR(clk)) | ||
314 | return; | ||
315 | |||
253 | spin_lock_irqsave(&clockfw_lock, flags); | 316 | spin_lock_irqsave(&clockfw_lock, flags); |
254 | if (arch_clock->clk_allow_idle) | 317 | if (arch_clock->clk_allow_idle) |
255 | arch_clock->clk_allow_idle(clk); | 318 | arch_clock->clk_allow_idle(clk); |
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 9dcce904b608..079b67deac0f 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/arch/board.h> | 24 | #include <asm/arch/board.h> |
25 | #include <asm/arch/mux.h> | 25 | #include <asm/arch/mux.h> |
26 | #include <asm/arch/gpio.h> | 26 | #include <asm/arch/gpio.h> |
27 | #include <asm/arch/menelaus.h> | ||
27 | 28 | ||
28 | 29 | ||
29 | void omap_nop_release(struct device *dev) | 30 | void omap_nop_release(struct device *dev) |
@@ -98,6 +99,62 @@ static inline void omap_init_i2c(void) {} | |||
98 | #endif | 99 | #endif |
99 | 100 | ||
100 | /*-------------------------------------------------------------------------*/ | 101 | /*-------------------------------------------------------------------------*/ |
102 | #if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE) | ||
103 | |||
104 | static void omap_init_kp(void) | ||
105 | { | ||
106 | if (machine_is_omap_h2() || machine_is_omap_h3()) { | ||
107 | omap_cfg_reg(F18_1610_KBC0); | ||
108 | omap_cfg_reg(D20_1610_KBC1); | ||
109 | omap_cfg_reg(D19_1610_KBC2); | ||
110 | omap_cfg_reg(E18_1610_KBC3); | ||
111 | omap_cfg_reg(C21_1610_KBC4); | ||
112 | |||
113 | omap_cfg_reg(G18_1610_KBR0); | ||
114 | omap_cfg_reg(F19_1610_KBR1); | ||
115 | omap_cfg_reg(H14_1610_KBR2); | ||
116 | omap_cfg_reg(E20_1610_KBR3); | ||
117 | omap_cfg_reg(E19_1610_KBR4); | ||
118 | omap_cfg_reg(N19_1610_KBR5); | ||
119 | } else if (machine_is_omap_perseus2()) { | ||
120 | omap_cfg_reg(E2_730_KBR0); | ||
121 | omap_cfg_reg(J7_730_KBR1); | ||
122 | omap_cfg_reg(E1_730_KBR2); | ||
123 | omap_cfg_reg(F3_730_KBR3); | ||
124 | omap_cfg_reg(D2_730_KBR4); | ||
125 | |||
126 | omap_cfg_reg(C2_730_KBC0); | ||
127 | omap_cfg_reg(D3_730_KBC1); | ||
128 | omap_cfg_reg(E4_730_KBC2); | ||
129 | omap_cfg_reg(F4_730_KBC3); | ||
130 | omap_cfg_reg(E3_730_KBC4); | ||
131 | } else if (machine_is_omap_h4()) { | ||
132 | omap_cfg_reg(T19_24XX_KBR0); | ||
133 | omap_cfg_reg(R19_24XX_KBR1); | ||
134 | omap_cfg_reg(V18_24XX_KBR2); | ||
135 | omap_cfg_reg(M21_24XX_KBR3); | ||
136 | omap_cfg_reg(E5__24XX_KBR4); | ||
137 | if (omap_has_menelaus()) { | ||
138 | omap_cfg_reg(B3__24XX_KBR5); | ||
139 | omap_cfg_reg(AA4_24XX_KBC2); | ||
140 | omap_cfg_reg(B13_24XX_KBC6); | ||
141 | } else { | ||
142 | omap_cfg_reg(M18_24XX_KBR5); | ||
143 | omap_cfg_reg(H19_24XX_KBC2); | ||
144 | omap_cfg_reg(N19_24XX_KBC6); | ||
145 | } | ||
146 | omap_cfg_reg(R20_24XX_KBC0); | ||
147 | omap_cfg_reg(M14_24XX_KBC1); | ||
148 | omap_cfg_reg(V17_24XX_KBC3); | ||
149 | omap_cfg_reg(P21_24XX_KBC4); | ||
150 | omap_cfg_reg(L14_24XX_KBC5); | ||
151 | } | ||
152 | } | ||
153 | #else | ||
154 | static inline void omap_init_kp(void) {} | ||
155 | #endif | ||
156 | |||
157 | /*-------------------------------------------------------------------------*/ | ||
101 | 158 | ||
102 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) | 159 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) |
103 | 160 | ||
@@ -240,6 +297,55 @@ static void __init omap_init_mmc(void) | |||
240 | static inline void omap_init_mmc(void) {} | 297 | static inline void omap_init_mmc(void) {} |
241 | #endif | 298 | #endif |
242 | 299 | ||
300 | /*-------------------------------------------------------------------------*/ | ||
301 | |||
302 | /* Numbering for the SPI-capable controllers when used for SPI: | ||
303 | * spi = 1 | ||
304 | * uwire = 2 | ||
305 | * mmc1..2 = 3..4 | ||
306 | * mcbsp1..3 = 5..7 | ||
307 | */ | ||
308 | |||
309 | #if defined(CONFIG_SPI_OMAP_UWIRE) || defined(CONFIG_SPI_OMAP_UWIRE_MODULE) | ||
310 | |||
311 | #define OMAP_UWIRE_BASE 0xfffb3000 | ||
312 | |||
313 | static struct resource uwire_resources[] = { | ||
314 | { | ||
315 | .start = OMAP_UWIRE_BASE, | ||
316 | .end = OMAP_UWIRE_BASE + 0x20, | ||
317 | .flags = IORESOURCE_MEM, | ||
318 | }, | ||
319 | }; | ||
320 | |||
321 | static struct platform_device omap_uwire_device = { | ||
322 | .name = "omap_uwire", | ||
323 | .id = -1, | ||
324 | .dev = { | ||
325 | .release = omap_nop_release, | ||
326 | }, | ||
327 | .num_resources = ARRAY_SIZE(uwire_resources), | ||
328 | .resource = uwire_resources, | ||
329 | }; | ||
330 | |||
331 | static void omap_init_uwire(void) | ||
332 | { | ||
333 | /* FIXME define and use a boot tag; not all boards will be hooking | ||
334 | * up devices to the microwire controller, and multi-board configs | ||
335 | * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway... | ||
336 | */ | ||
337 | |||
338 | /* board-specific code must configure chipselects (only a few | ||
339 | * are normally used) and SCLK/SDI/SDO (each has two choices). | ||
340 | */ | ||
341 | (void) platform_device_register(&omap_uwire_device); | ||
342 | } | ||
343 | #else | ||
344 | static inline void omap_init_uwire(void) {} | ||
345 | #endif | ||
346 | |||
347 | /*-------------------------------------------------------------------------*/ | ||
348 | |||
243 | #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) | 349 | #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) |
244 | 350 | ||
245 | #ifdef CONFIG_ARCH_OMAP24XX | 351 | #ifdef CONFIG_ARCH_OMAP24XX |
@@ -310,40 +416,6 @@ static void omap_init_rng(void) | |||
310 | static inline void omap_init_rng(void) {} | 416 | static inline void omap_init_rng(void) {} |
311 | #endif | 417 | #endif |
312 | 418 | ||
313 | #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) | ||
314 | |||
315 | static struct omap_lcd_config omap_fb_conf; | ||
316 | |||
317 | static u64 omap_fb_dma_mask = ~(u32)0; | ||
318 | |||
319 | static struct platform_device omap_fb_device = { | ||
320 | .name = "omapfb", | ||
321 | .id = -1, | ||
322 | .dev = { | ||
323 | .release = omap_nop_release, | ||
324 | .dma_mask = &omap_fb_dma_mask, | ||
325 | .coherent_dma_mask = ~(u32)0, | ||
326 | .platform_data = &omap_fb_conf, | ||
327 | }, | ||
328 | .num_resources = 0, | ||
329 | }; | ||
330 | |||
331 | static inline void omap_init_fb(void) | ||
332 | { | ||
333 | const struct omap_lcd_config *conf; | ||
334 | |||
335 | conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); | ||
336 | if (conf != NULL) | ||
337 | omap_fb_conf = *conf; | ||
338 | platform_device_register(&omap_fb_device); | ||
339 | } | ||
340 | |||
341 | #else | ||
342 | |||
343 | static inline void omap_init_fb(void) {} | ||
344 | |||
345 | #endif | ||
346 | |||
347 | /* | 419 | /* |
348 | * This gets called after board-specific INIT_MACHINE, and initializes most | 420 | * This gets called after board-specific INIT_MACHINE, and initializes most |
349 | * on-chip peripherals accessible on this board (except for few like USB): | 421 | * on-chip peripherals accessible on this board (except for few like USB): |
@@ -369,9 +441,10 @@ static int __init omap_init_devices(void) | |||
369 | /* please keep these calls, and their implementations above, | 441 | /* please keep these calls, and their implementations above, |
370 | * in alphabetical order so they're easier to sort through. | 442 | * in alphabetical order so they're easier to sort through. |
371 | */ | 443 | */ |
372 | omap_init_fb(); | ||
373 | omap_init_i2c(); | 444 | omap_init_i2c(); |
445 | omap_init_kp(); | ||
374 | omap_init_mmc(); | 446 | omap_init_mmc(); |
447 | omap_init_uwire(); | ||
375 | omap_init_wdt(); | 448 | omap_init_wdt(); |
376 | omap_init_rng(); | 449 | omap_init_rng(); |
377 | 450 | ||
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index a4e5ac77f6df..5dac4230360d 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c | |||
@@ -1258,6 +1258,11 @@ void omap_stop_lcd_dma(void) | |||
1258 | omap_writew(w, OMAP1610_DMA_LCD_CTRL); | 1258 | omap_writew(w, OMAP1610_DMA_LCD_CTRL); |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | int omap_lcd_dma_ext_running(void) | ||
1262 | { | ||
1263 | return lcd_dma.ext_ctrl && lcd_dma.active; | ||
1264 | } | ||
1265 | |||
1261 | /*----------------------------------------------------------------------------*/ | 1266 | /*----------------------------------------------------------------------------*/ |
1262 | 1267 | ||
1263 | static int __init omap_init_dma(void) | 1268 | static int __init omap_init_dma(void) |
@@ -1389,6 +1394,7 @@ EXPORT_SYMBOL(omap_free_lcd_dma); | |||
1389 | EXPORT_SYMBOL(omap_enable_lcd_dma); | 1394 | EXPORT_SYMBOL(omap_enable_lcd_dma); |
1390 | EXPORT_SYMBOL(omap_setup_lcd_dma); | 1395 | EXPORT_SYMBOL(omap_setup_lcd_dma); |
1391 | EXPORT_SYMBOL(omap_stop_lcd_dma); | 1396 | EXPORT_SYMBOL(omap_stop_lcd_dma); |
1397 | EXPORT_SYMBOL(omap_lcd_dma_ext_running); | ||
1392 | EXPORT_SYMBOL(omap_set_lcd_dma_b1); | 1398 | EXPORT_SYMBOL(omap_set_lcd_dma_b1); |
1393 | EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); | 1399 | EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); |
1394 | EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); | 1400 | EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); |
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 38d7ebf87920..eba3cb52ad87 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -97,6 +97,32 @@ int omap_dm_timers_active(void) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | 99 | ||
100 | /** | ||
101 | * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR | ||
102 | * @inputmask: current value of idlect mask | ||
103 | */ | ||
104 | __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) | ||
105 | { | ||
106 | int n; | ||
107 | |||
108 | /* If ARMXOR cannot be idled this function call is unnecessary */ | ||
109 | if (!(inputmask & (1 << 1))) | ||
110 | return inputmask; | ||
111 | |||
112 | /* If any active timer is using ARMXOR return modified mask */ | ||
113 | for (n = 0; dm_timers[n].base; ++n) | ||
114 | if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)& | ||
115 | OMAP_TIMER_CTRL_ST) { | ||
116 | if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0) | ||
117 | inputmask &= ~(1 << 1); | ||
118 | else | ||
119 | inputmask &= ~(1 << 2); | ||
120 | } | ||
121 | |||
122 | return inputmask; | ||
123 | } | ||
124 | |||
125 | |||
100 | void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | 126 | void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) |
101 | { | 127 | { |
102 | int n = (timer - dm_timers) << 1; | 128 | int n = (timer - dm_timers) << 1; |
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c new file mode 100644 index 000000000000..305e9b990b71 --- /dev/null +++ b/arch/arm/plat-omap/fb.c | |||
@@ -0,0 +1,80 @@ | |||
1 | #include <linux/config.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/platform_device.h> | ||
6 | #include <linux/bootmem.h> | ||
7 | |||
8 | #include <asm/hardware.h> | ||
9 | #include <asm/io.h> | ||
10 | #include <asm/mach-types.h> | ||
11 | #include <asm/mach/map.h> | ||
12 | |||
13 | #include <asm/arch/board.h> | ||
14 | #include <asm/arch/sram.h> | ||
15 | #include <asm/arch/omapfb.h> | ||
16 | |||
17 | #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) | ||
18 | |||
19 | static struct omapfb_platform_data omapfb_config; | ||
20 | |||
21 | static u64 omap_fb_dma_mask = ~(u32)0; | ||
22 | |||
23 | static struct platform_device omap_fb_device = { | ||
24 | .name = "omapfb", | ||
25 | .id = -1, | ||
26 | .dev = { | ||
27 | .dma_mask = &omap_fb_dma_mask, | ||
28 | .coherent_dma_mask = ~(u32)0, | ||
29 | .platform_data = &omapfb_config, | ||
30 | }, | ||
31 | .num_resources = 0, | ||
32 | }; | ||
33 | |||
34 | /* called from map_io */ | ||
35 | void omapfb_reserve_mem(void) | ||
36 | { | ||
37 | const struct omap_fbmem_config *fbmem_conf; | ||
38 | |||
39 | omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start; | ||
40 | omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size; | ||
41 | |||
42 | fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); | ||
43 | |||
44 | if (fbmem_conf != NULL) { | ||
45 | /* indicate that the bootloader already initialized the | ||
46 | * fb device, so we'll skip that part in the fb driver | ||
47 | */ | ||
48 | omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start; | ||
49 | omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size; | ||
50 | if (fbmem_conf->fb_sdram_size) { | ||
51 | pr_info("Reserving %u bytes SDRAM for frame buffer\n", | ||
52 | fbmem_conf->fb_sdram_size); | ||
53 | reserve_bootmem(fbmem_conf->fb_sdram_start, | ||
54 | fbmem_conf->fb_sdram_size); | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | |||
59 | static inline int omap_init_fb(void) | ||
60 | { | ||
61 | const struct omap_lcd_config *conf; | ||
62 | |||
63 | conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); | ||
64 | if (conf == NULL) | ||
65 | return 0; | ||
66 | |||
67 | omapfb_config.lcd = *conf; | ||
68 | |||
69 | return platform_device_register(&omap_fb_device); | ||
70 | } | ||
71 | |||
72 | arch_initcall(omap_init_fb); | ||
73 | |||
74 | #else | ||
75 | |||
76 | void omapfb_reserve_mem(void) {} | ||
77 | |||
78 | #endif | ||
79 | |||
80 | |||
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index b4d5b9e4bfce..d3c8ea7eecfd 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -174,7 +174,7 @@ static int gpio_bank_count; | |||
174 | static inline struct gpio_bank *get_gpio_bank(int gpio) | 174 | static inline struct gpio_bank *get_gpio_bank(int gpio) |
175 | { | 175 | { |
176 | #ifdef CONFIG_ARCH_OMAP15XX | 176 | #ifdef CONFIG_ARCH_OMAP15XX |
177 | if (cpu_is_omap1510()) { | 177 | if (cpu_is_omap15xx()) { |
178 | if (OMAP_GPIO_IS_MPUIO(gpio)) | 178 | if (OMAP_GPIO_IS_MPUIO(gpio)) |
179 | return &gpio_bank[0]; | 179 | return &gpio_bank[0]; |
180 | return &gpio_bank[1]; | 180 | return &gpio_bank[1]; |
@@ -223,7 +223,7 @@ static inline int gpio_valid(int gpio) | |||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | #ifdef CONFIG_ARCH_OMAP15XX | 225 | #ifdef CONFIG_ARCH_OMAP15XX |
226 | if (cpu_is_omap1510() && gpio < 16) | 226 | if (cpu_is_omap15xx() && gpio < 16) |
227 | return 0; | 227 | return 0; |
228 | #endif | 228 | #endif |
229 | #if defined(CONFIG_ARCH_OMAP16XX) | 229 | #if defined(CONFIG_ARCH_OMAP16XX) |
@@ -402,13 +402,13 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr | |||
402 | u32 gpio_bit = 1 << gpio; | 402 | u32 gpio_bit = 1 << gpio; |
403 | 403 | ||
404 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, | 404 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, |
405 | trigger & IRQT_LOW); | 405 | trigger & __IRQT_LOWLVL); |
406 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, | 406 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, |
407 | trigger & IRQT_HIGH); | 407 | trigger & __IRQT_HIGHLVL); |
408 | MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit, | 408 | MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit, |
409 | trigger & IRQT_RISING); | 409 | trigger & __IRQT_RISEDGE); |
410 | MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, | 410 | MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, |
411 | trigger & IRQT_FALLING); | 411 | trigger & __IRQT_FALEDGE); |
412 | /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level | 412 | /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level |
413 | * triggering requested. */ | 413 | * triggering requested. */ |
414 | } | 414 | } |
@@ -422,9 +422,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
422 | case METHOD_MPUIO: | 422 | case METHOD_MPUIO: |
423 | reg += OMAP_MPUIO_GPIO_INT_EDGE; | 423 | reg += OMAP_MPUIO_GPIO_INT_EDGE; |
424 | l = __raw_readl(reg); | 424 | l = __raw_readl(reg); |
425 | if (trigger == IRQT_RISING) | 425 | if (trigger & __IRQT_RISEDGE) |
426 | l |= 1 << gpio; | 426 | l |= 1 << gpio; |
427 | else if (trigger == IRQT_FALLING) | 427 | else if (trigger & __IRQT_FALEDGE) |
428 | l &= ~(1 << gpio); | 428 | l &= ~(1 << gpio); |
429 | else | 429 | else |
430 | goto bad; | 430 | goto bad; |
@@ -432,9 +432,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
432 | case METHOD_GPIO_1510: | 432 | case METHOD_GPIO_1510: |
433 | reg += OMAP1510_GPIO_INT_CONTROL; | 433 | reg += OMAP1510_GPIO_INT_CONTROL; |
434 | l = __raw_readl(reg); | 434 | l = __raw_readl(reg); |
435 | if (trigger == IRQT_RISING) | 435 | if (trigger & __IRQT_RISEDGE) |
436 | l |= 1 << gpio; | 436 | l |= 1 << gpio; |
437 | else if (trigger == IRQT_FALLING) | 437 | else if (trigger & __IRQT_FALEDGE) |
438 | l &= ~(1 << gpio); | 438 | l &= ~(1 << gpio); |
439 | else | 439 | else |
440 | goto bad; | 440 | goto bad; |
@@ -446,20 +446,21 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
446 | reg += OMAP1610_GPIO_EDGE_CTRL1; | 446 | reg += OMAP1610_GPIO_EDGE_CTRL1; |
447 | gpio &= 0x07; | 447 | gpio &= 0x07; |
448 | /* We allow only edge triggering, i.e. two lowest bits */ | 448 | /* We allow only edge triggering, i.e. two lowest bits */ |
449 | if (trigger & ~IRQT_BOTHEDGE) | 449 | if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL)) |
450 | BUG(); | 450 | BUG(); |
451 | /* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */ | ||
452 | trigger &= 0x03; | ||
453 | l = __raw_readl(reg); | 451 | l = __raw_readl(reg); |
454 | l &= ~(3 << (gpio << 1)); | 452 | l &= ~(3 << (gpio << 1)); |
455 | l |= trigger << (gpio << 1); | 453 | if (trigger & __IRQT_RISEDGE) |
454 | l |= 2 << (gpio << 1); | ||
455 | if (trigger & __IRQT_FALEDGE) | ||
456 | l |= 1 << (gpio << 1); | ||
456 | break; | 457 | break; |
457 | case METHOD_GPIO_730: | 458 | case METHOD_GPIO_730: |
458 | reg += OMAP730_GPIO_INT_CONTROL; | 459 | reg += OMAP730_GPIO_INT_CONTROL; |
459 | l = __raw_readl(reg); | 460 | l = __raw_readl(reg); |
460 | if (trigger == IRQT_RISING) | 461 | if (trigger & __IRQT_RISEDGE) |
461 | l |= 1 << gpio; | 462 | l |= 1 << gpio; |
462 | else if (trigger == IRQT_FALLING) | 463 | else if (trigger & __IRQT_FALEDGE) |
463 | l &= ~(1 << gpio); | 464 | l &= ~(1 << gpio); |
464 | else | 465 | else |
465 | goto bad; | 466 | goto bad; |
@@ -491,7 +492,9 @@ static int gpio_irq_type(unsigned irq, unsigned type) | |||
491 | if (check_gpio(gpio) < 0) | 492 | if (check_gpio(gpio) < 0) |
492 | return -EINVAL; | 493 | return -EINVAL; |
493 | 494 | ||
494 | if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE)) | 495 | if (type & IRQT_PROBE) |
496 | return -EINVAL; | ||
497 | if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL))) | ||
495 | return -EINVAL; | 498 | return -EINVAL; |
496 | 499 | ||
497 | bank = get_gpio_bank(gpio); | 500 | bank = get_gpio_bank(gpio); |
@@ -755,13 +758,32 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
755 | if (bank->method == METHOD_GPIO_24XX) | 758 | if (bank->method == METHOD_GPIO_24XX) |
756 | isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; | 759 | isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; |
757 | #endif | 760 | #endif |
758 | |||
759 | while(1) { | 761 | while(1) { |
760 | isr = __raw_readl(isr_reg); | 762 | u32 isr_saved, level_mask = 0; |
761 | _enable_gpio_irqbank(bank, isr, 0); | 763 | |
762 | _clear_gpio_irqbank(bank, isr); | 764 | isr_saved = isr = __raw_readl(isr_reg); |
763 | _enable_gpio_irqbank(bank, isr, 1); | 765 | |
764 | desc->chip->unmask(irq); | 766 | if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO)) |
767 | isr &= 0x0000ffff; | ||
768 | |||
769 | if (cpu_is_omap24xx()) | ||
770 | level_mask = | ||
771 | __raw_readl(bank->base + | ||
772 | OMAP24XX_GPIO_LEVELDETECT0) | | ||
773 | __raw_readl(bank->base + | ||
774 | OMAP24XX_GPIO_LEVELDETECT1); | ||
775 | |||
776 | /* clear edge sensitive interrupts before handler(s) are | ||
777 | called so that we don't miss any interrupt occurred while | ||
778 | executing them */ | ||
779 | _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0); | ||
780 | _clear_gpio_irqbank(bank, isr_saved & ~level_mask); | ||
781 | _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1); | ||
782 | |||
783 | /* if there is only edge sensitive GPIO pin interrupts | ||
784 | configured, we could unmask GPIO bank interrupt immediately */ | ||
785 | if (!level_mask) | ||
786 | desc->chip->unmask(irq); | ||
765 | 787 | ||
766 | if (!isr) | 788 | if (!isr) |
767 | break; | 789 | break; |
@@ -774,6 +796,20 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
774 | d = irq_desc + gpio_irq; | 796 | d = irq_desc + gpio_irq; |
775 | desc_handle_irq(gpio_irq, d, regs); | 797 | desc_handle_irq(gpio_irq, d, regs); |
776 | } | 798 | } |
799 | |||
800 | if (cpu_is_omap24xx()) { | ||
801 | /* clear level sensitive interrupts after handler(s) */ | ||
802 | _enable_gpio_irqbank(bank, isr_saved & level_mask, 0); | ||
803 | _clear_gpio_irqbank(bank, isr_saved & level_mask); | ||
804 | _enable_gpio_irqbank(bank, isr_saved & level_mask, 1); | ||
805 | } | ||
806 | |||
807 | /* if bank has any level sensitive GPIO pin interrupt | ||
808 | configured, we must unmask the bank interrupt only after | ||
809 | handler(s) are executed in order to avoid spurious bank | ||
810 | interrupt */ | ||
811 | if (level_mask) | ||
812 | desc->chip->unmask(irq); | ||
777 | } | 813 | } |
778 | } | 814 | } |
779 | 815 | ||
@@ -848,7 +884,7 @@ static int __init _omap_gpio_init(void) | |||
848 | 884 | ||
849 | initialized = 1; | 885 | initialized = 1; |
850 | 886 | ||
851 | if (cpu_is_omap1510()) { | 887 | if (cpu_is_omap15xx()) { |
852 | gpio_ick = clk_get(NULL, "arm_gpio_ck"); | 888 | gpio_ick = clk_get(NULL, "arm_gpio_ck"); |
853 | if (IS_ERR(gpio_ick)) | 889 | if (IS_ERR(gpio_ick)) |
854 | printk("Could not get arm_gpio_ck\n"); | 890 | printk("Could not get arm_gpio_ck\n"); |
@@ -869,7 +905,7 @@ static int __init _omap_gpio_init(void) | |||
869 | } | 905 | } |
870 | 906 | ||
871 | #ifdef CONFIG_ARCH_OMAP15XX | 907 | #ifdef CONFIG_ARCH_OMAP15XX |
872 | if (cpu_is_omap1510()) { | 908 | if (cpu_is_omap15xx()) { |
873 | printk(KERN_INFO "OMAP1510 GPIO hardware\n"); | 909 | printk(KERN_INFO "OMAP1510 GPIO hardware\n"); |
874 | gpio_bank_count = 2; | 910 | gpio_bank_count = 2; |
875 | gpio_bank = gpio_bank_1510; | 911 | gpio_bank = gpio_bank_1510; |
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 1cd2cace7e1b..196aac3ac329 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #ifdef CONFIG_MCBSP_DEBUG | 34 | #ifdef CONFIG_MCBSP_DEBUG |
35 | #define DBG(x...) printk(x) | 35 | #define DBG(x...) printk(x) |
36 | #else | 36 | #else |
37 | #define DBG(x...) do { } while (0) | 37 | #define DBG(x...) do { } while (0) |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | struct omap_mcbsp { | 40 | struct omap_mcbsp { |
@@ -44,6 +44,7 @@ struct omap_mcbsp { | |||
44 | omap_mcbsp_word_length rx_word_length; | 44 | omap_mcbsp_word_length rx_word_length; |
45 | omap_mcbsp_word_length tx_word_length; | 45 | omap_mcbsp_word_length tx_word_length; |
46 | 46 | ||
47 | omap_mcbsp_io_type_t io_type; /* IRQ or poll */ | ||
47 | /* IRQ based TX/RX */ | 48 | /* IRQ based TX/RX */ |
48 | int rx_irq; | 49 | int rx_irq; |
49 | int tx_irq; | 50 | int tx_irq; |
@@ -64,10 +65,19 @@ struct omap_mcbsp { | |||
64 | }; | 65 | }; |
65 | 66 | ||
66 | static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; | 67 | static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; |
68 | #ifdef CONFIG_ARCH_OMAP1 | ||
67 | static struct clk *mcbsp_dsp_ck = 0; | 69 | static struct clk *mcbsp_dsp_ck = 0; |
68 | static struct clk *mcbsp_api_ck = 0; | 70 | static struct clk *mcbsp_api_ck = 0; |
69 | static struct clk *mcbsp_dspxor_ck = 0; | 71 | static struct clk *mcbsp_dspxor_ck = 0; |
70 | 72 | #endif | |
73 | #ifdef CONFIG_ARCH_OMAP2 | ||
74 | static struct clk *mcbsp1_ick = 0; | ||
75 | static struct clk *mcbsp1_fck = 0; | ||
76 | static struct clk *mcbsp2_ick = 0; | ||
77 | static struct clk *mcbsp2_fck = 0; | ||
78 | static struct clk *sys_ck = 0; | ||
79 | static struct clk *sys_clkout = 0; | ||
80 | #endif | ||
71 | 81 | ||
72 | static void omap_mcbsp_dump_reg(u8 id) | 82 | static void omap_mcbsp_dump_reg(u8 id) |
73 | { | 83 | { |
@@ -88,7 +98,6 @@ static void omap_mcbsp_dump_reg(u8 id) | |||
88 | DBG("***********************\n"); | 98 | DBG("***********************\n"); |
89 | } | 99 | } |
90 | 100 | ||
91 | |||
92 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs) | 101 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs) |
93 | { | 102 | { |
94 | struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id); | 103 | struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id); |
@@ -109,7 +118,6 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_re | |||
109 | return IRQ_HANDLED; | 118 | return IRQ_HANDLED; |
110 | } | 119 | } |
111 | 120 | ||
112 | |||
113 | static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) | 121 | static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) |
114 | { | 122 | { |
115 | struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data); | 123 | struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data); |
@@ -176,7 +184,7 @@ static int omap_mcbsp_check(unsigned int id) | |||
176 | return 0; | 184 | return 0; |
177 | } | 185 | } |
178 | 186 | ||
179 | if (cpu_is_omap1510() || cpu_is_omap16xx()) { | 187 | if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) { |
180 | if (id > OMAP_MAX_MCBSP_COUNT) { | 188 | if (id > OMAP_MAX_MCBSP_COUNT) { |
181 | printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); | 189 | printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); |
182 | return -1; | 190 | return -1; |
@@ -187,9 +195,10 @@ static int omap_mcbsp_check(unsigned int id) | |||
187 | return -1; | 195 | return -1; |
188 | } | 196 | } |
189 | 197 | ||
198 | #ifdef CONFIG_ARCH_OMAP1 | ||
190 | static void omap_mcbsp_dsp_request(void) | 199 | static void omap_mcbsp_dsp_request(void) |
191 | { | 200 | { |
192 | if (cpu_is_omap1510() || cpu_is_omap16xx()) { | 201 | if (cpu_is_omap15xx() || cpu_is_omap16xx()) { |
193 | clk_enable(mcbsp_dsp_ck); | 202 | clk_enable(mcbsp_dsp_ck); |
194 | clk_enable(mcbsp_api_ck); | 203 | clk_enable(mcbsp_api_ck); |
195 | 204 | ||
@@ -207,12 +216,49 @@ static void omap_mcbsp_dsp_request(void) | |||
207 | 216 | ||
208 | static void omap_mcbsp_dsp_free(void) | 217 | static void omap_mcbsp_dsp_free(void) |
209 | { | 218 | { |
210 | if (cpu_is_omap1510() || cpu_is_omap16xx()) { | 219 | if (cpu_is_omap15xx() || cpu_is_omap16xx()) { |
211 | clk_disable(mcbsp_dspxor_ck); | 220 | clk_disable(mcbsp_dspxor_ck); |
212 | clk_disable(mcbsp_dsp_ck); | 221 | clk_disable(mcbsp_dsp_ck); |
213 | clk_disable(mcbsp_api_ck); | 222 | clk_disable(mcbsp_api_ck); |
214 | } | 223 | } |
215 | } | 224 | } |
225 | #endif | ||
226 | |||
227 | #ifdef CONFIG_ARCH_OMAP2 | ||
228 | static void omap2_mcbsp2_mux_setup(void) | ||
229 | { | ||
230 | omap_cfg_reg(Y15_24XX_MCBSP2_CLKX); | ||
231 | omap_cfg_reg(R14_24XX_MCBSP2_FSX); | ||
232 | omap_cfg_reg(W15_24XX_MCBSP2_DR); | ||
233 | omap_cfg_reg(V15_24XX_MCBSP2_DX); | ||
234 | omap_cfg_reg(V14_24XX_GPIO117); | ||
235 | omap_cfg_reg(W14_24XX_SYS_CLKOUT); | ||
236 | } | ||
237 | #endif | ||
238 | |||
239 | /* | ||
240 | * We can choose between IRQ based or polled IO. | ||
241 | * This needs to be called before omap_mcbsp_request(). | ||
242 | */ | ||
243 | int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) | ||
244 | { | ||
245 | if (omap_mcbsp_check(id) < 0) | ||
246 | return -EINVAL; | ||
247 | |||
248 | spin_lock(&mcbsp[id].lock); | ||
249 | |||
250 | if (!mcbsp[id].free) { | ||
251 | printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1); | ||
252 | spin_unlock(&mcbsp[id].lock); | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | mcbsp[id].io_type = io_type; | ||
257 | |||
258 | spin_unlock(&mcbsp[id].lock); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
216 | 262 | ||
217 | int omap_mcbsp_request(unsigned int id) | 263 | int omap_mcbsp_request(unsigned int id) |
218 | { | 264 | { |
@@ -221,12 +267,26 @@ int omap_mcbsp_request(unsigned int id) | |||
221 | if (omap_mcbsp_check(id) < 0) | 267 | if (omap_mcbsp_check(id) < 0) |
222 | return -EINVAL; | 268 | return -EINVAL; |
223 | 269 | ||
270 | #ifdef CONFIG_ARCH_OMAP1 | ||
224 | /* | 271 | /* |
225 | * On 1510, 1610 and 1710, McBSP1 and McBSP3 | 272 | * On 1510, 1610 and 1710, McBSP1 and McBSP3 |
226 | * are DSP public peripherals. | 273 | * are DSP public peripherals. |
227 | */ | 274 | */ |
228 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | 275 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) |
229 | omap_mcbsp_dsp_request(); | 276 | omap_mcbsp_dsp_request(); |
277 | #endif | ||
278 | |||
279 | #ifdef CONFIG_ARCH_OMAP2 | ||
280 | if (cpu_is_omap24xx()) { | ||
281 | if (id == OMAP_MCBSP1) { | ||
282 | clk_enable(mcbsp1_ick); | ||
283 | clk_enable(mcbsp1_fck); | ||
284 | } else { | ||
285 | clk_enable(mcbsp2_ick); | ||
286 | clk_enable(mcbsp2_fck); | ||
287 | } | ||
288 | } | ||
289 | #endif | ||
230 | 290 | ||
231 | spin_lock(&mcbsp[id].lock); | 291 | spin_lock(&mcbsp[id].lock); |
232 | if (!mcbsp[id].free) { | 292 | if (!mcbsp[id].free) { |
@@ -238,30 +298,33 @@ int omap_mcbsp_request(unsigned int id) | |||
238 | mcbsp[id].free = 0; | 298 | mcbsp[id].free = 0; |
239 | spin_unlock(&mcbsp[id].lock); | 299 | spin_unlock(&mcbsp[id].lock); |
240 | 300 | ||
241 | /* We need to get IRQs here */ | 301 | if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { |
242 | err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0, | 302 | /* We need to get IRQs here */ |
243 | "McBSP", | 303 | err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0, |
244 | (void *) (&mcbsp[id])); | 304 | "McBSP", |
245 | if (err != 0) { | 305 | (void *) (&mcbsp[id])); |
246 | printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n", | 306 | if (err != 0) { |
247 | mcbsp[id].tx_irq, mcbsp[id].id); | 307 | printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n", |
248 | return err; | 308 | mcbsp[id].tx_irq, mcbsp[id].id); |
249 | } | 309 | return err; |
310 | } | ||
250 | 311 | ||
251 | init_completion(&(mcbsp[id].tx_irq_completion)); | 312 | init_completion(&(mcbsp[id].tx_irq_completion)); |
252 | 313 | ||
253 | 314 | ||
254 | err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0, | 315 | err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0, |
255 | "McBSP", | 316 | "McBSP", |
256 | (void *) (&mcbsp[id])); | 317 | (void *) (&mcbsp[id])); |
257 | if (err != 0) { | 318 | if (err != 0) { |
258 | printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n", | 319 | printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n", |
259 | mcbsp[id].rx_irq, mcbsp[id].id); | 320 | mcbsp[id].rx_irq, mcbsp[id].id); |
260 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | 321 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); |
261 | return err; | 322 | return err; |
323 | } | ||
324 | |||
325 | init_completion(&(mcbsp[id].rx_irq_completion)); | ||
262 | } | 326 | } |
263 | 327 | ||
264 | init_completion(&(mcbsp[id].rx_irq_completion)); | ||
265 | return 0; | 328 | return 0; |
266 | 329 | ||
267 | } | 330 | } |
@@ -271,8 +334,24 @@ void omap_mcbsp_free(unsigned int id) | |||
271 | if (omap_mcbsp_check(id) < 0) | 334 | if (omap_mcbsp_check(id) < 0) |
272 | return; | 335 | return; |
273 | 336 | ||
274 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | 337 | #ifdef CONFIG_ARCH_OMAP1 |
275 | omap_mcbsp_dsp_free(); | 338 | if (cpu_class_is_omap1()) { |
339 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | ||
340 | omap_mcbsp_dsp_free(); | ||
341 | } | ||
342 | #endif | ||
343 | |||
344 | #ifdef CONFIG_ARCH_OMAP2 | ||
345 | if (cpu_is_omap24xx()) { | ||
346 | if (id == OMAP_MCBSP1) { | ||
347 | clk_disable(mcbsp1_ick); | ||
348 | clk_disable(mcbsp1_fck); | ||
349 | } else { | ||
350 | clk_disable(mcbsp2_ick); | ||
351 | clk_disable(mcbsp2_fck); | ||
352 | } | ||
353 | } | ||
354 | #endif | ||
276 | 355 | ||
277 | spin_lock(&mcbsp[id].lock); | 356 | spin_lock(&mcbsp[id].lock); |
278 | if (mcbsp[id].free) { | 357 | if (mcbsp[id].free) { |
@@ -284,9 +363,11 @@ void omap_mcbsp_free(unsigned int id) | |||
284 | mcbsp[id].free = 1; | 363 | mcbsp[id].free = 1; |
285 | spin_unlock(&mcbsp[id].lock); | 364 | spin_unlock(&mcbsp[id].lock); |
286 | 365 | ||
287 | /* Free IRQs */ | 366 | if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { |
288 | free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id])); | 367 | /* Free IRQs */ |
289 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | 368 | free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id])); |
369 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | ||
370 | } | ||
290 | } | 371 | } |
291 | 372 | ||
292 | /* | 373 | /* |
@@ -461,6 +542,115 @@ u32 omap_mcbsp_recv_word(unsigned int id) | |||
461 | } | 542 | } |
462 | 543 | ||
463 | 544 | ||
545 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | ||
546 | { | ||
547 | u32 io_base = mcbsp[id].io_base; | ||
548 | omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; | ||
549 | omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; | ||
550 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | ||
551 | |||
552 | if (tx_word_length != rx_word_length) | ||
553 | return -EINVAL; | ||
554 | |||
555 | /* First we wait for the transmitter to be ready */ | ||
556 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | ||
557 | while (!(spcr2 & XRDY)) { | ||
558 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | ||
559 | if (attempts++ > 1000) { | ||
560 | /* We must reset the transmitter */ | ||
561 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST)); | ||
562 | udelay(10); | ||
563 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | ||
564 | udelay(10); | ||
565 | printk("McBSP transmitter not ready\n"); | ||
566 | return -EAGAIN; | ||
567 | } | ||
568 | } | ||
569 | |||
570 | /* Now we can push the data */ | ||
571 | if (tx_word_length > OMAP_MCBSP_WORD_16) | ||
572 | OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); | ||
573 | OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff); | ||
574 | |||
575 | /* We wait for the receiver to be ready */ | ||
576 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | ||
577 | while (!(spcr1 & RRDY)) { | ||
578 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | ||
579 | if (attempts++ > 1000) { | ||
580 | /* We must reset the receiver */ | ||
581 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST)); | ||
582 | udelay(10); | ||
583 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | ||
584 | udelay(10); | ||
585 | printk("McBSP receiver not ready\n"); | ||
586 | return -EAGAIN; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /* Receiver is ready, let's read the dummy data */ | ||
591 | if (rx_word_length > OMAP_MCBSP_WORD_16) | ||
592 | word_msb = OMAP_MCBSP_READ(io_base, DRR2); | ||
593 | word_lsb = OMAP_MCBSP_READ(io_base, DRR1); | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) | ||
599 | { | ||
600 | u32 io_base = mcbsp[id].io_base, clock_word = 0; | ||
601 | omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; | ||
602 | omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; | ||
603 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | ||
604 | |||
605 | if (tx_word_length != rx_word_length) | ||
606 | return -EINVAL; | ||
607 | |||
608 | /* First we wait for the transmitter to be ready */ | ||
609 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | ||
610 | while (!(spcr2 & XRDY)) { | ||
611 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | ||
612 | if (attempts++ > 1000) { | ||
613 | /* We must reset the transmitter */ | ||
614 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST)); | ||
615 | udelay(10); | ||
616 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | ||
617 | udelay(10); | ||
618 | printk("McBSP transmitter not ready\n"); | ||
619 | return -EAGAIN; | ||
620 | } | ||
621 | } | ||
622 | |||
623 | /* We first need to enable the bus clock */ | ||
624 | if (tx_word_length > OMAP_MCBSP_WORD_16) | ||
625 | OMAP_MCBSP_WRITE(io_base, DXR2, clock_word >> 16); | ||
626 | OMAP_MCBSP_WRITE(io_base, DXR1, clock_word & 0xffff); | ||
627 | |||
628 | /* We wait for the receiver to be ready */ | ||
629 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | ||
630 | while (!(spcr1 & RRDY)) { | ||
631 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | ||
632 | if (attempts++ > 1000) { | ||
633 | /* We must reset the receiver */ | ||
634 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST)); | ||
635 | udelay(10); | ||
636 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | ||
637 | udelay(10); | ||
638 | printk("McBSP receiver not ready\n"); | ||
639 | return -EAGAIN; | ||
640 | } | ||
641 | } | ||
642 | |||
643 | /* Receiver is ready, there is something for us */ | ||
644 | if (rx_word_length > OMAP_MCBSP_WORD_16) | ||
645 | word_msb = OMAP_MCBSP_READ(io_base, DRR2); | ||
646 | word_lsb = OMAP_MCBSP_READ(io_base, DRR1); | ||
647 | |||
648 | word[0] = (word_lsb | (word_msb << 16)); | ||
649 | |||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | |||
464 | /* | 654 | /* |
465 | * Simple DMA based buffer rx/tx routines. | 655 | * Simple DMA based buffer rx/tx routines. |
466 | * Nothing fancy, just a single buffer tx/rx through DMA. | 656 | * Nothing fancy, just a single buffer tx/rx through DMA. |
@@ -471,6 +661,9 @@ u32 omap_mcbsp_recv_word(unsigned int id) | |||
471 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) | 661 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) |
472 | { | 662 | { |
473 | int dma_tx_ch; | 663 | int dma_tx_ch; |
664 | int src_port = 0; | ||
665 | int dest_port = 0; | ||
666 | int sync_dev = 0; | ||
474 | 667 | ||
475 | if (omap_mcbsp_check(id) < 0) | 668 | if (omap_mcbsp_check(id) < 0) |
476 | return -EINVAL; | 669 | return -EINVAL; |
@@ -487,20 +680,27 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
487 | 680 | ||
488 | init_completion(&(mcbsp[id].tx_dma_completion)); | 681 | init_completion(&(mcbsp[id].tx_dma_completion)); |
489 | 682 | ||
683 | if (cpu_class_is_omap1()) { | ||
684 | src_port = OMAP_DMA_PORT_TIPB; | ||
685 | dest_port = OMAP_DMA_PORT_EMIFF; | ||
686 | } | ||
687 | if (cpu_is_omap24xx()) | ||
688 | sync_dev = mcbsp[id].dma_tx_sync; | ||
689 | |||
490 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, | 690 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, |
491 | OMAP_DMA_DATA_TYPE_S16, | 691 | OMAP_DMA_DATA_TYPE_S16, |
492 | length >> 1, 1, | 692 | length >> 1, 1, |
493 | OMAP_DMA_SYNC_ELEMENT, | 693 | OMAP_DMA_SYNC_ELEMENT, |
494 | 0, 0); | 694 | sync_dev, 0); |
495 | 695 | ||
496 | omap_set_dma_dest_params(mcbsp[id].dma_tx_lch, | 696 | omap_set_dma_dest_params(mcbsp[id].dma_tx_lch, |
497 | OMAP_DMA_PORT_TIPB, | 697 | src_port, |
498 | OMAP_DMA_AMODE_CONSTANT, | 698 | OMAP_DMA_AMODE_CONSTANT, |
499 | mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1, | 699 | mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1, |
500 | 0, 0); | 700 | 0, 0); |
501 | 701 | ||
502 | omap_set_dma_src_params(mcbsp[id].dma_tx_lch, | 702 | omap_set_dma_src_params(mcbsp[id].dma_tx_lch, |
503 | OMAP_DMA_PORT_EMIFF, | 703 | dest_port, |
504 | OMAP_DMA_AMODE_POST_INC, | 704 | OMAP_DMA_AMODE_POST_INC, |
505 | buffer, | 705 | buffer, |
506 | 0, 0); | 706 | 0, 0); |
@@ -514,6 +714,9 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
514 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) | 714 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) |
515 | { | 715 | { |
516 | int dma_rx_ch; | 716 | int dma_rx_ch; |
717 | int src_port = 0; | ||
718 | int dest_port = 0; | ||
719 | int sync_dev = 0; | ||
517 | 720 | ||
518 | if (omap_mcbsp_check(id) < 0) | 721 | if (omap_mcbsp_check(id) < 0) |
519 | return -EINVAL; | 722 | return -EINVAL; |
@@ -530,20 +733,27 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
530 | 733 | ||
531 | init_completion(&(mcbsp[id].rx_dma_completion)); | 734 | init_completion(&(mcbsp[id].rx_dma_completion)); |
532 | 735 | ||
736 | if (cpu_class_is_omap1()) { | ||
737 | src_port = OMAP_DMA_PORT_TIPB; | ||
738 | dest_port = OMAP_DMA_PORT_EMIFF; | ||
739 | } | ||
740 | if (cpu_is_omap24xx()) | ||
741 | sync_dev = mcbsp[id].dma_rx_sync; | ||
742 | |||
533 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, | 743 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, |
534 | OMAP_DMA_DATA_TYPE_S16, | 744 | OMAP_DMA_DATA_TYPE_S16, |
535 | length >> 1, 1, | 745 | length >> 1, 1, |
536 | OMAP_DMA_SYNC_ELEMENT, | 746 | OMAP_DMA_SYNC_ELEMENT, |
537 | 0, 0); | 747 | sync_dev, 0); |
538 | 748 | ||
539 | omap_set_dma_src_params(mcbsp[id].dma_rx_lch, | 749 | omap_set_dma_src_params(mcbsp[id].dma_rx_lch, |
540 | OMAP_DMA_PORT_TIPB, | 750 | src_port, |
541 | OMAP_DMA_AMODE_CONSTANT, | 751 | OMAP_DMA_AMODE_CONSTANT, |
542 | mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1, | 752 | mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1, |
543 | 0, 0); | 753 | 0, 0); |
544 | 754 | ||
545 | omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, | 755 | omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, |
546 | OMAP_DMA_PORT_EMIFF, | 756 | dest_port, |
547 | OMAP_DMA_AMODE_POST_INC, | 757 | OMAP_DMA_AMODE_POST_INC, |
548 | buffer, | 758 | buffer, |
549 | 0, 0); | 759 | 0, 0); |
@@ -688,6 +898,23 @@ static const struct omap_mcbsp_info mcbsp_1610[] = { | |||
688 | }; | 898 | }; |
689 | #endif | 899 | #endif |
690 | 900 | ||
901 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
902 | static const struct omap_mcbsp_info mcbsp_24xx[] = { | ||
903 | [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE), | ||
904 | .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, | ||
905 | .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, | ||
906 | .rx_irq = INT_24XX_MCBSP1_IRQ_RX, | ||
907 | .tx_irq = INT_24XX_MCBSP1_IRQ_TX, | ||
908 | }, | ||
909 | [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE), | ||
910 | .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, | ||
911 | .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, | ||
912 | .rx_irq = INT_24XX_MCBSP2_IRQ_RX, | ||
913 | .tx_irq = INT_24XX_MCBSP2_IRQ_TX, | ||
914 | }, | ||
915 | }; | ||
916 | #endif | ||
917 | |||
691 | static int __init omap_mcbsp_init(void) | 918 | static int __init omap_mcbsp_init(void) |
692 | { | 919 | { |
693 | int mcbsp_count = 0, i; | 920 | int mcbsp_count = 0, i; |
@@ -695,6 +922,7 @@ static int __init omap_mcbsp_init(void) | |||
695 | 922 | ||
696 | printk("Initializing OMAP McBSP system\n"); | 923 | printk("Initializing OMAP McBSP system\n"); |
697 | 924 | ||
925 | #ifdef CONFIG_ARCH_OMAP1 | ||
698 | mcbsp_dsp_ck = clk_get(0, "dsp_ck"); | 926 | mcbsp_dsp_ck = clk_get(0, "dsp_ck"); |
699 | if (IS_ERR(mcbsp_dsp_ck)) { | 927 | if (IS_ERR(mcbsp_dsp_ck)) { |
700 | printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n"); | 928 | printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n"); |
@@ -710,6 +938,29 @@ static int __init omap_mcbsp_init(void) | |||
710 | printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n"); | 938 | printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n"); |
711 | return PTR_ERR(mcbsp_dspxor_ck); | 939 | return PTR_ERR(mcbsp_dspxor_ck); |
712 | } | 940 | } |
941 | #endif | ||
942 | #ifdef CONFIG_ARCH_OMAP2 | ||
943 | mcbsp1_ick = clk_get(0, "mcbsp1_ick"); | ||
944 | if (IS_ERR(mcbsp1_ick)) { | ||
945 | printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n"); | ||
946 | return PTR_ERR(mcbsp1_ick); | ||
947 | } | ||
948 | mcbsp1_fck = clk_get(0, "mcbsp1_fck"); | ||
949 | if (IS_ERR(mcbsp1_fck)) { | ||
950 | printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n"); | ||
951 | return PTR_ERR(mcbsp1_fck); | ||
952 | } | ||
953 | mcbsp2_ick = clk_get(0, "mcbsp2_ick"); | ||
954 | if (IS_ERR(mcbsp2_ick)) { | ||
955 | printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n"); | ||
956 | return PTR_ERR(mcbsp2_ick); | ||
957 | } | ||
958 | mcbsp2_fck = clk_get(0, "mcbsp2_fck"); | ||
959 | if (IS_ERR(mcbsp2_fck)) { | ||
960 | printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n"); | ||
961 | return PTR_ERR(mcbsp2_fck); | ||
962 | } | ||
963 | #endif | ||
713 | 964 | ||
714 | #ifdef CONFIG_ARCH_OMAP730 | 965 | #ifdef CONFIG_ARCH_OMAP730 |
715 | if (cpu_is_omap730()) { | 966 | if (cpu_is_omap730()) { |
@@ -718,7 +969,7 @@ static int __init omap_mcbsp_init(void) | |||
718 | } | 969 | } |
719 | #endif | 970 | #endif |
720 | #ifdef CONFIG_ARCH_OMAP15XX | 971 | #ifdef CONFIG_ARCH_OMAP15XX |
721 | if (cpu_is_omap1510()) { | 972 | if (cpu_is_omap15xx()) { |
722 | mcbsp_info = mcbsp_1510; | 973 | mcbsp_info = mcbsp_1510; |
723 | mcbsp_count = ARRAY_SIZE(mcbsp_1510); | 974 | mcbsp_count = ARRAY_SIZE(mcbsp_1510); |
724 | } | 975 | } |
@@ -729,6 +980,19 @@ static int __init omap_mcbsp_init(void) | |||
729 | mcbsp_count = ARRAY_SIZE(mcbsp_1610); | 980 | mcbsp_count = ARRAY_SIZE(mcbsp_1610); |
730 | } | 981 | } |
731 | #endif | 982 | #endif |
983 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
984 | if (cpu_is_omap24xx()) { | ||
985 | mcbsp_info = mcbsp_24xx; | ||
986 | mcbsp_count = ARRAY_SIZE(mcbsp_24xx); | ||
987 | |||
988 | /* REVISIT: where's the right place? */ | ||
989 | omap2_mcbsp2_mux_setup(); | ||
990 | sys_ck = clk_get(0, "sys_ck"); | ||
991 | sys_clkout = clk_get(0, "sys_clkout"); | ||
992 | clk_set_parent(sys_clkout, sys_ck); | ||
993 | clk_enable(sys_clkout); | ||
994 | } | ||
995 | #endif | ||
732 | for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) { | 996 | for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) { |
733 | if (i >= mcbsp_count) { | 997 | if (i >= mcbsp_count) { |
734 | mcbsp[i].io_base = 0; | 998 | mcbsp[i].io_base = 0; |
@@ -741,6 +1005,7 @@ static int __init omap_mcbsp_init(void) | |||
741 | mcbsp[i].dma_rx_lch = -1; | 1005 | mcbsp[i].dma_rx_lch = -1; |
742 | 1006 | ||
743 | mcbsp[i].io_base = mcbsp_info[i].virt_base; | 1007 | mcbsp[i].io_base = mcbsp_info[i].virt_base; |
1008 | mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */ | ||
744 | mcbsp[i].tx_irq = mcbsp_info[i].tx_irq; | 1009 | mcbsp[i].tx_irq = mcbsp_info[i].tx_irq; |
745 | mcbsp[i].rx_irq = mcbsp_info[i].rx_irq; | 1010 | mcbsp[i].rx_irq = mcbsp_info[i].rx_irq; |
746 | mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync; | 1011 | mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync; |
@@ -751,11 +1016,11 @@ static int __init omap_mcbsp_init(void) | |||
751 | return 0; | 1016 | return 0; |
752 | } | 1017 | } |
753 | 1018 | ||
754 | |||
755 | arch_initcall(omap_mcbsp_init); | 1019 | arch_initcall(omap_mcbsp_init); |
756 | 1020 | ||
757 | EXPORT_SYMBOL(omap_mcbsp_config); | 1021 | EXPORT_SYMBOL(omap_mcbsp_config); |
758 | EXPORT_SYMBOL(omap_mcbsp_request); | 1022 | EXPORT_SYMBOL(omap_mcbsp_request); |
1023 | EXPORT_SYMBOL(omap_mcbsp_set_io_type); | ||
759 | EXPORT_SYMBOL(omap_mcbsp_free); | 1024 | EXPORT_SYMBOL(omap_mcbsp_free); |
760 | EXPORT_SYMBOL(omap_mcbsp_start); | 1025 | EXPORT_SYMBOL(omap_mcbsp_start); |
761 | EXPORT_SYMBOL(omap_mcbsp_stop); | 1026 | EXPORT_SYMBOL(omap_mcbsp_stop); |
@@ -763,4 +1028,6 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_word); | |||
763 | EXPORT_SYMBOL(omap_mcbsp_recv_word); | 1028 | EXPORT_SYMBOL(omap_mcbsp_recv_word); |
764 | EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); | 1029 | EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); |
765 | EXPORT_SYMBOL(omap_mcbsp_recv_buffer); | 1030 | EXPORT_SYMBOL(omap_mcbsp_recv_buffer); |
1031 | EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); | ||
1032 | EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll); | ||
766 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); | 1033 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); |
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c index 5cc6775c789c..37792d43738b 100644 --- a/arch/arm/plat-omap/ocpi.c +++ b/arch/arm/plat-omap/ocpi.c | |||
@@ -62,9 +62,6 @@ int ocpi_enable(void) | |||
62 | if (!cpu_is_omap16xx()) | 62 | if (!cpu_is_omap16xx()) |
63 | return -ENODEV; | 63 | return -ENODEV; |
64 | 64 | ||
65 | /* Make sure there's clock for OCPI */ | ||
66 | clk_enable(ocpi_ck); | ||
67 | |||
68 | /* Enable access for OHCI in OCPI */ | 65 | /* Enable access for OHCI in OCPI */ |
69 | val = omap_readl(OCPI_PROT); | 66 | val = omap_readl(OCPI_PROT); |
70 | val &= ~0xff; | 67 | val &= ~0xff; |
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c index 093efd786f21..1a24e2c10714 100644 --- a/arch/arm/plat-omap/pm.c +++ b/arch/arm/plat-omap/pm.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/pm.h> | 38 | #include <linux/pm.h> |
39 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
40 | #include <linux/proc_fs.h> | 40 | #include <linux/proc_fs.h> |
41 | #include <linux/pm.h> | ||
41 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
42 | 43 | ||
43 | #include <asm/io.h> | 44 | #include <asm/io.h> |
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/plat-omap/sleep.S deleted file mode 100644 index 4cd7d292f854..000000000000 --- a/arch/arm/plat-omap/sleep.S +++ /dev/null | |||
@@ -1,452 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/sleep.S | ||
3 | * | ||
4 | * Low-level OMAP730/1510/1610 sleep/wakeUp support | ||
5 | * | ||
6 | * Initial SA1110 code: | ||
7 | * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> | ||
8 | * | ||
9 | * Adapted for PXA by Nicolas Pitre: | ||
10 | * Copyright (c) 2002 Monta Vista Software, Inc. | ||
11 | * | ||
12 | * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the License, or (at your | ||
17 | * option) any later version. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
20 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
22 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
25 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License along | ||
31 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
32 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | */ | ||
34 | |||
35 | #include <linux/config.h> | ||
36 | #include <linux/linkage.h> | ||
37 | #include <asm/assembler.h> | ||
38 | #include <asm/arch/io.h> | ||
39 | #include <asm/arch/pm.h> | ||
40 | |||
41 | .text | ||
42 | |||
43 | /* | ||
44 | * Forces OMAP into idle state | ||
45 | * | ||
46 | * omapXXXX_idle_loop_suspend() | ||
47 | * | ||
48 | * Note: This code get's copied to internal SRAM at boot. When the OMAP | ||
49 | * wakes up it continues execution at the point it went to sleep. | ||
50 | * | ||
51 | * Note: Because of slightly different configuration values we have | ||
52 | * processor specific functions here. | ||
53 | */ | ||
54 | |||
55 | #if defined(CONFIG_ARCH_OMAP730) | ||
56 | ENTRY(omap730_idle_loop_suspend) | ||
57 | |||
58 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
59 | |||
60 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
61 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
62 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
63 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
64 | |||
65 | @ turn off clock domains | ||
66 | @ get ARM_IDLECT2 into r2 | ||
67 | ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
68 | mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff | ||
69 | orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 | ||
70 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
71 | |||
72 | @ request ARM idle | ||
73 | @ get ARM_IDLECT1 into r1 | ||
74 | ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
75 | orr r3, r1, #OMAP730_IDLE_LOOP_REQUEST & 0xffff | ||
76 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
77 | |||
78 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
79 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
80 | l_730: subs r5, r5, #1 | ||
81 | bne l_730 | ||
82 | /* | ||
83 | * Let's wait for the next clock tick to wake us up. | ||
84 | */ | ||
85 | mov r0, #0 | ||
86 | mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt | ||
87 | /* | ||
88 | * omap730_idle_loop_suspend()'s resume point. | ||
89 | * | ||
90 | * It will just start executing here, so we'll restore stuff from the | ||
91 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
92 | */ | ||
93 | |||
94 | @ restore ARM_IDLECT1 and ARM_IDLECT2 and return | ||
95 | @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 | ||
96 | strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
97 | strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
98 | |||
99 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
100 | |||
101 | ENTRY(omap730_idle_loop_suspend_sz) | ||
102 | .word . - omap730_idle_loop_suspend | ||
103 | #endif /* CONFIG_ARCH_OMAP730 */ | ||
104 | |||
105 | #ifdef CONFIG_ARCH_OMAP15XX | ||
106 | ENTRY(omap1510_idle_loop_suspend) | ||
107 | |||
108 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
109 | |||
110 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
111 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
112 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
113 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
114 | |||
115 | @ turn off clock domains | ||
116 | @ get ARM_IDLECT2 into r2 | ||
117 | ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
118 | mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff | ||
119 | orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 | ||
120 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
121 | |||
122 | @ request ARM idle | ||
123 | @ get ARM_IDLECT1 into r1 | ||
124 | ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
125 | orr r3, r1, #OMAP1510_IDLE_LOOP_REQUEST & 0xffff | ||
126 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
127 | |||
128 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
129 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
130 | l_1510: subs r5, r5, #1 | ||
131 | bne l_1510 | ||
132 | /* | ||
133 | * Let's wait for the next clock tick to wake us up. | ||
134 | */ | ||
135 | mov r0, #0 | ||
136 | mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt | ||
137 | /* | ||
138 | * omap1510_idle_loop_suspend()'s resume point. | ||
139 | * | ||
140 | * It will just start executing here, so we'll restore stuff from the | ||
141 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
142 | */ | ||
143 | |||
144 | @ restore ARM_IDLECT1 and ARM_IDLECT2 and return | ||
145 | @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 | ||
146 | strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
147 | strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
148 | |||
149 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
150 | |||
151 | ENTRY(omap1510_idle_loop_suspend_sz) | ||
152 | .word . - omap1510_idle_loop_suspend | ||
153 | #endif /* CONFIG_ARCH_OMAP15XX */ | ||
154 | |||
155 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
156 | ENTRY(omap1610_idle_loop_suspend) | ||
157 | |||
158 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
159 | |||
160 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
161 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
162 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
163 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
164 | |||
165 | @ turn off clock domains | ||
166 | @ get ARM_IDLECT2 into r2 | ||
167 | ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
168 | mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff | ||
169 | orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 | ||
170 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
171 | |||
172 | @ request ARM idle | ||
173 | @ get ARM_IDLECT1 into r1 | ||
174 | ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
175 | orr r3, r1, #OMAP1610_IDLE_LOOP_REQUEST & 0xffff | ||
176 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
177 | |||
178 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
179 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
180 | l_1610: subs r5, r5, #1 | ||
181 | bne l_1610 | ||
182 | /* | ||
183 | * Let's wait for the next clock tick to wake us up. | ||
184 | */ | ||
185 | mov r0, #0 | ||
186 | mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt | ||
187 | /* | ||
188 | * omap1610_idle_loop_suspend()'s resume point. | ||
189 | * | ||
190 | * It will just start executing here, so we'll restore stuff from the | ||
191 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
192 | */ | ||
193 | |||
194 | @ restore ARM_IDLECT1 and ARM_IDLECT2 and return | ||
195 | @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 | ||
196 | strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
197 | strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
198 | |||
199 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
200 | |||
201 | ENTRY(omap1610_idle_loop_suspend_sz) | ||
202 | .word . - omap1610_idle_loop_suspend | ||
203 | #endif /* CONFIG_ARCH_OMAP16XX */ | ||
204 | |||
205 | /* | ||
206 | * Forces OMAP into deep sleep state | ||
207 | * | ||
208 | * omapXXXX_cpu_suspend() | ||
209 | * | ||
210 | * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed | ||
211 | * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1 | ||
212 | * in register r1. | ||
213 | * | ||
214 | * Note: This code get's copied to internal SRAM at boot. When the OMAP | ||
215 | * wakes up it continues execution at the point it went to sleep. | ||
216 | * | ||
217 | * Note: Because of errata work arounds we have processor specific functions | ||
218 | * here. They are mostly the same, but slightly different. | ||
219 | * | ||
220 | */ | ||
221 | |||
222 | #if defined(CONFIG_ARCH_OMAP730) | ||
223 | ENTRY(omap730_cpu_suspend) | ||
224 | |||
225 | @ save registers on stack | ||
226 | stmfd sp!, {r0 - r12, lr} | ||
227 | |||
228 | @ Drain write cache | ||
229 | mov r4, #0 | ||
230 | mcr p15, 0, r0, c7, c10, 4 | ||
231 | nop | ||
232 | |||
233 | @ load base address of Traffic Controller | ||
234 | mov r6, #TCMIF_ASM_BASE & 0xff000000 | ||
235 | orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 | ||
236 | orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 | ||
237 | |||
238 | @ prepare to put SDRAM into self-refresh manually | ||
239 | ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
240 | orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 | ||
241 | orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff | ||
242 | str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
243 | |||
244 | @ prepare to put EMIFS to Sleep | ||
245 | ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
246 | orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff | ||
247 | str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
248 | |||
249 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
250 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
251 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
252 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
253 | |||
254 | @ turn off clock domains | ||
255 | @ do not disable PERCK (0x04) | ||
256 | mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff | ||
257 | orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 | ||
258 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
259 | |||
260 | @ request ARM idle | ||
261 | mov r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff | ||
262 | orr r3, r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff00 | ||
263 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
264 | |||
265 | @ disable instruction cache | ||
266 | mrc p15, 0, r9, c1, c0, 0 | ||
267 | bic r2, r9, #0x1000 | ||
268 | mcr p15, 0, r2, c1, c0, 0 | ||
269 | nop | ||
270 | |||
271 | /* | ||
272 | * Let's wait for the next wake up event to wake us up. r0 can't be | ||
273 | * used here because r0 holds ARM_IDLECT1 | ||
274 | */ | ||
275 | mov r2, #0 | ||
276 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | ||
277 | /* | ||
278 | * omap730_cpu_suspend()'s resume point. | ||
279 | * | ||
280 | * It will just start executing here, so we'll restore stuff from the | ||
281 | * stack. | ||
282 | */ | ||
283 | @ re-enable Icache | ||
284 | mcr p15, 0, r9, c1, c0, 0 | ||
285 | |||
286 | @ reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
287 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
288 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
289 | |||
290 | @ Restore EMIFF controls | ||
291 | str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
292 | str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
293 | |||
294 | @ restore regs and return | ||
295 | ldmfd sp!, {r0 - r12, pc} | ||
296 | |||
297 | ENTRY(omap730_cpu_suspend_sz) | ||
298 | .word . - omap730_cpu_suspend | ||
299 | #endif /* CONFIG_ARCH_OMAP730 */ | ||
300 | |||
301 | #ifdef CONFIG_ARCH_OMAP15XX | ||
302 | ENTRY(omap1510_cpu_suspend) | ||
303 | |||
304 | @ save registers on stack | ||
305 | stmfd sp!, {r0 - r12, lr} | ||
306 | |||
307 | @ load base address of Traffic Controller | ||
308 | mov r4, #TCMIF_ASM_BASE & 0xff000000 | ||
309 | orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000 | ||
310 | orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00 | ||
311 | |||
312 | @ work around errata of OMAP1510 PDE bit for TC shut down | ||
313 | @ clear PDE bit | ||
314 | ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
315 | bic r5, r5, #PDE_BIT & 0xff | ||
316 | str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
317 | |||
318 | @ set PWD_EN bit | ||
319 | and r5, r5, #PWD_EN_BIT & 0xff | ||
320 | str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
321 | |||
322 | @ prepare to put SDRAM into self-refresh manually | ||
323 | ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
324 | orr r5, r5, #SELF_REFRESH_MODE & 0xff000000 | ||
325 | orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff | ||
326 | str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
327 | |||
328 | @ prepare to put EMIFS to Sleep | ||
329 | ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
330 | orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff | ||
331 | str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
332 | |||
333 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
334 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
335 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
336 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
337 | |||
338 | @ turn off clock domains | ||
339 | mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff | ||
340 | orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 | ||
341 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
342 | |||
343 | @ request ARM idle | ||
344 | mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff | ||
345 | orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00 | ||
346 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
347 | |||
348 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
349 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
350 | l_1510_2: | ||
351 | subs r5, r5, #1 | ||
352 | bne l_1510_2 | ||
353 | /* | ||
354 | * Let's wait for the next wake up event to wake us up. r0 can't be | ||
355 | * used here because r0 holds ARM_IDLECT1 | ||
356 | */ | ||
357 | mov r2, #0 | ||
358 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | ||
359 | /* | ||
360 | * omap1510_cpu_suspend()'s resume point. | ||
361 | * | ||
362 | * It will just start executing here, so we'll restore stuff from the | ||
363 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
364 | */ | ||
365 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
366 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
367 | |||
368 | @ restore regs and return | ||
369 | ldmfd sp!, {r0 - r12, pc} | ||
370 | |||
371 | ENTRY(omap1510_cpu_suspend_sz) | ||
372 | .word . - omap1510_cpu_suspend | ||
373 | #endif /* CONFIG_ARCH_OMAP15XX */ | ||
374 | |||
375 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
376 | ENTRY(omap1610_cpu_suspend) | ||
377 | |||
378 | @ save registers on stack | ||
379 | stmfd sp!, {r0 - r12, lr} | ||
380 | |||
381 | @ Drain write cache | ||
382 | mov r4, #0 | ||
383 | mcr p15, 0, r0, c7, c10, 4 | ||
384 | nop | ||
385 | |||
386 | @ load base address of Traffic Controller | ||
387 | mov r6, #TCMIF_ASM_BASE & 0xff000000 | ||
388 | orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 | ||
389 | orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 | ||
390 | |||
391 | @ prepare to put SDRAM into self-refresh manually | ||
392 | ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
393 | orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 | ||
394 | orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff | ||
395 | str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
396 | |||
397 | @ prepare to put EMIFS to Sleep | ||
398 | ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
399 | orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff | ||
400 | str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
401 | |||
402 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
403 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
404 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
405 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
406 | |||
407 | @ turn off clock domains | ||
408 | @ do not disable PERCK (0x04) | ||
409 | mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff | ||
410 | orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 | ||
411 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
412 | |||
413 | @ request ARM idle | ||
414 | mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff | ||
415 | orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00 | ||
416 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
417 | |||
418 | @ disable instruction cache | ||
419 | mrc p15, 0, r9, c1, c0, 0 | ||
420 | bic r2, r9, #0x1000 | ||
421 | mcr p15, 0, r2, c1, c0, 0 | ||
422 | nop | ||
423 | |||
424 | /* | ||
425 | * Let's wait for the next wake up event to wake us up. r0 can't be | ||
426 | * used here because r0 holds ARM_IDLECT1 | ||
427 | */ | ||
428 | mov r2, #0 | ||
429 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | ||
430 | /* | ||
431 | * omap1610_cpu_suspend()'s resume point. | ||
432 | * | ||
433 | * It will just start executing here, so we'll restore stuff from the | ||
434 | * stack. | ||
435 | */ | ||
436 | @ re-enable Icache | ||
437 | mcr p15, 0, r9, c1, c0, 0 | ||
438 | |||
439 | @ reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
440 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
441 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
442 | |||
443 | @ Restore EMIFF controls | ||
444 | str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
445 | str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
446 | |||
447 | @ restore regs and return | ||
448 | ldmfd sp!, {r0 - r12, pc} | ||
449 | |||
450 | ENTRY(omap1610_cpu_suspend_sz) | ||
451 | .word . - omap1610_cpu_suspend | ||
452 | #endif /* CONFIG_ARCH_OMAP16XX */ | ||
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index ee82763b02b8..b7bf09b1b412 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c | |||
@@ -16,24 +16,94 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | 18 | ||
19 | #include <asm/mach/map.h> | ||
20 | #include <asm/tlb.h> | 19 | #include <asm/tlb.h> |
21 | #include <asm/io.h> | 20 | #include <asm/io.h> |
22 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
23 | 22 | ||
23 | #include <asm/mach/map.h> | ||
24 | |||
24 | #include <asm/arch/sram.h> | 25 | #include <asm/arch/sram.h> |
26 | #include <asm/arch/board.h> | ||
25 | 27 | ||
26 | #define OMAP1_SRAM_PA 0x20000000 | 28 | #define OMAP1_SRAM_PA 0x20000000 |
27 | #define OMAP1_SRAM_VA 0xd0000000 | 29 | #define OMAP1_SRAM_VA 0xd0000000 |
28 | #define OMAP2_SRAM_PA 0x40200000 | 30 | #define OMAP2_SRAM_PA 0x40200000 |
31 | #define OMAP2_SRAM_PUB_PA 0x4020f800 | ||
29 | #define OMAP2_SRAM_VA 0xd0000000 | 32 | #define OMAP2_SRAM_VA 0xd0000000 |
33 | #define OMAP2_SRAM_PUB_VA 0xd0000800 | ||
30 | 34 | ||
35 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
36 | #define SRAM_BOOTLOADER_SZ 0x00 | ||
37 | #else | ||
31 | #define SRAM_BOOTLOADER_SZ 0x80 | 38 | #define SRAM_BOOTLOADER_SZ 0x80 |
39 | #endif | ||
40 | |||
41 | #define VA_REQINFOPERM0 IO_ADDRESS(0x68005048) | ||
42 | #define VA_READPERM0 IO_ADDRESS(0x68005050) | ||
43 | #define VA_WRITEPERM0 IO_ADDRESS(0x68005058) | ||
44 | #define VA_CONTROL_STAT IO_ADDRESS(0x480002F8) | ||
45 | #define GP_DEVICE 0x300 | ||
46 | #define TYPE_MASK 0x700 | ||
47 | |||
48 | #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) | ||
32 | 49 | ||
33 | static unsigned long omap_sram_base; | 50 | static unsigned long omap_sram_base; |
34 | static unsigned long omap_sram_size; | 51 | static unsigned long omap_sram_size; |
35 | static unsigned long omap_sram_ceil; | 52 | static unsigned long omap_sram_ceil; |
36 | 53 | ||
54 | unsigned long omap_fb_sram_start; | ||
55 | unsigned long omap_fb_sram_size; | ||
56 | |||
57 | /* Depending on the target RAMFS firewall setup, the public usable amount of | ||
58 | * SRAM varies. The default accessable size for all device types is 2k. A GP | ||
59 | * device allows ARM11 but not other initators for full size. This | ||
60 | * functionality seems ok until some nice security API happens. | ||
61 | */ | ||
62 | static int is_sram_locked(void) | ||
63 | { | ||
64 | int type = 0; | ||
65 | |||
66 | if (cpu_is_omap242x()) | ||
67 | type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK; | ||
68 | |||
69 | if (type == GP_DEVICE) { | ||
70 | /* RAMFW: R/W access to all initators for all qualifier sets */ | ||
71 | if (cpu_is_omap242x()) { | ||
72 | __raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */ | ||
73 | __raw_writel(0xCFDE, VA_READPERM0); /* all i-read */ | ||
74 | __raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */ | ||
75 | } | ||
76 | return 0; | ||
77 | } else | ||
78 | return 1; /* assume locked with no PPA or security driver */ | ||
79 | } | ||
80 | |||
81 | void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, | ||
82 | unsigned long *start, unsigned long *size) | ||
83 | { | ||
84 | const struct omap_fbmem_config *fbmem_conf; | ||
85 | |||
86 | fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); | ||
87 | if (fbmem_conf != NULL) { | ||
88 | *start = fbmem_conf->fb_sram_start; | ||
89 | *size = fbmem_conf->fb_sram_size; | ||
90 | } else { | ||
91 | *size = 0; | ||
92 | *start = 0; | ||
93 | } | ||
94 | |||
95 | if (*size && ( | ||
96 | *start < start_avail || | ||
97 | *start + *size > start_avail + size_avail)) { | ||
98 | printk(KERN_ERR "invalid FB SRAM configuration\n"); | ||
99 | *start = start_avail; | ||
100 | *size = size_avail; | ||
101 | } | ||
102 | |||
103 | if (*size) | ||
104 | pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size); | ||
105 | } | ||
106 | |||
37 | /* | 107 | /* |
38 | * The amount of SRAM depends on the core type. | 108 | * The amount of SRAM depends on the core type. |
39 | * Note that we cannot try to test for SRAM here because writes | 109 | * Note that we cannot try to test for SRAM here because writes |
@@ -42,26 +112,45 @@ static unsigned long omap_sram_ceil; | |||
42 | */ | 112 | */ |
43 | void __init omap_detect_sram(void) | 113 | void __init omap_detect_sram(void) |
44 | { | 114 | { |
45 | if (!cpu_is_omap24xx()) | 115 | unsigned long sram_start; |
116 | |||
117 | if (cpu_is_omap24xx()) { | ||
118 | if (is_sram_locked()) { | ||
119 | omap_sram_base = OMAP2_SRAM_PUB_VA; | ||
120 | sram_start = OMAP2_SRAM_PUB_PA; | ||
121 | omap_sram_size = 0x800; /* 2K */ | ||
122 | } else { | ||
123 | omap_sram_base = OMAP2_SRAM_VA; | ||
124 | sram_start = OMAP2_SRAM_PA; | ||
125 | if (cpu_is_omap242x()) | ||
126 | omap_sram_size = 0xa0000; /* 640K */ | ||
127 | else if (cpu_is_omap243x()) | ||
128 | omap_sram_size = 0x10000; /* 64K */ | ||
129 | } | ||
130 | } else { | ||
46 | omap_sram_base = OMAP1_SRAM_VA; | 131 | omap_sram_base = OMAP1_SRAM_VA; |
47 | else | 132 | sram_start = OMAP1_SRAM_PA; |
48 | omap_sram_base = OMAP2_SRAM_VA; | 133 | |
49 | 134 | if (cpu_is_omap730()) | |
50 | if (cpu_is_omap730()) | 135 | omap_sram_size = 0x32000; /* 200K */ |
51 | omap_sram_size = 0x32000; /* 200K */ | 136 | else if (cpu_is_omap15xx()) |
52 | else if (cpu_is_omap15xx()) | 137 | omap_sram_size = 0x30000; /* 192K */ |
53 | omap_sram_size = 0x30000; /* 192K */ | 138 | else if (cpu_is_omap1610() || cpu_is_omap1621() || |
54 | else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710()) | 139 | cpu_is_omap1710()) |
55 | omap_sram_size = 0x4000; /* 16K */ | 140 | omap_sram_size = 0x4000; /* 16K */ |
56 | else if (cpu_is_omap1611()) | 141 | else if (cpu_is_omap1611()) |
57 | omap_sram_size = 0x3e800; /* 250K */ | 142 | omap_sram_size = 0x3e800; /* 250K */ |
58 | else if (cpu_is_omap2420()) | 143 | else { |
59 | omap_sram_size = 0xa0014; /* 640K */ | 144 | printk(KERN_ERR "Could not detect SRAM size\n"); |
60 | else { | 145 | omap_sram_size = 0x4000; |
61 | printk(KERN_ERR "Could not detect SRAM size\n"); | 146 | } |
62 | omap_sram_size = 0x4000; | ||
63 | } | 147 | } |
64 | 148 | get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ, | |
149 | omap_sram_size - SRAM_BOOTLOADER_SZ, | ||
150 | &omap_fb_sram_start, &omap_fb_sram_size); | ||
151 | if (omap_fb_sram_size) | ||
152 | omap_sram_size -= sram_start + omap_sram_size - | ||
153 | omap_fb_sram_start; | ||
65 | omap_sram_ceil = omap_sram_base + omap_sram_size; | 154 | omap_sram_ceil = omap_sram_base + omap_sram_size; |
66 | } | 155 | } |
67 | 156 | ||
@@ -80,12 +169,20 @@ static struct map_desc omap_sram_io_desc[] __initdata = { | |||
80 | */ | 169 | */ |
81 | void __init omap_map_sram(void) | 170 | void __init omap_map_sram(void) |
82 | { | 171 | { |
172 | unsigned long base; | ||
173 | |||
83 | if (omap_sram_size == 0) | 174 | if (omap_sram_size == 0) |
84 | return; | 175 | return; |
85 | 176 | ||
86 | if (cpu_is_omap24xx()) { | 177 | if (cpu_is_omap24xx()) { |
87 | omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; | 178 | omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; |
88 | omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA); | 179 | |
180 | if (is_sram_locked()) | ||
181 | base = OMAP2_SRAM_PUB_PA; | ||
182 | else | ||
183 | base = OMAP2_SRAM_PA; | ||
184 | base = ROUND_DOWN(base, PAGE_SIZE); | ||
185 | omap_sram_io_desc[0].pfn = __phys_to_pfn(base); | ||
89 | } | 186 | } |
90 | 187 | ||
91 | omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; | 188 | omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; |
@@ -93,7 +190,8 @@ void __init omap_map_sram(void) | |||
93 | iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); | 190 | iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); |
94 | 191 | ||
95 | printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", | 192 | printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", |
96 | omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual, | 193 | __pfn_to_phys(omap_sram_io_desc[0].pfn), |
194 | omap_sram_io_desc[0].virtual, | ||
97 | omap_sram_io_desc[0].length); | 195 | omap_sram_io_desc[0].length); |
98 | 196 | ||
99 | /* | 197 | /* |
@@ -118,8 +216,9 @@ void * omap_sram_push(void * start, unsigned long size) | |||
118 | printk(KERN_ERR "Not enough space in SRAM\n"); | 216 | printk(KERN_ERR "Not enough space in SRAM\n"); |
119 | return NULL; | 217 | return NULL; |
120 | } | 218 | } |
219 | |||
121 | omap_sram_ceil -= size; | 220 | omap_sram_ceil -= size; |
122 | omap_sram_ceil &= ~0x3; | 221 | omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *)); |
123 | memcpy((void *)omap_sram_ceil, start, size); | 222 | memcpy((void *)omap_sram_ceil, start, size); |
124 | 223 | ||
125 | return (void *)omap_sram_ceil; | 224 | return (void *)omap_sram_ceil; |
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c new file mode 100644 index 000000000000..b2a943bf11ef --- /dev/null +++ b/arch/arm/plat-omap/timer32k.c | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/timer32k.c | ||
3 | * | ||
4 | * OMAP 32K Timer | ||
5 | * | ||
6 | * Copyright (C) 2004 - 2005 Nokia Corporation | ||
7 | * Partial timer rewrite and additional dynamic tick timer support by | ||
8 | * Tony Lindgen <tony@atomide.com> and | ||
9 | * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
10 | * | ||
11 | * MPU timer code based on the older MPU timer code for OMAP | ||
12 | * Copyright (C) 2000 RidgeRun, Inc. | ||
13 | * Author: Greg Lonnon <glonnon@ridgerun.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2 of the License, or (at your | ||
18 | * option) any later version. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
22 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
23 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
26 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
29 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License along | ||
32 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
33 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
34 | */ | ||
35 | |||
36 | #include <linux/config.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/sched.h> | ||
42 | #include <linux/spinlock.h> | ||
43 | #include <linux/err.h> | ||
44 | #include <linux/clk.h> | ||
45 | |||
46 | #include <asm/system.h> | ||
47 | #include <asm/hardware.h> | ||
48 | #include <asm/io.h> | ||
49 | #include <asm/leds.h> | ||
50 | #include <asm/irq.h> | ||
51 | #include <asm/mach/irq.h> | ||
52 | #include <asm/mach/time.h> | ||
53 | |||
54 | struct sys_timer omap_timer; | ||
55 | |||
56 | /* | ||
57 | * --------------------------------------------------------------------------- | ||
58 | * 32KHz OS timer | ||
59 | * | ||
60 | * This currently works only on 16xx, as 1510 does not have the continuous | ||
61 | * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track | ||
62 | * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer | ||
63 | * on 1510 would be possible, but the timer would not be as accurate as | ||
64 | * with the 32KHz synchronized timer. | ||
65 | * --------------------------------------------------------------------------- | ||
66 | */ | ||
67 | |||
68 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
69 | #define TIMER_32K_SYNCHRONIZED 0xfffbc410 | ||
70 | #elif defined(CONFIG_ARCH_OMAP24XX) | ||
71 | #define TIMER_32K_SYNCHRONIZED 0x48004010 | ||
72 | #else | ||
73 | #error OMAP 32KHz timer does not currently work on 15XX! | ||
74 | #endif | ||
75 | |||
76 | /* 16xx specific defines */ | ||
77 | #define OMAP1_32K_TIMER_BASE 0xfffb9000 | ||
78 | #define OMAP1_32K_TIMER_CR 0x08 | ||
79 | #define OMAP1_32K_TIMER_TVR 0x00 | ||
80 | #define OMAP1_32K_TIMER_TCR 0x04 | ||
81 | |||
82 | /* 24xx specific defines */ | ||
83 | #define OMAP2_GP_TIMER_BASE 0x48028000 | ||
84 | #define CM_CLKSEL_WKUP 0x48008440 | ||
85 | #define GP_TIMER_TIDR 0x00 | ||
86 | #define GP_TIMER_TISR 0x18 | ||
87 | #define GP_TIMER_TIER 0x1c | ||
88 | #define GP_TIMER_TCLR 0x24 | ||
89 | #define GP_TIMER_TCRR 0x28 | ||
90 | #define GP_TIMER_TLDR 0x2c | ||
91 | #define GP_TIMER_TTGR 0x30 | ||
92 | #define GP_TIMER_TSICR 0x40 | ||
93 | |||
94 | #define OMAP_32K_TICKS_PER_HZ (32768 / HZ) | ||
95 | |||
96 | /* | ||
97 | * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1 | ||
98 | * so with HZ = 128, TVR = 255. | ||
99 | */ | ||
100 | #define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1) | ||
101 | |||
102 | #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ | ||
103 | (((nr_jiffies) * (clock_rate)) / HZ) | ||
104 | |||
105 | static inline void omap_32k_timer_write(int val, int reg) | ||
106 | { | ||
107 | if (cpu_class_is_omap1()) | ||
108 | omap_writew(val, OMAP1_32K_TIMER_BASE + reg); | ||
109 | |||
110 | if (cpu_is_omap24xx()) | ||
111 | omap_writel(val, OMAP2_GP_TIMER_BASE + reg); | ||
112 | } | ||
113 | |||
114 | static inline unsigned long omap_32k_timer_read(int reg) | ||
115 | { | ||
116 | if (cpu_class_is_omap1()) | ||
117 | return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff; | ||
118 | |||
119 | if (cpu_is_omap24xx()) | ||
120 | return omap_readl(OMAP2_GP_TIMER_BASE + reg); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * The 32KHz synchronized timer is an additional timer on 16xx. | ||
125 | * It is always running. | ||
126 | */ | ||
127 | static inline unsigned long omap_32k_sync_timer_read(void) | ||
128 | { | ||
129 | return omap_readl(TIMER_32K_SYNCHRONIZED); | ||
130 | } | ||
131 | |||
132 | static inline void omap_32k_timer_start(unsigned long load_val) | ||
133 | { | ||
134 | if (cpu_class_is_omap1()) { | ||
135 | omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR); | ||
136 | omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR); | ||
137 | } | ||
138 | |||
139 | if (cpu_is_omap24xx()) { | ||
140 | omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR); | ||
141 | omap_32k_timer_write((1 << 1), GP_TIMER_TIER); | ||
142 | omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static inline void omap_32k_timer_stop(void) | ||
147 | { | ||
148 | if (cpu_class_is_omap1()) | ||
149 | omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR); | ||
150 | |||
151 | if (cpu_is_omap24xx()) | ||
152 | omap_32k_timer_write(0x0, GP_TIMER_TCLR); | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Rounds down to nearest usec. Note that this will overflow for larger values. | ||
157 | */ | ||
158 | static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k) | ||
159 | { | ||
160 | return (ticks_32k * 5*5*5*5*5*5) >> 9; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Rounds down to nearest nsec. | ||
165 | */ | ||
166 | static inline unsigned long long | ||
167 | omap_32k_ticks_to_nsecs(unsigned long ticks_32k) | ||
168 | { | ||
169 | return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9; | ||
170 | } | ||
171 | |||
172 | static unsigned long omap_32k_last_tick = 0; | ||
173 | |||
174 | /* | ||
175 | * Returns elapsed usecs since last 32k timer interrupt | ||
176 | */ | ||
177 | static unsigned long omap_32k_timer_gettimeoffset(void) | ||
178 | { | ||
179 | unsigned long now = omap_32k_sync_timer_read(); | ||
180 | return omap_32k_ticks_to_usecs(now - omap_32k_last_tick); | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * Returns current time from boot in nsecs. It's OK for this to wrap | ||
185 | * around for now, as it's just a relative time stamp. | ||
186 | */ | ||
187 | unsigned long long sched_clock(void) | ||
188 | { | ||
189 | return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read()); | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this | ||
194 | * function is also called from other interrupts to remove latency | ||
195 | * issues with dynamic tick. In the dynamic tick case, we need to lock | ||
196 | * with irqsave. | ||
197 | */ | ||
198 | static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, | ||
199 | struct pt_regs *regs) | ||
200 | { | ||
201 | unsigned long flags; | ||
202 | unsigned long now; | ||
203 | |||
204 | write_seqlock_irqsave(&xtime_lock, flags); | ||
205 | |||
206 | if (cpu_is_omap24xx()) { | ||
207 | u32 status = omap_32k_timer_read(GP_TIMER_TISR); | ||
208 | omap_32k_timer_write(status, GP_TIMER_TISR); | ||
209 | } | ||
210 | |||
211 | now = omap_32k_sync_timer_read(); | ||
212 | |||
213 | while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) { | ||
214 | omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; | ||
215 | timer_tick(regs); | ||
216 | } | ||
217 | |||
218 | /* Restart timer so we don't drift off due to modulo or dynamic tick. | ||
219 | * By default we program the next timer to be continuous to avoid | ||
220 | * latencies during high system load. During dynamic tick operation the | ||
221 | * continuous timer can be overridden from pm_idle to be longer. | ||
222 | */ | ||
223 | omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now); | ||
224 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
225 | |||
226 | return IRQ_HANDLED; | ||
227 | } | ||
228 | |||
229 | #ifdef CONFIG_NO_IDLE_HZ | ||
230 | /* | ||
231 | * Programs the next timer interrupt needed. Called when dynamic tick is | ||
232 | * enabled, and to reprogram the ticks to skip from pm_idle. Note that | ||
233 | * we can keep the timer continuous, and don't need to set it to run in | ||
234 | * one-shot mode. This is because the timer will get reprogrammed again | ||
235 | * after next interrupt. | ||
236 | */ | ||
237 | void omap_32k_timer_reprogram(unsigned long next_tick) | ||
238 | { | ||
239 | omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1); | ||
240 | } | ||
241 | |||
242 | static struct irqaction omap_32k_timer_irq; | ||
243 | extern struct timer_update_handler timer_update; | ||
244 | |||
245 | static int omap_32k_timer_enable_dyn_tick(void) | ||
246 | { | ||
247 | /* No need to reprogram timer, just use the next interrupt */ | ||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int omap_32k_timer_disable_dyn_tick(void) | ||
252 | { | ||
253 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static struct dyn_tick_timer omap_dyn_tick_timer = { | ||
258 | .enable = omap_32k_timer_enable_dyn_tick, | ||
259 | .disable = omap_32k_timer_disable_dyn_tick, | ||
260 | .reprogram = omap_32k_timer_reprogram, | ||
261 | .handler = omap_32k_timer_interrupt, | ||
262 | }; | ||
263 | #endif /* CONFIG_NO_IDLE_HZ */ | ||
264 | |||
265 | static struct irqaction omap_32k_timer_irq = { | ||
266 | .name = "32KHz timer", | ||
267 | .flags = SA_INTERRUPT | SA_TIMER, | ||
268 | .handler = omap_32k_timer_interrupt, | ||
269 | }; | ||
270 | |||
271 | static struct clk * gpt1_ick; | ||
272 | static struct clk * gpt1_fck; | ||
273 | |||
274 | static __init void omap_init_32k_timer(void) | ||
275 | { | ||
276 | #ifdef CONFIG_NO_IDLE_HZ | ||
277 | omap_timer.dyn_tick = &omap_dyn_tick_timer; | ||
278 | #endif | ||
279 | |||
280 | if (cpu_class_is_omap1()) | ||
281 | setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); | ||
282 | if (cpu_is_omap24xx()) | ||
283 | setup_irq(37, &omap_32k_timer_irq); | ||
284 | omap_timer.offset = omap_32k_timer_gettimeoffset; | ||
285 | omap_32k_last_tick = omap_32k_sync_timer_read(); | ||
286 | |||
287 | /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */ | ||
288 | if (cpu_is_omap24xx()) { | ||
289 | omap_32k_timer_write(0, GP_TIMER_TCLR); | ||
290 | omap_writel(0, CM_CLKSEL_WKUP); /* 32KHz clock source */ | ||
291 | |||
292 | gpt1_ick = clk_get(NULL, "gpt1_ick"); | ||
293 | if (IS_ERR(gpt1_ick)) | ||
294 | printk(KERN_ERR "Could not get gpt1_ick\n"); | ||
295 | else | ||
296 | clk_enable(gpt1_ick); | ||
297 | |||
298 | gpt1_fck = clk_get(NULL, "gpt1_fck"); | ||
299 | if (IS_ERR(gpt1_fck)) | ||
300 | printk(KERN_ERR "Could not get gpt1_fck\n"); | ||
301 | else | ||
302 | clk_enable(gpt1_fck); | ||
303 | |||
304 | mdelay(100); /* Wait for clocks to stabilize */ | ||
305 | |||
306 | omap_32k_timer_write(0x7, GP_TIMER_TISR); | ||
307 | } | ||
308 | |||
309 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * --------------------------------------------------------------------------- | ||
314 | * Timer initialization | ||
315 | * --------------------------------------------------------------------------- | ||
316 | */ | ||
317 | static void __init omap_timer_init(void) | ||
318 | { | ||
319 | omap_init_32k_timer(); | ||
320 | } | ||
321 | |||
322 | struct sys_timer omap_timer = { | ||
323 | .init = omap_timer_init, | ||
324 | .offset = NULL, /* Initialized later */ | ||
325 | }; | ||