aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/dma/amba-pl08x.c77
-rw-r--r--include/linux/amba/pl08x.h15
2 files changed, 56 insertions, 36 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 4ee0ab19b1b6..986c12775b0b 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -126,6 +126,8 @@ struct pl08x_lli {
126 * @phy_chans: array of data for the physical channels 126 * @phy_chans: array of data for the physical channels
127 * @pool: a pool for the LLI descriptors 127 * @pool: a pool for the LLI descriptors
128 * @pool_ctr: counter of LLIs in the pool 128 * @pool_ctr: counter of LLIs in the pool
129 * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI fetches
130 * @mem_buses: set to indicate memory transfers on AHB2.
129 * @lock: a spinlock for this struct 131 * @lock: a spinlock for this struct
130 */ 132 */
131struct pl08x_driver_data { 133struct pl08x_driver_data {
@@ -138,6 +140,8 @@ struct pl08x_driver_data {
138 struct pl08x_phy_chan *phy_chans; 140 struct pl08x_phy_chan *phy_chans;
139 struct dma_pool *pool; 141 struct dma_pool *pool;
140 int pool_ctr; 142 int pool_ctr;
143 u8 lli_buses;
144 u8 mem_buses;
141 spinlock_t lock; 145 spinlock_t lock;
142}; 146};
143 147
@@ -526,20 +530,12 @@ static int pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
526 530
527 BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS); 531 BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS);
528 532
529 llis_va[num_llis].cctl = cctl; 533 llis_va[num_llis].cctl = cctl;
530 llis_va[num_llis].src = txd->srcbus.addr; 534 llis_va[num_llis].src = txd->srcbus.addr;
531 llis_va[num_llis].dst = txd->dstbus.addr; 535 llis_va[num_llis].dst = txd->dstbus.addr;
532
533 /*
534 * On versions with dual masters, you can optionally AND on
535 * PL080_LLI_LM_AHB2 to the LLI to tell the hardware to read
536 * in new LLIs with that controller, but we always try to
537 * choose AHB1 to point into memory. The idea is to have AHB2
538 * fixed on the peripheral and AHB1 messing around in the
539 * memory. So we don't manipulate this bit currently.
540 */
541
542 llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli); 536 llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli);
537 if (pl08x->lli_buses & PL08X_AHB2)
538 llis_va[num_llis].lli |= PL080_LLI_LM_AHB2;
543 539
544 if (cctl & PL080_CONTROL_SRC_INCR) 540 if (cctl & PL080_CONTROL_SRC_INCR)
545 txd->srcbus.addr += len; 541 txd->srcbus.addr += len;
@@ -639,13 +635,6 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
639 pl08x_choose_master_bus(&txd->srcbus, &txd->dstbus, 635 pl08x_choose_master_bus(&txd->srcbus, &txd->dstbus,
640 &mbus, &sbus, cctl); 636 &mbus, &sbus, cctl);
641 637
642
643 /*
644 * The lowest bit of the LLI register
645 * is also used to indicate which master to
646 * use for reading the LLIs.
647 */
648
649 if (txd->len < mbus->buswidth) { 638 if (txd->len < mbus->buswidth) {
650 /* 639 /*
651 * Less than a bus width available 640 * Less than a bus width available
@@ -1282,6 +1271,23 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
1282 return 0; 1271 return 0;
1283} 1272}
1284 1273
1274/*
1275 * Given the source and destination available bus masks, select which
1276 * will be routed to each port. We try to have source and destination
1277 * on separate ports, but always respect the allowable settings.
1278 */
1279static u32 pl08x_select_bus(struct pl08x_driver_data *pl08x, u8 src, u8 dst)
1280{
1281 u32 cctl = 0;
1282
1283 if (!(dst & PL08X_AHB1) || ((dst & PL08X_AHB2) && (src & PL08X_AHB1)))
1284 cctl |= PL080_CONTROL_DST_AHB2;
1285 if (!(src & PL08X_AHB1) || ((src & PL08X_AHB2) && !(dst & PL08X_AHB2)))
1286 cctl |= PL080_CONTROL_SRC_AHB2;
1287
1288 return cctl;
1289}
1290
1285static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan) 1291static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan)
1286{ 1292{
1287 struct pl08x_txd *txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT); 1293 struct pl08x_txd *txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
@@ -1330,15 +1336,9 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
1330 /* Both to be incremented or the code will break */ 1336 /* Both to be incremented or the code will break */
1331 txd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR; 1337 txd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR;
1332 1338
1333 /*
1334 * On the PL080 we have two bus masters and we should select one for
1335 * source and one for destination. We try to use AHB2 for the bus
1336 * which does not increment (typically the peripheral) else we just
1337 * choose something.
1338 */
1339 if (pl08x->vd->dualmaster) 1339 if (pl08x->vd->dualmaster)
1340 /* Source increments, use AHB2 for destination */ 1340 txd->cctl |= pl08x_select_bus(pl08x,
1341 txd->cctl |= PL080_CONTROL_DST_AHB2; 1341 pl08x->mem_buses, pl08x->mem_buses);
1342 1342
1343 ret = pl08x_prep_channel_resources(plchan, txd); 1343 ret = pl08x_prep_channel_resources(plchan, txd);
1344 if (ret) 1344 if (ret)
@@ -1359,6 +1359,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
1359 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); 1359 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1360 struct pl08x_driver_data *pl08x = plchan->host; 1360 struct pl08x_driver_data *pl08x = plchan->host;
1361 struct pl08x_txd *txd; 1361 struct pl08x_txd *txd;
1362 u8 src_buses, dst_buses;
1362 int ret; 1363 int ret;
1363 1364
1364 /* 1365 /*
@@ -1403,31 +1404,31 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
1403 if (direction == DMA_TO_DEVICE) { 1404 if (direction == DMA_TO_DEVICE) {
1404 txd->ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT; 1405 txd->ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT;
1405 txd->cctl |= PL080_CONTROL_SRC_INCR; 1406 txd->cctl |= PL080_CONTROL_SRC_INCR;
1406 if (pl08x->vd->dualmaster)
1407 /* Source increments, use AHB2 for destination */
1408 txd->cctl |= PL080_CONTROL_DST_AHB2;
1409 txd->srcbus.addr = sgl->dma_address; 1407 txd->srcbus.addr = sgl->dma_address;
1410 if (plchan->runtime_addr) 1408 if (plchan->runtime_addr)
1411 txd->dstbus.addr = plchan->runtime_addr; 1409 txd->dstbus.addr = plchan->runtime_addr;
1412 else 1410 else
1413 txd->dstbus.addr = plchan->cd->addr; 1411 txd->dstbus.addr = plchan->cd->addr;
1412 src_buses = pl08x->mem_buses;
1413 dst_buses = plchan->cd->periph_buses;
1414 } else if (direction == DMA_FROM_DEVICE) { 1414 } else if (direction == DMA_FROM_DEVICE) {
1415 txd->ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT; 1415 txd->ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
1416 txd->cctl |= PL080_CONTROL_DST_INCR; 1416 txd->cctl |= PL080_CONTROL_DST_INCR;
1417 if (pl08x->vd->dualmaster)
1418 /* Destination increments, use AHB2 for source */
1419 txd->cctl |= PL080_CONTROL_SRC_AHB2;
1420 if (plchan->runtime_addr) 1417 if (plchan->runtime_addr)
1421 txd->srcbus.addr = plchan->runtime_addr; 1418 txd->srcbus.addr = plchan->runtime_addr;
1422 else 1419 else
1423 txd->srcbus.addr = plchan->cd->addr; 1420 txd->srcbus.addr = plchan->cd->addr;
1424 txd->dstbus.addr = sgl->dma_address; 1421 txd->dstbus.addr = sgl->dma_address;
1422 src_buses = plchan->cd->periph_buses;
1423 dst_buses = pl08x->mem_buses;
1425 } else { 1424 } else {
1426 dev_err(&pl08x->adev->dev, 1425 dev_err(&pl08x->adev->dev,
1427 "%s direction unsupported\n", __func__); 1426 "%s direction unsupported\n", __func__);
1428 return NULL; 1427 return NULL;
1429 } 1428 }
1430 1429
1430 txd->cctl |= pl08x_select_bus(pl08x, src_buses, dst_buses);
1431
1431 ret = pl08x_prep_channel_resources(plchan, txd); 1432 ret = pl08x_prep_channel_resources(plchan, txd);
1432 if (ret) 1433 if (ret)
1433 return NULL; 1434 return NULL;
@@ -1879,6 +1880,14 @@ static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
1879 pl08x->adev = adev; 1880 pl08x->adev = adev;
1880 pl08x->vd = vd; 1881 pl08x->vd = vd;
1881 1882
1883 /* By default, AHB1 only. If dualmaster, from platform */
1884 pl08x->lli_buses = PL08X_AHB1;
1885 pl08x->mem_buses = PL08X_AHB1;
1886 if (pl08x->vd->dualmaster) {
1887 pl08x->lli_buses = pl08x->pd->lli_buses;
1888 pl08x->mem_buses = pl08x->pd->mem_buses;
1889 }
1890
1882 /* A DMA memory pool for LLIs, align on 1-byte boundary */ 1891 /* A DMA memory pool for LLIs, align on 1-byte boundary */
1883 pl08x->pool = dma_pool_create(DRIVER_NAME, &pl08x->adev->dev, 1892 pl08x->pool = dma_pool_create(DRIVER_NAME, &pl08x->adev->dev,
1884 PL08X_LLI_TSFR_SIZE, PL08X_ALIGN, 0); 1893 PL08X_LLI_TSFR_SIZE, PL08X_ALIGN, 0);
diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h
index 8d9083067d3d..f858651027fd 100644
--- a/include/linux/amba/pl08x.h
+++ b/include/linux/amba/pl08x.h
@@ -25,6 +25,12 @@
25struct pl08x_lli; 25struct pl08x_lli;
26struct pl08x_driver_data; 26struct pl08x_driver_data;
27 27
28/* Bitmasks for selecting AHB ports for DMA transfers */
29enum {
30 PL08X_AHB1 = (1 << 0),
31 PL08X_AHB2 = (1 << 1)
32};
33
28/** 34/**
29 * struct pl08x_channel_data - data structure to pass info between 35 * struct pl08x_channel_data - data structure to pass info between
30 * platform and PL08x driver regarding channel configuration 36 * platform and PL08x driver regarding channel configuration
@@ -51,6 +57,8 @@ struct pl08x_driver_data;
51 * round round round) 57 * round round round)
52 * @single: the device connected to this channel will request single 58 * @single: the device connected to this channel will request single
53 * DMA transfers, not bursts. (Bursts are default.) 59 * DMA transfers, not bursts. (Bursts are default.)
60 * @periph_buses: the device connected to this channel is accessible via
61 * these buses (use PL08X_AHB1 | PL08X_AHB2).
54 */ 62 */
55struct pl08x_channel_data { 63struct pl08x_channel_data {
56 char *bus_id; 64 char *bus_id;
@@ -61,6 +69,7 @@ struct pl08x_channel_data {
61 dma_addr_t addr; 69 dma_addr_t addr;
62 bool circular_buffer; 70 bool circular_buffer;
63 bool single; 71 bool single;
72 u8 periph_buses;
64}; 73};
65 74
66/** 75/**
@@ -193,8 +202,8 @@ struct pl08x_dma_chan {
193 * less than zero, else it returns the allocated signal number 202 * less than zero, else it returns the allocated signal number
194 * @put_signal: indicate to the platform that this physical signal is not 203 * @put_signal: indicate to the platform that this physical signal is not
195 * running any DMA transfer and multiplexing can be recycled 204 * running any DMA transfer and multiplexing can be recycled
196 * @bus_bit_lli: Bit[0] of the address indicated which AHB bus master the 205 * @lli_buses: buses which LLIs can be fetched from: PL08X_AHB1 | PL08X_AHB2
197 * LLI addresses are on 0/1 Master 1/2. 206 * @mem_buses: buses which memory can be accessed from: PL08X_AHB1 | PL08X_AHB2
198 */ 207 */
199struct pl08x_platform_data { 208struct pl08x_platform_data {
200 struct pl08x_channel_data *slave_channels; 209 struct pl08x_channel_data *slave_channels;
@@ -202,6 +211,8 @@ struct pl08x_platform_data {
202 struct pl08x_channel_data memcpy_channel; 211 struct pl08x_channel_data memcpy_channel;
203 int (*get_signal)(struct pl08x_dma_chan *); 212 int (*get_signal)(struct pl08x_dma_chan *);
204 void (*put_signal)(struct pl08x_dma_chan *); 213 void (*put_signal)(struct pl08x_dma_chan *);
214 u8 lli_buses;
215 u8 mem_buses;
205}; 216};
206 217
207#ifdef CONFIG_AMBA_PL08X 218#ifdef CONFIG_AMBA_PL08X