// SPDX-License-Identifier: GPL-2.0-only /* * Core driver for the High Speed UART DMA * * Copyright (C) 2015 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> * * Partially based on the bits found in drivers/tty/serial/mfd.c.
*/
/* * DMA channel allocation: * 1. Even number chans are used for DMA Read (UART TX), odd chans for DMA * Write (UART RX). * 2. 0/1 channel are assigned to port 0, 2/3 chan to port 1, 4/5 chan to * port 3, and so on.
*/
/* Start the channel with a new descriptor */
hsu_dma_start_channel(hsuc);
}
/* * hsu_dma_get_status() - get DMA channel status * @chip: HSUART DMA chip * @nr: DMA channel number * @status: pointer for DMA Channel Status Register value * * Description: * The function reads and clears the DMA Channel Status Register, checks * if it was a timeout interrupt and returns a corresponding value. * * Caller should provide a valid pointer for the DMA Channel Status * Register value that will be returned in @status. * * Return: * 1 for DMA timeout status, 0 for other DMA status, or error code for * invalid parameters or no interrupt pending.
*/ int hsu_dma_get_status(struct hsu_dma_chip *chip, unsignedshort nr,
u32 *status)
{ struct hsu_dma_chan *hsuc; unsignedlong flags;
u32 sr;
/* Sanity check */ if (nr >= chip->hsu->nr_channels) return -EINVAL;
hsuc = &chip->hsu->chan[nr];
/* * No matter what situation, need read clear the IRQ status * There is a bug, see Errata 5, HSD 2900918
*/
spin_lock_irqsave(&hsuc->vchan.lock, flags);
sr = hsu_chan_readl(hsuc, HSU_CH_SR);
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
/* Check if any interrupt is pending */
sr &= ~(HSU_CH_SR_DESCE_ANY | HSU_CH_SR_CDESC_ANY); if (!sr) return -EIO;
/* Timeout IRQ, need wait some time, see Errata 2 */ if (sr & HSU_CH_SR_DESCTO_ANY)
udelay(2);
/* * At this point, at least one of Descriptor Time Out, Channel Error * or Descriptor Done bits must be set. Clear the Descriptor Time Out * bits and if sr is still non-zero, it must be channel error or * descriptor done which are higher priority than timeout and handled * in hsu_dma_do_irq(). Else, it must be a timeout.
*/
sr &= ~HSU_CH_SR_DESCTO_ANY;
*status = sr;
return sr ? 0 : 1;
}
EXPORT_SYMBOL_GPL(hsu_dma_get_status);
/* * hsu_dma_do_irq() - DMA interrupt handler * @chip: HSUART DMA chip * @nr: DMA channel number * @status: Channel Status Register value * * Description: * This function handles Channel Error and Descriptor Done interrupts. * This function should be called after determining that the DMA interrupt * is not a normal timeout interrupt, ie. hsu_dma_get_status() returned 0. * * Return: * 0 for invalid channel number, 1 otherwise.
*/ int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsignedshort nr, u32 status)
{ struct dma_chan_percpu *stat; struct hsu_dma_chan *hsuc; struct hsu_dma_desc *desc; unsignedlong flags;
/* Sanity check */ if (nr >= chip->hsu->nr_channels) return 0;
hsuc = &chip->hsu->chan[nr];
stat = this_cpu_ptr(hsuc->vchan.chan.local);
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.