summaryrefslogtreecommitdiff
path: root/chip/mchp/dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/mchp/dma.c')
-rw-r--r--chip/mchp/dma.c393
1 files changed, 0 insertions, 393 deletions
diff --git a/chip/mchp/dma.c b/chip/mchp/dma.c
deleted file mode 100644
index 982dfa8122..0000000000
--- a/chip/mchp/dma.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/* Copyright 2017 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "common.h"
-#include "console.h"
-#include "dma.h"
-#include "hooks.h"
-#include "registers.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#include "tfdp_chip.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_DMA, outstr)
-#define CPRINTS(format, args...) cprints(CC_DMA, format, ## args)
-
-dma_chan_t *dma_get_channel(enum dma_channel channel)
-{
- dma_chan_t *pd = NULL;
-
- if (channel < MCHP_DMAC_COUNT) {
- pd = (dma_chan_t *)(MCHP_DMA_BASE + MCHP_DMA_CH_OFS +
- (channel << MCHP_DMA_CH_OFS_BITPOS));
- }
-
- return pd;
-}
-
-void dma_disable(enum dma_channel channel)
-{
- if (channel < MCHP_DMAC_COUNT) {
- if (MCHP_DMA_CH_CTRL(channel) & MCHP_DMA_RUN)
- MCHP_DMA_CH_CTRL(channel) &= ~(MCHP_DMA_RUN);
-
- if (MCHP_DMA_CH_ACT(channel) & MCHP_DMA_ACT_EN)
- MCHP_DMA_CH_ACT(channel) = 0;
- }
-}
-
-void dma_disable_all(void)
-{
- uint16_t ch;
- uint32_t unused = 0;
-
- for (ch = 0; ch < MCHP_DMAC_COUNT; ch++) {
- /* Abort any current transfer. */
- MCHP_DMA_CH_CTRL(ch) |= MCHP_DMA_ABORT;
- /* Disable the channel. */
- MCHP_DMA_CH_CTRL(ch) &= ~(MCHP_DMA_RUN);
- MCHP_DMA_CH_ACT(ch) = 0;
- }
-
- /* Soft-reset the block. */
- MCHP_DMA_MAIN_CTRL = MCHP_DMA_MAIN_CTRL_SRST;
- unused += MCHP_DMA_MAIN_CTRL;
- MCHP_DMA_MAIN_CTRL = MCHP_DMA_MAIN_CTRL_ACT;
-}
-
-/**
- * Prepare a channel for use and start it
- *
- * @param chan Channel to read
- * @param count Number of bytes to transfer
- * @param periph Pointer to peripheral data register
- * @param memory Pointer to memory address for receive/transmit
- * @param flags DMA flags for the control register, normally:
- * MCHP_DMA_INC_MEM | MCHP_DMA_TO_DEV for tx
- * MCHP_DMA_INC_MEM for rx
- * Plus transfer unit length(1, 2, or 4) in bits[22:20]
- * @note MCHP DMA does not require address aliasing. Because count
- * is the number of bytes to transfer memory start - memory end = count.
- */
-static void prepare_channel(enum dma_channel ch, unsigned int count,
- void *periph, void *memory, unsigned int flags)
-{
- if (ch < MCHP_DMAC_COUNT) {
-
- MCHP_DMA_CH_CTRL(ch) = 0;
- MCHP_DMA_CH_MEM_START(ch) = (uint32_t)memory;
- MCHP_DMA_CH_MEM_END(ch) = (uint32_t)memory + count;
-
- MCHP_DMA_CH_DEV_ADDR(ch) = (uint32_t)periph;
-
- MCHP_DMA_CH_CTRL(ch) = flags;
- MCHP_DMA_CH_ACT(ch) = MCHP_DMA_ACT_EN;
- }
-}
-
-void dma_go(dma_chan_t *chan)
-{
- /* Flush data in write buffer so that DMA can get the
- * latest data.
- */
- asm volatile("dsb;");
-
- if (chan != NULL)
- chan->ctrl |= MCHP_DMA_RUN;
-}
-
-void dma_go_chan(enum dma_channel ch)
-{
- asm volatile("dsb;");
- if (ch < MCHP_DMAC_COUNT)
- MCHP_DMA_CH_CTRL(ch) |= MCHP_DMA_RUN;
-}
-
-void dma_prepare_tx(const struct dma_option *option, unsigned count,
- const void *memory)
-{
- if (option != NULL)
- /*
- * Cast away const for memory pointer; this is ok because
- * we know we're preparing the channel for transmit.
- */
- prepare_channel(option->channel, count, option->periph,
- (void *)memory,
- MCHP_DMA_INC_MEM |
- MCHP_DMA_TO_DEV |
- MCHP_DMA_DEV(option->channel) |
- option->flags);
-}
-
-void dma_xfr_prepare_tx(const struct dma_option *option, uint32_t count,
- const void *memory, uint32_t dma_xfr_units)
-{
- uint32_t nflags;
-
- if (option != NULL) {
- nflags = option->flags & ~(MCHP_DMA_XFER_SIZE_MASK);
- nflags |= MCHP_DMA_XFER_SIZE(dma_xfr_units & 0x07);
- /*
- * Cast away const for memory pointer; this is ok because
- * we know we're preparing the channel for transmit.
- */
- prepare_channel(option->channel, count, option->periph,
- (void *)memory,
- MCHP_DMA_INC_MEM |
- MCHP_DMA_TO_DEV |
- MCHP_DMA_DEV(option->channel) |
- nflags);
- }
-}
-
-void dma_start_rx(const struct dma_option *option, unsigned count,
- void *memory)
-{
- if (option != NULL) {
- prepare_channel(option->channel, count, option->periph,
- memory,
- MCHP_DMA_INC_MEM |
- MCHP_DMA_DEV(option->channel) |
- option->flags);
- dma_go_chan(option->channel);
- }
-}
-
-/*
- * Configure and start DMA channel for read from device and write to
- * memory. Allow caller to override DMA transfer unit length.
- */
-void dma_xfr_start_rx(const struct dma_option *option,
- uint32_t dma_xfr_ulen,
- uint32_t count, void *memory)
-{
- uint32_t ch, ctrl;
-
- if (option != NULL) {
- ch = option->channel;
- if (ch < MCHP_DMAC_COUNT) {
-
- MCHP_DMA_CH_CTRL(ch) = 0;
- MCHP_DMA_CH_MEM_START(ch) = (uint32_t)memory;
- MCHP_DMA_CH_MEM_END(ch) = (uint32_t)memory +
- count;
-
- MCHP_DMA_CH_DEV_ADDR(ch) =
- (uint32_t)option->periph;
-
- ctrl = option->flags &
- ~(MCHP_DMA_XFER_SIZE_MASK);
- ctrl |= MCHP_DMA_INC_MEM;
- ctrl |= MCHP_DMA_XFER_SIZE(dma_xfr_ulen);
- ctrl |= MCHP_DMA_DEV(option->channel);
- MCHP_DMA_CH_CTRL(ch) = ctrl;
- MCHP_DMA_CH_ACT(ch) = MCHP_DMA_ACT_EN;
- }
-
- dma_go_chan(option->channel);
- }
-}
-
-/*
- * Return the number of bytes transferred.
- * The number of bytes transferred can be easily determined
- * from the difference in DMA memory start address register
- * and memory end address register. No need to look at DMA
- * transfer size field because the hardware increments memory
- * start address by unit size on each unit transferred.
- * Why is a signed integer being used for a count value?
- */
-int dma_bytes_done(dma_chan_t *chan, int orig_count)
-{
- int bcnt;
-
- if (chan == NULL)
- return 0;
-
- bcnt = (int)chan->mem_end;
- bcnt -= (int)chan->mem_start;
- bcnt = orig_count - bcnt;
-
- return bcnt;
-}
-
-bool dma_is_enabled(dma_chan_t *chan)
-{
- return (chan->ctrl & MCHP_DMA_RUN);
-}
-
-int dma_bytes_done_chan(enum dma_channel ch, uint32_t orig_count)
-{
- uint32_t cnt;
-
- cnt = 0;
- if (ch < MCHP_DMAC_COUNT)
- if (MCHP_DMA_CH_CTRL(ch) & MCHP_DMA_RUN)
- cnt = (uint32_t)orig_count -
- (MCHP_DMA_CH_MEM_END(ch) -
- MCHP_DMA_CH_MEM_START(ch));
-
- return (int)cnt;
-}
-
-/*
- * Initialize DMA block.
- * Clear PCR DMA sleep enable.
- * Soft-Reset block should clear after one clock but read-back to
- * be safe.
- * Set block activate bit after reset.
- */
-void dma_init(void)
-{
- MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_DMA);
- MCHP_DMA_MAIN_CTRL = MCHP_DMA_MAIN_CTRL_SRST;
- MCHP_DMA_MAIN_CTRL;
- MCHP_DMA_MAIN_CTRL = MCHP_DMA_MAIN_CTRL_ACT;
-}
-
-int dma_wait(enum dma_channel channel)
-{
- timestamp_t deadline;
-
- if (channel < MCHP_DMAC_COUNT) {
- if (MCHP_DMA_CH_ACT(channel) == 0)
- return EC_SUCCESS;
-
- deadline.val = get_time().val + DMA_TRANSFER_TIMEOUT_US;
-
- while (!(MCHP_DMA_CH_ISTS(channel) &
- MCHP_DMA_STS_DONE)) {
-
- if (deadline.val <= get_time().val)
- return EC_ERROR_TIMEOUT;
-
- udelay(DMA_POLLING_INTERVAL_US);
- }
- return EC_SUCCESS;
- }
-
- return EC_ERROR_INVAL;
-}
-
-/*
- * Clear all interrupt status in specified DMA channel
- */
-void dma_clear_isr(enum dma_channel channel)
-{
- if (channel < MCHP_DMAC_COUNT)
- MCHP_DMA_CH_ISTS(channel) = 0x0f;
-}
-
-void dma_cfg_buffers(enum dma_channel ch, const void *membuf,
- uint32_t nb, const void *pdev)
-{
- if (ch < MCHP_DMAC_COUNT) {
- MCHP_DMA_CH_MEM_START(ch) = (uint32_t)membuf;
- MCHP_DMA_CH_MEM_END(ch) = (uint32_t)membuf + nb;
- MCHP_DMA_CH_DEV_ADDR(ch) = (uint32_t)pdev;
- }
-}
-
-/*
- * ch = zero based DMA channel number
- * unit_len = DMA unit size 1, 2 or 4 bytes
- * flags
- * b[0] = direction, 0=device_to_memory, 1=memory_to_device
- * b[1] = 1 increment memory address
- * b[2] = 1 increment device address
- * b[3] = disable HW flow control
- */
-void dma_cfg_xfr(enum dma_channel ch, uint8_t unit_len,
- uint8_t dev_id, uint8_t flags)
-{
- uint32_t ctrl;
-
- if (ch < MCHP_DMAC_COUNT) {
- ctrl = MCHP_DMA_XFER_SIZE(unit_len & 0x07);
- ctrl += MCHP_DMA_DEV(dev_id & MCHP_DMA_DEV_MASK0);
- if (flags & 0x01)
- ctrl |= MCHP_DMA_TO_DEV;
- if (flags & 0x02)
- ctrl |= MCHP_DMA_INC_MEM;
- if (flags & 0x04)
- ctrl |= MCHP_DMA_INC_DEV;
- if (flags & 0x08)
- ctrl |= MCHP_DMA_DIS_HW_FLOW;
- MCHP_DMA_CH_CTRL(ch) = ctrl;
- }
-}
-
-void dma_clr_chan(enum dma_channel ch)
-{
- if (ch < MCHP_DMAC_COUNT) {
- MCHP_DMA_CH_ACT(ch) = 0;
- MCHP_DMA_CH_CTRL(ch) = 0;
- MCHP_DMA_CH_IEN(ch) = 0;
- MCHP_DMA_CH_ISTS(ch) = 0xff;
- MCHP_DMA_CH_FSM_RO(ch) = MCHP_DMA_CH_ISTS(ch);
- MCHP_DMA_CH_ACT(ch) = 1;
- }
-}
-
-void dma_run(enum dma_channel ch)
-{
- if (ch < MCHP_DMAC_COUNT) {
- if (MCHP_DMA_CH_CTRL(ch) & MCHP_DMA_DIS_HW_FLOW)
- MCHP_DMA_CH_CTRL(ch) |= MCHP_DMA_SW_GO;
- else
- MCHP_DMA_CH_CTRL(ch) |= MCHP_DMA_RUN;
- }
-}
-
-/*
- * Check if DMA channel is done or stopped on error
- * Returns 0 not done or stopped on error
- * Returns non-zero if done or stopped.
- * Caller should check bit pattern for specific bit,
- * done, flow control error, and bus error.
- */
-uint32_t dma_is_done_chan(enum dma_channel ch)
-{
- if (ch < MCHP_DMAC_COUNT)
- return (uint32_t)(MCHP_DMA_CH_ISTS(ch) & 0x07);
-
- return 0;
-}
-
-/*
- * Use DMA Channel 0 CRC32 ALU to compute CRC32 of data.
- * Hardware implements IEEE 802.3 CRC32.
- * IEEE 802.3 CRC32 initial value = 0xffffffff.
- * Data must be aligned >= 4-bytes and number of bytes must
- * be a multiple of 4.
- */
-int dma_crc32_start(const uint8_t *mstart, const uint32_t nbytes, int ien)
-{
- if ((mstart == NULL) || (nbytes == 0))
- return EC_ERROR_INVAL;
-
- if ((((uint32_t)mstart | nbytes) & 0x03) != 0)
- return EC_ERROR_INVAL;
-
- MCHP_DMA_CH_ACT(0) = 0;
- MCHP_DMA_CH_CTRL(0) = 0;
- MCHP_DMA_CH_IEN(0) = 0;
- MCHP_DMA_CH_ISTS(0) = 0xff;
- MCHP_DMA_CH0_CRC32_EN = 1;
- MCHP_DMA_CH0_CRC32_DATA = 0xfffffffful;
- /* program device address to point to read-only register */
- MCHP_DMA_CH_DEV_ADDR(0) = (uint32_t)(MCHP_DMA_CH_BASE + 0x1c);
- MCHP_DMA_CH_MEM_START(0) = (uint32_t)mstart;
- MCHP_DMA_CH_MEM_END(0) = (uint32_t)mstart + nbytes;
- if (ien != 0)
- MCHP_DMA_CH_IEN(0) = 0x07;
- MCHP_DMA_CH_ACT(0) = 1;
- MCHP_DMA_CH_CTRL(0) = MCHP_DMA_TO_DEV + MCHP_DMA_INC_MEM +
- MCHP_DMA_DIS_HW_FLOW + MCHP_DMA_XFER_SIZE(4);
- MCHP_DMA_CH_CTRL(0) |= MCHP_DMA_SW_GO;
- return EC_SUCCESS;
-}