diff options
-rw-r--r-- | drivers/dma/amba-pl08x.c | 77 | ||||
-rw-r--r-- | include/linux/amba/pl08x.h | 15 |
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 | */ |
131 | struct pl08x_driver_data { | 133 | struct 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 | */ | ||
1279 | static 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 | |||
1285 | static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan) | 1291 | static 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 @@ | |||
25 | struct pl08x_lli; | 25 | struct pl08x_lli; |
26 | struct pl08x_driver_data; | 26 | struct pl08x_driver_data; |
27 | 27 | ||
28 | /* Bitmasks for selecting AHB ports for DMA transfers */ | ||
29 | enum { | ||
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 | */ |
55 | struct pl08x_channel_data { | 63 | struct 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 | */ |
199 | struct pl08x_platform_data { | 208 | struct 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 |