| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 | // SPDX-License-Identifier: GPL-2.0+/* * Copyright (C) 2008 by NXP Semiconductors * @Author: Kevin Wells * @Descr: LPC3250 DMA controller interface support functions * * Copyright (c) 2015 Tyco Fire Protection Products. */#include <common.h>#include <errno.h>#include <asm/arch/dma.h>#include <asm/arch/cpu.h>#include <asm/arch/clk.h>#include <asm/arch/sys_proto.h>#include <asm/io.h>/* DMA controller channel register structure */struct dmac_chan_reg {	u32 src_addr;	u32 dest_addr;	u32 lli;	u32 control;	u32 config_ch;	u32 reserved[3];};/* DMA controller register structures */struct dma_reg {	u32 int_stat;	u32 int_tc_stat;	u32 int_tc_clear;	u32 int_err_stat;	u32 int_err_clear;	u32 raw_tc_stat;	u32 raw_err_stat;	u32 chan_enable;	u32 sw_burst_req;	u32 sw_single_req;	u32 sw_last_burst_req;	u32 sw_last_single_req;	u32 config;	u32 sync;	u32 reserved[50];	struct dmac_chan_reg dma_chan[8];};#define DMA_NO_OF_CHANNELS	8/* config register definitions */#define DMAC_CTRL_ENABLE	(1 << 0) /* For enabling the DMA controller */static u32 alloc_ch;static struct dma_reg *dma = (struct dma_reg *)DMA_BASE;int lpc32xx_dma_get_channel(void){	int i;	if (!alloc_ch) { /* First time caller */		/*		 * DMA clock are enable by "lpc32xx_dma_init()" and should		 * be call by board "board_early_init_f()" function.		 */		/*		 * Make sure DMA controller and all channels are disabled.		 * Controller is in little-endian mode. Disable sync signals.		 */		writel(0, &dma->config);		writel(0, &dma->sync);		/* Clear interrupt and error statuses */		writel(0xFF, &dma->int_tc_clear);		writel(0xFF, &dma->raw_tc_stat);		writel(0xFF, &dma->int_err_clear);		writel(0xFF, &dma->raw_err_stat);		/* Enable DMA controller */		writel(DMAC_CTRL_ENABLE, &dma->config);	}	i = ffz(alloc_ch);	/* Check if all the available channels are busy */	if (unlikely(i == DMA_NO_OF_CHANNELS))		return -1;	alloc_ch |= BIT_MASK(i);	return i;}int lpc32xx_dma_start_xfer(unsigned int channel,			   const struct lpc32xx_dmac_ll *desc, u32 config){	if (unlikely(((BIT_MASK(channel) & alloc_ch) == 0) ||		     (channel >= DMA_NO_OF_CHANNELS))) {		pr_err("Request for xfer on unallocated channel %d", channel);		return -1;	}	writel(BIT_MASK(channel), &dma->int_tc_clear);	writel(BIT_MASK(channel), &dma->int_err_clear);	writel(desc->dma_src, &dma->dma_chan[channel].src_addr);	writel(desc->dma_dest, &dma->dma_chan[channel].dest_addr);	writel(desc->next_lli, &dma->dma_chan[channel].lli);	writel(desc->next_ctrl, &dma->dma_chan[channel].control);	writel(config, &dma->dma_chan[channel].config_ch);	return 0;}int lpc32xx_dma_wait_status(unsigned int channel){	unsigned long start;	u32 reg;	/* Check if given channel is valid */	if (unlikely(channel >= DMA_NO_OF_CHANNELS)) {		pr_err("Request for status on unallocated channel %d", channel);		return -1;	}	start = get_timer(0);	while (1) {		reg = readl(&dma->raw_tc_stat);		reg |= readl(dma->raw_err_stat);		if (reg & BIT_MASK(channel))			break;		if (get_timer(start) > CONFIG_SYS_HZ) {			pr_err("DMA status timeout channel %d\n", channel);			return -ETIMEDOUT;		}		udelay(1);	}	if (unlikely(readl(&dma->raw_err_stat) & BIT_MASK(channel))) {		setbits_le32(&dma->int_err_clear, BIT_MASK(channel));		setbits_le32(&dma->raw_err_stat, BIT_MASK(channel));		pr_err("DMA error on channel %d\n", channel);		return -1;	}	setbits_le32(&dma->int_tc_clear, BIT_MASK(channel));	setbits_le32(&dma->raw_tc_stat, BIT_MASK(channel));	return 0;}
 |