Commit 90bd4e6d authored by Rajashekhara, Sudhakar's avatar Rajashekhara, Sudhakar Committed by Kevin Hilman

davinci: support for EDMA resource sharing

Current EDMA driver is not taking care of EDMA channels/slots
which are allocated from other processor, say DSP. If a
channel/slot is allocated from DSP, the existing EDMA driver
can still allocate the same resource on ARM.

This patch enables the user to pass the channel/slots reserved
for DSP as platform data. EDMA driver scans this list during
probe and prepares a bitmap of channel/slots which can be used
on ARM side.

Trying to reserve channels by doing a 'pre-allocate' using
edma_alloc_{slot|channel}() API does not work because

1) The reservation should be done in probe() to avoid race
   with other ARM side driver trying to use EDMA

2) The alloc channel API sets up the access through shadow region
   0 which will be incorrect for DSP usage. It also sets up the
   channel <-> queue number mapping which is not required as DSP
   will likely do its own mapping anyway.

3) (minor) There is no API to allocate channels in bulk.
Signed-off-by: default avatarSudhakar Rajashekhara <sudhakar.raj@ti.com>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: default avatarSekhar Nori <nsekhar@ti.com>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent bc3ac9f3
...@@ -205,6 +205,18 @@ static inline void edma_parm_or(unsigned ctlr, int offset, int param_no, ...@@ -205,6 +205,18 @@ static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,
edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or); edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or);
} }
static inline void set_bits(int offset, int len, unsigned long *p)
{
for (; len > 0; len--)
set_bit(offset + (len - 1), p);
}
static inline void clear_bits(int offset, int len, unsigned long *p)
{
for (; len > 0; len--)
clear_bit(offset + (len - 1), p);
}
/*****************************************************************************/ /*****************************************************************************/
/* actual number of DMA channels and slots on this silicon */ /* actual number of DMA channels and slots on this silicon */
...@@ -1377,8 +1389,10 @@ static int __init edma_probe(struct platform_device *pdev) ...@@ -1377,8 +1389,10 @@ static int __init edma_probe(struct platform_device *pdev)
struct edma_soc_info **info = pdev->dev.platform_data; struct edma_soc_info **info = pdev->dev.platform_data;
const s8 (*queue_priority_mapping)[2]; const s8 (*queue_priority_mapping)[2];
const s8 (*queue_tc_mapping)[2]; const s8 (*queue_tc_mapping)[2];
int i, j, found = 0; int i, j, off, ln, found = 0;
int status = -1; int status = -1;
const s16 (*rsv_chans)[2];
const s16 (*rsv_slots)[2];
int irq[EDMA_MAX_CC] = {0, 0}; int irq[EDMA_MAX_CC] = {0, 0};
int err_irq[EDMA_MAX_CC] = {0, 0}; int err_irq[EDMA_MAX_CC] = {0, 0};
struct resource *r[EDMA_MAX_CC] = {NULL}; struct resource *r[EDMA_MAX_CC] = {NULL};
...@@ -1446,6 +1460,31 @@ static int __init edma_probe(struct platform_device *pdev) ...@@ -1446,6 +1460,31 @@ static int __init edma_probe(struct platform_device *pdev)
memset(edma_cc[j]->edma_unused, 0xff, memset(edma_cc[j]->edma_unused, 0xff,
sizeof(edma_cc[j]->edma_unused)); 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);
}
}
/* 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);
}
}
}
sprintf(irq_name, "edma%d", j); sprintf(irq_name, "edma%d", j);
irq[j] = platform_get_irq_byname(pdev, irq_name); irq[j] = platform_get_irq_byname(pdev, irq_name);
edma_cc[j]->irq_res_start = irq[j]; edma_cc[j]->irq_res_start = irq[j];
......
...@@ -271,6 +271,12 @@ void edma_clear_event(unsigned channel); ...@@ -271,6 +271,12 @@ void edma_clear_event(unsigned channel);
void edma_pause(unsigned channel); void edma_pause(unsigned channel);
void edma_resume(unsigned channel); void edma_resume(unsigned channel);
struct edma_rsv_info {
const s16 (*rsv_chans)[2];
const s16 (*rsv_slots)[2];
};
/* platform_data for EDMA driver */ /* platform_data for EDMA driver */
struct edma_soc_info { struct edma_soc_info {
...@@ -282,6 +288,9 @@ struct edma_soc_info { ...@@ -282,6 +288,9 @@ struct edma_soc_info {
unsigned n_cc; unsigned n_cc;
enum dma_event_q default_queue; enum dma_event_q default_queue;
/* Resource reservation for other cores */
struct edma_rsv_info *rsv;
const s8 (*queue_tc_mapping)[2]; const s8 (*queue_tc_mapping)[2];
const s8 (*queue_priority_mapping)[2]; const s8 (*queue_priority_mapping)[2];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment