dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
edmacc_regs_base[j]);
for (i = 0; i < edma_cc[j]->num_slots; i++)
memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
&dummy_paramset, PARM_SIZE);
/* Mark all channels as unused */
memset(edma_cc[j]->edma_unused, 0xff, //此處先將dma的所有通道設為未使用
sizeof(edma_cc[j]->edma_unused));
if (info[j]->rsv) {
/* Clear the reserved channels in unused list */
rsv_chans = info[j]->rsv->rsv_chans;
if (rsv_chans) {
for (i = 0; rsv_chans[i][0] != -1; i++) {
off = rsv_chans[i][0];
ln = rsv_chans[i][1];
clear_bits(off, ln,
edma_cc[j]->edma_unused); //此處將前邊結da850_dma0_rsv_chans、da850_dma1_rsv_chans構體中的通道標記為已經使用。
}
}
/* Set the reserved slots in inuse list */
rsv_slots = info[j]->rsv->rsv_slots;
if (rsv_slots) {
for (i = 0; rsv_slots[i][0] != -1; i++) {
off = rsv_slots[i][0];
ln = rsv_slots[i][1];
set_bits(off, ln,
edma_cc[j]->edma_inuse); //此處將前邊結da850_dma0_rsv_slots、da850_dma1_rsv_slots構體中的slot標記為已經使用。
}
}
}
/* Event queue to TC mapping */
for (i = 0; queue_tc_mapping[i][0] != -1; i++)
map_queue_tc(j, queue_tc_mapping[i][0],
queue_tc_mapping[i][1]);
/* Event queue priority mapping */
for (i = 0; queue_priority_mapping[i][0] != -1; i++)
assign_priority_to_queue(j,
queue_priority_mapping[i][0],
queue_priority_mapping[i][1]);
/* Map the channel to param entry if channel mapping logic
* exist
*/
if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
map_dmach_param(j);
for (i = 0; i < info[j]->n_region; i++) {
edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
edma_write_array(j, EDMA_QRAE, i, 0x0);
}
arch_num_cc++;
}
if (tc_errs_handled) {
status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
"edma_tc0", &pdev->dev);
if (status < 0) {
dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
IRQ_TCERRINT0, status);
return status;
}
status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
"edma_tc1", &pdev->dev);
if (status < 0) {
dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
IRQ_TCERRINT, status);
return status;
}
}
return 0;
fail:
for (i = 0; i < EDMA_MAX_CC; i++) {
if (err_irq[i])
free_irq(err_irq[i], &pdev->dev);
if (irq[i])
free_irq(irq[i], &pdev->dev);
}
fail1:
for (i = 0; i < EDMA_MAX_CC; i++) {
if (r[i])
release_mem_region(r[i]->start, len[i]);
if (edmacc_regs_base[i])
iounmap(edmacc_regs_base[i]);
kfree(edma_cc[i]);
}
#if 0
fail2:
iounmap(edma30_tc0cfg_reg);
#endif
return status;
}
liuning 20:29:57
此函數完成標記以後,在擷取dma通道時就不會再擷取已經標記為已經使用的通道,但是如果擷取通道時擷取固定通道,則不受上邊標記的限制,具體分析如下:
int edma_alloc_channel(int channel,
void (*callback)(unsigned channel, u16 ch_status, void *data),
void *data,
enum dma_event_q eventq_no)
{
unsigned i, done = 0, ctlr = 0;
int ret = 0;
if (!unused_chan_list_done) {
/*
* Scan all the platform devices to find out the EDMA channels
* used and clear them in the unused list, making the rest
* available for ARM usage.
*/
ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
prepare_unused_channel_list);
if (ret < 0)
return ret;