// SPDX-License-Identifier: GPL-2.0-or-later /* * Driver for the Atmel AHB DMA Controller (aka HDMA or DMAC on AT91 systems) * * Copyright (C) 2008 Atmel Corporation * Copyright (C) 2022 Microchip Technology, Inc. and its subsidiaries * * This supports the Atmel AHB DMA Controller found in several Atmel SoCs. * The only Atmel DMA Controller that is not covered by this driver is the one * found on AT91SAM9263.
*/
/* Software Single Request Register */ #define AT_DMA_SREQ 0x08 #define AT_DMA_SSREQ(x) BIT((x) << 1) /* Request a source single transfer on channel x */ #define AT_DMA_DSREQ(x) BIT(1 + ((x) << 1)) /* Request a destination single transfer on channel x */
/* Software Chunk Transfer Request Register */ #define AT_DMA_CREQ 0x0c #define AT_DMA_SCREQ(x) BIT((x) << 1) /* Request a source chunk transfer on channel x */ #define AT_DMA_DCREQ(x) BIT(1 + ((x) << 1)) /* Request a destination chunk transfer on channel x */
/* Software Last Transfer Flag Register */ #define AT_DMA_LAST 0x10 #define AT_DMA_SLAST(x) BIT((x) << 1) /* This src rq is last tx of buffer on channel x */ #define AT_DMA_DLAST(x) BIT(1 + ((x) << 1)) /* This dst rq is last tx of buffer on channel x */
/* Request Synchronization Register */ #define AT_DMA_SYNC 0x14 #define AT_DMA_SYR(h) BIT((h)) /* Synchronize handshake line h */
/* LLI == Linked List Item; aka DMA buffer descriptor */ struct at_lli { /* values that are not changed by hardware */
u32 saddr;
u32 daddr; /* value that may get written back: */
u32 ctrla; /* more values that are not changed by hardware */
u32 ctrlb;
u32 dscr; /* chain to next lli */
};
/** * struct atdma_sg - atdma scatter gather entry * @len: length of the current Linked List Item. * @lli: linked list item that is passed to the DMA controller * @lli_phys: physical address of the LLI.
*/ struct atdma_sg { unsignedint len; struct at_lli *lli;
dma_addr_t lli_phys;
};
/** * struct at_desc - software descriptor * @vd: pointer to the virtual dma descriptor. * @atchan: pointer to the atmel dma channel. * @total_len: total transaction byte count * @sglen: number of sg entries. * @sg: array of sgs. * @boundary: number of transfers to perform before the automatic address increment operation * @dst_hole: value to add to the destination address when the boundary has been reached * @src_hole: value to add to the source address when the boundary has been reached * @memset_buffer: buffer used for the memset operation * @memset_paddr: physical address of the buffer used for the memset operation * @memset_vaddr: virtual address of the buffer used for the memset operation
*/ struct at_desc { struct virt_dma_desc vd; struct at_dma_chan *atchan;
size_t total_len; unsignedint sglen; /* Interleaved data */
size_t boundary;
size_t dst_hole;
size_t src_hole;
/** * enum atc_status - information bits stored in channel status flag * * @ATC_IS_PAUSED: If channel is pauses * @ATC_IS_CYCLIC: If channel is cyclic * * Manipulated with atomic operations.
*/ enum atc_status {
ATC_IS_PAUSED = 1,
ATC_IS_CYCLIC = 24,
};
/** * struct at_dma_chan - internal representation of an Atmel HDMAC channel * @vc: virtual dma channel entry. * @atdma: pointer to the driver data. * @ch_regs: memory mapped register base * @mask: channel index in a mask * @per_if: peripheral interface * @mem_if: memory interface * @status: transmit status information from irq/prep* functions * to tasklet (use atomic operations) * @save_cfg: configuration register that is saved on suspend/resume cycle * @save_dscr: for cyclic operations, preserve next descriptor address in * the cyclic list on suspend/resume cycle * @dma_sconfig: configuration for slave transfers, passed via * .device_config * @desc: pointer to the atmel dma descriptor.
*/ struct at_dma_chan { struct virt_dma_chan vc; struct at_dma *atdma; void __iomem *ch_regs;
u8 mask;
u8 per_if;
u8 mem_if; unsignedlong status;
u32 save_cfg;
u32 save_dscr; struct dma_slave_config dma_sconfig; struct at_desc *desc;
};
/** * atc_chan_is_enabled - test if given channel is enabled * @atchan: channel we want to test status
*/ staticinlineint atc_chan_is_enabled(struct at_dma_chan *atchan)
{ struct at_dma *atdma = to_at_dma(atchan->vc.chan.device);
/** * atc_chan_is_paused - test channel pause/resume status * @atchan: channel we want to test status
*/ staticinlineint atc_chan_is_paused(struct at_dma_chan *atchan)
{ return test_bit(ATC_IS_PAUSED, &atchan->status);
}
/** * atc_chan_is_cyclic - test if given channel has cyclic property set * @atchan: channel we want to test status
*/ staticinlineint atc_chan_is_cyclic(struct at_dma_chan *atchan)
{ return test_bit(ATC_IS_CYCLIC, &atchan->status);
}
/** * set_lli_eol - set end-of-link to descriptor so it will end transfer * @desc: descriptor, signle or at the end of a chain, to end chain on * @i: index of the atmel scatter gather entry that is at the end of the chain.
*/ staticvoid set_lli_eol(struct at_desc *desc, unsignedint i)
{
u32 ctrlb = desc->sg[i].lli->ctrlb;
/* * Initial number of descriptors to allocate for each channel. This could * be increased during dma usage.
*/ staticunsignedint init_nr_desc_per_channel = 64;
module_param(init_nr_desc_per_channel, uint, 0644);
MODULE_PARM_DESC(init_nr_desc_per_channel, "initial descriptors per channel (default: 64)");
/** * struct at_dma_platform_data - Controller configuration parameters * @nr_channels: Number of channels supported by hardware (max 8) * @cap_mask: dma_capability flags supported by the platform
*/ struct at_dma_platform_data { unsignedint nr_channels;
dma_cap_mask_t cap_mask;
};
/** * struct at_dma_slave - Controller-specific information about a slave * @dma_dev: required DMA master device * @cfg: Platform-specific initializer for the CFG register
*/ struct at_dma_slave { struct device *dma_dev;
u32 cfg;
};
for (i = 0; i < desc->sglen; i++) { if (desc->sg[i].lli)
dma_pool_free(atdma->lli_pool, desc->sg[i].lli,
desc->sg[i].lli_phys);
}
/* If the transfer was a memset, free our temporary buffer */ if (desc->memset_buffer) {
dma_pool_free(atdma->memset_pool, desc->memset_vaddr,
desc->memset_paddr);
desc->memset_buffer = false;
}
kfree(desc);
}
/** * atc_calc_bytes_left - calculates the number of bytes left according to the * value read from CTRLA. * * @current_len: the number of bytes left before reading CTRLA * @ctrla: the value of CTRLA
*/ staticinline u32 atc_calc_bytes_left(u32 current_len, u32 ctrla)
{
u32 btsize = FIELD_GET(ATC_BTSIZE, ctrla);
u32 src_width = FIELD_GET(ATC_SRC_WIDTH, ctrla);
/* * According to the datasheet, when reading the Control A Register * (ctrla), the Buffer Transfer Size (btsize) bitfield refers to the * number of transfers completed on the Source Interface. * So btsize is always a number of source width transfers.
*/ return current_len - (btsize << src_width);
}
/** * atc_get_llis_residue - Get residue for a hardware linked list transfer * @atchan: pointer to an atmel hdmac channel. * @desc: pointer to the descriptor for which the residue is calculated. * @residue: residue to be set to dma_tx_state. * * Calculate the residue by removing the length of the Linked List Item (LLI) * already transferred from the total length. To get the current LLI we can use * the value of the channel's DSCR register and compare it against the DSCR * value of each LLI. * * The CTRLA register provides us with the amount of data already read from the * source for the LLI. So we can compute a more accurate residue by also * removing the number of bytes corresponding to this amount of data. * * However, the DSCR and CTRLA registers cannot be read both atomically. Hence a * race condition may occur: the first read register may refer to one LLI * whereas the second read may refer to a later LLI in the list because of the * DMA transfer progression inbetween the two reads. * * One solution could have been to pause the DMA transfer, read the DSCR and * CTRLA then resume the DMA transfer. Nonetheless, this approach presents some * drawbacks: * - If the DMA transfer is paused, RX overruns or TX underruns are more likey * to occur depending on the system latency. Taking the USART driver as an * example, it uses a cyclic DMA transfer to read data from the Receive * Holding Register (RHR) to avoid RX overruns since the RHR is not protected * by any FIFO on most Atmel SoCs. So pausing the DMA transfer to compute the * residue would break the USART driver design. * - The atc_pause() function masks interrupts but we'd rather avoid to do so * for system latency purpose. * * Then we'd rather use another solution: the DSCR is read a first time, the * CTRLA is read in turn, next the DSCR is read a second time. If the two * consecutive read values of the DSCR are the same then we assume both refers * to the very same LLI as well as the CTRLA value read inbetween does. For * cyclic transfers, the assumption is that a full loop is "not so fast". If the * two DSCR values are different, we read again the CTRLA then the DSCR till two * consecutive read values from DSCR are equal or till the maximum trials is * reach. This algorithm is very unlikely not to find a stable value for DSCR. * * Returns: %0 on success, -errno otherwise.
*/ staticint atc_get_llis_residue(struct at_dma_chan *atchan, struct at_desc *desc, u32 *residue)
{
u32 len, ctrla, dscr; unsignedint i;
len = desc->total_len;
dscr = channel_readl(atchan, DSCR);
rmb(); /* ensure DSCR is read before CTRLA */
ctrla = channel_readl(atchan, CTRLA); for (i = 0; i < ATC_MAX_DSCR_TRIALS; ++i) {
u32 new_dscr;
rmb(); /* ensure DSCR is read after CTRLA */
new_dscr = channel_readl(atchan, DSCR);
/* * If the DSCR register value has not changed inside the DMA * controller since the previous read, we assume that both the * dscr and ctrla values refers to the very same descriptor.
*/ if (likely(new_dscr == dscr)) break;
/* * DSCR has changed inside the DMA controller, so the previously * read value of CTRLA may refer to an already processed * descriptor hence could be outdated. We need to update ctrla * to match the current descriptor.
*/
dscr = new_dscr;
rmb(); /* ensure DSCR is read before CTRLA */
ctrla = channel_readl(atchan, CTRLA);
} if (unlikely(i == ATC_MAX_DSCR_TRIALS)) return -ETIMEDOUT;
/* For the first descriptor we can be more accurate. */ if (desc->sg[0].lli->dscr == dscr) {
*residue = atc_calc_bytes_left(len, ctrla); return 0;
}
len -= desc->sg[0].len;
for (i = 1; i < desc->sglen; i++) { if (desc->sg[i].lli && desc->sg[i].lli->dscr == dscr) break;
len -= desc->sg[i].len;
}
/* * For the current LLI in the chain we can calculate the remaining bytes * using the channel's CTRLA register.
*/
*residue = atc_calc_bytes_left(len, ctrla); return 0;
}
/** * atc_get_residue - get the number of bytes residue for a cookie. * The residue is passed by address and updated on success. * @chan: DMA channel * @cookie: transaction identifier to check status of * @residue: residue to be updated. * * Return: %0 on success, -errno otherwise.
*/ staticint atc_get_residue(struct dma_chan *chan, dma_cookie_t cookie,
u32 *residue)
{ struct at_dma_chan *atchan = to_at_dma_chan(chan); struct virt_dma_desc *vd; struct at_desc *desc = NULL;
u32 len, ctrla;
/* * KERN_CRITICAL may seem harsh, but since this only happens * when someone submits a bad physical address in a * descriptor, we should consider ourselves lucky that the * controller flagged an error instead of scribbling over * random memory locations.
*/
dev_crit(chan2dev(&atchan->vc.chan), "Bad descriptor submitted for DMA!\n");
dev_crit(chan2dev(&atchan->vc.chan), "cookie: %d\n",
desc->vd.tx.cookie); for (i = 0; i < desc->sglen; i++)
atc_dump_lli(atchan, desc->sg[i].lli);
}
/* * The controller can only "skip" X bytes every Y bytes, so we * need to make sure we are given a template that fit that * description, ie a template with chunks that always have the * same size, with the same ICGs.
*/ for (i = 0; i < xt->frame_size; i++) { struct data_chunk *chunk = xt->sgl + i;
if ((chunk->size != xt->sgl->size) ||
(dmaengine_get_dst_icg(xt, chunk) != dmaengine_get_dst_icg(xt, first)) ||
(dmaengine_get_src_icg(xt, chunk) != dmaengine_get_src_icg(xt, first))) {
dev_err(chan2dev(chan), "%s: the controller can transfer only identical chunks\n",
__func__); return NULL;
}
/* * We can be a lot more clever here, but this should take care * of the most common optimization.
*/
src_width = dst_width = atc_get_xfer_width(src, dest, len);
mem = sg_dma_address(sg);
len = sg_dma_len(sg); if (unlikely(!len)) {
dev_dbg(chan2dev(chan), "prep_slave_sg: sg(%d) data length is zero\n", i); goto err;
}
mem_width = 2; if (unlikely(mem & 3 || len & 3))
mem_width = 0;
mem = sg_dma_address(sg);
len = sg_dma_len(sg); if (unlikely(!len)) {
dev_dbg(chan2dev(chan), "prep_slave_sg: sg(%d) data length is zero\n", i); goto err;
}
mem_width = 2; if (unlikely(mem & 3 || len & 3))
mem_width = 0;
/** * atc_prep_dma_cyclic - prepare the cyclic DMA transfer * @chan: the DMA channel to prepare * @buf_addr: physical DMA address where the buffer starts * @buf_len: total number of bytes for the entire buffer * @period_len: number of bytes for each period * @direction: transfer direction, to or from device * @flags: tx descriptor status flags
*/ staticstruct dma_async_tx_descriptor *
atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction, unsignedlong flags)
{ struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma_slave *atslave = chan->private; struct dma_slave_config *sconfig = &atchan->dma_sconfig; struct at_desc *desc; unsignedlong was_cyclic; unsignedint reg_width; unsignedint periods = buf_len / period_len; unsignedint i;
/* build cyclic linked list */ for (i = 0; i < periods; i++) { if (atc_dma_cyclic_fill_desc(chan, desc, i, buf_addr,
reg_width, period_len, direction)) goto err_fill_desc;
atdma_lli_chain(desc, i);
}
desc->total_len = buf_len; /* lets make a cyclic list */
desc->sg[i - 1].lli->dscr = desc->sg[0].lli_phys;
/* * This is only called when something went wrong elsewhere, so * we don't really care about the data. Just disable the * channel. We still have to poll the channel enable bit due * to AHB/HSB limitations.
*/
spin_lock_irqsave(&atchan->vc.lock, flags);
/* disabling channel: must also remove suspend state */
dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask);
/* confirm that this channel is disabled */ while (dma_readl(atdma, CHSR) & atchan->mask)
cpu_relax();
if (atchan->desc) {
vchan_terminate_vdesc(&atchan->desc->vd);
atchan->desc = NULL;
}
vchan_get_all_descriptors(&atchan->vc, &list);
clear_bit(ATC_IS_PAUSED, &atchan->status); /* if channel dedicated to cyclic operations, free it */
clear_bit(ATC_IS_CYCLIC, &atchan->status);
spin_unlock_irqrestore(&atchan->vc.lock, flags);
vchan_dma_desc_free_list(&atchan->vc, &list);
return 0;
}
/** * atc_tx_status - poll for transaction completion * @chan: DMA channel * @cookie: transaction identifier to check status of * @txstate: if not %NULL updated with transaction state * * If @txstate is passed in, upon return it reflect the driver * internal state and can be used with dma_async_is_complete() to check * the status of multiple cookies without re-checking hardware state.
*/ staticenum dma_status
atc_tx_status(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *txstate)
{ struct at_dma_chan *atchan = to_at_dma_chan(chan); unsignedlong flags; enum dma_status dma_status;
u32 residue; int ret;
spin_lock_irqsave(&atchan->vc.lock, flags); /* Get number of bytes left in the active transactions */
ret = atc_get_residue(chan, cookie, &residue);
spin_unlock_irqrestore(&atchan->vc.lock, flags);
/* ASSERT: channel is idle */ if (atc_chan_is_enabled(atchan)) {
dev_dbg(chan2dev(chan), "DMA channel not idle ?\n"); return -EIO;
}
cfg = ATC_DEFAULT_CFG;
atslave = chan->private; if (atslave) { /* * We need controller-specific data to set up slave * transfers.
*/
BUG_ON(!atslave->dma_dev || atslave->dma_dev != atdma->dma_device.dev);
/* if cfg configuration specified take it instead of default */ if (atslave->cfg)
cfg = atslave->cfg;
}
atslave->cfg = ATC_DST_H2SEL | ATC_SRC_H2SEL; /* * We can fill both SRC_PER and DST_PER, one of these fields will be * ignored depending on DMA transfer direction.
*/
per_id = dma_spec->args[1] & AT91_DMA_CFG_PER_ID_MASK;
atslave->cfg |= ATC_DST_PER_ID(per_id) | ATC_SRC_PER_ID(per_id); /* * We have to translate the value we get from the device tree since * the half FIFO configuration value had to be 0 to keep backward * compatibility.
*/ switch (dma_spec->args[1] & AT91_DMA_CFG_FIFOCFG_MASK) { case AT91_DMA_CFG_FIFOCFG_ALAP:
atslave->cfg |= FIELD_PREP(ATC_FIFOCFG,
ATC_FIFOCFG_LARGESTBURST); break; case AT91_DMA_CFG_FIFOCFG_ASAP:
atslave->cfg |= FIELD_PREP(ATC_FIFOCFG,
ATC_FIFOCFG_ENOUGHSPACE); break; case AT91_DMA_CFG_FIFOCFG_HALF: default:
atslave->cfg |= FIELD_PREP(ATC_FIFOCFG, ATC_FIFOCFG_HALFFIFO);
}
atslave->dma_dev = &dmac_pdev->dev;
/* create a pool of consistent memory blocks for hardware descriptors */
atdma->lli_pool = dma_pool_create("at_hdmac_lli_pool",
&pdev->dev, sizeof(struct at_lli),
4 /* word alignment */, 0); if (!atdma->lli_pool) {
dev_err(&pdev->dev, "Unable to allocate DMA LLI descriptor pool\n");
err = -ENOMEM; goto err_desc_pool_create;
}
/* create a pool of consistent memory blocks for memset blocks */
atdma->memset_pool = dma_pool_create("at_hdmac_memset_pool",
&pdev->dev, sizeof(int), 4, 0); if (!atdma->memset_pool) {
dev_err(&pdev->dev, "No memory for memset dma pool\n");
err = -ENOMEM; goto err_memset_pool_create;
}
/* clear any pending interrupt */ while (dma_readl(atdma, EBCISR))
cpu_relax();
/* initialize channels related values */
INIT_LIST_HEAD(&atdma->dma_device.channels); for (i = 0; i < plat_dat->nr_channels; i++) { struct at_dma_chan *atchan = &atdma->chan[i];
/* set base routines */
atdma->dma_device.device_alloc_chan_resources = atc_alloc_chan_resources;
atdma->dma_device.device_free_chan_resources = atc_free_chan_resources;
atdma->dma_device.device_tx_status = atc_tx_status;
atdma->dma_device.device_issue_pending = atc_issue_pending;
atdma->dma_device.dev = &pdev->dev;
/* set prep routines based on capability */ if (dma_has_cap(DMA_INTERLEAVE, atdma->dma_device.cap_mask))
atdma->dma_device.device_prep_interleaved_dma = atc_prep_dma_interleaved;
if (dma_has_cap(DMA_MEMCPY, atdma->dma_device.cap_mask))
atdma->dma_device.device_prep_dma_memcpy = atc_prep_dma_memcpy;
err = dma_async_device_register(&atdma->dma_device); if (err) {
dev_err(&pdev->dev, "Unable to register: %d.\n", err); goto err_dma_async_device_register;
}
/* * Do not return an error if the dmac node is not present in order to * not break the existing way of requesting channel with * dma_request_channel().
*/ if (pdev->dev.of_node) {
err = of_dma_controller_register(pdev->dev.of_node,
at_dma_xlate, atdma); if (err) {
dev_err(&pdev->dev, "could not register of_dma_controller\n"); goto err_of_dma_controller_register;
}
}
/* Channel should be paused by user
* do it anyway even if it is not done already */ if (!atc_chan_is_paused(atchan)) {
dev_warn(chan2dev(chan), "cyclic channel not paused, should be done by channel user\n");
atc_pause(chan);
}
/* now preserve additional data for cyclic operations */ /* next descriptor address in the cyclic list */
atchan->save_dscr = channel_readl(atchan, DSCR);
/* restore channel status for cyclic descriptors list:
* next descriptor in the cyclic list at the time of suspend */
channel_writel(atchan, SADDR, 0);
channel_writel(atchan, DADDR, 0);
channel_writel(atchan, CTRLA, 0);
channel_writel(atchan, CTRLB, 0);
channel_writel(atchan, DSCR, atchan->save_dscr);
dma_writel(atdma, CHER, atchan->mask);
/* channel pause status should be removed by channel user
* We cannot take the initiative to do it here */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.