aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci
diff options
context:
space:
mode:
authorRajashekhara, Sudhakar <sudhakar.raj@ti.com>2010-06-29 02:05:13 -0400
committerKevin Hilman <khilman@deeprootsystems.com>2010-08-05 12:58:25 -0400
commit90bd4e6dd7f4b747477f2ad0125adb933cf3bcfa (patch)
tree081fdeffcd68ac2aebf9cfea60de94770b9bef64 /arch/arm/mach-davinci
parentbc3ac9f31642fb4697b313c2eb575c5286f35c2a (diff)
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: Sudhakar Rajashekhara <sudhakar.raj@ti.com> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Sekhar Nori <nsekhar@ti.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci')
-rw-r--r--arch/arm/mach-davinci/dma.c41
-rw-r--r--arch/arm/mach-davinci/include/mach/edma.h9
2 files changed, 49 insertions, 1 deletions
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 0b6c01fbedd5..2ede598b77dd 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -205,6 +205,18 @@ static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,
205 edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or); 205 edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or);
206} 206}
207 207
208static inline void set_bits(int offset, int len, unsigned long *p)
209{
210 for (; len > 0; len--)
211 set_bit(offset + (len - 1), p);
212}
213
214static inline void clear_bits(int offset, int len, unsigned long *p)
215{
216 for (; len > 0; len--)
217 clear_bit(offset + (len - 1), p);
218}
219
208/*****************************************************************************/ 220/*****************************************************************************/
209 221
210/* actual number of DMA channels and slots on this silicon */ 222/* actual number of DMA channels and slots on this silicon */
@@ -1377,8 +1389,10 @@ static int __init edma_probe(struct platform_device *pdev)
1377 struct edma_soc_info **info = pdev->dev.platform_data; 1389 struct edma_soc_info **info = pdev->dev.platform_data;
1378 const s8 (*queue_priority_mapping)[2]; 1390 const s8 (*queue_priority_mapping)[2];
1379 const s8 (*queue_tc_mapping)[2]; 1391 const s8 (*queue_tc_mapping)[2];
1380 int i, j, found = 0; 1392 int i, j, off, ln, found = 0;
1381 int status = -1; 1393 int status = -1;
1394 const s16 (*rsv_chans)[2];
1395 const s16 (*rsv_slots)[2];
1382 int irq[EDMA_MAX_CC] = {0, 0}; 1396 int irq[EDMA_MAX_CC] = {0, 0};
1383 int err_irq[EDMA_MAX_CC] = {0, 0}; 1397 int err_irq[EDMA_MAX_CC] = {0, 0};
1384 struct resource *r[EDMA_MAX_CC] = {NULL}; 1398 struct resource *r[EDMA_MAX_CC] = {NULL};
@@ -1446,6 +1460,31 @@ static int __init edma_probe(struct platform_device *pdev)
1446 memset(edma_cc[j]->edma_unused, 0xff, 1460 memset(edma_cc[j]->edma_unused, 0xff,
1447 sizeof(edma_cc[j]->edma_unused)); 1461 sizeof(edma_cc[j]->edma_unused));
1448 1462
1463 if (info[j]->rsv) {
1464
1465 /* Clear the reserved channels in unused list */
1466 rsv_chans = info[j]->rsv->rsv_chans;
1467 if (rsv_chans) {
1468 for (i = 0; rsv_chans[i][0] != -1; i++) {
1469 off = rsv_chans[i][0];
1470 ln = rsv_chans[i][1];
1471 clear_bits(off, ln,
1472 edma_cc[j]->edma_unused);
1473 }
1474 }
1475
1476 /* Set the reserved slots in inuse list */
1477 rsv_slots = info[j]->rsv->rsv_slots;
1478 if (rsv_slots) {
1479 for (i = 0; rsv_slots[i][0] != -1; i++) {
1480 off = rsv_slots[i][0];
1481 ln = rsv_slots[i][1];
1482 set_bits(off, ln,
1483 edma_cc[j]->edma_inuse);
1484 }
1485 }
1486 }
1487
1449 sprintf(irq_name, "edma%d", j); 1488 sprintf(irq_name, "edma%d", j);
1450 irq[j] = platform_get_irq_byname(pdev, irq_name); 1489 irq[j] = platform_get_irq_byname(pdev, irq_name);
1451 edma_cc[j]->irq_res_start = irq[j]; 1490 edma_cc[j]->irq_res_start = irq[j];
diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
index 9a3bcc6f2602..dc10ef6cf572 100644
--- a/arch/arm/mach-davinci/include/mach/edma.h
+++ b/arch/arm/mach-davinci/include/mach/edma.h
@@ -271,6 +271,12 @@ void edma_clear_event(unsigned channel);
271void edma_pause(unsigned channel); 271void edma_pause(unsigned channel);
272void edma_resume(unsigned channel); 272void edma_resume(unsigned channel);
273 273
274struct edma_rsv_info {
275
276 const s16 (*rsv_chans)[2];
277 const s16 (*rsv_slots)[2];
278};
279
274/* platform_data for EDMA driver */ 280/* platform_data for EDMA driver */
275struct edma_soc_info { 281struct edma_soc_info {
276 282
@@ -282,6 +288,9 @@ struct edma_soc_info {
282 unsigned n_cc; 288 unsigned n_cc;
283 enum dma_event_q default_queue; 289 enum dma_event_q default_queue;
284 290
291 /* Resource reservation for other cores */
292 struct edma_rsv_info *rsv;
293
285 const s8 (*queue_tc_mapping)[2]; 294 const s8 (*queue_tc_mapping)[2];
286 const s8 (*queue_priority_mapping)[2]; 295 const s8 (*queue_priority_mapping)[2];
287}; 296};