uboot/drivers/dma/lpc32xx_dma.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2008 by NXP Semiconductors
   4 * @Author: Kevin Wells
   5 * @Descr: LPC3250 DMA controller interface support functions
   6 *
   7 * Copyright (c) 2015 Tyco Fire Protection Products.
   8 */
   9
  10#include <common.h>
  11#include <errno.h>
  12#include <init.h>
  13#include <asm/arch/dma.h>
  14#include <asm/arch/cpu.h>
  15#include <asm/arch/clk.h>
  16#include <asm/arch/sys_proto.h>
  17#include <asm/io.h>
  18#include <linux/bitops.h>
  19#include <linux/delay.h>
  20
  21/* DMA controller channel register structure */
  22struct dmac_chan_reg {
  23        u32 src_addr;
  24        u32 dest_addr;
  25        u32 lli;
  26        u32 control;
  27        u32 config_ch;
  28        u32 reserved[3];
  29};
  30
  31/* DMA controller register structures */
  32struct dma_reg {
  33        u32 int_stat;
  34        u32 int_tc_stat;
  35        u32 int_tc_clear;
  36        u32 int_err_stat;
  37        u32 int_err_clear;
  38        u32 raw_tc_stat;
  39        u32 raw_err_stat;
  40        u32 chan_enable;
  41        u32 sw_burst_req;
  42        u32 sw_single_req;
  43        u32 sw_last_burst_req;
  44        u32 sw_last_single_req;
  45        u32 config;
  46        u32 sync;
  47        u32 reserved[50];
  48        struct dmac_chan_reg dma_chan[8];
  49};
  50
  51#define DMA_NO_OF_CHANNELS      8
  52
  53/* config register definitions */
  54#define DMAC_CTRL_ENABLE        (1 << 0) /* For enabling the DMA controller */
  55
  56static u32 alloc_ch;
  57
  58static struct dma_reg *dma = (struct dma_reg *)DMA_BASE;
  59
  60int lpc32xx_dma_get_channel(void)
  61{
  62        int i;
  63
  64        if (!alloc_ch) { /* First time caller */
  65                /*
  66                 * DMA clock are enable by "lpc32xx_dma_init()" and should
  67                 * be call by board "board_early_init_f()" function.
  68                 */
  69
  70                /*
  71                 * Make sure DMA controller and all channels are disabled.
  72                 * Controller is in little-endian mode. Disable sync signals.
  73                 */
  74                writel(0, &dma->config);
  75                writel(0, &dma->sync);
  76
  77                /* Clear interrupt and error statuses */
  78                writel(0xFF, &dma->int_tc_clear);
  79                writel(0xFF, &dma->raw_tc_stat);
  80                writel(0xFF, &dma->int_err_clear);
  81                writel(0xFF, &dma->raw_err_stat);
  82
  83                /* Enable DMA controller */
  84                writel(DMAC_CTRL_ENABLE, &dma->config);
  85        }
  86
  87        i = ffz(alloc_ch);
  88
  89        /* Check if all the available channels are busy */
  90        if (unlikely(i == DMA_NO_OF_CHANNELS))
  91                return -1;
  92        alloc_ch |= BIT_MASK(i);
  93        return i;
  94}
  95
  96int lpc32xx_dma_start_xfer(unsigned int channel,
  97                           const struct lpc32xx_dmac_ll *desc, u32 config)
  98{
  99        if (unlikely(((BIT_MASK(channel) & alloc_ch) == 0) ||
 100                     (channel >= DMA_NO_OF_CHANNELS))) {
 101                pr_err("Request for xfer on unallocated channel %d", channel);
 102                return -1;
 103        }
 104        writel(BIT_MASK(channel), &dma->int_tc_clear);
 105        writel(BIT_MASK(channel), &dma->int_err_clear);
 106        writel(desc->dma_src, &dma->dma_chan[channel].src_addr);
 107        writel(desc->dma_dest, &dma->dma_chan[channel].dest_addr);
 108        writel(desc->next_lli, &dma->dma_chan[channel].lli);
 109        writel(desc->next_ctrl, &dma->dma_chan[channel].control);
 110        writel(config, &dma->dma_chan[channel].config_ch);
 111
 112        return 0;
 113}
 114
 115int lpc32xx_dma_wait_status(unsigned int channel)
 116{
 117        unsigned long start;
 118        u32 reg;
 119
 120        /* Check if given channel is valid */
 121        if (unlikely(channel >= DMA_NO_OF_CHANNELS)) {
 122                pr_err("Request for status on unallocated channel %d", channel);
 123                return -1;
 124        }
 125
 126        start = get_timer(0);
 127        while (1) {
 128                reg = readl(&dma->raw_tc_stat);
 129                reg |= readl(dma->raw_err_stat);
 130                if (reg & BIT_MASK(channel))
 131                        break;
 132
 133                if (get_timer(start) > CONFIG_SYS_HZ) {
 134                        pr_err("DMA status timeout channel %d\n", channel);
 135                        return -ETIMEDOUT;
 136                }
 137                udelay(1);
 138        }
 139
 140        if (unlikely(readl(&dma->raw_err_stat) & BIT_MASK(channel))) {
 141                setbits_le32(&dma->int_err_clear, BIT_MASK(channel));
 142                setbits_le32(&dma->raw_err_stat, BIT_MASK(channel));
 143                pr_err("DMA error on channel %d\n", channel);
 144                return -1;
 145        }
 146        setbits_le32(&dma->int_tc_clear, BIT_MASK(channel));
 147        setbits_le32(&dma->raw_tc_stat, BIT_MASK(channel));
 148        return 0;
 149}
 150