Lines Matching +full:dma +full:- +full:maxburst
1 // SPDX-License-Identifier: GPL-2.0-only
6 * Copyright (C) 2013-2015 Alexander Popov <[email protected]>.
21 #include <linux/dma-direction.h>
22 #include <linux/dma-mapping.h>
55 * automatically disables LPBFIFO reading request to the DMA controller
61 * mpc512x_lpbfifo_irq - IRQ handler for LPB FIFO
76 if (!req || req->dir == MPC512X_LPBFIFO_REQ_DIR_READ) { in mpc512x_lpbfifo_irq()
81 status = in_be32(&lpbfifo.regs->status); in mpc512x_lpbfifo_irq()
83 dev_err(dev, "DMA transfer from RAM to peripheral failed\n"); in mpc512x_lpbfifo_irq()
84 out_be32(&lpbfifo.regs->enable, in mpc512x_lpbfifo_irq()
89 out_be32(&lpbfifo.regs->status, MPC512X_SCLPC_SUCCESS); in mpc512x_lpbfifo_irq()
101 if (req->callback) in mpc512x_lpbfifo_irq()
102 req->callback(req); in mpc512x_lpbfifo_irq()
112 * mpc512x_lpbfifo_callback is called by DMA driver when
113 * DMA transaction is finished.
136 if (req->dir == MPC512X_LPBFIFO_REQ_DIR_WRITE) in mpc512x_lpbfifo_callback()
140 dma_unmap_single(lpbfifo.chan->device->dev, in mpc512x_lpbfifo_callback()
141 lpbfifo.ram_bus_addr, req->size, dir); in mpc512x_lpbfifo_callback()
151 if (req->callback) in mpc512x_lpbfifo_callback()
152 req->callback(req); in mpc512x_lpbfifo_callback()
162 u32 bpt = 32; /* max bytes per LPBFIFO transaction involving DMA */ in mpc512x_lpbfifo_kick()
175 * - the packet size must be a multiple of 4 since FIFO Data Word in mpc512x_lpbfifo_kick()
176 * Register allows only full-word access according the Reference in mpc512x_lpbfifo_kick()
178 * - the physical address of the device on LPB and the packet size in mpc512x_lpbfifo_kick()
179 * must be aligned on BPT (bytes per transaction) or 8-bytes in mpc512x_lpbfifo_kick()
181 * - but we choose DMA maxburst equal (or very close to) BPT to prevent in mpc512x_lpbfifo_kick()
182 * DMA controller from overtaking FIFO and causing FIFO underflow in mpc512x_lpbfifo_kick()
184 * not to confuse DMA driver which requires the packet size to be in mpc512x_lpbfifo_kick()
185 * aligned on maxburst boundary; in mpc512x_lpbfifo_kick()
186 * - BPT should be set to the LPB device port size for operation with in mpc512x_lpbfifo_kick()
187 * disabled auto-incrementing according Reference Manual. in mpc512x_lpbfifo_kick()
189 if (lpbfifo.req->size == 0 || !IS_ALIGNED(lpbfifo.req->size, 4)) in mpc512x_lpbfifo_kick()
190 return -EINVAL; in mpc512x_lpbfifo_kick()
192 if (lpbfifo.req->portsize != LPB_DEV_PORTSIZE_UNDEFINED) { in mpc512x_lpbfifo_kick()
193 bpt = lpbfifo.req->portsize; in mpc512x_lpbfifo_kick()
198 if (IS_ALIGNED(lpbfifo.req->dev_phys_addr, min(bpt, 0x8u)) && in mpc512x_lpbfifo_kick()
199 IS_ALIGNED(lpbfifo.req->size, bpt)) { in mpc512x_lpbfifo_kick()
204 return -EINVAL; in mpc512x_lpbfifo_kick()
214 phys_addr_t access_start = lpbfifo.req->dev_phys_addr; in mpc512x_lpbfifo_kick()
215 phys_addr_t access_end = access_start + lpbfifo.req->size; in mpc512x_lpbfifo_kick()
223 return -EFAULT; in mpc512x_lpbfifo_kick()
225 /* 2. Prepare DMA */ in mpc512x_lpbfifo_kick()
226 dma_dev = lpbfifo.chan->device; in mpc512x_lpbfifo_kick()
228 if (lpbfifo.req->dir == MPC512X_LPBFIFO_REQ_DIR_WRITE) { in mpc512x_lpbfifo_kick()
242 /* Make DMA channel work with LPB FIFO data register */ in mpc512x_lpbfifo_kick()
243 if (dma_dev->device_config(lpbfifo.chan, &dma_conf)) { in mpc512x_lpbfifo_kick()
244 ret = -EINVAL; in mpc512x_lpbfifo_kick()
250 sg_dma_address(&sg) = dma_map_single(dma_dev->dev, in mpc512x_lpbfifo_kick()
251 lpbfifo.req->ram_virt_addr, lpbfifo.req->size, dir); in mpc512x_lpbfifo_kick()
252 if (dma_mapping_error(dma_dev->dev, sg_dma_address(&sg))) in mpc512x_lpbfifo_kick()
253 return -EFAULT; in mpc512x_lpbfifo_kick()
257 sg_dma_len(&sg) = lpbfifo.req->size; in mpc512x_lpbfifo_kick()
262 ret = -ENOSPC; in mpc512x_lpbfifo_kick()
265 dma_tx->callback = mpc512x_lpbfifo_callback; in mpc512x_lpbfifo_kick()
266 dma_tx->callback_param = NULL; in mpc512x_lpbfifo_kick()
269 out_be32(&lpbfifo.regs->enable, in mpc512x_lpbfifo_kick()
271 out_be32(&lpbfifo.regs->enable, 0x0); in mpc512x_lpbfifo_kick()
274 * Configure the watermarks for write operation (RAM->DMA->FIFO->dev): in mpc512x_lpbfifo_kick()
275 * - high watermark 7 words according the Reference Manual, in mpc512x_lpbfifo_kick()
276 * - low watermark 512 bytes (half of the FIFO). in mpc512x_lpbfifo_kick()
280 out_be32(&lpbfifo.regs->fifo_ctrl, MPC512X_SCLPC_FIFO_CTRL(0x7)); in mpc512x_lpbfifo_kick()
281 out_be32(&lpbfifo.regs->fifo_alarm, MPC512X_SCLPC_FIFO_ALARM(0x200)); in mpc512x_lpbfifo_kick()
287 out_be32(&lpbfifo.regs->start_addr, lpbfifo.req->dev_phys_addr); in mpc512x_lpbfifo_kick()
294 if (lpbfifo.req->dir == MPC512X_LPBFIFO_REQ_DIR_READ) in mpc512x_lpbfifo_kick()
299 out_be32(&lpbfifo.regs->ctrl, bits); in mpc512x_lpbfifo_kick()
303 if (lpbfifo.req->dir == MPC512X_LPBFIFO_REQ_DIR_WRITE) in mpc512x_lpbfifo_kick()
308 out_be32(&lpbfifo.regs->enable, bits); in mpc512x_lpbfifo_kick()
311 bits = lpbfifo.req->size | MPC512X_SCLPC_START; in mpc512x_lpbfifo_kick()
312 out_be32(&lpbfifo.regs->pkt_size, bits); in mpc512x_lpbfifo_kick()
314 /* 5. Finally kick DMA off */ in mpc512x_lpbfifo_kick()
315 cookie = dma_tx->tx_submit(dma_tx); in mpc512x_lpbfifo_kick()
317 ret = -ENOSPC; in mpc512x_lpbfifo_kick()
324 out_be32(&lpbfifo.regs->enable, in mpc512x_lpbfifo_kick()
327 dma_unmap_single(dma_dev->dev, sg_dma_address(&sg), in mpc512x_lpbfifo_kick()
328 lpbfifo.req->size, dir); in mpc512x_lpbfifo_kick()
337 return -ENODEV; in mpc512x_lpbfifo_submit_locked()
341 return -EBUSY; in mpc512x_lpbfifo_submit_locked()
370 * ordering a DMA transfer.
374 int ret = -ENODEV; in get_cs_ranges()
380 lb_node = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-localbus"); in get_cs_ranges()
419 lpbfifo.chan = dma_request_chan(&pdev->dev, "rx-tx"); in mpc512x_lpbfifo_probe()
423 if (of_address_to_resource(pdev->dev.of_node, 0, &r) != 0) { in mpc512x_lpbfifo_probe()
424 dev_err(&pdev->dev, "bad 'reg' in 'sclpc' device tree node\n"); in mpc512x_lpbfifo_probe()
425 ret = -ENODEV; in mpc512x_lpbfifo_probe()
432 if (!devm_request_mem_region(&pdev->dev, lpbfifo.regs_phys, in mpc512x_lpbfifo_probe()
434 dev_err(&pdev->dev, "unable to request region\n"); in mpc512x_lpbfifo_probe()
435 ret = -EBUSY; in mpc512x_lpbfifo_probe()
439 lpbfifo.regs = devm_ioremap(&pdev->dev, in mpc512x_lpbfifo_probe()
442 dev_err(&pdev->dev, "mapping registers failed\n"); in mpc512x_lpbfifo_probe()
443 ret = -ENOMEM; in mpc512x_lpbfifo_probe()
447 out_be32(&lpbfifo.regs->enable, in mpc512x_lpbfifo_probe()
450 if (get_cs_ranges(&pdev->dev) != 0) { in mpc512x_lpbfifo_probe()
451 dev_err(&pdev->dev, "bad '/localbus' device tree node\n"); in mpc512x_lpbfifo_probe()
452 ret = -ENODEV; in mpc512x_lpbfifo_probe()
456 lpbfifo.irq = irq_of_parse_and_map(pdev->dev.of_node, 0); in mpc512x_lpbfifo_probe()
458 dev_err(&pdev->dev, "mapping irq failed\n"); in mpc512x_lpbfifo_probe()
459 ret = -ENODEV; in mpc512x_lpbfifo_probe()
464 DRV_NAME, &pdev->dev) != 0) { in mpc512x_lpbfifo_probe()
465 dev_err(&pdev->dev, "requesting irq failed\n"); in mpc512x_lpbfifo_probe()
466 ret = -ENODEV; in mpc512x_lpbfifo_probe()
470 dev_info(&pdev->dev, "probe succeeded\n"); in mpc512x_lpbfifo_probe()
483 struct dma_device *dma_dev = lpbfifo.chan->device; in mpc512x_lpbfifo_remove()
491 dma_dev->device_terminate_all(lpbfifo.chan); in mpc512x_lpbfifo_remove()
492 out_be32(®s->enable, MPC512X_SCLPC_RESET | MPC512X_SCLPC_FIFO_RESET); in mpc512x_lpbfifo_remove()
494 free_irq(lpbfifo.irq, &pdev->dev); in mpc512x_lpbfifo_remove()
500 { .compatible = "fsl,mpc512x-lpbfifo", },