aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2007-02-13 07:02:52 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-02-14 10:04:22 -0500
commit0c6022d453ecebdace0ce15434c7108e158149ca (patch)
tree153ce6dd661059601fa8591d36e0b81c6663566a /arch/arm
parentd2a76020e3a52c6370a7d603082b4cdb3db0703e (diff)
[ARM] 4177/1: S3C24XX: Add DMA channel allocation order
Allow the CPU code, and any board specific initialisation code to change the allocation order of the DMA channels, or stop a peripheral allocating any DMA at-all. This is due to the scarce mapping of DMA channels on some earlier S3C24XX cpus, where the selection changes depending on the channel in use. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/plat-s3c24xx/dma.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index c784e1f816bb..44e39438b9d8 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1354,18 +1354,22 @@ static inline int is_channel_valid(unsigned int channel)
1354 return (channel & DMA_CH_VALID); 1354 return (channel & DMA_CH_VALID);
1355} 1355}
1356 1356
1357static struct s3c24xx_dma_order *dma_order;
1358
1359
1357/* s3c2410_dma_map_channel() 1360/* s3c2410_dma_map_channel()
1358 * 1361 *
1359 * turn the virtual channel number into a real, and un-used hardware 1362 * turn the virtual channel number into a real, and un-used hardware
1360 * channel. 1363 * channel.
1361 * 1364 *
1362 * currently this code uses first-free channel from the specified harware 1365 * first, try the dma ordering given to us by either the relevant
1363 * map, not taking into account anything that the board setup code may 1366 * dma code, or the board. Then just find the first usable free
1364 * have to say about the likely peripheral set to be in use. 1367 * channel
1365*/ 1368*/
1366 1369
1367struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel) 1370struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
1368{ 1371{
1372 struct s3c24xx_dma_order_ch *ord = NULL;
1369 struct s3c24xx_dma_map *ch_map; 1373 struct s3c24xx_dma_map *ch_map;
1370 struct s3c2410_dma_chan *dmach; 1374 struct s3c2410_dma_chan *dmach;
1371 int ch; 1375 int ch;
@@ -1375,6 +1379,27 @@ struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
1375 1379
1376 ch_map = dma_sel.map + channel; 1380 ch_map = dma_sel.map + channel;
1377 1381
1382 /* first, try the board mapping */
1383
1384 if (dma_order) {
1385 ord = &dma_order->channels[channel];
1386
1387 for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
1388 if (!is_channel_valid(ord->list[ch]))
1389 continue;
1390
1391 if (s3c2410_chans[ord->list[ch]].in_use == 0) {
1392 ch = ord->list[ch] & ~DMA_CH_VALID;
1393 goto found;
1394 }
1395 }
1396
1397 if (ord->flags & DMA_CH_NEVER)
1398 return NULL;
1399 }
1400
1401 /* second, search the channel map for first free */
1402
1378 for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) { 1403 for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
1379 if (!is_channel_valid(ch_map->channels[ch])) 1404 if (!is_channel_valid(ch_map->channels[ch]))
1380 continue; 1405 continue;
@@ -1390,6 +1415,7 @@ struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
1390 1415
1391 /* update our channel mapping */ 1416 /* update our channel mapping */
1392 1417
1418 found:
1393 dmach = &s3c2410_chans[ch]; 1419 dmach = &s3c2410_chans[ch];
1394 dma_chan_map[channel] = dmach; 1420 dma_chan_map[channel] = dmach;
1395 1421
@@ -1439,3 +1465,20 @@ int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
1439 1465
1440 return 0; 1466 return 0;
1441} 1467}
1468
1469int __init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord)
1470{
1471 struct s3c24xx_dma_order *nord = dma_order;
1472
1473 if (nord == NULL)
1474 nord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL);
1475
1476 if (nord == NULL) {
1477 printk(KERN_ERR "no memory to store dma channel order\n");
1478 return -ENOMEM;
1479 }
1480
1481 dma_order = nord;
1482 memcpy(nord, ord, sizeof(struct s3c24xx_dma_order));
1483 return 0;
1484}