| @@ -88,22 +88,6 @@ struct dma_link_info { · 87 unmodified lines |
| 88 | | 88 | |
| 89 | }; | 89 | }; |
| 90 | | 90 | |
| 91 | static struct dma_link_info *dma_linked_lch; | | |
| 92 | | | |
| 93 | #ifndef CONFIG_ARCH_OMAP1 | | |
| 94 | | | |
| 95 | /* Chain handling macros */ | | |
| 96 | #define OMAP_DMA_CHAIN_QEMPTY(chain_id) \ | | |
| 97 | (0 == dma_linked_lch[chain_id].q_count) | | |
| 98 | #define __OMAP_DMA_CHAIN_INCQ(end) \ | | |
| 99 | ((end) = ((end)+1) % dma_linked_lch[chain_id].no_of_lchs_linked) | | |
| 100 | #define OMAP_DMA_CHAIN_INCQHEAD(chain_id) \ | | |
| 101 | do { \ | | |
| 102 | __OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_head); \ | | |
| 103 | dma_linked_lch[chain_id].q_count--; \ | | |
| 104 | } while (0) | | |
| 105 | #endif | | |
| 106 | | | |
| 107 | static int dma_lch_count; | 91 | static int dma_lch_count; |
| 108 | static int dma_chan_count; | 92 | static int dma_chan_count; |
| 109 | static int omap_dma_reserve_channels; | 93 | static int omap_dma_reserve_channels; |
| @@ -469,12 +453,6 @@ static inline void enable_lnk(int lch) · 359 unmodified lines |
| 469 | if (dma_chan[lch].next_lch != -1) | 453 | if (dma_chan[lch].next_lch != -1) |
| 470 | l = dma_chan[lch].next_lch | (1 << 15); | 454 | l = dma_chan[lch].next_lch | (1 << 15); |
| 471 | | 455 | |
| 472 | #ifndef CONFIG_ARCH_OMAP1 | | |
| 473 | if (dma_omap2plus()) | | |
| 474 | if (dma_chan[lch].next_linked_ch != -1) | | |
| 475 | l = dma_chan[lch].next_linked_ch | (1 << 15); | | |
| 476 | #endif | | |
| 477 | | | |
| 478 | p->dma_write(l, CLNK_CTRL, lch); | 456 | p->dma_write(l, CLNK_CTRL, lch); |
| 479 | } | 457 | } |
| 480 | | 458 | |
| @@ -501,42 +479,6 @@ static inline void disable_lnk(int lch) · 20 unmodified lines |
| 501 | dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; | 479 | dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; |
| 502 | } | 480 | } |
| 503 | | 481 | |
| 504 | static inline void omap2_enable_irq_lch(int lch) | | |
| 505 | { | | |
| 506 | u32 val; | | |
| 507 | unsigned long flags; | | |
| 508 | | | |
| 509 | if (dma_omap1()) | | |
| 510 | return; | | |
| 511 | | | |
| 512 | spin_lock_irqsave(&dma_chan_lock, flags); | | |
| 513 | /* clear IRQ STATUS */ | | |
| 514 | p->dma_write(1 << lch, IRQSTATUS_L0, lch); | | |
| 515 | /* Enable interrupt */ | | |
| 516 | val = p->dma_read(IRQENABLE_L0, lch); | | |
| 517 | val |= 1 << lch; | | |
| 518 | p->dma_write(val, IRQENABLE_L0, lch); | | |
| 519 | spin_unlock_irqrestore(&dma_chan_lock, flags); | | |
| 520 | } | | |
| 521 | | | |
| 522 | static inline void omap2_disable_irq_lch(int lch) | | |
| 523 | { | | |
| 524 | u32 val; | | |
| 525 | unsigned long flags; | | |
| 526 | | | |
| 527 | if (dma_omap1()) | | |
| 528 | return; | | |
| 529 | | | |
| 530 | spin_lock_irqsave(&dma_chan_lock, flags); | | |
| 531 | /* Disable interrupt */ | | |
| 532 | val = p->dma_read(IRQENABLE_L0, lch); | | |
| 533 | val &= ~(1 << lch); | | |
| 534 | p->dma_write(val, IRQENABLE_L0, lch); | | |
| 535 | /* clear IRQ STATUS */ | | |
| 536 | p->dma_write(1 << lch, IRQSTATUS_L0, lch); | | |
| 537 | spin_unlock_irqrestore(&dma_chan_lock, flags); | | |
| 538 | } | | |
| 539 | | | |
| 540 | int omap_request_dma(int dev_id, const char *dev_name, | 482 | int omap_request_dma(int dev_id, const char *dev_name, |
| 541 | void (*callback)(int lch, u16 ch_status, void *data), | 483 | void (*callback)(int lch, u16 ch_status, void *data), |
| 542 | void *data, int *dma_ch_out) | 484 | void *data, int *dma_ch_out) |
| @@ -565,9 +507,6 @@ int omap_request_dma(int dev_id, const char *dev_name, · 22 unmodified lines |
| 565 | if (p->clear_lch_regs) | 507 | if (p->clear_lch_regs) |
| 566 | p->clear_lch_regs(free_ch); | 508 | p->clear_lch_regs(free_ch); |
| 567 | | 509 | |
| 568 | if (dma_omap2plus()) | | |
| 569 | omap_clear_dma(free_ch); | | |
| 570 | | | |
| 571 | spin_unlock_irqrestore(&dma_chan_lock, flags); | 510 | spin_unlock_irqrestore(&dma_chan_lock, flags); |
| 572 | | 511 | |
| 573 | chan->dev_name = dev_name; | 512 | chan->dev_name = dev_name; |
| @@ -575,20 +514,10 @@ int omap_request_dma(int dev_id, const char *dev_name, · 1 unmodified line |
| 575 | chan->data = data; | 514 | chan->data = data; |
| 576 | chan->flags = 0; | 515 | chan->flags = 0; |
| 577 | | 516 | |
| 578 | #ifndef CONFIG_ARCH_OMAP1 | | |
| 579 | if (dma_omap2plus()) { | | |
| 580 | chan->chain_id = -1; | | |
| 581 | chan->next_linked_ch = -1; | | |
| 582 | } | | |
| 583 | #endif | | |
| 584 | | | |
| 585 | chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; | 517 | chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; |
| 586 | | 518 | |
| 587 | if (dma_omap1()) | 519 | if (dma_omap1()) |
| 588 | chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ; | 520 | chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ; |
| 589 | else if (dma_omap2plus()) | | |
| 590 | chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ | | | |
| 591 | OMAP2_DMA_TRANS_ERR_IRQ; | | |
| 592 | | 521 | |
| 593 | if (dma_omap16xx()) { | 522 | if (dma_omap16xx()) { |
| 594 | /* If the sync device is set, configure it dynamically. */ | 523 | /* If the sync device is set, configure it dynamically. */ |
| @@ -605,11 +534,6 @@ int omap_request_dma(int dev_id, const char *dev_name, · 10 unmodified lines |
| 605 | p->dma_write(dev_id, CCR, free_ch); | 534 | p->dma_write(dev_id, CCR, free_ch); |
| 606 | } | 535 | } |
| 607 | | 536 | |
| 608 | if (dma_omap2plus()) { | | |
| 609 | omap_enable_channel_irq(free_ch); | | |
| 610 | omap2_enable_irq_lch(free_ch); | | |
| 611 | } | | |
| 612 | | | |
| 613 | *dma_ch_out = free_ch; | 537 | *dma_ch_out = free_ch; |
| 614 | | 538 | |
| 615 | return 0; | 539 | return 0; |
| @@ -626,20 +550,12 @@ void omap_free_dma(int lch) · 10 unmodified lines |
| 626 | return; | 550 | return; |
| 627 | } | 551 | } |
| 628 | | 552 | |
| 629 | /* Disable interrupt for logical channel */ | | |
| 630 | if (dma_omap2plus()) | | |
| 631 | omap2_disable_irq_lch(lch); | | |
| 632 | | | |
| 633 | /* Disable all DMA interrupts for the channel. */ | 553 | /* Disable all DMA interrupts for the channel. */ |
| 634 | omap_disable_channel_irq(lch); | 554 | omap_disable_channel_irq(lch); |
| 635 | | 555 | |
| 636 | /* Make sure the DMA transfer is stopped. */ | 556 | /* Make sure the DMA transfer is stopped. */ |
| 637 | p->dma_write(0, CCR, lch); | 557 | p->dma_write(0, CCR, lch); |
| 638 | | 558 | |
| 639 | /* Clear registers */ | | |
| 640 | if (dma_omap2plus()) | | |
| 641 | omap_clear_dma(lch); | | |
| 642 | | | |
| 643 | spin_lock_irqsave(&dma_chan_lock, flags); | 559 | spin_lock_irqsave(&dma_chan_lock, flags); |
| 644 | dma_chan[lch].dev_id = -1; | 560 | dma_chan[lch].dev_id = -1; |
| 645 | dma_chan[lch].next_lch = -1; | 561 | dma_chan[lch].next_lch = -1; |
| @@ -989,109 +905,6 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id) · 343 unmodified lines |
| 989 | #define omap1_dma_irq_handler NULL | 905 | #define omap1_dma_irq_handler NULL |
| 990 | #endif | 906 | #endif |
| 991 | | 907 | |
| 992 | #ifdef CONFIG_ARCH_OMAP2PLUS | | |
| 993 | | | |
| 994 | static int omap2_dma_handle_ch(int ch) | | |
| 995 | { | | |
| 996 | u32 status = p->dma_read(CSR, ch); | | |
| 997 | | | |
| 998 | if (!status) { | | |
| 999 | if (printk_ratelimit()) | | |
| 1000 | pr_warn("Spurious DMA IRQ for lch %d\n", ch); | | |
| 1001 | p->dma_write(1 << ch, IRQSTATUS_L0, ch); | | |
| 1002 | return 0; | | |
| 1003 | } | | |
| 1004 | if (unlikely(dma_chan[ch].dev_id == -1)) { | | |
| 1005 | if (printk_ratelimit()) | | |
| 1006 | pr_warn("IRQ %04x for non-allocated DMA channel %d\n", | | |
| 1007 | status, ch); | | |
| 1008 | return 0; | | |
| 1009 | } | | |
| 1010 | if (unlikely(status & OMAP_DMA_DROP_IRQ)) | | |
| 1011 | pr_info("DMA synchronization event drop occurred with device %d\n", | | |
| 1012 | dma_chan[ch].dev_id); | | |
| 1013 | if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) { | | |
| 1014 | printk(KERN_INFO "DMA transaction error with device %d\n", | | |
| 1015 | dma_chan[ch].dev_id); | | |
| 1016 | if (IS_DMA_ERRATA(DMA_ERRATA_i378)) { | | |
| 1017 | u32 ccr; | | |
| 1018 | | | |
| 1019 | ccr = p->dma_read(CCR, ch); | | |
| 1020 | ccr &= ~OMAP_DMA_CCR_EN; | | |
| 1021 | p->dma_write(ccr, CCR, ch); | | |
| 1022 | dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; | | |
| 1023 | } | | |
| 1024 | } | | |
| 1025 | if (unlikely(status & OMAP2_DMA_SECURE_ERR_IRQ)) | | |
| 1026 | printk(KERN_INFO "DMA secure error with device %d\n", | | |
| 1027 | dma_chan[ch].dev_id); | | |
| 1028 | if (unlikely(status & OMAP2_DMA_MISALIGNED_ERR_IRQ)) | | |
| 1029 | printk(KERN_INFO "DMA misaligned error with device %d\n", | | |
| 1030 | dma_chan[ch].dev_id); | | |
| 1031 | | | |
| 1032 | p->dma_write(status, CSR, ch); | | |
| 1033 | p->dma_write(1 << ch, IRQSTATUS_L0, ch); | | |
| 1034 | /* read back the register to flush the write */ | | |
| 1035 | p->dma_read(IRQSTATUS_L0, ch); | | |
| 1036 | | | |
| 1037 | /* If the ch is not chained then chain_id will be -1 */ | | |
| 1038 | if (dma_chan[ch].chain_id != -1) { | | |
| 1039 | int chain_id = dma_chan[ch].chain_id; | | |
| 1040 | dma_chan[ch].state = DMA_CH_NOTSTARTED; | | |
| 1041 | if (p->dma_read(CLNK_CTRL, ch) & (1 << 15)) | | |
| 1042 | dma_chan[dma_chan[ch].next_linked_ch].state = | | |
| 1043 | DMA_CH_STARTED; | | |
| 1044 | if (dma_linked_lch[chain_id].chain_mode == | | |
| 1045 | OMAP_DMA_DYNAMIC_CHAIN) | | |
| 1046 | disable_lnk(ch); | | |
| 1047 | | | |
| 1048 | if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) | | |
| 1049 | OMAP_DMA_CHAIN_INCQHEAD(chain_id); | | |
| 1050 | | | |
| 1051 | status = p->dma_read(CSR, ch); | | |
| 1052 | p->dma_write(status, CSR, ch); | | |
| 1053 | } | | |
| 1054 | | | |
| 1055 | if (likely(dma_chan[ch].callback != NULL)) | | |
| 1056 | dma_chan[ch].callback(ch, status, dma_chan[ch].data); | | |
| 1057 | | | |
| 1058 | return 0; | | |
| 1059 | } | | |
| 1060 | | | |
| 1061 | /* STATUS register count is from 1-32 while our is 0-31 */ | | |
| 1062 | static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) | | |
| 1063 | { | | |
| 1064 | u32 val, enable_reg; | | |
| 1065 | int i; | | |
| 1066 | | | |
| 1067 | val = p->dma_read(IRQSTATUS_L0, 0); | | |
| 1068 | if (val == 0) { | | |
| 1069 | if (printk_ratelimit()) | | |
| 1070 | printk(KERN_WARNING "Spurious DMA IRQ\n"); | | |
| 1071 | return IRQ_HANDLED; | | |
| 1072 | } | | |
| 1073 | enable_reg = p->dma_read(IRQENABLE_L0, 0); | | |
| 1074 | val &= enable_reg; /* Dispatch only relevant interrupts */ | | |
| 1075 | for (i = 0; i < dma_lch_count && val != 0; i++) { | | |
| 1076 | if (val & 1) | | |
| 1077 | omap2_dma_handle_ch(i); | | |
| 1078 | val >>= 1; | | |
| 1079 | } | | |
| 1080 | | | |
| 1081 | return IRQ_HANDLED; | | |
| 1082 | } | | |
| 1083 | | | |
| 1084 | static struct irqaction omap24xx_dma_irq = { | | |
| 1085 | .name = "DMA", | | |
| 1086 | .handler = omap2_dma_irq_handler, | | |
| 1087 | }; | | |
| 1088 | | | |
| 1089 | #else | | |
| 1090 | static struct irqaction omap24xx_dma_irq; | | |
| 1091 | #endif | | |
| 1092 | | | |
| 1093 | /*----------------------------------------------------------------------------*/ | | |
| 1094 | | | |
| 1095 | /* | 908 | /* |
| 1096 | * Note that we are currently using only IRQENABLE_L0 and L1. | 909 | * Note that we are currently using only IRQENABLE_L0 and L1. |
| 1097 | * As the DSP may be using IRQENABLE_L2 and L3, let's not | 910 | * As the DSP may be using IRQENABLE_L2 and L3, let's not |
| @@ -1139,7 +952,6 @@ static int omap_system_dma_probe(struct platform_device *pdev) · 41 unmodified lines |
| 1139 | int ch, ret = 0; | 952 | int ch, ret = 0; |
| 1140 | int dma_irq; | 953 | int dma_irq; |
| 1141 | char irq_name[4]; | 954 | char irq_name[4]; |
| 1142 | int irq_rel; | | |
| 1143 | | 955 | |
| 1144 | p = pdev->dev.platform_data; | 956 | p = pdev->dev.platform_data; |
| 1145 | if (!p) { | 957 | if (!p) { |
| @@ -1165,21 +977,9 @@ static int omap_system_dma_probe(struct platform_device *pdev) · 19 unmodified lines |
| 1165 | if (!dma_chan) | 977 | if (!dma_chan) |
| 1166 | return -ENOMEM; | 978 | return -ENOMEM; |
| 1167 | | 979 | |
| 1168 | if (dma_omap2plus()) { | | |
| 1169 | dma_linked_lch = kcalloc(dma_lch_count, | | |
| 1170 | sizeof(*dma_linked_lch), | | |
| 1171 | GFP_KERNEL); | | |
| 1172 | if (!dma_linked_lch) { | | |
| 1173 | ret = -ENOMEM; | | |
| 1174 | goto exit_dma_lch_fail; | | |
| 1175 | } | | |
| 1176 | } | | |
| 1177 | | | |
| 1178 | spin_lock_init(&dma_chan_lock); | 980 | spin_lock_init(&dma_chan_lock); |
| 1179 | for (ch = 0; ch < dma_chan_count; ch++) { | 981 | for (ch = 0; ch < dma_chan_count; ch++) { |
| 1180 | omap_clear_dma(ch); | 982 | omap_clear_dma(ch); |
| 1181 | if (dma_omap2plus()) | | |
| 1182 | omap2_disable_irq_lch(ch); | | |
| 1183 | | 983 | |
| 1184 | dma_chan[ch].dev_id = -1; | 984 | dma_chan[ch].dev_id = -1; |
| 1185 | dma_chan[ch].next_lch = -1; | 985 | dma_chan[ch].next_lch = -1; |
| @@ -1216,22 +1016,6 @@ static int omap_system_dma_probe(struct platform_device *pdev) · 30 unmodified lines |
| 1216 | omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, | 1016 | omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, |
| 1217 | DMA_DEFAULT_FIFO_DEPTH, 0); | 1017 | DMA_DEFAULT_FIFO_DEPTH, 0); |
| 1218 | | 1018 | |
| 1219 | if (dma_omap2plus() && !(d->dev_caps & DMA_ENGINE_HANDLE_IRQ)) { | | |
| 1220 | strcpy(irq_name, "0"); | | |
| 1221 | dma_irq = platform_get_irq_byname(pdev, irq_name); | | |
| 1222 | if (dma_irq < 0) { | | |
| 1223 | dev_err(&pdev->dev, "failed: request IRQ %d", dma_irq); | | |
| 1224 | ret = dma_irq; | | |
| 1225 | goto exit_dma_lch_fail; | | |
| 1226 | } | | |
| 1227 | ret = setup_irq(dma_irq, &omap24xx_dma_irq); | | |
| 1228 | if (ret) { | | |
| 1229 | dev_err(&pdev->dev, "set_up failed for IRQ %d for DMA (error %d)\n", | | |
| 1230 | dma_irq, ret); | | |
| 1231 | goto exit_dma_lch_fail; | | |
| 1232 | } | | |
| 1233 | } | | |
| 1234 | | | |
| 1235 | /* reserve dma channels 0 and 1 in high security devices on 34xx */ | 1019 | /* reserve dma channels 0 and 1 in high security devices on 34xx */ |
| 1236 | if (d->dev_caps & HS_CHANNELS_RESERVED) { | 1020 | if (d->dev_caps & HS_CHANNELS_RESERVED) { |
| 1237 | pr_info("Reserving DMA channels 0 and 1 for HS ROM code\n"); | 1021 | pr_info("Reserving DMA channels 0 and 1 for HS ROM code\n"); |
| @@ -1242,34 +1026,21 @@ static int omap_system_dma_probe(struct platform_device *pdev) · 4 unmodified lines |
| 1242 | return 0; | 1026 | return 0; |
| 1243 | | 1027 | |
| 1244 | exit_dma_irq_fail: | 1028 | exit_dma_irq_fail: |
| 1245 | dev_err(&pdev->dev, "unable to request IRQ %d for DMA (error %d)\n", | | |
| 1246 | dma_irq, ret); | | |
| 1247 | for (irq_rel = 0; irq_rel < ch; irq_rel++) { | | |
| 1248 | dma_irq = platform_get_irq(pdev, irq_rel); | | |
| 1249 | free_irq(dma_irq, (void *)(irq_rel + 1)); | | |
| 1250 | } | | |
| 1251 | | | |
| 1252 | exit_dma_lch_fail: | | |
| 1253 | return ret; | 1029 | return ret; |
| 1254 | } | 1030 | } |
| 1255 | | 1031 | |
| 1256 | static int omap_system_dma_remove(struct platform_device *pdev) | 1032 | static int omap_system_dma_remove(struct platform_device *pdev) |
| 1257 | { | 1033 | { |
| 1258 | int dma_irq; | 1034 | int dma_irq, irq_rel = 0; |
| 1259 | | 1035 | |
| 1260 | if (dma_omap2plus()) { | 1036 | if (dma_omap2plus()) |
| 1261 | char irq_name[4]; | 1037 | return 0; |
| 1262 | strcpy(irq_name, "0"); | 1038 | |
| 1263 | dma_irq = platform_get_irq_byname(pdev, irq_name); | 1039 | for ( ; irq_rel < dma_chan_count; irq_rel++) { |
| 1264 | if (dma_irq >= 0) | 1040 | dma_irq = platform_get_irq(pdev, irq_rel); |
| 1265 | remove_irq(dma_irq, &omap24xx_dma_irq); | 1041 | free_irq(dma_irq, (void *)(irq_rel + 1)); |
| 1266 | } else { | | |
| 1267 | int irq_rel = 0; | | |
| 1268 | for ( ; irq_rel < dma_chan_count; irq_rel++) { | | |
| 1269 | dma_irq = platform_get_irq(pdev, irq_rel); | | |
| 1270 | free_irq(dma_irq, (void *)(irq_rel + 1)); | | |
| 1271 | } | | |
| 1272 | } | 1042 | } |
| | 1043 | |
| 1273 | return 0; | 1044 | return 0; |
| 1274 | } | 1045 | } |
| 1275 | | 1046 | |