diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 16:05:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 16:05:57 -0400 |
commit | 932c37c375cca25175f9b6acee4c75d7a96d985f (patch) | |
tree | d7ba3620cd9a7a21c2de1bdfc7badd7637ed635e /arch/arm/plat-omap | |
parent | c855ff3718e5f667b463b20b9de516b4cd7625ad (diff) | |
parent | 805f53f085346b6765eda02820721a14ce0d644f (diff) |
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (28 commits)
ARM: OMAP: Fix GCC-reported compile time bug
ARM: OMAP: restore CONFIG_GENERIC_TIME
ARM: OMAP: partial LED fixes
ARM: OMAP: add SoSSI clock (call propagate_rate for childrens)
ARM: OMAP: FB sync with N800 tree (support for dynamic SRAM allocations)
ARM: OMAP: Sync framebuffer headers with N800 tree
ARM: OMAP: Mostly cosmetic to sync up with linux-omap tree
ARM: OMAP: Fix gpmc header
ARM: OMAP: Add mailbox support for IVA
[ARM] armv7: add Makefile and Kconfig entries
[ARM] armv7: add support for asid-tagged VIVT I-cache
[ARM] armv7: add dedicated ARMv7 barrier instructions
[ARM] armv7: Add ARMv7 cacheid macros
[ARM] armv7: add support for ARMv7 cores.
[ARM] Fix ARM branch relocation range
[ARM] 4363/1: AT91: Remove legacy PIO definitions
[ARM] 4361/1: AT91: Build error
ARM: OMAP: Sync core code with linux-omap
ARM: OMAP: Sync headers with linux-omap
ARM: OMAP: h4 must have blinky leds!!
...
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/Kconfig | 13 | ||||
-rw-r--r-- | arch/arm/plat-omap/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/plat-omap/clock.c | 37 | ||||
-rw-r--r-- | arch/arm/plat-omap/common.c | 8 | ||||
-rw-r--r-- | arch/arm/plat-omap/debug-leds.c | 314 | ||||
-rw-r--r-- | arch/arm/plat-omap/devices.c | 74 | ||||
-rw-r--r-- | arch/arm/plat-omap/dma.c | 25 | ||||
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 2 | ||||
-rw-r--r-- | arch/arm/plat-omap/fb.c | 305 | ||||
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 3 | ||||
-rw-r--r-- | arch/arm/plat-omap/mailbox.c | 509 | ||||
-rw-r--r-- | arch/arm/plat-omap/mailbox.h | 100 | ||||
-rw-r--r-- | arch/arm/plat-omap/sram.c | 56 | ||||
-rw-r--r-- | arch/arm/plat-omap/usb.c | 199 |
14 files changed, 1532 insertions, 118 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 9e8d21eca4ec..cfc69f3842fd 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
@@ -20,6 +20,11 @@ endchoice | |||
20 | 20 | ||
21 | comment "OMAP Feature Selections" | 21 | comment "OMAP Feature Selections" |
22 | 22 | ||
23 | config OMAP_DEBUG_LEDS | ||
24 | bool | ||
25 | help | ||
26 | For debug card leds on TI reference boards. | ||
27 | |||
23 | config OMAP_RESET_CLOCKS | 28 | config OMAP_RESET_CLOCKS |
24 | bool "Reset unused clocks during boot" | 29 | bool "Reset unused clocks during boot" |
25 | depends on ARCH_OMAP | 30 | depends on ARCH_OMAP |
@@ -58,6 +63,14 @@ config OMAP_MUX_WARNINGS | |||
58 | to change the pin multiplexing setup. When there are no warnings | 63 | to change the pin multiplexing setup. When there are no warnings |
59 | printed, it's safe to deselect OMAP_MUX for your product. | 64 | printed, it's safe to deselect OMAP_MUX for your product. |
60 | 65 | ||
66 | config OMAP_MCBSP | ||
67 | bool "McBSP support" | ||
68 | depends on ARCH_OMAP | ||
69 | default y | ||
70 | help | ||
71 | Say Y here if you want support for the OMAP Multichannel | ||
72 | Buffered Serial Port. | ||
73 | |||
61 | choice | 74 | choice |
62 | prompt "System timer" | 75 | prompt "System timer" |
63 | default OMAP_MPU_TIMER | 76 | default OMAP_MPU_TIMER |
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 2896b4546411..41a3c1cf3bd4 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile | |||
@@ -3,7 +3,8 @@ | |||
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 fb.o | 6 | obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o \ |
7 | usb.o fb.o | ||
7 | obj-m := | 8 | obj-m := |
8 | obj-n := | 9 | obj-n := |
9 | obj- := | 10 | obj- := |
@@ -16,4 +17,4 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o | |||
16 | 17 | ||
17 | obj-$(CONFIG_CPU_FREQ) += cpu-omap.o | 18 | obj-$(CONFIG_CPU_FREQ) += cpu-omap.o |
18 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o | 19 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o |
19 | 20 | obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o | |
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index f1179ad4be1b..0a603242f367 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c | |||
@@ -33,6 +33,41 @@ static DEFINE_SPINLOCK(clockfw_lock); | |||
33 | 33 | ||
34 | static struct clk_functions *arch_clock; | 34 | static struct clk_functions *arch_clock; |
35 | 35 | ||
36 | #ifdef CONFIG_PM_DEBUG | ||
37 | |||
38 | static void print_parents(struct clk *clk) | ||
39 | { | ||
40 | struct clk *p; | ||
41 | int printed = 0; | ||
42 | |||
43 | list_for_each_entry(p, &clocks, node) { | ||
44 | if (p->parent == clk && p->usecount) { | ||
45 | if (!clk->usecount && !printed) { | ||
46 | printk("MISMATCH: %s\n", clk->name); | ||
47 | printed = 1; | ||
48 | } | ||
49 | printk("\t%-15s\n", p->name); | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | void clk_print_usecounts(void) | ||
55 | { | ||
56 | unsigned long flags; | ||
57 | struct clk *p; | ||
58 | |||
59 | spin_lock_irqsave(&clockfw_lock, flags); | ||
60 | list_for_each_entry(p, &clocks, node) { | ||
61 | if (p->usecount) | ||
62 | printk("%-15s: %d\n", p->name, p->usecount); | ||
63 | print_parents(p); | ||
64 | |||
65 | } | ||
66 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
67 | } | ||
68 | |||
69 | #endif | ||
70 | |||
36 | /*------------------------------------------------------------------------- | 71 | /*------------------------------------------------------------------------- |
37 | * Standard clock functions defined in include/linux/clk.h | 72 | * Standard clock functions defined in include/linux/clk.h |
38 | *-------------------------------------------------------------------------*/ | 73 | *-------------------------------------------------------------------------*/ |
@@ -249,6 +284,8 @@ void followparent_recalc(struct clk *clk) | |||
249 | return; | 284 | return; |
250 | 285 | ||
251 | clk->rate = clk->parent->rate; | 286 | clk->rate = clk->parent->rate; |
287 | if (unlikely(clk->flags & RATE_PROPAGATES)) | ||
288 | propagate_rate(clk); | ||
252 | } | 289 | } |
253 | 290 | ||
254 | /* Propagate rate to children */ | 291 | /* Propagate rate to children */ |
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index fecd3d625995..dd8708ad0a71 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c | |||
@@ -93,8 +93,12 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) | |||
93 | * in the kernel. */ | 93 | * in the kernel. */ |
94 | for (i = 0; i < omap_board_config_size; i++) { | 94 | for (i = 0; i < omap_board_config_size; i++) { |
95 | if (omap_board_config[i].tag == tag) { | 95 | if (omap_board_config[i].tag == tag) { |
96 | kinfo = &omap_board_config[i]; | 96 | if (skip == 0) { |
97 | break; | 97 | kinfo = &omap_board_config[i]; |
98 | break; | ||
99 | } else { | ||
100 | skip--; | ||
101 | } | ||
98 | } | 102 | } |
99 | } | 103 | } |
100 | if (kinfo == NULL) | 104 | if (kinfo == NULL) |
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c new file mode 100644 index 000000000000..9128a80d228f --- /dev/null +++ b/arch/arm/plat-omap/debug-leds.c | |||
@@ -0,0 +1,314 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/debug-leds.c | ||
3 | * | ||
4 | * Copyright 2003 by Texas Instruments Incorporated | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/leds.h> | ||
14 | |||
15 | #include <asm/io.h> | ||
16 | #include <asm/hardware.h> | ||
17 | #include <asm/leds.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/mach-types.h> | ||
20 | |||
21 | #include <asm/arch/fpga.h> | ||
22 | #include <asm/arch/gpio.h> | ||
23 | |||
24 | |||
25 | /* Many OMAP development platforms reuse the same "debug board"; these | ||
26 | * platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the | ||
27 | * debug board (all green), accessed through FPGA registers. | ||
28 | * | ||
29 | * The "surfer" expansion board and H2 sample board also have two-color | ||
30 | * green+red LEDs (in parallel), used here for timer and idle indicators | ||
31 | * in preference to the ones on the debug board, for a "Disco LED" effect. | ||
32 | * | ||
33 | * This driver exports either the original ARM LED API, the new generic | ||
34 | * one, or both. | ||
35 | */ | ||
36 | |||
37 | static spinlock_t lock; | ||
38 | static struct h2p2_dbg_fpga __iomem *fpga; | ||
39 | static u16 led_state, hw_led_state; | ||
40 | |||
41 | |||
42 | #ifdef CONFIG_LEDS_OMAP_DEBUG | ||
43 | #define new_led_api() 1 | ||
44 | #else | ||
45 | #define new_led_api() 0 | ||
46 | #endif | ||
47 | |||
48 | |||
49 | /*-------------------------------------------------------------------------*/ | ||
50 | |||
51 | /* original ARM debug LED API: | ||
52 | * - timer and idle leds (some boards use non-FPGA leds here); | ||
53 | * - up to 4 generic leds, easily accessed in-kernel (any context) | ||
54 | */ | ||
55 | |||
56 | #define GPIO_LED_RED 3 | ||
57 | #define GPIO_LED_GREEN OMAP_MPUIO(4) | ||
58 | |||
59 | #define LED_STATE_ENABLED 0x01 | ||
60 | #define LED_STATE_CLAIMED 0x02 | ||
61 | #define LED_TIMER_ON 0x04 | ||
62 | |||
63 | #define GPIO_IDLE GPIO_LED_GREEN | ||
64 | #define GPIO_TIMER GPIO_LED_RED | ||
65 | |||
66 | static void h2p2_dbg_leds_event(led_event_t evt) | ||
67 | { | ||
68 | unsigned long flags; | ||
69 | |||
70 | spin_lock_irqsave(&lock, flags); | ||
71 | |||
72 | if (!(led_state & LED_STATE_ENABLED) && evt != led_start) | ||
73 | goto done; | ||
74 | |||
75 | switch (evt) { | ||
76 | case led_start: | ||
77 | if (fpga) | ||
78 | led_state |= LED_STATE_ENABLED; | ||
79 | break; | ||
80 | |||
81 | case led_stop: | ||
82 | case led_halted: | ||
83 | /* all leds off during suspend or shutdown */ | ||
84 | |||
85 | if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) { | ||
86 | omap_set_gpio_dataout(GPIO_TIMER, 0); | ||
87 | omap_set_gpio_dataout(GPIO_IDLE, 0); | ||
88 | } | ||
89 | |||
90 | __raw_writew(~0, &fpga->leds); | ||
91 | led_state &= ~LED_STATE_ENABLED; | ||
92 | goto done; | ||
93 | |||
94 | case led_claim: | ||
95 | led_state |= LED_STATE_CLAIMED; | ||
96 | hw_led_state = 0; | ||
97 | break; | ||
98 | |||
99 | case led_release: | ||
100 | led_state &= ~LED_STATE_CLAIMED; | ||
101 | break; | ||
102 | |||
103 | #ifdef CONFIG_LEDS_TIMER | ||
104 | case led_timer: | ||
105 | led_state ^= LED_TIMER_ON; | ||
106 | |||
107 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
108 | hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; | ||
109 | else { | ||
110 | omap_set_gpio_dataout(GPIO_TIMER, | ||
111 | led_state & LED_TIMER_ON); | ||
112 | goto done; | ||
113 | } | ||
114 | |||
115 | break; | ||
116 | #endif | ||
117 | |||
118 | #ifdef CONFIG_LEDS_CPU | ||
119 | /* LED lit iff busy */ | ||
120 | case led_idle_start: | ||
121 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
122 | hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; | ||
123 | else { | ||
124 | omap_set_gpio_dataout(GPIO_IDLE, 1); | ||
125 | goto done; | ||
126 | } | ||
127 | |||
128 | break; | ||
129 | |||
130 | case led_idle_end: | ||
131 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
132 | hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; | ||
133 | else { | ||
134 | omap_set_gpio_dataout(GPIO_IDLE, 0); | ||
135 | goto done; | ||
136 | } | ||
137 | |||
138 | break; | ||
139 | #endif | ||
140 | |||
141 | case led_green_on: | ||
142 | hw_led_state |= H2P2_DBG_FPGA_LED_GREEN; | ||
143 | break; | ||
144 | case led_green_off: | ||
145 | hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN; | ||
146 | break; | ||
147 | |||
148 | case led_amber_on: | ||
149 | hw_led_state |= H2P2_DBG_FPGA_LED_AMBER; | ||
150 | break; | ||
151 | case led_amber_off: | ||
152 | hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER; | ||
153 | break; | ||
154 | |||
155 | case led_red_on: | ||
156 | hw_led_state |= H2P2_DBG_FPGA_LED_RED; | ||
157 | break; | ||
158 | case led_red_off: | ||
159 | hw_led_state &= ~H2P2_DBG_FPGA_LED_RED; | ||
160 | break; | ||
161 | |||
162 | case led_blue_on: | ||
163 | hw_led_state |= H2P2_DBG_FPGA_LED_BLUE; | ||
164 | break; | ||
165 | case led_blue_off: | ||
166 | hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE; | ||
167 | break; | ||
168 | |||
169 | default: | ||
170 | break; | ||
171 | } | ||
172 | |||
173 | |||
174 | /* | ||
175 | * Actually burn the LEDs | ||
176 | */ | ||
177 | if (led_state & LED_STATE_ENABLED) | ||
178 | __raw_writew(~hw_led_state, &fpga->leds); | ||
179 | |||
180 | done: | ||
181 | spin_unlock_irqrestore(&lock, flags); | ||
182 | } | ||
183 | |||
184 | /*-------------------------------------------------------------------------*/ | ||
185 | |||
186 | /* "new" LED API | ||
187 | * - with syfs access and generic triggering | ||
188 | * - not readily accessible to in-kernel drivers | ||
189 | */ | ||
190 | |||
191 | struct dbg_led { | ||
192 | struct led_classdev cdev; | ||
193 | u16 mask; | ||
194 | }; | ||
195 | |||
196 | static struct dbg_led dbg_leds[] = { | ||
197 | /* REVISIT at least H2 uses different timer & cpu leds... */ | ||
198 | #ifndef CONFIG_LEDS_TIMER | ||
199 | { .mask = 1 << 0, .cdev.name = "d4:green", | ||
200 | .cdev.default_trigger = "heartbeat", }, | ||
201 | #endif | ||
202 | #ifndef CONFIG_LEDS_CPU | ||
203 | { .mask = 1 << 1, .cdev.name = "d5:green", }, /* !idle */ | ||
204 | #endif | ||
205 | { .mask = 1 << 2, .cdev.name = "d6:green", }, | ||
206 | { .mask = 1 << 3, .cdev.name = "d7:green", }, | ||
207 | |||
208 | { .mask = 1 << 4, .cdev.name = "d8:green", }, | ||
209 | { .mask = 1 << 5, .cdev.name = "d9:green", }, | ||
210 | { .mask = 1 << 6, .cdev.name = "d10:green", }, | ||
211 | { .mask = 1 << 7, .cdev.name = "d11:green", }, | ||
212 | |||
213 | { .mask = 1 << 8, .cdev.name = "d12:green", }, | ||
214 | { .mask = 1 << 9, .cdev.name = "d13:green", }, | ||
215 | { .mask = 1 << 10, .cdev.name = "d14:green", }, | ||
216 | { .mask = 1 << 11, .cdev.name = "d15:green", }, | ||
217 | |||
218 | #ifndef CONFIG_LEDS | ||
219 | { .mask = 1 << 12, .cdev.name = "d16:green", }, | ||
220 | { .mask = 1 << 13, .cdev.name = "d17:green", }, | ||
221 | { .mask = 1 << 14, .cdev.name = "d18:green", }, | ||
222 | { .mask = 1 << 15, .cdev.name = "d19:green", }, | ||
223 | #endif | ||
224 | }; | ||
225 | |||
226 | static void | ||
227 | fpga_led_set(struct led_classdev *cdev, enum led_brightness value) | ||
228 | { | ||
229 | struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); | ||
230 | unsigned long flags; | ||
231 | |||
232 | spin_lock_irqsave(&lock, flags); | ||
233 | if (value == LED_OFF) | ||
234 | hw_led_state &= ~led->mask; | ||
235 | else | ||
236 | hw_led_state |= led->mask; | ||
237 | __raw_writew(~hw_led_state, &fpga->leds); | ||
238 | spin_unlock_irqrestore(&lock, flags); | ||
239 | } | ||
240 | |||
241 | static void __init newled_init(struct device *dev) | ||
242 | { | ||
243 | unsigned i; | ||
244 | struct dbg_led *led; | ||
245 | int status; | ||
246 | |||
247 | for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) { | ||
248 | led->cdev.brightness_set = fpga_led_set; | ||
249 | status = led_classdev_register(dev, &led->cdev); | ||
250 | if (status < 0) | ||
251 | break; | ||
252 | } | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | |||
257 | /*-------------------------------------------------------------------------*/ | ||
258 | |||
259 | static int /* __init */ fpga_probe(struct platform_device *pdev) | ||
260 | { | ||
261 | struct resource *iomem; | ||
262 | |||
263 | spin_lock_init(&lock); | ||
264 | |||
265 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
266 | if (!iomem) | ||
267 | return -ENODEV; | ||
268 | |||
269 | fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); | ||
270 | __raw_writew(~0, &fpga->leds); | ||
271 | |||
272 | #ifdef CONFIG_LEDS | ||
273 | leds_event = h2p2_dbg_leds_event; | ||
274 | leds_event(led_start); | ||
275 | #endif | ||
276 | |||
277 | if (new_led_api()) { | ||
278 | newled_init(&pdev->dev); | ||
279 | } | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int fpga_suspend_late(struct platform_device *pdev, pm_message_t mesg) | ||
285 | { | ||
286 | __raw_writew(~0, &fpga->leds); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int fpga_resume_early(struct platform_device *pdev) | ||
291 | { | ||
292 | __raw_writew(~hw_led_state, &fpga->leds); | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | |||
297 | static struct platform_driver led_driver = { | ||
298 | .driver.name = "omap_dbg_led", | ||
299 | .probe = fpga_probe, | ||
300 | .suspend_late = fpga_suspend_late, | ||
301 | .resume_early = fpga_resume_early, | ||
302 | }; | ||
303 | |||
304 | static int __init fpga_init(void) | ||
305 | { | ||
306 | if (machine_is_omap_h4() | ||
307 | || machine_is_omap_h3() | ||
308 | || machine_is_omap_h2() | ||
309 | || machine_is_omap_perseus2() | ||
310 | ) | ||
311 | return platform_driver_register(&led_driver); | ||
312 | return 0; | ||
313 | } | ||
314 | fs_initcall(fpga_init); | ||
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index eeb33fed6f7c..c5dab1d6417e 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c | |||
@@ -25,7 +25,71 @@ | |||
25 | #include <asm/arch/gpio.h> | 25 | #include <asm/arch/gpio.h> |
26 | #include <asm/arch/menelaus.h> | 26 | #include <asm/arch/menelaus.h> |
27 | 27 | ||
28 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | 28 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) |
29 | |||
30 | #include "../plat-omap/dsp/dsp_common.h" | ||
31 | |||
32 | static struct dsp_platform_data dsp_pdata = { | ||
33 | .kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list), | ||
34 | }; | ||
35 | |||
36 | static struct resource omap_dsp_resources[] = { | ||
37 | { | ||
38 | .name = "dsp_mmu", | ||
39 | .start = -1, | ||
40 | .flags = IORESOURCE_IRQ, | ||
41 | }, | ||
42 | }; | ||
43 | |||
44 | static struct platform_device omap_dsp_device = { | ||
45 | .name = "dsp", | ||
46 | .id = -1, | ||
47 | .num_resources = ARRAY_SIZE(omap_dsp_resources), | ||
48 | .resource = omap_dsp_resources, | ||
49 | .dev = { | ||
50 | .platform_data = &dsp_pdata, | ||
51 | }, | ||
52 | }; | ||
53 | |||
54 | static inline void omap_init_dsp(void) | ||
55 | { | ||
56 | struct resource *res; | ||
57 | int irq; | ||
58 | |||
59 | if (cpu_is_omap15xx()) | ||
60 | irq = INT_1510_DSP_MMU; | ||
61 | else if (cpu_is_omap16xx()) | ||
62 | irq = INT_1610_DSP_MMU; | ||
63 | else if (cpu_is_omap24xx()) | ||
64 | irq = INT_24XX_DSP_MMU; | ||
65 | |||
66 | res = platform_get_resource_byname(&omap_dsp_device, | ||
67 | IORESOURCE_IRQ, "dsp_mmu"); | ||
68 | res->start = irq; | ||
69 | |||
70 | platform_device_register(&omap_dsp_device); | ||
71 | } | ||
72 | |||
73 | int dsp_kfunc_device_register(struct dsp_kfunc_device *kdev) | ||
74 | { | ||
75 | static DEFINE_MUTEX(dsp_pdata_lock); | ||
76 | |||
77 | mutex_init(&kdev->lock); | ||
78 | |||
79 | mutex_lock(&dsp_pdata_lock); | ||
80 | list_add_tail(&kdev->entry, &dsp_pdata.kdev_list); | ||
81 | mutex_unlock(&dsp_pdata_lock); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | EXPORT_SYMBOL(dsp_kfunc_device_register); | ||
86 | |||
87 | #else | ||
88 | static inline void omap_init_dsp(void) { } | ||
89 | #endif /* CONFIG_OMAP_DSP */ | ||
90 | |||
91 | /*-------------------------------------------------------------------------*/ | ||
92 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | ||
29 | 93 | ||
30 | #define OMAP1_I2C_BASE 0xfffb3800 | 94 | #define OMAP1_I2C_BASE 0xfffb3800 |
31 | #define OMAP2_I2C_BASE1 0x48070000 | 95 | #define OMAP2_I2C_BASE1 0x48070000 |
@@ -48,8 +112,8 @@ static struct resource i2c_resources1[] = { | |||
48 | /* DMA not used; works around erratum writing to non-empty i2c fifo */ | 112 | /* DMA not used; works around erratum writing to non-empty i2c fifo */ |
49 | 113 | ||
50 | static struct platform_device omap_i2c_device1 = { | 114 | static struct platform_device omap_i2c_device1 = { |
51 | .name = "i2c_omap", | 115 | .name = "i2c_omap", |
52 | .id = 1, | 116 | .id = 1, |
53 | .num_resources = ARRAY_SIZE(i2c_resources1), | 117 | .num_resources = ARRAY_SIZE(i2c_resources1), |
54 | .resource = i2c_resources1, | 118 | .resource = i2c_resources1, |
55 | }; | 119 | }; |
@@ -376,7 +440,7 @@ static inline void omap_init_wdt(void) {} | |||
376 | 440 | ||
377 | /*-------------------------------------------------------------------------*/ | 441 | /*-------------------------------------------------------------------------*/ |
378 | 442 | ||
379 | #if defined(CONFIG_OMAP_RNG) || defined(CONFIG_OMAP_RNG_MODULE) | 443 | #if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE) |
380 | 444 | ||
381 | #ifdef CONFIG_ARCH_OMAP24XX | 445 | #ifdef CONFIG_ARCH_OMAP24XX |
382 | #define OMAP_RNG_BASE 0x480A0000 | 446 | #define OMAP_RNG_BASE 0x480A0000 |
@@ -436,6 +500,7 @@ static int __init omap_init_devices(void) | |||
436 | /* please keep these calls, and their implementations above, | 500 | /* please keep these calls, and their implementations above, |
437 | * in alphabetical order so they're easier to sort through. | 501 | * in alphabetical order so they're easier to sort through. |
438 | */ | 502 | */ |
503 | omap_init_dsp(); | ||
439 | omap_init_i2c(); | 504 | omap_init_i2c(); |
440 | omap_init_kp(); | 505 | omap_init_kp(); |
441 | omap_init_mmc(); | 506 | omap_init_mmc(); |
@@ -446,4 +511,3 @@ static int __init omap_init_devices(void) | |||
446 | return 0; | 511 | return 0; |
447 | } | 512 | } |
448 | arch_initcall(omap_init_devices); | 513 | arch_initcall(omap_init_devices); |
449 | |||
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index f3f84fbf8b87..2d86b106ff3e 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c | |||
@@ -925,10 +925,17 @@ static int omap2_dma_handle_ch(int ch) | |||
925 | { | 925 | { |
926 | u32 status = OMAP_DMA_CSR_REG(ch); | 926 | u32 status = OMAP_DMA_CSR_REG(ch); |
927 | 927 | ||
928 | if (!status) | 928 | if (!status) { |
929 | if (printk_ratelimit()) | ||
930 | printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); | ||
929 | return 0; | 931 | return 0; |
930 | if (unlikely(dma_chan[ch].dev_id == -1)) | 932 | } |
933 | if (unlikely(dma_chan[ch].dev_id == -1)) { | ||
934 | if (printk_ratelimit()) | ||
935 | printk(KERN_WARNING "IRQ %04x for non-allocated DMA" | ||
936 | "channel %d\n", status, ch); | ||
931 | return 0; | 937 | return 0; |
938 | } | ||
932 | if (unlikely(status & OMAP_DMA_DROP_IRQ)) | 939 | if (unlikely(status & OMAP_DMA_DROP_IRQ)) |
933 | printk(KERN_INFO | 940 | printk(KERN_INFO |
934 | "DMA synchronization event drop occurred with device " | 941 | "DMA synchronization event drop occurred with device " |
@@ -959,11 +966,15 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) | |||
959 | int i; | 966 | int i; |
960 | 967 | ||
961 | val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); | 968 | val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); |
962 | 969 | if (val == 0) { | |
963 | for (i = 1; i <= OMAP_LOGICAL_DMA_CH_COUNT; i++) { | 970 | if (printk_ratelimit()) |
964 | int active = val & (1 << (i - 1)); | 971 | printk(KERN_WARNING "Spurious DMA IRQ\n"); |
965 | if (active) | 972 | return IRQ_HANDLED; |
966 | omap2_dma_handle_ch(i - 1); | 973 | } |
974 | for (i = 0; i < OMAP_LOGICAL_DMA_CH_COUNT && val != 0; i++) { | ||
975 | if (val & 1) | ||
976 | omap2_dma_handle_ch(i); | ||
977 | val >>= 1; | ||
967 | } | 978 | } |
968 | 979 | ||
969 | return IRQ_HANDLED; | 980 | return IRQ_HANDLED; |
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 659619f235ca..36073dfaa4db 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -372,7 +372,7 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | |||
372 | 372 | ||
373 | /* When the functional clock disappears, too quick writes seem to | 373 | /* When the functional clock disappears, too quick writes seem to |
374 | * cause an abort. */ | 374 | * cause an abort. */ |
375 | __delay(15000); | 375 | __delay(150000); |
376 | } | 376 | } |
377 | 377 | ||
378 | #endif | 378 | #endif |
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index 56acb8720f78..4493bcff5172 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c | |||
@@ -1,3 +1,26 @@ | |||
1 | /* | ||
2 | * File: arch/arm/plat-omap/fb.c | ||
3 | * | ||
4 | * Framebuffer device registration for TI OMAP platforms | ||
5 | * | ||
6 | * Copyright (C) 2006 Nokia Corporation | ||
7 | * Author: Imre Deak <imre.deak@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
1 | #include <linux/module.h> | 24 | #include <linux/module.h> |
2 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
3 | #include <linux/init.h> | 26 | #include <linux/init.h> |
@@ -16,6 +39,8 @@ | |||
16 | #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) | 39 | #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) |
17 | 40 | ||
18 | static struct omapfb_platform_data omapfb_config; | 41 | static struct omapfb_platform_data omapfb_config; |
42 | static int config_invalid; | ||
43 | static int configured_regions; | ||
19 | 44 | ||
20 | static u64 omap_fb_dma_mask = ~(u32)0; | 45 | static u64 omap_fb_dma_mask = ~(u32)0; |
21 | 46 | ||
@@ -30,39 +55,270 @@ static struct platform_device omap_fb_device = { | |||
30 | .num_resources = 0, | 55 | .num_resources = 0, |
31 | }; | 56 | }; |
32 | 57 | ||
33 | /* called from map_io */ | 58 | static inline int ranges_overlap(unsigned long start1, unsigned long size1, |
34 | void omapfb_reserve_mem(void) | 59 | unsigned long start2, unsigned long size2) |
35 | { | 60 | { |
36 | const struct omap_fbmem_config *fbmem_conf; | 61 | return (start1 >= start2 && start1 < start2 + size2) || |
62 | (start2 >= start1 && start2 < start1 + size1); | ||
63 | } | ||
37 | 64 | ||
38 | omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start; | 65 | static inline int range_included(unsigned long start1, unsigned long size1, |
39 | omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size; | 66 | unsigned long start2, unsigned long size2) |
67 | { | ||
68 | return start1 >= start2 && start1 + size1 <= start2 + size2; | ||
69 | } | ||
40 | 70 | ||
41 | fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); | ||
42 | 71 | ||
43 | if (fbmem_conf != NULL) { | 72 | /* Check if there is an overlapping region. */ |
44 | /* indicate that the bootloader already initialized the | 73 | static int fbmem_region_reserved(unsigned long start, size_t size) |
45 | * fb device, so we'll skip that part in the fb driver | 74 | { |
46 | */ | 75 | struct omapfb_mem_region *rg; |
47 | omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start; | 76 | int i; |
48 | omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size; | 77 | |
49 | if (fbmem_conf->fb_sdram_size) { | 78 | rg = &omapfb_config.mem_desc.region[0]; |
50 | pr_info("Reserving %u bytes SDRAM for frame buffer\n", | 79 | for (i = 0; i < OMAPFB_PLANE_NUM; i++, rg++) { |
51 | fbmem_conf->fb_sdram_size); | 80 | if (!rg->paddr) |
52 | reserve_bootmem(fbmem_conf->fb_sdram_start, | 81 | /* Empty slot. */ |
53 | fbmem_conf->fb_sdram_size); | 82 | continue; |
83 | if (ranges_overlap(start, size, rg->paddr, rg->size)) | ||
84 | return 1; | ||
85 | } | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Get the region_idx`th region from board config/ATAG and convert it to | ||
91 | * our internal format. | ||
92 | */ | ||
93 | static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg) | ||
94 | { | ||
95 | const struct omap_fbmem_config *conf; | ||
96 | u32 paddr; | ||
97 | |||
98 | conf = omap_get_nr_config(OMAP_TAG_FBMEM, | ||
99 | struct omap_fbmem_config, region_idx); | ||
100 | if (conf == NULL) | ||
101 | return -ENOENT; | ||
102 | |||
103 | paddr = conf->start; | ||
104 | /* | ||
105 | * Low bits encode the page allocation mode, if high bits | ||
106 | * are zero. Otherwise we need a page aligned fixed | ||
107 | * address. | ||
108 | */ | ||
109 | memset(rg, 0, sizeof(*rg)); | ||
110 | rg->type = paddr & ~PAGE_MASK; | ||
111 | rg->paddr = paddr & PAGE_MASK; | ||
112 | rg->size = PAGE_ALIGN(conf->size); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int set_fbmem_region_type(struct omapfb_mem_region *rg, int mem_type, | ||
117 | unsigned long mem_start, | ||
118 | unsigned long mem_size) | ||
119 | { | ||
120 | /* | ||
121 | * Check if the configuration specifies the type explicitly. | ||
122 | * type = 0 && paddr = 0, a default don't care case maps to | ||
123 | * the SDRAM type. | ||
124 | */ | ||
125 | if (rg->type || (!rg->type && !rg->paddr)) | ||
126 | return 0; | ||
127 | if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) { | ||
128 | rg->type = mem_type; | ||
129 | return 0; | ||
130 | } | ||
131 | /* Can't determine it. */ | ||
132 | return -1; | ||
133 | } | ||
134 | |||
135 | static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg, | ||
136 | unsigned long start_avail, unsigned size_avail) | ||
137 | { | ||
138 | unsigned long paddr = rg->paddr; | ||
139 | size_t size = rg->size; | ||
140 | |||
141 | if (rg->type > OMAPFB_MEMTYPE_MAX) { | ||
142 | printk(KERN_ERR | ||
143 | "Invalid start address for FB region %d\n", region_idx); | ||
144 | return -EINVAL; | ||
145 | } | ||
146 | |||
147 | if (!rg->size) { | ||
148 | printk(KERN_ERR "Zero size for FB region %d\n", region_idx); | ||
149 | return -EINVAL; | ||
150 | } | ||
151 | |||
152 | if (!paddr) | ||
153 | /* Allocate this dynamically, leave paddr 0 for now. */ | ||
154 | return 0; | ||
155 | |||
156 | /* | ||
157 | * Fixed region for the given RAM range. Check if it's already | ||
158 | * reserved by the FB code or someone else. | ||
159 | */ | ||
160 | if (fbmem_region_reserved(paddr, size) || | ||
161 | !range_included(paddr, size, start_avail, size_avail)) { | ||
162 | printk(KERN_ERR "Trying to use reserved memory " | ||
163 | "for FB region %d\n", region_idx); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Called from map_io. We need to call to this early enough so that we | ||
172 | * can reserve the fixed SDRAM regions before VM could get hold of them. | ||
173 | */ | ||
174 | void omapfb_reserve_sdram(void) | ||
175 | { | ||
176 | struct bootmem_data *bdata; | ||
177 | unsigned long sdram_start, sdram_size; | ||
178 | unsigned long reserved; | ||
179 | int i; | ||
180 | |||
181 | if (config_invalid) | ||
182 | return; | ||
183 | |||
184 | bdata = NODE_DATA(0)->bdata; | ||
185 | sdram_start = bdata->node_boot_start; | ||
186 | sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; | ||
187 | reserved = 0; | ||
188 | for (i = 0; ; i++) { | ||
189 | struct omapfb_mem_region rg; | ||
190 | |||
191 | if (get_fbmem_region(i, &rg) < 0) | ||
192 | break; | ||
193 | if (i == OMAPFB_PLANE_NUM) { | ||
194 | printk(KERN_ERR | ||
195 | "Extraneous FB mem configuration entries\n"); | ||
196 | config_invalid = 1; | ||
197 | return; | ||
54 | } | 198 | } |
199 | /* Check if it's our memory type. */ | ||
200 | if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SDRAM, | ||
201 | sdram_start, sdram_size) < 0 || | ||
202 | (rg.type != OMAPFB_MEMTYPE_SDRAM)) | ||
203 | continue; | ||
204 | BUG_ON(omapfb_config.mem_desc.region[i].size); | ||
205 | if (check_fbmem_region(i, &rg, sdram_start, sdram_size) < 0) { | ||
206 | config_invalid = 1; | ||
207 | return; | ||
208 | } | ||
209 | if (rg.paddr) | ||
210 | reserve_bootmem(rg.paddr, rg.size); | ||
211 | reserved += rg.size; | ||
212 | omapfb_config.mem_desc.region[i] = rg; | ||
213 | configured_regions++; | ||
55 | } | 214 | } |
215 | omapfb_config.mem_desc.region_cnt = i; | ||
216 | if (reserved) | ||
217 | pr_info("Reserving %lu bytes SDRAM for frame buffer\n", | ||
218 | reserved); | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Called at sram init time, before anything is pushed to the SRAM stack. | ||
223 | * Because of the stack scheme, we will allocate everything from the | ||
224 | * start of the lowest address region to the end of SRAM. This will also | ||
225 | * include padding for page alignment and possible holes between regions. | ||
226 | * | ||
227 | * As opposed to the SDRAM case, we'll also do any dynamic allocations at | ||
228 | * this point, since the driver built as a module would have problem with | ||
229 | * freeing / reallocating the regions. | ||
230 | */ | ||
231 | unsigned long omapfb_reserve_sram(unsigned long sram_pstart, | ||
232 | unsigned long sram_vstart, | ||
233 | unsigned long sram_size, | ||
234 | unsigned long pstart_avail, | ||
235 | unsigned long size_avail) | ||
236 | { | ||
237 | struct omapfb_mem_region rg; | ||
238 | unsigned long pend_avail; | ||
239 | unsigned long reserved; | ||
240 | int i; | ||
241 | |||
242 | if (config_invalid) | ||
243 | return 0; | ||
244 | |||
245 | reserved = 0; | ||
246 | pend_avail = pstart_avail + size_avail; | ||
247 | for (i = 0; ; i++) { | ||
248 | if (get_fbmem_region(i, &rg) < 0) | ||
249 | break; | ||
250 | if (i == OMAPFB_PLANE_NUM) { | ||
251 | printk(KERN_ERR | ||
252 | "Extraneous FB mem configuration entries\n"); | ||
253 | config_invalid = 1; | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | /* Check if it's our memory type. */ | ||
258 | if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SRAM, | ||
259 | sram_pstart, sram_size) < 0 || | ||
260 | (rg.type != OMAPFB_MEMTYPE_SRAM)) | ||
261 | continue; | ||
262 | BUG_ON(omapfb_config.mem_desc.region[i].size); | ||
263 | |||
264 | if (check_fbmem_region(i, &rg, pstart_avail, size_avail) < 0) { | ||
265 | config_invalid = 1; | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | if (!rg.paddr) { | ||
270 | /* Dynamic allocation */ | ||
271 | if ((size_avail & PAGE_MASK) < rg.size) { | ||
272 | printk("Not enough SRAM for FB region %d\n", | ||
273 | i); | ||
274 | config_invalid = 1; | ||
275 | return 0; | ||
276 | } | ||
277 | size_avail = (size_avail - rg.size) & PAGE_MASK; | ||
278 | rg.paddr = pstart_avail + size_avail; | ||
279 | } | ||
280 | /* Reserve everything above the start of the region. */ | ||
281 | if (pend_avail - rg.paddr > reserved) | ||
282 | reserved = pend_avail - rg.paddr; | ||
283 | size_avail = pend_avail - reserved - pstart_avail; | ||
284 | |||
285 | /* | ||
286 | * We have a kernel mapping for this already, so the | ||
287 | * driver won't have to make one. | ||
288 | */ | ||
289 | rg.vaddr = (void *)(sram_vstart + rg.paddr - sram_pstart); | ||
290 | omapfb_config.mem_desc.region[i] = rg; | ||
291 | configured_regions++; | ||
292 | } | ||
293 | omapfb_config.mem_desc.region_cnt = i; | ||
294 | if (reserved) | ||
295 | pr_info("Reserving %lu bytes SRAM for frame buffer\n", | ||
296 | reserved); | ||
297 | return reserved; | ||
298 | } | ||
299 | |||
300 | void omapfb_set_ctrl_platform_data(void *data) | ||
301 | { | ||
302 | omapfb_config.ctrl_platform_data = data; | ||
56 | } | 303 | } |
57 | 304 | ||
58 | static inline int omap_init_fb(void) | 305 | static inline int omap_init_fb(void) |
59 | { | 306 | { |
60 | const struct omap_lcd_config *conf; | 307 | const struct omap_lcd_config *conf; |
61 | 308 | ||
309 | if (config_invalid) | ||
310 | return 0; | ||
311 | if (configured_regions != omapfb_config.mem_desc.region_cnt) { | ||
312 | printk(KERN_ERR "Invalid FB mem configuration entries\n"); | ||
313 | return 0; | ||
314 | } | ||
62 | conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); | 315 | conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); |
63 | if (conf == NULL) | 316 | if (conf == NULL) { |
317 | if (configured_regions) | ||
318 | /* FB mem config, but no LCD config? */ | ||
319 | printk(KERN_ERR "Missing LCD configuration\n"); | ||
64 | return 0; | 320 | return 0; |
65 | 321 | } | |
66 | omapfb_config.lcd = *conf; | 322 | omapfb_config.lcd = *conf; |
67 | 323 | ||
68 | return platform_device_register(&omap_fb_device); | 324 | return platform_device_register(&omap_fb_device); |
@@ -72,7 +328,16 @@ arch_initcall(omap_init_fb); | |||
72 | 328 | ||
73 | #else | 329 | #else |
74 | 330 | ||
75 | void omapfb_reserve_mem(void) {} | 331 | void omapfb_reserve_sdram(void) {} |
332 | unsigned long omapfb_reserve_sram(unsigned long sram_pstart, | ||
333 | unsigned long sram_vstart, | ||
334 | unsigned long sram_size, | ||
335 | unsigned long start_avail, | ||
336 | unsigned long size_avail) | ||
337 | { | ||
338 | return 0; | ||
339 | } | ||
340 | |||
76 | 341 | ||
77 | #endif | 342 | #endif |
78 | 343 | ||
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 9dc6d3617bdb..337455dfe64d 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/sched.h> | ||
17 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
18 | #include <linux/sysdev.h> | 17 | #include <linux/sysdev.h> |
19 | #include <linux/err.h> | 18 | #include <linux/err.h> |
@@ -1545,7 +1544,7 @@ void omap2_gpio_resume_after_retention(void) | |||
1545 | * This may get called early from board specific init | 1544 | * This may get called early from board specific init |
1546 | * for boards that have interrupts routed via FPGA. | 1545 | * for boards that have interrupts routed via FPGA. |
1547 | */ | 1546 | */ |
1548 | int omap_gpio_init(void) | 1547 | int __init omap_gpio_init(void) |
1549 | { | 1548 | { |
1550 | if (!initialized) | 1549 | if (!initialized) |
1551 | return _omap_gpio_init(); | 1550 | return _omap_gpio_init(); |
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c new file mode 100644 index 000000000000..de7e6ef48bd0 --- /dev/null +++ b/arch/arm/plat-omap/mailbox.c | |||
@@ -0,0 +1,509 @@ | |||
1 | /* | ||
2 | * OMAP mailbox driver | ||
3 | * | ||
4 | * Copyright (C) 2006 Nokia Corporation. All rights reserved. | ||
5 | * | ||
6 | * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com> | ||
7 | * Restructured by Hiroshi DOYU <Hiroshi.DOYU@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/init.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/blkdev.h> | ||
31 | #include <linux/err.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/arch/mailbox.h> | ||
35 | #include "mailbox.h" | ||
36 | |||
37 | static struct omap_mbox *mboxes; | ||
38 | static DEFINE_RWLOCK(mboxes_lock); | ||
39 | |||
40 | /* Mailbox Sequence Bit function */ | ||
41 | void omap_mbox_init_seq(struct omap_mbox *mbox) | ||
42 | { | ||
43 | mbox_seq_init(mbox); | ||
44 | } | ||
45 | EXPORT_SYMBOL(omap_mbox_init_seq); | ||
46 | |||
47 | /* | ||
48 | * message sender | ||
49 | */ | ||
50 | static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) | ||
51 | { | ||
52 | int ret = 0, i = 1000; | ||
53 | |||
54 | while (mbox_fifo_full(mbox)) { | ||
55 | if (mbox->ops->type == OMAP_MBOX_TYPE2) | ||
56 | return -1; | ||
57 | if (--i == 0) | ||
58 | return -1; | ||
59 | udelay(1); | ||
60 | } | ||
61 | |||
62 | if (arg && mbox->txq->callback) { | ||
63 | ret = mbox->txq->callback(arg); | ||
64 | if (ret) | ||
65 | goto out; | ||
66 | } | ||
67 | |||
68 | mbox_seq_toggle(mbox, &msg); | ||
69 | mbox_fifo_write(mbox, msg); | ||
70 | out: | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) | ||
75 | { | ||
76 | struct request *rq; | ||
77 | struct request_queue *q = mbox->txq->queue; | ||
78 | int ret = 0; | ||
79 | |||
80 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); | ||
81 | if (unlikely(!rq)) { | ||
82 | ret = -ENOMEM; | ||
83 | goto fail; | ||
84 | } | ||
85 | |||
86 | rq->data = (void *)msg; | ||
87 | blk_insert_request(q, rq, 0, arg); | ||
88 | |||
89 | schedule_work(&mbox->txq->work); | ||
90 | fail: | ||
91 | return ret; | ||
92 | } | ||
93 | EXPORT_SYMBOL(omap_mbox_msg_send); | ||
94 | |||
95 | static void mbox_tx_work(struct work_struct *work) | ||
96 | { | ||
97 | int ret; | ||
98 | struct request *rq; | ||
99 | struct omap_mbox_queue *mq = container_of(work, | ||
100 | struct omap_mbox_queue, work); | ||
101 | struct omap_mbox *mbox = mq->queue->queuedata; | ||
102 | struct request_queue *q = mbox->txq->queue; | ||
103 | |||
104 | while (1) { | ||
105 | spin_lock(q->queue_lock); | ||
106 | rq = elv_next_request(q); | ||
107 | spin_unlock(q->queue_lock); | ||
108 | |||
109 | if (!rq) | ||
110 | break; | ||
111 | |||
112 | ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special); | ||
113 | if (ret) { | ||
114 | enable_mbox_irq(mbox, IRQ_TX); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | spin_lock(q->queue_lock); | ||
119 | blkdev_dequeue_request(rq); | ||
120 | end_that_request_last(rq, 0); | ||
121 | spin_unlock(q->queue_lock); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * Message receiver(workqueue) | ||
127 | */ | ||
128 | static void mbox_rx_work(struct work_struct *work) | ||
129 | { | ||
130 | struct omap_mbox_queue *mq = | ||
131 | container_of(work, struct omap_mbox_queue, work); | ||
132 | struct omap_mbox *mbox = mq->queue->queuedata; | ||
133 | struct request_queue *q = mbox->rxq->queue; | ||
134 | struct request *rq; | ||
135 | mbox_msg_t msg; | ||
136 | unsigned long flags; | ||
137 | |||
138 | if (mbox->rxq->callback == NULL) { | ||
139 | sysfs_notify(&mbox->dev.kobj, NULL, "mbox"); | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | while (1) { | ||
144 | spin_lock_irqsave(q->queue_lock, flags); | ||
145 | rq = elv_next_request(q); | ||
146 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
147 | if (!rq) | ||
148 | break; | ||
149 | |||
150 | msg = (mbox_msg_t) rq->data; | ||
151 | |||
152 | spin_lock_irqsave(q->queue_lock, flags); | ||
153 | blkdev_dequeue_request(rq); | ||
154 | end_that_request_last(rq, 0); | ||
155 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
156 | |||
157 | mbox->rxq->callback((void *)msg); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Mailbox interrupt handler | ||
163 | */ | ||
164 | static void mbox_txq_fn(request_queue_t * q) | ||
165 | { | ||
166 | } | ||
167 | |||
168 | static void mbox_rxq_fn(request_queue_t * q) | ||
169 | { | ||
170 | } | ||
171 | |||
172 | static void __mbox_tx_interrupt(struct omap_mbox *mbox) | ||
173 | { | ||
174 | disable_mbox_irq(mbox, IRQ_TX); | ||
175 | ack_mbox_irq(mbox, IRQ_TX); | ||
176 | schedule_work(&mbox->txq->work); | ||
177 | } | ||
178 | |||
179 | static void __mbox_rx_interrupt(struct omap_mbox *mbox) | ||
180 | { | ||
181 | struct request *rq; | ||
182 | mbox_msg_t msg; | ||
183 | request_queue_t *q = mbox->rxq->queue; | ||
184 | |||
185 | disable_mbox_irq(mbox, IRQ_RX); | ||
186 | |||
187 | while (!mbox_fifo_empty(mbox)) { | ||
188 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); | ||
189 | if (unlikely(!rq)) | ||
190 | goto nomem; | ||
191 | |||
192 | msg = mbox_fifo_read(mbox); | ||
193 | rq->data = (void *)msg; | ||
194 | |||
195 | if (unlikely(mbox_seq_test(mbox, msg))) { | ||
196 | pr_info("mbox: Illegal seq bit!(%08x)\n", msg); | ||
197 | if (mbox->err_notify) | ||
198 | mbox->err_notify(); | ||
199 | } | ||
200 | |||
201 | blk_insert_request(q, rq, 0, NULL); | ||
202 | if (mbox->ops->type == OMAP_MBOX_TYPE1) | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | /* no more messages in the fifo. clear IRQ source. */ | ||
207 | ack_mbox_irq(mbox, IRQ_RX); | ||
208 | enable_mbox_irq(mbox, IRQ_RX); | ||
209 | nomem: | ||
210 | schedule_work(&mbox->rxq->work); | ||
211 | } | ||
212 | |||
213 | static irqreturn_t mbox_interrupt(int irq, void *p) | ||
214 | { | ||
215 | struct omap_mbox *mbox = (struct omap_mbox *)p; | ||
216 | |||
217 | if (is_mbox_irq(mbox, IRQ_TX)) | ||
218 | __mbox_tx_interrupt(mbox); | ||
219 | |||
220 | if (is_mbox_irq(mbox, IRQ_RX)) | ||
221 | __mbox_rx_interrupt(mbox); | ||
222 | |||
223 | return IRQ_HANDLED; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * sysfs files | ||
228 | */ | ||
229 | static ssize_t | ||
230 | omap_mbox_write(struct device *dev, struct device_attribute *attr, | ||
231 | const char * buf, size_t count) | ||
232 | { | ||
233 | int ret; | ||
234 | mbox_msg_t *p = (mbox_msg_t *)buf; | ||
235 | struct omap_mbox *mbox = dev_get_drvdata(dev); | ||
236 | |||
237 | for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) { | ||
238 | ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL); | ||
239 | if (ret) | ||
240 | return -EAGAIN; | ||
241 | p++; | ||
242 | } | ||
243 | |||
244 | return (size_t)((char *)p - buf); | ||
245 | } | ||
246 | |||
247 | static ssize_t | ||
248 | omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) | ||
249 | { | ||
250 | unsigned long flags; | ||
251 | struct request *rq; | ||
252 | mbox_msg_t *p = (mbox_msg_t *) buf; | ||
253 | struct omap_mbox *mbox = dev_get_drvdata(dev); | ||
254 | struct request_queue *q = mbox->rxq->queue; | ||
255 | |||
256 | while (1) { | ||
257 | spin_lock_irqsave(q->queue_lock, flags); | ||
258 | rq = elv_next_request(q); | ||
259 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
260 | |||
261 | if (!rq) | ||
262 | break; | ||
263 | |||
264 | *p = (mbox_msg_t) rq->data; | ||
265 | |||
266 | spin_lock_irqsave(q->queue_lock, flags); | ||
267 | blkdev_dequeue_request(rq); | ||
268 | end_that_request_last(rq, 0); | ||
269 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
270 | |||
271 | if (unlikely(mbox_seq_test(mbox, *p))) { | ||
272 | pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p); | ||
273 | continue; | ||
274 | } | ||
275 | p++; | ||
276 | } | ||
277 | |||
278 | pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); | ||
279 | |||
280 | return (size_t) ((char *)p - buf); | ||
281 | } | ||
282 | |||
283 | static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write); | ||
284 | |||
285 | static ssize_t mbox_show(struct class *class, char *buf) | ||
286 | { | ||
287 | return sprintf(buf, "mbox"); | ||
288 | } | ||
289 | |||
290 | static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL); | ||
291 | |||
292 | static struct class omap_mbox_class = { | ||
293 | .name = "omap_mbox", | ||
294 | }; | ||
295 | |||
296 | static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, | ||
297 | request_fn_proc * proc, | ||
298 | void (*work) (struct work_struct *)) | ||
299 | { | ||
300 | request_queue_t *q; | ||
301 | struct omap_mbox_queue *mq; | ||
302 | |||
303 | mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); | ||
304 | if (!mq) | ||
305 | return NULL; | ||
306 | |||
307 | spin_lock_init(&mq->lock); | ||
308 | |||
309 | q = blk_init_queue(proc, &mq->lock); | ||
310 | if (!q) | ||
311 | goto error; | ||
312 | q->queuedata = mbox; | ||
313 | mq->queue = q; | ||
314 | |||
315 | INIT_WORK(&mq->work, work); | ||
316 | |||
317 | return mq; | ||
318 | error: | ||
319 | kfree(mq); | ||
320 | return NULL; | ||
321 | } | ||
322 | |||
323 | static void mbox_queue_free(struct omap_mbox_queue *q) | ||
324 | { | ||
325 | blk_cleanup_queue(q->queue); | ||
326 | kfree(q); | ||
327 | } | ||
328 | |||
329 | static int omap_mbox_init(struct omap_mbox *mbox) | ||
330 | { | ||
331 | int ret; | ||
332 | struct omap_mbox_queue *mq; | ||
333 | |||
334 | if (likely(mbox->ops->startup)) { | ||
335 | ret = mbox->ops->startup(mbox); | ||
336 | if (unlikely(ret)) | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | mbox->dev.class = &omap_mbox_class; | ||
341 | strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN); | ||
342 | dev_set_drvdata(&mbox->dev, mbox); | ||
343 | |||
344 | ret = device_register(&mbox->dev); | ||
345 | if (unlikely(ret)) | ||
346 | goto fail_device_reg; | ||
347 | |||
348 | ret = device_create_file(&mbox->dev, &dev_attr_mbox); | ||
349 | if (unlikely(ret)) { | ||
350 | printk(KERN_ERR | ||
351 | "device_create_file failed: %d\n", ret); | ||
352 | goto fail_create_mbox; | ||
353 | } | ||
354 | |||
355 | ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED, | ||
356 | mbox->name, mbox); | ||
357 | if (unlikely(ret)) { | ||
358 | printk(KERN_ERR | ||
359 | "failed to register mailbox interrupt:%d\n", ret); | ||
360 | goto fail_request_irq; | ||
361 | } | ||
362 | enable_mbox_irq(mbox, IRQ_RX); | ||
363 | |||
364 | mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work); | ||
365 | if (!mq) { | ||
366 | ret = -ENOMEM; | ||
367 | goto fail_alloc_txq; | ||
368 | } | ||
369 | mbox->txq = mq; | ||
370 | |||
371 | mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work); | ||
372 | if (!mq) { | ||
373 | ret = -ENOMEM; | ||
374 | goto fail_alloc_rxq; | ||
375 | } | ||
376 | mbox->rxq = mq; | ||
377 | |||
378 | return 0; | ||
379 | |||
380 | fail_alloc_rxq: | ||
381 | mbox_queue_free(mbox->txq); | ||
382 | fail_alloc_txq: | ||
383 | free_irq(mbox->irq, mbox); | ||
384 | fail_request_irq: | ||
385 | device_remove_file(&mbox->dev, &dev_attr_mbox); | ||
386 | fail_create_mbox: | ||
387 | device_unregister(&mbox->dev); | ||
388 | fail_device_reg: | ||
389 | if (unlikely(mbox->ops->shutdown)) | ||
390 | mbox->ops->shutdown(mbox); | ||
391 | |||
392 | return ret; | ||
393 | } | ||
394 | |||
395 | static void omap_mbox_fini(struct omap_mbox *mbox) | ||
396 | { | ||
397 | mbox_queue_free(mbox->txq); | ||
398 | mbox_queue_free(mbox->rxq); | ||
399 | |||
400 | free_irq(mbox->irq, mbox); | ||
401 | device_remove_file(&mbox->dev, &dev_attr_mbox); | ||
402 | class_unregister(&omap_mbox_class); | ||
403 | |||
404 | if (unlikely(mbox->ops->shutdown)) | ||
405 | mbox->ops->shutdown(mbox); | ||
406 | } | ||
407 | |||
408 | static struct omap_mbox **find_mboxes(const char *name) | ||
409 | { | ||
410 | struct omap_mbox **p; | ||
411 | |||
412 | for (p = &mboxes; *p; p = &(*p)->next) { | ||
413 | if (strcmp((*p)->name, name) == 0) | ||
414 | break; | ||
415 | } | ||
416 | |||
417 | return p; | ||
418 | } | ||
419 | |||
420 | struct omap_mbox *omap_mbox_get(const char *name) | ||
421 | { | ||
422 | struct omap_mbox *mbox; | ||
423 | int ret; | ||
424 | |||
425 | read_lock(&mboxes_lock); | ||
426 | mbox = *(find_mboxes(name)); | ||
427 | if (mbox == NULL) { | ||
428 | read_unlock(&mboxes_lock); | ||
429 | return ERR_PTR(-ENOENT); | ||
430 | } | ||
431 | |||
432 | read_unlock(&mboxes_lock); | ||
433 | |||
434 | ret = omap_mbox_init(mbox); | ||
435 | if (ret) | ||
436 | return ERR_PTR(-ENODEV); | ||
437 | |||
438 | return mbox; | ||
439 | } | ||
440 | EXPORT_SYMBOL(omap_mbox_get); | ||
441 | |||
442 | void omap_mbox_put(struct omap_mbox *mbox) | ||
443 | { | ||
444 | omap_mbox_fini(mbox); | ||
445 | } | ||
446 | EXPORT_SYMBOL(omap_mbox_put); | ||
447 | |||
448 | int omap_mbox_register(struct omap_mbox *mbox) | ||
449 | { | ||
450 | int ret = 0; | ||
451 | struct omap_mbox **tmp; | ||
452 | |||
453 | if (!mbox) | ||
454 | return -EINVAL; | ||
455 | if (mbox->next) | ||
456 | return -EBUSY; | ||
457 | |||
458 | write_lock(&mboxes_lock); | ||
459 | tmp = find_mboxes(mbox->name); | ||
460 | if (*tmp) | ||
461 | ret = -EBUSY; | ||
462 | else | ||
463 | *tmp = mbox; | ||
464 | write_unlock(&mboxes_lock); | ||
465 | |||
466 | return ret; | ||
467 | } | ||
468 | EXPORT_SYMBOL(omap_mbox_register); | ||
469 | |||
470 | int omap_mbox_unregister(struct omap_mbox *mbox) | ||
471 | { | ||
472 | struct omap_mbox **tmp; | ||
473 | |||
474 | write_lock(&mboxes_lock); | ||
475 | tmp = &mboxes; | ||
476 | while (*tmp) { | ||
477 | if (mbox == *tmp) { | ||
478 | *tmp = mbox->next; | ||
479 | mbox->next = NULL; | ||
480 | write_unlock(&mboxes_lock); | ||
481 | return 0; | ||
482 | } | ||
483 | tmp = &(*tmp)->next; | ||
484 | } | ||
485 | write_unlock(&mboxes_lock); | ||
486 | |||
487 | return -EINVAL; | ||
488 | } | ||
489 | EXPORT_SYMBOL(omap_mbox_unregister); | ||
490 | |||
491 | static int __init omap_mbox_class_init(void) | ||
492 | { | ||
493 | int ret = class_register(&omap_mbox_class); | ||
494 | if (!ret) | ||
495 | ret = class_create_file(&omap_mbox_class, &class_attr_mbox); | ||
496 | |||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | static void __exit omap_mbox_class_exit(void) | ||
501 | { | ||
502 | class_remove_file(&omap_mbox_class, &class_attr_mbox); | ||
503 | class_unregister(&omap_mbox_class); | ||
504 | } | ||
505 | |||
506 | subsys_initcall(omap_mbox_class_init); | ||
507 | module_exit(omap_mbox_class_exit); | ||
508 | |||
509 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/arm/plat-omap/mailbox.h b/arch/arm/plat-omap/mailbox.h new file mode 100644 index 000000000000..67c6740b8ad5 --- /dev/null +++ b/arch/arm/plat-omap/mailbox.h | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * Mailbox internal functions | ||
3 | * | ||
4 | * Copyright (C) 2006 Nokia Corporation | ||
5 | * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | */ | ||
11 | |||
12 | #ifndef __ARCH_ARM_PLAT_MAILBOX_H | ||
13 | #define __ARCH_ARM_PLAT_MAILBOX_H | ||
14 | |||
15 | /* | ||
16 | * Mailbox sequence bit API | ||
17 | */ | ||
18 | #if defined(CONFIG_ARCH_OMAP1) | ||
19 | # define MBOX_USE_SEQ_BIT | ||
20 | #elif defined(CONFIG_ARCH_OMAP2) | ||
21 | # define MBOX_USE_SEQ_BIT | ||
22 | #endif | ||
23 | |||
24 | #ifdef MBOX_USE_SEQ_BIT | ||
25 | /* seq_rcv should be initialized with any value other than | ||
26 | * 0 and 1 << 31, to allow either value for the first | ||
27 | * message. */ | ||
28 | static inline void mbox_seq_init(struct omap_mbox *mbox) | ||
29 | { | ||
30 | /* any value other than 0 and 1 << 31 */ | ||
31 | mbox->seq_rcv = 0xffffffff; | ||
32 | } | ||
33 | |||
34 | static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) | ||
35 | { | ||
36 | /* add seq_snd to msg */ | ||
37 | *msg = (*msg & 0x7fffffff) | mbox->seq_snd; | ||
38 | /* flip seq_snd */ | ||
39 | mbox->seq_snd ^= 1 << 31; | ||
40 | } | ||
41 | |||
42 | static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) | ||
43 | { | ||
44 | mbox_msg_t seq = msg & (1 << 31); | ||
45 | if (seq == mbox->seq_rcv) | ||
46 | return -1; | ||
47 | mbox->seq_rcv = seq; | ||
48 | return 0; | ||
49 | } | ||
50 | #else | ||
51 | static inline void mbox_seq_init(struct omap_mbox *mbox) | ||
52 | { | ||
53 | } | ||
54 | static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) | ||
55 | { | ||
56 | } | ||
57 | static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) | ||
58 | { | ||
59 | return 0; | ||
60 | } | ||
61 | #endif | ||
62 | |||
63 | /* Mailbox FIFO handle functions */ | ||
64 | static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) | ||
65 | { | ||
66 | return mbox->ops->fifo_read(mbox); | ||
67 | } | ||
68 | static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) | ||
69 | { | ||
70 | mbox->ops->fifo_write(mbox, msg); | ||
71 | } | ||
72 | static inline int mbox_fifo_empty(struct omap_mbox *mbox) | ||
73 | { | ||
74 | return mbox->ops->fifo_empty(mbox); | ||
75 | } | ||
76 | static inline int mbox_fifo_full(struct omap_mbox *mbox) | ||
77 | { | ||
78 | return mbox->ops->fifo_full(mbox); | ||
79 | } | ||
80 | |||
81 | /* Mailbox IRQ handle functions */ | ||
82 | static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
83 | { | ||
84 | mbox->ops->enable_irq(mbox, irq); | ||
85 | } | ||
86 | static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
87 | { | ||
88 | mbox->ops->disable_irq(mbox, irq); | ||
89 | } | ||
90 | static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
91 | { | ||
92 | if (mbox->ops->ack_irq) | ||
93 | mbox->ops->ack_irq(mbox, irq); | ||
94 | } | ||
95 | static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
96 | { | ||
97 | return mbox->ops->is_irq(mbox, irq); | ||
98 | } | ||
99 | |||
100 | #endif /* __ARCH_ARM_PLAT_MAILBOX_H */ | ||
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 19014b2ff4c6..bc46f33aede3 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c | |||
@@ -46,14 +46,19 @@ | |||
46 | 46 | ||
47 | #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) | 47 | #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) |
48 | 48 | ||
49 | static unsigned long omap_sram_start; | ||
49 | static unsigned long omap_sram_base; | 50 | static unsigned long omap_sram_base; |
50 | static unsigned long omap_sram_size; | 51 | static unsigned long omap_sram_size; |
51 | static unsigned long omap_sram_ceil; | 52 | static unsigned long omap_sram_ceil; |
52 | 53 | ||
53 | unsigned long omap_fb_sram_start; | 54 | extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart, |
54 | unsigned long omap_fb_sram_size; | 55 | unsigned long sram_vstart, |
56 | unsigned long sram_size, | ||
57 | unsigned long pstart_avail, | ||
58 | unsigned long size_avail); | ||
55 | 59 | ||
56 | /* Depending on the target RAMFS firewall setup, the public usable amount of | 60 | /* |
61 | * Depending on the target RAMFS firewall setup, the public usable amount of | ||
57 | * SRAM varies. The default accessable size for all device types is 2k. A GP | 62 | * SRAM varies. The default accessable size for all device types is 2k. A GP |
58 | * device allows ARM11 but not other initators for full size. This | 63 | * device allows ARM11 but not other initators for full size. This |
59 | * functionality seems ok until some nice security API happens. | 64 | * functionality seems ok until some nice security API happens. |
@@ -77,32 +82,6 @@ static int is_sram_locked(void) | |||
77 | return 1; /* assume locked with no PPA or security driver */ | 82 | return 1; /* assume locked with no PPA or security driver */ |
78 | } | 83 | } |
79 | 84 | ||
80 | void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, | ||
81 | unsigned long *start, unsigned long *size) | ||
82 | { | ||
83 | const struct omap_fbmem_config *fbmem_conf; | ||
84 | |||
85 | fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); | ||
86 | if (fbmem_conf != NULL) { | ||
87 | *start = fbmem_conf->fb_sram_start; | ||
88 | *size = fbmem_conf->fb_sram_size; | ||
89 | } else { | ||
90 | *size = 0; | ||
91 | *start = 0; | ||
92 | } | ||
93 | |||
94 | if (*size && ( | ||
95 | *start < start_avail || | ||
96 | *start + *size > start_avail + size_avail)) { | ||
97 | printk(KERN_ERR "invalid FB SRAM configuration\n"); | ||
98 | *start = start_avail; | ||
99 | *size = size_avail; | ||
100 | } | ||
101 | |||
102 | if (*size) | ||
103 | pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size); | ||
104 | } | ||
105 | |||
106 | /* | 85 | /* |
107 | * The amount of SRAM depends on the core type. | 86 | * The amount of SRAM depends on the core type. |
108 | * Note that we cannot try to test for SRAM here because writes | 87 | * Note that we cannot try to test for SRAM here because writes |
@@ -111,16 +90,16 @@ void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, | |||
111 | */ | 90 | */ |
112 | void __init omap_detect_sram(void) | 91 | void __init omap_detect_sram(void) |
113 | { | 92 | { |
114 | unsigned long sram_start; | 93 | unsigned long reserved; |
115 | 94 | ||
116 | if (cpu_is_omap24xx()) { | 95 | if (cpu_is_omap24xx()) { |
117 | if (is_sram_locked()) { | 96 | if (is_sram_locked()) { |
118 | omap_sram_base = OMAP2_SRAM_PUB_VA; | 97 | omap_sram_base = OMAP2_SRAM_PUB_VA; |
119 | sram_start = OMAP2_SRAM_PUB_PA; | 98 | omap_sram_start = OMAP2_SRAM_PUB_PA; |
120 | omap_sram_size = 0x800; /* 2K */ | 99 | omap_sram_size = 0x800; /* 2K */ |
121 | } else { | 100 | } else { |
122 | omap_sram_base = OMAP2_SRAM_VA; | 101 | omap_sram_base = OMAP2_SRAM_VA; |
123 | sram_start = OMAP2_SRAM_PA; | 102 | omap_sram_start = OMAP2_SRAM_PA; |
124 | if (cpu_is_omap242x()) | 103 | if (cpu_is_omap242x()) |
125 | omap_sram_size = 0xa0000; /* 640K */ | 104 | omap_sram_size = 0xa0000; /* 640K */ |
126 | else if (cpu_is_omap243x()) | 105 | else if (cpu_is_omap243x()) |
@@ -128,7 +107,7 @@ void __init omap_detect_sram(void) | |||
128 | } | 107 | } |
129 | } else { | 108 | } else { |
130 | omap_sram_base = OMAP1_SRAM_VA; | 109 | omap_sram_base = OMAP1_SRAM_VA; |
131 | sram_start = OMAP1_SRAM_PA; | 110 | omap_sram_start = OMAP1_SRAM_PA; |
132 | 111 | ||
133 | if (cpu_is_omap730()) | 112 | if (cpu_is_omap730()) |
134 | omap_sram_size = 0x32000; /* 200K */ | 113 | omap_sram_size = 0x32000; /* 200K */ |
@@ -144,12 +123,11 @@ void __init omap_detect_sram(void) | |||
144 | omap_sram_size = 0x4000; | 123 | omap_sram_size = 0x4000; |
145 | } | 124 | } |
146 | } | 125 | } |
147 | get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ, | 126 | reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base, |
148 | omap_sram_size - SRAM_BOOTLOADER_SZ, | 127 | omap_sram_size, |
149 | &omap_fb_sram_start, &omap_fb_sram_size); | 128 | omap_sram_start + SRAM_BOOTLOADER_SZ, |
150 | if (omap_fb_sram_size) | 129 | omap_sram_size - SRAM_BOOTLOADER_SZ); |
151 | omap_sram_size -= sram_start + omap_sram_size - | 130 | omap_sram_size -= reserved; |
152 | omap_fb_sram_start; | ||
153 | omap_sram_ceil = omap_sram_base + omap_sram_size; | 131 | omap_sram_ceil = omap_sram_base + omap_sram_size; |
154 | } | 132 | } |
155 | 133 | ||
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index 7e8096809be2..25489aafb113 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c | |||
@@ -37,9 +37,27 @@ | |||
37 | #include <asm/arch/usb.h> | 37 | #include <asm/arch/usb.h> |
38 | #include <asm/arch/board.h> | 38 | #include <asm/arch/board.h> |
39 | 39 | ||
40 | #ifdef CONFIG_ARCH_OMAP1 | ||
41 | |||
42 | #define INT_USB_IRQ_GEN IH2_BASE + 20 | ||
43 | #define INT_USB_IRQ_NISO IH2_BASE + 30 | ||
44 | #define INT_USB_IRQ_ISO IH2_BASE + 29 | ||
45 | #define INT_USB_IRQ_HGEN INT_USB_HHC_1 | ||
46 | #define INT_USB_IRQ_OTG IH2_BASE + 8 | ||
47 | |||
48 | #else | ||
49 | |||
50 | #define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN | ||
51 | #define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO | ||
52 | #define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO | ||
53 | #define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN | ||
54 | #define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG | ||
55 | |||
56 | #endif | ||
57 | |||
58 | |||
40 | /* These routines should handle the standard chip-specific modes | 59 | /* These routines should handle the standard chip-specific modes |
41 | * for usb0/1/2 ports, covering basic mux and transceiver setup. | 60 | * for usb0/1/2 ports, covering basic mux and transceiver setup. |
42 | * Call omap_usb_init() once, from INIT_MACHINE(). | ||
43 | * | 61 | * |
44 | * Some board-*.c files will need to set up additional mux options, | 62 | * Some board-*.c files will need to set up additional mux options, |
45 | * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. | 63 | * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. |
@@ -96,19 +114,26 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) | |||
96 | { | 114 | { |
97 | u32 syscon1 = 0; | 115 | u32 syscon1 = 0; |
98 | 116 | ||
117 | if (cpu_is_omap24xx()) | ||
118 | CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL); | ||
119 | |||
99 | if (nwires == 0) { | 120 | if (nwires == 0) { |
100 | if (!cpu_is_omap15xx()) { | 121 | if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { |
101 | /* pulldown D+/D- */ | 122 | /* pulldown D+/D- */ |
102 | USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); | 123 | USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); |
103 | } | 124 | } |
104 | return 0; | 125 | return 0; |
105 | } | 126 | } |
106 | 127 | ||
107 | if (is_device) | 128 | if (is_device) { |
108 | omap_cfg_reg(W4_USB_PUEN); | 129 | if (cpu_is_omap24xx()) |
130 | omap_cfg_reg(J20_24XX_USB0_PUEN); | ||
131 | else | ||
132 | omap_cfg_reg(W4_USB_PUEN); | ||
133 | } | ||
109 | 134 | ||
110 | /* internal transceiver */ | 135 | /* internal transceiver (unavailable on 17xx, 24xx) */ |
111 | if (nwires == 2) { | 136 | if (!cpu_class_is_omap2() && nwires == 2) { |
112 | // omap_cfg_reg(P9_USB_DP); | 137 | // omap_cfg_reg(P9_USB_DP); |
113 | // omap_cfg_reg(R8_USB_DM); | 138 | // omap_cfg_reg(R8_USB_DM); |
114 | 139 | ||
@@ -136,29 +161,50 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) | |||
136 | return 0; | 161 | return 0; |
137 | } | 162 | } |
138 | 163 | ||
139 | omap_cfg_reg(V6_USB0_TXD); | 164 | if (cpu_is_omap24xx()) { |
140 | omap_cfg_reg(W9_USB0_TXEN); | 165 | omap_cfg_reg(K18_24XX_USB0_DAT); |
141 | omap_cfg_reg(W5_USB0_SE0); | 166 | omap_cfg_reg(K19_24XX_USB0_TXEN); |
167 | omap_cfg_reg(J14_24XX_USB0_SE0); | ||
168 | if (nwires != 3) | ||
169 | omap_cfg_reg(J18_24XX_USB0_RCV); | ||
170 | } else { | ||
171 | omap_cfg_reg(V6_USB0_TXD); | ||
172 | omap_cfg_reg(W9_USB0_TXEN); | ||
173 | omap_cfg_reg(W5_USB0_SE0); | ||
174 | if (nwires != 3) | ||
175 | omap_cfg_reg(Y5_USB0_RCV); | ||
176 | } | ||
142 | 177 | ||
143 | /* NOTE: SPEED and SUSP aren't configured here */ | 178 | /* NOTE: SPEED and SUSP aren't configured here. OTG hosts |
179 | * may be able to use I2C requests to set those bits along | ||
180 | * with VBUS switching and overcurrent detction. | ||
181 | */ | ||
144 | 182 | ||
145 | if (nwires != 3) | 183 | if (cpu_class_is_omap1() && nwires != 6) |
146 | omap_cfg_reg(Y5_USB0_RCV); | ||
147 | if (nwires != 6) | ||
148 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; | 184 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; |
149 | 185 | ||
150 | switch (nwires) { | 186 | switch (nwires) { |
151 | case 3: | 187 | case 3: |
152 | syscon1 = 2; | 188 | syscon1 = 2; |
189 | if (cpu_is_omap24xx()) | ||
190 | CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); | ||
153 | break; | 191 | break; |
154 | case 4: | 192 | case 4: |
155 | syscon1 = 1; | 193 | syscon1 = 1; |
194 | if (cpu_is_omap24xx()) | ||
195 | CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); | ||
156 | break; | 196 | break; |
157 | case 6: | 197 | case 6: |
158 | syscon1 = 3; | 198 | syscon1 = 3; |
159 | omap_cfg_reg(AA9_USB0_VP); | 199 | if (cpu_is_omap24xx()) { |
160 | omap_cfg_reg(R9_USB0_VM); | 200 | omap_cfg_reg(J19_24XX_USB0_VP); |
161 | USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; | 201 | omap_cfg_reg(K20_24XX_USB0_VM); |
202 | CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR); | ||
203 | } else { | ||
204 | omap_cfg_reg(AA9_USB0_VP); | ||
205 | omap_cfg_reg(R9_USB0_VM); | ||
206 | USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; | ||
207 | } | ||
162 | break; | 208 | break; |
163 | default: | 209 | default: |
164 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", | 210 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", |
@@ -171,14 +217,22 @@ static u32 __init omap_usb1_init(unsigned nwires) | |||
171 | { | 217 | { |
172 | u32 syscon1 = 0; | 218 | u32 syscon1 = 0; |
173 | 219 | ||
174 | if (nwires != 6 && !cpu_is_omap15xx()) | 220 | if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) |
175 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; | 221 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; |
222 | if (cpu_is_omap24xx()) | ||
223 | CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL); | ||
224 | |||
176 | if (nwires == 0) | 225 | if (nwires == 0) |
177 | return 0; | 226 | return 0; |
178 | 227 | ||
179 | /* external transceiver */ | 228 | /* external transceiver */ |
180 | omap_cfg_reg(USB1_TXD); | 229 | if (cpu_class_is_omap1()) { |
181 | omap_cfg_reg(USB1_TXEN); | 230 | omap_cfg_reg(USB1_TXD); |
231 | omap_cfg_reg(USB1_TXEN); | ||
232 | if (nwires != 3) | ||
233 | omap_cfg_reg(USB1_RCV); | ||
234 | } | ||
235 | |||
182 | if (cpu_is_omap15xx()) { | 236 | if (cpu_is_omap15xx()) { |
183 | omap_cfg_reg(USB1_SEO); | 237 | omap_cfg_reg(USB1_SEO); |
184 | omap_cfg_reg(USB1_SPEED); | 238 | omap_cfg_reg(USB1_SPEED); |
@@ -190,20 +244,38 @@ static u32 __init omap_usb1_init(unsigned nwires) | |||
190 | } else if (cpu_is_omap1710()) { | 244 | } else if (cpu_is_omap1710()) { |
191 | omap_cfg_reg(R13_1710_USB1_SE0); | 245 | omap_cfg_reg(R13_1710_USB1_SE0); |
192 | // SUSP | 246 | // SUSP |
247 | } else if (cpu_is_omap24xx()) { | ||
248 | /* NOTE: board-specific code must set up pin muxing for usb1, | ||
249 | * since each signal could come out on either of two balls. | ||
250 | */ | ||
193 | } else { | 251 | } else { |
194 | pr_debug("usb unrecognized\n"); | 252 | pr_debug("usb%d cpu unrecognized\n", 1); |
253 | return 0; | ||
195 | } | 254 | } |
196 | if (nwires != 3) | ||
197 | omap_cfg_reg(USB1_RCV); | ||
198 | 255 | ||
199 | switch (nwires) { | 256 | switch (nwires) { |
257 | case 2: | ||
258 | if (!cpu_is_omap24xx()) | ||
259 | goto bad; | ||
260 | /* NOTE: board-specific code must override this setting if | ||
261 | * this TLL link is not using DP/DM | ||
262 | */ | ||
263 | syscon1 = 1; | ||
264 | CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL); | ||
265 | break; | ||
200 | case 3: | 266 | case 3: |
201 | syscon1 = 2; | 267 | syscon1 = 2; |
268 | if (cpu_is_omap24xx()) | ||
269 | CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); | ||
202 | break; | 270 | break; |
203 | case 4: | 271 | case 4: |
204 | syscon1 = 1; | 272 | syscon1 = 1; |
273 | if (cpu_is_omap24xx()) | ||
274 | CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); | ||
205 | break; | 275 | break; |
206 | case 6: | 276 | case 6: |
277 | if (cpu_is_omap24xx()) | ||
278 | goto bad; | ||
207 | syscon1 = 3; | 279 | syscon1 = 3; |
208 | omap_cfg_reg(USB1_VP); | 280 | omap_cfg_reg(USB1_VP); |
209 | omap_cfg_reg(USB1_VM); | 281 | omap_cfg_reg(USB1_VM); |
@@ -211,6 +283,7 @@ static u32 __init omap_usb1_init(unsigned nwires) | |||
211 | USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; | 283 | USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; |
212 | break; | 284 | break; |
213 | default: | 285 | default: |
286 | bad: | ||
214 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", | 287 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", |
215 | 1, nwires); | 288 | 1, nwires); |
216 | } | 289 | } |
@@ -221,10 +294,17 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) | |||
221 | { | 294 | { |
222 | u32 syscon1 = 0; | 295 | u32 syscon1 = 0; |
223 | 296 | ||
224 | /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */ | 297 | if (cpu_is_omap24xx()) { |
298 | CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL) | ||
299 | | USBT2TLL5PI); | ||
300 | alt_pingroup = 0; | ||
301 | } | ||
302 | |||
303 | /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ | ||
225 | if (alt_pingroup || nwires == 0) | 304 | if (alt_pingroup || nwires == 0) |
226 | return 0; | 305 | return 0; |
227 | if (nwires != 6 && !cpu_is_omap15xx()) | 306 | |
307 | if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) | ||
228 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; | 308 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; |
229 | 309 | ||
230 | /* external transceiver */ | 310 | /* external transceiver */ |
@@ -242,19 +322,54 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) | |||
242 | if (nwires != 3) | 322 | if (nwires != 3) |
243 | omap_cfg_reg(Y5_USB2_RCV); | 323 | omap_cfg_reg(Y5_USB2_RCV); |
244 | // FIXME omap_cfg_reg(USB2_SPEED); | 324 | // FIXME omap_cfg_reg(USB2_SPEED); |
325 | } else if (cpu_is_omap24xx()) { | ||
326 | omap_cfg_reg(Y11_24XX_USB2_DAT); | ||
327 | omap_cfg_reg(AA10_24XX_USB2_SE0); | ||
328 | if (nwires > 2) | ||
329 | omap_cfg_reg(AA12_24XX_USB2_TXEN); | ||
330 | if (nwires > 3) | ||
331 | omap_cfg_reg(AA6_24XX_USB2_RCV); | ||
245 | } else { | 332 | } else { |
246 | pr_debug("usb unrecognized\n"); | 333 | pr_debug("usb%d cpu unrecognized\n", 1); |
334 | return 0; | ||
247 | } | 335 | } |
248 | // omap_cfg_reg(USB2_SUSP); | 336 | // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP); |
249 | 337 | ||
250 | switch (nwires) { | 338 | switch (nwires) { |
339 | case 2: | ||
340 | if (!cpu_is_omap24xx()) | ||
341 | goto bad; | ||
342 | /* NOTE: board-specific code must override this setting if | ||
343 | * this TLL link is not using DP/DM | ||
344 | */ | ||
345 | syscon1 = 1; | ||
346 | CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL); | ||
347 | break; | ||
251 | case 3: | 348 | case 3: |
252 | syscon1 = 2; | 349 | syscon1 = 2; |
350 | if (cpu_is_omap24xx()) | ||
351 | CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); | ||
253 | break; | 352 | break; |
254 | case 4: | 353 | case 4: |
255 | syscon1 = 1; | 354 | syscon1 = 1; |
355 | if (cpu_is_omap24xx()) | ||
356 | CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); | ||
357 | break; | ||
358 | case 5: | ||
359 | if (!cpu_is_omap24xx()) | ||
360 | goto bad; | ||
361 | omap_cfg_reg(AA4_24XX_USB2_TLLSE0); | ||
362 | /* NOTE: board-specific code must override this setting if | ||
363 | * this TLL link is not using DP/DM. Something must also | ||
364 | * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} | ||
365 | */ | ||
366 | syscon1 = 3; | ||
367 | CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL) | ||
368 | | USBT2TLL5PI; | ||
256 | break; | 369 | break; |
257 | case 6: | 370 | case 6: |
371 | if (cpu_is_omap24xx()) | ||
372 | goto bad; | ||
258 | syscon1 = 3; | 373 | syscon1 = 3; |
259 | if (cpu_is_omap15xx()) { | 374 | if (cpu_is_omap15xx()) { |
260 | omap_cfg_reg(USB2_VP); | 375 | omap_cfg_reg(USB2_VP); |
@@ -266,6 +381,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) | |||
266 | } | 381 | } |
267 | break; | 382 | break; |
268 | default: | 383 | default: |
384 | bad: | ||
269 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", | 385 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", |
270 | 2, nwires); | 386 | 2, nwires); |
271 | } | 387 | } |
@@ -294,13 +410,13 @@ static struct resource udc_resources[] = { | |||
294 | .end = UDC_BASE + 0xff, | 410 | .end = UDC_BASE + 0xff, |
295 | .flags = IORESOURCE_MEM, | 411 | .flags = IORESOURCE_MEM, |
296 | }, { /* general IRQ */ | 412 | }, { /* general IRQ */ |
297 | .start = IH2_BASE + 20, | 413 | .start = INT_USB_IRQ_GEN, |
298 | .flags = IORESOURCE_IRQ, | 414 | .flags = IORESOURCE_IRQ, |
299 | }, { /* PIO IRQ */ | 415 | }, { /* PIO IRQ */ |
300 | .start = IH2_BASE + 30, | 416 | .start = INT_USB_IRQ_NISO, |
301 | .flags = IORESOURCE_IRQ, | 417 | .flags = IORESOURCE_IRQ, |
302 | }, { /* SOF IRQ */ | 418 | }, { /* SOF IRQ */ |
303 | .start = IH2_BASE + 29, | 419 | .start = INT_USB_IRQ_ISO, |
304 | .flags = IORESOURCE_IRQ, | 420 | .flags = IORESOURCE_IRQ, |
305 | }, | 421 | }, |
306 | }; | 422 | }; |
@@ -329,11 +445,11 @@ static u64 ohci_dmamask = ~(u32)0; | |||
329 | static struct resource ohci_resources[] = { | 445 | static struct resource ohci_resources[] = { |
330 | { | 446 | { |
331 | .start = OMAP_OHCI_BASE, | 447 | .start = OMAP_OHCI_BASE, |
332 | .end = OMAP_OHCI_BASE + 4096 - 1, | 448 | .end = OMAP_OHCI_BASE + 0xff, |
333 | .flags = IORESOURCE_MEM, | 449 | .flags = IORESOURCE_MEM, |
334 | }, | 450 | }, |
335 | { | 451 | { |
336 | .start = INT_USB_HHC_1, | 452 | .start = INT_USB_IRQ_HGEN, |
337 | .flags = IORESOURCE_IRQ, | 453 | .flags = IORESOURCE_IRQ, |
338 | }, | 454 | }, |
339 | }; | 455 | }; |
@@ -361,7 +477,7 @@ static struct resource otg_resources[] = { | |||
361 | .end = OTG_BASE + 0xff, | 477 | .end = OTG_BASE + 0xff, |
362 | .flags = IORESOURCE_MEM, | 478 | .flags = IORESOURCE_MEM, |
363 | }, { | 479 | }, { |
364 | .start = IH2_BASE + 8, | 480 | .start = INT_USB_IRQ_OTG, |
365 | .flags = IORESOURCE_IRQ, | 481 | .flags = IORESOURCE_IRQ, |
366 | }, | 482 | }, |
367 | }; | 483 | }; |
@@ -385,7 +501,7 @@ static struct platform_device otg_device = { | |||
385 | 501 | ||
386 | 502 | ||
387 | // FIXME correct answer depends on hmc_mode, | 503 | // FIXME correct answer depends on hmc_mode, |
388 | // as does any nonzero value for config->otg port number | 504 | // as does (on omap1) any nonzero value for config->otg port number |
389 | #ifdef CONFIG_USB_GADGET_OMAP | 505 | #ifdef CONFIG_USB_GADGET_OMAP |
390 | #define is_usb0_device(config) 1 | 506 | #define is_usb0_device(config) 1 |
391 | #else | 507 | #else |
@@ -426,12 +542,13 @@ omap_otg_init(struct omap_usb_config *config) | |||
426 | if (config->otg) | 542 | if (config->otg) |
427 | syscon |= OTG_EN; | 543 | syscon |= OTG_EN; |
428 | #endif | 544 | #endif |
429 | pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); | 545 | if (cpu_class_is_omap1()) |
546 | pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); | ||
430 | pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); | 547 | pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); |
431 | OTG_SYSCON_2_REG = syscon; | 548 | OTG_SYSCON_2_REG = syscon; |
432 | 549 | ||
433 | printk("USB: hmc %d", config->hmc_mode); | 550 | printk("USB: hmc %d", config->hmc_mode); |
434 | if (alt_pingroup) | 551 | if (!alt_pingroup) |
435 | printk(", usb2 alt %d wires", config->pins[2]); | 552 | printk(", usb2 alt %d wires", config->pins[2]); |
436 | else if (config->pins[0]) | 553 | else if (config->pins[0]) |
437 | printk(", usb0 %d wires%s", config->pins[0], | 554 | printk(", usb0 %d wires%s", config->pins[0], |
@@ -444,10 +561,12 @@ omap_otg_init(struct omap_usb_config *config) | |||
444 | printk(", Mini-AB on usb%d", config->otg - 1); | 561 | printk(", Mini-AB on usb%d", config->otg - 1); |
445 | printk("\n"); | 562 | printk("\n"); |
446 | 563 | ||
447 | /* leave USB clocks/controllers off until needed */ | 564 | if (cpu_class_is_omap1()) { |
448 | ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; | 565 | /* leave USB clocks/controllers off until needed */ |
449 | ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; | 566 | ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; |
450 | ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; | 567 | ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; |
568 | ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; | ||
569 | } | ||
451 | syscon = OTG_SYSCON_1_REG; | 570 | syscon = OTG_SYSCON_1_REG; |
452 | syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; | 571 | syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; |
453 | 572 | ||
@@ -585,7 +704,7 @@ omap_usb_init(void) | |||
585 | } | 704 | } |
586 | platform_data = *config; | 705 | platform_data = *config; |
587 | 706 | ||
588 | if (cpu_is_omap730() || cpu_is_omap16xx()) | 707 | if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx()) |
589 | omap_otg_init(&platform_data); | 708 | omap_otg_init(&platform_data); |
590 | else if (cpu_is_omap15xx()) | 709 | else if (cpu_is_omap15xx()) |
591 | omap_1510_usb_init(&platform_data); | 710 | omap_1510_usb_init(&platform_data); |