* Based on code from LTIB:
* Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/list.h>
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/sys_proto.h>
-#include <asm/arch/dma.h>
+#include <asm/imx-common/dma.h>
+#include <asm/imx-common/regs-apbh.h>
static struct mxs_dma_chan mxs_dma_channels[MXS_MAX_DMA_CHANNELS];
+static struct mxs_apbh_regs *apbh_regs = (struct mxs_apbh_regs *)MXS_APBH_BASE;
/*
* Test is the DMA channel is valid channel
{
struct mxs_dma_chan *pchan;
- if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS)) {
+ printf("Invalid DMA channel %d\n", channel);
return -EINVAL;
+ }
pchan = mxs_dma_channels + channel;
- if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED)) {
+ printf("DMA channel %d not allocated\n", channel);
return -EINVAL;
+ }
return 0;
}
*/
static int mxs_dma_read_semaphore(int channel)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
uint32_t tmp;
int ret;
*/
static int mxs_dma_enable(int channel)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
unsigned int sem;
struct mxs_dma_chan *pchan;
struct mxs_dma_desc *pdesc;
pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node);
if (pdesc == NULL)
- return -EFAULT;
+ return -EINVAL;
if (pchan->flags & MXS_DMA_FLAGS_BUSY) {
if (!(pdesc->cmd.data & MXS_DMA_DESC_CHAIN))
} else {
pchan->active_num += pchan->pending_num;
pchan->pending_num = 0;
+ writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
+ &apbh_regs->hw_apbh_ctrl0_clr);
writel(mxs_dma_cmd_address(pdesc),
&apbh_regs->ch[channel].hw_apbh_ch_nxtcmdar);
writel(pchan->active_num,
&apbh_regs->ch[channel].hw_apbh_ch_sema);
- writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
- &apbh_regs->hw_apbh_ctrl0_clr);
}
pchan->flags |= MXS_DMA_FLAGS_BUSY;
static int mxs_dma_disable(int channel)
{
struct mxs_dma_chan *pchan;
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(channel);
pchan = mxs_dma_channels + channel;
- if (!(pchan->flags & MXS_DMA_FLAGS_BUSY))
+ if ((pchan->flags & MXS_DMA_FLAGS_BUSY)) {
+ printf("%s: DMA channel %d busy\n", __func__, channel);
return -EINVAL;
-
+ }
writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
&apbh_regs->hw_apbh_ctrl0_set);
-
- pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
pchan->active_num = 0;
pchan->pending_num = 0;
list_splice_init(&pchan->active, &pchan->done);
*/
static int mxs_dma_reset(int channel)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
+#if defined(CONFIG_MX23)
+ uint32_t *setreg = &apbh_regs->hw_apbh_ctrl0_set;
+ uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET;
+#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6))
+ uint32_t *setreg = &apbh_regs->hw_apbh_channel_ctrl_set;
+ uint32_t offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET;
+#endif
ret = mxs_dma_validate_chan(channel);
if (ret)
return ret;
- writel(1 << (channel + APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET),
- &apbh_regs->hw_apbh_channel_ctrl_set);
+ writel(1 << (channel + offset), setreg);
return 0;
}
*/
static int mxs_dma_enable_irq(int channel, int enable)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(channel);
*/
static int mxs_dma_ack_irq(int channel)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(channel);
*/
static int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(chan);
*/
void mxs_dma_init(void)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
-
mxs_reset_block(&apbh_regs->hw_apbh_ctrl0_reg);
#ifdef CONFIG_APBH_DMA_BURST8