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