diff options
Diffstat (limited to 'chip/mchp/dma.c')
-rw-r--r-- | chip/mchp/dma.c | 393 |
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; -} |