diff options
Diffstat (limited to 'arch/arm/plat-omap/dma.c')
-rw-r--r-- | arch/arm/plat-omap/dma.c | 88 |
1 files changed, 74 insertions, 14 deletions
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 68eaae324b6a..d17375e06a1e 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c | |||
@@ -32,9 +32,9 @@ | |||
32 | 32 | ||
33 | #include <asm/system.h> | 33 | #include <asm/system.h> |
34 | #include <mach/hardware.h> | 34 | #include <mach/hardware.h> |
35 | #include <mach/dma.h> | 35 | #include <plat/dma.h> |
36 | 36 | ||
37 | #include <mach/tc.h> | 37 | #include <plat/tc.h> |
38 | 38 | ||
39 | #undef DEBUG | 39 | #undef DEBUG |
40 | 40 | ||
@@ -54,6 +54,12 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; | |||
54 | 54 | ||
55 | static int enable_1510_mode; | 55 | static int enable_1510_mode; |
56 | 56 | ||
57 | static struct omap_dma_global_context_registers { | ||
58 | u32 dma_irqenable_l0; | ||
59 | u32 dma_ocp_sysconfig; | ||
60 | u32 dma_gcr; | ||
61 | } omap_dma_global_context; | ||
62 | |||
57 | struct omap_dma_lch { | 63 | struct omap_dma_lch { |
58 | int next_lch; | 64 | int next_lch; |
59 | int dev_id; | 65 | int dev_id; |
@@ -1246,7 +1252,7 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) | |||
1246 | * OMAP_DMA_DYNAMIC_CHAIN | 1252 | * OMAP_DMA_DYNAMIC_CHAIN |
1247 | * @params - Channel parameters | 1253 | * @params - Channel parameters |
1248 | * | 1254 | * |
1249 | * @return - Succes : 0 | 1255 | * @return - Success : 0 |
1250 | * Failure: -EINVAL/-ENOMEM | 1256 | * Failure: -EINVAL/-ENOMEM |
1251 | */ | 1257 | */ |
1252 | int omap_request_dma_chain(int dev_id, const char *dev_name, | 1258 | int omap_request_dma_chain(int dev_id, const char *dev_name, |
@@ -2355,44 +2361,83 @@ void omap_stop_lcd_dma(void) | |||
2355 | } | 2361 | } |
2356 | EXPORT_SYMBOL(omap_stop_lcd_dma); | 2362 | EXPORT_SYMBOL(omap_stop_lcd_dma); |
2357 | 2363 | ||
2364 | void omap_dma_global_context_save(void) | ||
2365 | { | ||
2366 | omap_dma_global_context.dma_irqenable_l0 = | ||
2367 | dma_read(IRQENABLE_L0); | ||
2368 | omap_dma_global_context.dma_ocp_sysconfig = | ||
2369 | dma_read(OCP_SYSCONFIG); | ||
2370 | omap_dma_global_context.dma_gcr = dma_read(GCR); | ||
2371 | } | ||
2372 | |||
2373 | void omap_dma_global_context_restore(void) | ||
2374 | { | ||
2375 | int ch; | ||
2376 | |||
2377 | dma_write(omap_dma_global_context.dma_gcr, GCR); | ||
2378 | dma_write(omap_dma_global_context.dma_ocp_sysconfig, | ||
2379 | OCP_SYSCONFIG); | ||
2380 | dma_write(omap_dma_global_context.dma_irqenable_l0, | ||
2381 | IRQENABLE_L0); | ||
2382 | |||
2383 | /* | ||
2384 | * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared | ||
2385 | * after secure sram context save and restore. Hence we need to | ||
2386 | * manually clear those IRQs to avoid spurious interrupts. This | ||
2387 | * affects only secure devices. | ||
2388 | */ | ||
2389 | if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) | ||
2390 | dma_write(0x3 , IRQSTATUS_L0); | ||
2391 | |||
2392 | for (ch = 0; ch < dma_chan_count; ch++) | ||
2393 | if (dma_chan[ch].dev_id != -1) | ||
2394 | omap_clear_dma(ch); | ||
2395 | } | ||
2396 | |||
2358 | /*----------------------------------------------------------------------------*/ | 2397 | /*----------------------------------------------------------------------------*/ |
2359 | 2398 | ||
2360 | static int __init omap_init_dma(void) | 2399 | static int __init omap_init_dma(void) |
2361 | { | 2400 | { |
2401 | unsigned long base; | ||
2362 | int ch, r; | 2402 | int ch, r; |
2363 | 2403 | ||
2364 | if (cpu_class_is_omap1()) { | 2404 | if (cpu_class_is_omap1()) { |
2365 | omap_dma_base = OMAP1_IO_ADDRESS(OMAP1_DMA_BASE); | 2405 | base = OMAP1_DMA_BASE; |
2366 | dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; | 2406 | dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; |
2367 | } else if (cpu_is_omap24xx()) { | 2407 | } else if (cpu_is_omap24xx()) { |
2368 | omap_dma_base = OMAP2_IO_ADDRESS(OMAP24XX_DMA4_BASE); | 2408 | base = OMAP24XX_DMA4_BASE; |
2369 | dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; | 2409 | dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; |
2370 | } else if (cpu_is_omap34xx()) { | 2410 | } else if (cpu_is_omap34xx()) { |
2371 | omap_dma_base = OMAP2_IO_ADDRESS(OMAP34XX_DMA4_BASE); | 2411 | base = OMAP34XX_DMA4_BASE; |
2372 | dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; | 2412 | dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; |
2373 | } else if (cpu_is_omap44xx()) { | 2413 | } else if (cpu_is_omap44xx()) { |
2374 | omap_dma_base = OMAP2_IO_ADDRESS(OMAP44XX_DMA4_BASE); | 2414 | base = OMAP44XX_DMA4_BASE; |
2375 | dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; | 2415 | dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; |
2376 | } else { | 2416 | } else { |
2377 | pr_err("DMA init failed for unsupported omap\n"); | 2417 | pr_err("DMA init failed for unsupported omap\n"); |
2378 | return -ENODEV; | 2418 | return -ENODEV; |
2379 | } | 2419 | } |
2380 | 2420 | ||
2421 | omap_dma_base = ioremap(base, SZ_4K); | ||
2422 | BUG_ON(!omap_dma_base); | ||
2423 | |||
2381 | if (cpu_class_is_omap2() && omap_dma_reserve_channels | 2424 | if (cpu_class_is_omap2() && omap_dma_reserve_channels |
2382 | && (omap_dma_reserve_channels <= dma_lch_count)) | 2425 | && (omap_dma_reserve_channels <= dma_lch_count)) |
2383 | dma_lch_count = omap_dma_reserve_channels; | 2426 | dma_lch_count = omap_dma_reserve_channels; |
2384 | 2427 | ||
2385 | dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count, | 2428 | dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count, |
2386 | GFP_KERNEL); | 2429 | GFP_KERNEL); |
2387 | if (!dma_chan) | 2430 | if (!dma_chan) { |
2388 | return -ENOMEM; | 2431 | r = -ENOMEM; |
2432 | goto out_unmap; | ||
2433 | } | ||
2389 | 2434 | ||
2390 | if (cpu_class_is_omap2()) { | 2435 | if (cpu_class_is_omap2()) { |
2391 | dma_linked_lch = kzalloc(sizeof(struct dma_link_info) * | 2436 | dma_linked_lch = kzalloc(sizeof(struct dma_link_info) * |
2392 | dma_lch_count, GFP_KERNEL); | 2437 | dma_lch_count, GFP_KERNEL); |
2393 | if (!dma_linked_lch) { | 2438 | if (!dma_linked_lch) { |
2394 | kfree(dma_chan); | 2439 | r = -ENOMEM; |
2395 | return -ENOMEM; | 2440 | goto out_free; |
2396 | } | 2441 | } |
2397 | } | 2442 | } |
2398 | 2443 | ||
@@ -2466,7 +2511,7 @@ static int __init omap_init_dma(void) | |||
2466 | for (i = 0; i < ch; i++) | 2511 | for (i = 0; i < ch; i++) |
2467 | free_irq(omap1_dma_irq[i], | 2512 | free_irq(omap1_dma_irq[i], |
2468 | (void *) (i + 1)); | 2513 | (void *) (i + 1)); |
2469 | return r; | 2514 | goto out_free; |
2470 | } | 2515 | } |
2471 | } | 2516 | } |
2472 | } | 2517 | } |
@@ -2484,8 +2529,8 @@ static int __init omap_init_dma(void) | |||
2484 | setup_irq(irq, &omap24xx_dma_irq); | 2529 | setup_irq(irq, &omap24xx_dma_irq); |
2485 | } | 2530 | } |
2486 | 2531 | ||
2487 | /* Enable smartidle idlemodes and autoidle */ | ||
2488 | if (cpu_is_omap34xx()) { | 2532 | if (cpu_is_omap34xx()) { |
2533 | /* Enable smartidle idlemodes and autoidle */ | ||
2489 | u32 v = dma_read(OCP_SYSCONFIG); | 2534 | u32 v = dma_read(OCP_SYSCONFIG); |
2490 | v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | | 2535 | v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | |
2491 | DMA_SYSCONFIG_SIDLEMODE_MASK | | 2536 | DMA_SYSCONFIG_SIDLEMODE_MASK | |
@@ -2494,6 +2539,13 @@ static int __init omap_init_dma(void) | |||
2494 | DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | | 2539 | DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | |
2495 | DMA_SYSCONFIG_AUTOIDLE); | 2540 | DMA_SYSCONFIG_AUTOIDLE); |
2496 | dma_write(v , OCP_SYSCONFIG); | 2541 | dma_write(v , OCP_SYSCONFIG); |
2542 | /* reserve dma channels 0 and 1 in high security devices */ | ||
2543 | if (omap_type() != OMAP2_DEVICE_TYPE_GP) { | ||
2544 | printk(KERN_INFO "Reserving DMA channels 0 and 1 for " | ||
2545 | "HS ROM code\n"); | ||
2546 | dma_chan[0].dev_id = 0; | ||
2547 | dma_chan[1].dev_id = 1; | ||
2548 | } | ||
2497 | } | 2549 | } |
2498 | 2550 | ||
2499 | 2551 | ||
@@ -2508,11 +2560,19 @@ static int __init omap_init_dma(void) | |||
2508 | "(error %d)\n", r); | 2560 | "(error %d)\n", r); |
2509 | for (i = 0; i < dma_chan_count; i++) | 2561 | for (i = 0; i < dma_chan_count; i++) |
2510 | free_irq(omap1_dma_irq[i], (void *) (i + 1)); | 2562 | free_irq(omap1_dma_irq[i], (void *) (i + 1)); |
2511 | return r; | 2563 | goto out_free; |
2512 | } | 2564 | } |
2513 | } | 2565 | } |
2514 | 2566 | ||
2515 | return 0; | 2567 | return 0; |
2568 | |||
2569 | out_free: | ||
2570 | kfree(dma_chan); | ||
2571 | |||
2572 | out_unmap: | ||
2573 | iounmap(omap_dma_base); | ||
2574 | |||
2575 | return r; | ||
2516 | } | 2576 | } |
2517 | 2577 | ||
2518 | arch_initcall(omap_init_dma); | 2578 | arch_initcall(omap_init_dma); |