// SPDX-License-Identifier: GPL-2.0-or-later /* * Driver for the Cirrus Logic EP93xx DMA Controller * * Copyright (C) 2011 Mika Westerberg * * DMA M2P implementation is based on the original * arch/arm/mach-ep93xx/dma-m2p.c which has following copyrights: * * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> * Copyright (C) 2006 Applied Data Systems * Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com> * * This driver is based on dw_dmac and amba-pl08x drivers.
*/
/** * struct ep93xx_dma_desc - EP93xx specific transaction descriptor * @src_addr: source address of the transaction * @dst_addr: destination address of the transaction * @size: size of the transaction (in bytes) * @complete: this descriptor is completed * @txd: dmaengine API descriptor * @tx_list: list of linked descriptors * @node: link used for putting this into a channel queue
*/ struct ep93xx_dma_desc {
u32 src_addr;
u32 dst_addr;
size_t size; bool complete; struct dma_async_tx_descriptor txd; struct list_head tx_list; struct list_head node;
};
/** * struct ep93xx_dma_chan - an EP93xx DMA M2P/M2M channel * @chan: dmaengine API channel * @edma: pointer to the engine device * @regs: memory mapped registers * @dma_cfg: channel number, direction * @irq: interrupt number of the channel * @clk: clock used by this channel * @tasklet: channel specific tasklet used for callbacks * @lock: lock protecting the fields following * @flags: flags for the channel * @buffer: which buffer to use next (0/1) * @active: flattened chain of descriptors currently being processed * @queue: pending descriptors which are handled next * @free_list: list of free descriptors which can be used * @runtime_addr: physical address currently used as dest/src (M2M only). This * is set via .device_config before slave operation is * prepared * @runtime_ctrl: M2M runtime values for the control register. * @slave_config: slave configuration * * As EP93xx DMA controller doesn't support real chained DMA descriptors we * will have slightly different scheme here: @active points to a head of * flattened DMA descriptor chain. * * @queue holds pending transactions. These are linked through the first * descriptor in the chain. When a descriptor is moved to the @active queue, * the first and chained descriptors are flattened into a single list. *
*/ struct ep93xx_dma_chan { struct dma_chan chan; conststruct ep93xx_dma_engine *edma; void __iomem *regs; struct ep93xx_dma_chan_cfg dma_cfg; int irq; struct clk *clk; struct tasklet_struct tasklet; /* protects the fields following */
spinlock_t lock; unsignedlong flags; /* Channel is configured for cyclic transfers */ #define EP93XX_DMA_IS_CYCLIC 0
/** * struct ep93xx_dma_engine - the EP93xx DMA engine instance * @dma_dev: holds the dmaengine device * @m2m: is this an M2M or M2P device * @hw_setup: method which sets the channel up for operation * @hw_synchronize: synchronizes DMA channel termination to current context * @hw_shutdown: shuts the channel down and flushes whatever is left * @hw_submit: pushes active descriptor(s) to the hardware * @hw_interrupt: handle the interrupt * @num_channels: number of channels for this instance * @channels: array of channels * * There is one instance of this struct for the M2P channels and one for the * M2M channels. hw_xxx() methods are used to perform operations which are * different on M2M and M2P channels. These methods are called with channel * lock held and interrupts disabled so they cannot sleep.
*/ struct ep93xx_dma_engine { struct dma_device dma_dev; bool m2m; int (*hw_setup)(struct ep93xx_dma_chan *); void (*hw_synchronize)(struct ep93xx_dma_chan *); void (*hw_shutdown)(struct ep93xx_dma_chan *); void (*hw_submit)(struct ep93xx_dma_chan *); int (*hw_interrupt)(struct ep93xx_dma_chan *); #define INTERRUPT_UNKNOWN 0 #define INTERRUPT_DONE 1 #define INTERRUPT_NEXT_BUFFER 2
/* * ep93xx_dma_chan_direction - returns direction the channel can be used * * This function can be used in filter functions to find out whether the * channel supports given DMA direction. Only M2P channels have such * limitation, for M2M channels the direction is configurable.
*/ staticinlineenum dma_transfer_direction
ep93xx_dma_chan_direction(struct dma_chan *chan)
{ if (!ep93xx_dma_chan_is_m2p(chan)) return DMA_TRANS_NONE;
/* even channels are for TX, odd for RX */ return (chan->chan_id % 2 == 0) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
}
/** * ep93xx_dma_set_active - set new active descriptor chain * @edmac: channel * @desc: head of the new active descriptor chain * * Sets @desc to be the head of the new active descriptor chain. This is the * chain which is processed next. The active list must be empty before calling * this function. * * Called with @edmac->lock held and interrupts disabled.
*/ staticvoid ep93xx_dma_set_active(struct ep93xx_dma_chan *edmac, struct ep93xx_dma_desc *desc)
{
BUG_ON(!list_empty(&edmac->active));
list_add_tail(&desc->node, &edmac->active);
/* Flatten the @desc->tx_list chain into @edmac->active list */ while (!list_empty(&desc->tx_list)) { struct ep93xx_dma_desc *d = list_first_entry(&desc->tx_list, struct ep93xx_dma_desc, node);
/* * We copy the callback parameters from the first descriptor * to all the chained descriptors. This way we can call the * callback without having to find out the first descriptor in * the chain. Useful for cyclic transfers.
*/
d->txd.callback = desc->txd.callback;
d->txd.callback_param = desc->txd.callback_param;
list_move_tail(&d->node, &edmac->active);
}
}
/* Called with @edmac->lock held and interrupts disabled */ staticstruct ep93xx_dma_desc *
ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
{ return list_first_entry_or_null(&edmac->active, struct ep93xx_dma_desc, node);
}
/** * ep93xx_dma_advance_active - advances to the next active descriptor * @edmac: channel * * Function advances active descriptor to the next in the @edmac->active and * returns %true if we still have descriptors in the chain to process. * Otherwise returns %false. * * When the channel is in cyclic mode always returns %true. * * Called with @edmac->lock held and interrupts disabled.
*/ staticbool ep93xx_dma_advance_active(struct ep93xx_dma_chan *edmac)
{ struct ep93xx_dma_desc *desc;
list_rotate_left(&edmac->active);
if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) returntrue;
desc = ep93xx_dma_get_active(edmac); if (!desc) returnfalse;
/* * If txd.cookie is set it means that we are back in the first * descriptor in the chain and hence done with it.
*/ return !desc->txd.cookie;
}
/* * M2P DMA implementation
*/
staticvoid m2p_set_control(struct ep93xx_dma_chan *edmac, u32 control)
{
writel(control, edmac->regs + M2P_CONTROL); /* * EP93xx User's Guide states that we must perform a dummy read after * write to the control register.
*/
readl(edmac->regs + M2P_CONTROL);
}
if (irq_status & M2P_INTERRUPT_ERROR) { struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
/* Clear the error interrupt */
writel(1, edmac->regs + M2P_INTERRUPT);
/* * It seems that there is no easy way of reporting errors back * to client so we just report the error here and continue as * usual. * * Revisit this when there is a mechanism to report back the * errors.
*/
dev_err(chan2dev(edmac), "DMA transfer failed! Details:\n" "\tcookie : %d\n" "\tsrc_addr : 0x%08x\n" "\tdst_addr : 0x%08x\n" "\tsize : %zu\n",
desc->txd.cookie, desc->src_addr, desc->dst_addr,
desc->size);
}
/* * Even latest E2 silicon revision sometimes assert STALL interrupt * instead of NFB. Therefore we treat them equally, basing on the * amount of data we still have to transfer.
*/ if (!(irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB))) return INTERRUPT_UNKNOWN;
if (ep93xx_dma_advance_active(edmac)) {
m2p_fill_desc(edmac); return INTERRUPT_NEXT_BUFFER;
}
/* Disable interrupts */
control = readl(edmac->regs + M2P_CONTROL);
control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
m2p_set_control(edmac, control);
return INTERRUPT_DONE;
}
/* * M2M DMA implementation
*/
staticint m2m_hw_setup(struct ep93xx_dma_chan *edmac)
{
u32 control = 0;
if (edmac->dma_cfg.dir == DMA_MEM_TO_MEM) { /* This is memcpy channel, nothing to configure */
writel(control, edmac->regs + M2M_CONTROL); return 0;
}
switch (edmac->dma_cfg.port) { case EP93XX_DMA_SSP: /* * This was found via experimenting - anything less than 5 * causes the channel to perform only a partial transfer which * leads to problems since we don't get DONE interrupt then.
*/
control = (5 << M2M_CONTROL_PWSC_SHIFT);
control |= M2M_CONTROL_NO_HDSK;
if (edmac->dma_cfg.dir == DMA_MEM_TO_DEV) {
control |= M2M_CONTROL_DAH;
control |= M2M_CONTROL_TM_TX;
control |= M2M_CONTROL_RSS_SSPTX;
} else {
control |= M2M_CONTROL_SAH;
control |= M2M_CONTROL_TM_RX;
control |= M2M_CONTROL_RSS_SSPRX;
} break;
case EP93XX_DMA_IDE: /* * This IDE part is totally untested. Values below are taken * from the EP93xx Users's Guide and might not be correct.
*/ if (edmac->dma_cfg.dir == DMA_MEM_TO_DEV) { /* Worst case from the UG */
control = (3 << M2M_CONTROL_PWSC_SHIFT);
control |= M2M_CONTROL_DAH;
control |= M2M_CONTROL_TM_TX;
} else {
control = (2 << M2M_CONTROL_PWSC_SHIFT);
control |= M2M_CONTROL_SAH;
control |= M2M_CONTROL_TM_RX;
}
control |= M2M_CONTROL_NO_HDSK;
control |= M2M_CONTROL_RSS_IDE;
control |= M2M_CONTROL_PW_16; break;
/* * Since we allow clients to configure PW (peripheral width) we always * clear PW bits here and then set them according what is given in * the runtime configuration.
*/
control &= ~M2M_CONTROL_PW_MASK;
control |= edmac->runtime_ctrl;
m2m_fill_desc(edmac);
control |= M2M_CONTROL_DONEINT;
if (ep93xx_dma_advance_active(edmac)) {
m2m_fill_desc(edmac);
control |= M2M_CONTROL_NFBINT;
}
/* * Now we can finally enable the channel. For M2M channel this must be * done _after_ the BCRx registers are programmed.
*/
control |= M2M_CONTROL_ENABLE;
writel(control, edmac->regs + M2M_CONTROL);
if (edmac->dma_cfg.dir == DMA_MEM_TO_MEM) { /* * For memcpy channels the software trigger must be asserted * in order to start the memcpy operation.
*/
control |= M2M_CONTROL_START;
writel(control, edmac->regs + M2M_CONTROL);
}
}
/* * According to EP93xx User's Guide, we should receive DONE interrupt when all * M2M DMA controller transactions complete normally. This is not always the * case - sometimes EP93xx M2M DMA asserts DONE interrupt when the DMA channel * is still running (channel Buffer FSM in DMA_BUF_ON state, and channel * Control FSM in DMA_MEM_RD state, observed at least in IDE-DMA operation). * In effect, disabling the channel when only DONE bit is set could stop * currently running DMA transfer. To avoid this, we use Buffer FSM and * Control FSM to check current state of DMA channel.
*/ staticint m2m_hw_interrupt(struct ep93xx_dma_chan *edmac)
{
u32 status = readl(edmac->regs + M2M_STATUS);
u32 ctl_fsm = status & M2M_STATUS_CTL_MASK;
u32 buf_fsm = status & M2M_STATUS_BUF_MASK; bool done = status & M2M_STATUS_DONE; bool last_done;
u32 control; struct ep93xx_dma_desc *desc;
/* Accept only DONE and NFB interrupts */ if (!(readl(edmac->regs + M2M_INTERRUPT) & M2M_INTERRUPT_MASK)) return INTERRUPT_UNKNOWN;
if (done) { /* Clear the DONE bit */
writel(0, edmac->regs + M2M_INTERRUPT);
}
/* * Check whether we are done with descriptors or not. This, together * with DMA channel state, determines action to take in interrupt.
*/
desc = ep93xx_dma_get_active(edmac);
last_done = !desc || desc->txd.cookie;
/* * Use M2M DMA Buffer FSM and Control FSM to check current state of * DMA channel. Using DONE and NFB bits from channel status register * or bits from channel interrupt register is not reliable.
*/ if (!last_done &&
(buf_fsm == M2M_STATUS_BUF_NO ||
buf_fsm == M2M_STATUS_BUF_ON)) { /* * Two buffers are ready for update when Buffer FSM is in * DMA_NO_BUF state. Only one buffer can be prepared without * disabling the channel or polling the DONE bit. * To simplify things, always prepare only one buffer.
*/ if (ep93xx_dma_advance_active(edmac)) {
m2m_fill_desc(edmac); if (done && edmac->dma_cfg.dir == DMA_MEM_TO_MEM) { /* Software trigger for memcpy channel */
control = readl(edmac->regs + M2M_CONTROL);
control |= M2M_CONTROL_START;
writel(control, edmac->regs + M2M_CONTROL);
} return INTERRUPT_NEXT_BUFFER;
} else {
last_done = true;
}
}
/* * Disable the channel only when Buffer FSM is in DMA_NO_BUF state * and Control FSM is in DMA_STALL state.
*/ if (last_done &&
buf_fsm == M2M_STATUS_BUF_NO &&
ctl_fsm == M2M_STATUS_CTL_STALL) { /* Disable interrupts and the channel */
control = readl(edmac->regs + M2M_CONTROL);
control &= ~(M2M_CONTROL_DONEINT | M2M_CONTROL_NFBINT
| M2M_CONTROL_ENABLE);
writel(control, edmac->regs + M2M_CONTROL); return INTERRUPT_DONE;
}
/* * Nothing to do this time.
*/ return INTERRUPT_NEXT_BUFFER;
}
/** * ep93xx_dma_advance_work - start processing the next pending transaction * @edmac: channel * * If we have pending transactions queued and we are currently idling, this * function takes the next queued transaction from the @edmac->queue and * pushes it to the hardware for execution.
*/ staticvoid ep93xx_dma_advance_work(struct ep93xx_dma_chan *edmac)
{ struct ep93xx_dma_desc *new; unsignedlong flags;
memset(&cb, 0, sizeof(cb));
spin_lock_irq(&edmac->lock); /* * If dma_terminate_all() was called before we get to run, the active * list has become empty. If that happens we aren't supposed to do * anything more than call ep93xx_dma_advance_work().
*/
desc = ep93xx_dma_get_active(edmac); if (desc) { if (desc->complete) { /* mark descriptor complete for non cyclic case only */ if (!test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
dma_cookie_complete(&desc->txd);
list_splice_init(&edmac->active, &list);
}
dmaengine_desc_get_callback(&desc->txd, &cb);
}
spin_unlock_irq(&edmac->lock);
/* Pick up the next descriptor from the queue */
ep93xx_dma_advance_work(edmac);
/* Now we can release all the chained descriptors */
list_for_each_entry_safe(desc, d, &list, node) {
dma_descriptor_unmap(&desc->txd);
ep93xx_dma_desc_put(edmac, desc);
}
desc = ep93xx_dma_get_active(edmac); if (!desc) {
dev_warn(chan2dev(edmac), "got interrupt while active list is empty\n");
spin_unlock(&edmac->lock); return IRQ_NONE;
}
switch (edmac->edma->hw_interrupt(edmac)) { case INTERRUPT_DONE:
desc->complete = true;
tasklet_schedule(&edmac->tasklet); break;
case INTERRUPT_NEXT_BUFFER: if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
tasklet_schedule(&edmac->tasklet); break;
default:
dev_warn(chan2dev(edmac), "unknown interrupt!\n");
ret = IRQ_NONE; break;
}
spin_unlock(&edmac->lock); return ret;
}
/** * ep93xx_dma_tx_submit - set the prepared descriptor(s) to be executed * @tx: descriptor to be executed * * Function will execute given descriptor on the hardware or if the hardware * is busy, queue the descriptor to be executed later on. Returns cookie which * can be used to poll the status of the descriptor.
*/ static dma_cookie_t ep93xx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
{ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(tx->chan); struct ep93xx_dma_desc *desc;
dma_cookie_t cookie; unsignedlong flags;
/* * If nothing is currently processed, we push this descriptor * directly to the hardware. Otherwise we put the descriptor * to the pending queue.
*/ if (list_empty(&edmac->active)) {
ep93xx_dma_set_active(edmac, desc);
edmac->edma->hw_submit(edmac);
} else {
list_add_tail(&desc->node, &edmac->queue);
}
/** * ep93xx_dma_alloc_chan_resources - allocate resources for the channel * @chan: channel to allocate resources * * Function allocates necessary resources for the given DMA channel and * returns number of allocated descriptors for the channel. Negative errno * is returned in case of failure.
*/ staticint ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
{ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); constchar *name = dma_chan_name(chan); int ret, i;
/* Sanity check the channel parameters */ if (!edmac->edma->m2m) { if (edmac->dma_cfg.port > EP93XX_DMA_IRDA) return -EINVAL; if (edmac->dma_cfg.dir != ep93xx_dma_chan_direction(chan)) return -EINVAL;
} else { if (edmac->dma_cfg.dir != DMA_MEM_TO_MEM) { switch (edmac->dma_cfg.port) { case EP93XX_DMA_SSP: case EP93XX_DMA_IDE: if (!is_slave_direction(edmac->dma_cfg.dir)) return -EINVAL; break; default: return -EINVAL;
}
}
}
ret = clk_prepare_enable(edmac->clk); if (ret) return ret;
ret = request_irq(edmac->irq, ep93xx_dma_interrupt, 0, name, edmac); if (ret) goto fail_clk_disable;
spin_lock_irq(&edmac->lock);
dma_cookie_init(&edmac->chan);
ret = edmac->edma->hw_setup(edmac);
spin_unlock_irq(&edmac->lock);
if (ret) goto fail_free_irq;
for (i = 0; i < DMA_MAX_CHAN_DESCRIPTORS; i++) { struct ep93xx_dma_desc *desc;
/** * ep93xx_dma_free_chan_resources - release resources for the channel * @chan: channel * * Function releases all the resources allocated for the given channel. * The channel must be idle when this is called.
*/ staticvoid ep93xx_dma_free_chan_resources(struct dma_chan *chan)
{ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); struct ep93xx_dma_desc *desc, *d; unsignedlong flags;
LIST_HEAD(list);
/** * ep93xx_dma_prep_slave_sg - prepare a slave DMA operation * @chan: channel * @sgl: list of buffers to transfer * @sg_len: number of entries in @sgl * @dir: direction of the DMA transfer * @flags: flags for the descriptor * @context: operation context (ignored) * * Returns a valid DMA descriptor or %NULL in case of failure.
*/ staticstruct dma_async_tx_descriptor *
ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsignedint sg_len, enum dma_transfer_direction dir, unsignedlong flags, void *context)
{ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); struct ep93xx_dma_desc *desc, *first; struct scatterlist *sg; int i;
if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) {
dev_warn(chan2dev(edmac), "channel was configured with different direction\n"); return NULL;
}
if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) {
dev_warn(chan2dev(edmac), "channel is already used for cyclic transfers\n"); return NULL;
}
/** * ep93xx_dma_prep_dma_cyclic - prepare a cyclic DMA operation * @chan: channel * @dma_addr: DMA mapped address of the buffer * @buf_len: length of the buffer (in bytes) * @period_len: length of a single period * @dir: direction of the operation * @flags: tx descriptor status flags * * Prepares a descriptor for cyclic DMA operation. This means that once the * descriptor is submitted, we will be submitting in a @period_len sized * buffers and calling callback once the period has been elapsed. Transfer * terminates only when client calls dmaengine_terminate_all() for this * channel. * * Returns a valid DMA descriptor or %NULL in case of failure.
*/ staticstruct dma_async_tx_descriptor *
ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
size_t buf_len, size_t period_len, enum dma_transfer_direction dir, unsignedlong flags)
{ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); struct ep93xx_dma_desc *desc, *first;
size_t offset = 0;
if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) {
dev_warn(chan2dev(edmac), "channel was configured with different direction\n"); return NULL;
}
if (test_and_set_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) {
dev_warn(chan2dev(edmac), "channel is already used for cyclic transfers\n"); return NULL;
}
if (period_len > DMA_MAX_CHAN_BYTES) {
dev_warn(chan2dev(edmac), "too big period length %zu\n",
period_len); return NULL;
}
/** * ep93xx_dma_synchronize - Synchronizes the termination of transfers to the * current context. * @chan: channel * * Synchronizes the DMA channel termination to the current context. When this * function returns it is guaranteed that all transfers for previously issued * descriptors have stopped and it is safe to free the memory associated * with them. Furthermore it is guaranteed that all complete callback functions * for a previously submitted descriptor have finished running and it is safe to * free resources accessed from within the complete callbacks.
*/ staticvoid ep93xx_dma_synchronize(struct dma_chan *chan)
{ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
if (edmac->edma->hw_synchronize)
edmac->edma->hw_synchronize(edmac);
}
/** * ep93xx_dma_terminate_all - terminate all transactions * @chan: channel * * Stops all DMA transactions. All descriptors are put back to the * @edmac->free_list and callbacks are _not_ called.
*/ staticint ep93xx_dma_terminate_all(struct dma_chan *chan)
{ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); struct ep93xx_dma_desc *desc, *_d; unsignedlong flags;
LIST_HEAD(list);
spin_lock_irqsave(&edmac->lock, flags); /* First we disable and flush the DMA channel */
edmac->edma->hw_shutdown(edmac);
clear_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags);
list_splice_init(&edmac->active, &list);
list_splice_init(&edmac->queue, &list); /* * We then re-enable the channel. This way we can continue submitting * the descriptors by just calling ->hw_submit() again.
*/
edmac->edma->hw_setup(edmac);
spin_unlock_irqrestore(&edmac->lock, flags);
/** * ep93xx_dma_tx_status - check if a transaction is completed * @chan: channel * @cookie: transaction specific cookie * @state: state of the transaction is stored here if given * * This function can be used to query state of a given transaction.
*/ staticenum dma_status ep93xx_dma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *state)
{ return dma_cookie_status(chan, cookie, state);
}
/** * ep93xx_dma_issue_pending - push pending transactions to the hardware * @chan: channel * * When this function is called, all pending transactions are pushed to the * hardware and executed.
*/ staticvoid ep93xx_dma_issue_pending(struct dma_chan *chan)
{
ep93xx_dma_advance_work(to_ep93xx_dma_chan(chan));
}
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.