^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (C) 2007-2008 Atmel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (C) 2010-2011 ST Microelectronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // Copyright (C) 2013,2018 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/dmaengine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static void dw_dma_initialize_chan(struct dw_dma_chan *dwc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct dw_dma *dw = to_dw_dma(dwc->chan.device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) u32 cfghi = is_slave_direction(dwc->direction) ? 0 : DWC_CFGH_FIFO_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) bool hs_polarity = dwc->dws.hs_polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) cfghi |= DWC_CFGH_SRC_PER(dwc->dws.src_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) cfghi |= DWC_CFGH_PROTCTL(dw->pdata->protctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Set polarity of handshake interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) cfglo |= hs_polarity ? DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) channel_writel(dwc, CFG_LO, cfglo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) channel_writel(dwc, CFG_HI, cfghi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void dw_dma_suspend_chan(struct dw_dma_chan *dwc, bool drain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u32 cfglo = channel_readl(dwc, CFG_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void dw_dma_resume_chan(struct dw_dma_chan *dwc, bool drain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 cfglo = channel_readl(dwc, CFG_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static u32 dw_dma_bytes2block(struct dw_dma_chan *dwc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) size_t bytes, unsigned int width, size_t *len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u32 block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if ((bytes >> width) > dwc->block_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) block = dwc->block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *len = dwc->block_size << width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) block = bytes >> width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *len = bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static size_t dw_dma_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return DWC_CTLH_BLOCK_TS(block) << width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct dma_slave_config *sconfig = &dwc->dma_sconfig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u8 smsize = (dwc->direction == DMA_DEV_TO_MEM) ? sconfig->src_maxburst : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u8 dmsize = (dwc->direction == DMA_MEM_TO_DEV) ? sconfig->dst_maxburst : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u8 p_master = dwc->dws.p_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) u8 m_master = dwc->dws.m_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u8 dms = (dwc->direction == DMA_MEM_TO_DEV) ? p_master : m_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u8 sms = (dwc->direction == DMA_DEV_TO_MEM) ? p_master : m_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) DWC_CTLL_DMS(dms) | DWC_CTLL_SMS(sms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static void dw_dma_encode_maxburst(struct dw_dma_chan *dwc, u32 *maxburst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * Fix burst size according to dw_dmac. We need to convert them as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *maxburst = *maxburst > 1 ? fls(*maxburst) - 2 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static void dw_dma_set_device_name(struct dw_dma *dw, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) snprintf(dw->name, sizeof(dw->name), "dw:dmac%d", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static void dw_dma_disable(struct dw_dma *dw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) do_dw_dma_off(dw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void dw_dma_enable(struct dw_dma *dw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) do_dw_dma_on(dw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int dw_dma_probe(struct dw_dma_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct dw_dma *dw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dw = devm_kzalloc(chip->dev, sizeof(*dw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!dw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Channel operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dw->initialize_chan = dw_dma_initialize_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dw->suspend_chan = dw_dma_suspend_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) dw->resume_chan = dw_dma_resume_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) dw->prepare_ctllo = dw_dma_prepare_ctllo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) dw->encode_maxburst = dw_dma_encode_maxburst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dw->bytes2block = dw_dma_bytes2block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dw->block2bytes = dw_dma_block2bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Device operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) dw->set_device_name = dw_dma_set_device_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) dw->disable = dw_dma_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) dw->enable = dw_dma_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) chip->dw = dw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return do_dma_probe(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) EXPORT_SYMBOL_GPL(dw_dma_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int dw_dma_remove(struct dw_dma_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return do_dma_remove(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) EXPORT_SYMBOL_GPL(dw_dma_remove);