132d31c79SAmireddy Mallikarjuna reddy // SPDX-License-Identifier: GPL-2.0 232d31c79SAmireddy Mallikarjuna reddy /* 332d31c79SAmireddy Mallikarjuna reddy * Lightning Mountain centralized DMA controller driver 432d31c79SAmireddy Mallikarjuna reddy * 532d31c79SAmireddy Mallikarjuna reddy * Copyright (c) 2016 - 2020 Intel Corporation. 632d31c79SAmireddy Mallikarjuna reddy */ 732d31c79SAmireddy Mallikarjuna reddy 832d31c79SAmireddy Mallikarjuna reddy #include <linux/bitfield.h> 932d31c79SAmireddy Mallikarjuna reddy #include <linux/clk.h> 1032d31c79SAmireddy Mallikarjuna reddy #include <linux/dma-mapping.h> 1132d31c79SAmireddy Mallikarjuna reddy #include <linux/dmapool.h> 1232d31c79SAmireddy Mallikarjuna reddy #include <linux/err.h> 1332d31c79SAmireddy Mallikarjuna reddy #include <linux/export.h> 1432d31c79SAmireddy Mallikarjuna reddy #include <linux/init.h> 1532d31c79SAmireddy Mallikarjuna reddy #include <linux/interrupt.h> 1632d31c79SAmireddy Mallikarjuna reddy #include <linux/iopoll.h> 1732d31c79SAmireddy Mallikarjuna reddy #include <linux/of_dma.h> 1832d31c79SAmireddy Mallikarjuna reddy #include <linux/of_irq.h> 1932d31c79SAmireddy Mallikarjuna reddy #include <linux/platform_device.h> 2032d31c79SAmireddy Mallikarjuna reddy #include <linux/reset.h> 2132d31c79SAmireddy Mallikarjuna reddy 2232d31c79SAmireddy Mallikarjuna reddy #include "../dmaengine.h" 2332d31c79SAmireddy Mallikarjuna reddy #include "../virt-dma.h" 2432d31c79SAmireddy Mallikarjuna reddy 2532d31c79SAmireddy Mallikarjuna reddy #define DRIVER_NAME "lgm-dma" 2632d31c79SAmireddy Mallikarjuna reddy 2732d31c79SAmireddy Mallikarjuna reddy #define DMA_ID 0x0008 2832d31c79SAmireddy Mallikarjuna reddy #define DMA_ID_REV GENMASK(7, 0) 2932d31c79SAmireddy Mallikarjuna reddy #define DMA_ID_PNR GENMASK(19, 16) 3032d31c79SAmireddy Mallikarjuna reddy #define DMA_ID_CHNR GENMASK(26, 20) 3132d31c79SAmireddy Mallikarjuna reddy #define DMA_ID_DW_128B BIT(27) 3232d31c79SAmireddy Mallikarjuna reddy #define DMA_ID_AW_36B BIT(28) 3332d31c79SAmireddy Mallikarjuna reddy #define DMA_VER32 0x32 3432d31c79SAmireddy Mallikarjuna reddy #define DMA_VER31 0x31 3532d31c79SAmireddy Mallikarjuna reddy #define DMA_VER22 0x0A 3632d31c79SAmireddy Mallikarjuna reddy 3732d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL 0x0010 3832d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_RST BIT(0) 3932d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_DSRAM_PATH BIT(1) 4032d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_DBURST_WR BIT(3) 4132d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_VLD_DF_ACK BIT(4) 4232d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_CH_FL BIT(6) 4332d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_DS_FOD BIT(7) 4432d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_DRB BIT(8) 4532d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_ENBE BIT(9) 4632d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_DESC_TMOUT_CNT_V31 GENMASK(27, 16) 4732d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_DESC_TMOUT_EN_V31 BIT(30) 4832d31c79SAmireddy Mallikarjuna reddy #define DMA_CTRL_PKTARB BIT(31) 4932d31c79SAmireddy Mallikarjuna reddy 5032d31c79SAmireddy Mallikarjuna reddy #define DMA_CPOLL 0x0014 5132d31c79SAmireddy Mallikarjuna reddy #define DMA_CPOLL_CNT GENMASK(15, 4) 5232d31c79SAmireddy Mallikarjuna reddy #define DMA_CPOLL_EN BIT(31) 5332d31c79SAmireddy Mallikarjuna reddy 5432d31c79SAmireddy Mallikarjuna reddy #define DMA_CS 0x0018 5532d31c79SAmireddy Mallikarjuna reddy #define DMA_CS_MASK GENMASK(5, 0) 5632d31c79SAmireddy Mallikarjuna reddy 5732d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL 0x001C 5832d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL_ON BIT(0) 5932d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL_RST BIT(1) 6032d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL_CH_POLL_EN BIT(2) 6132d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL_CH_ABC BIT(3) /* Adaptive Burst Chop */ 6232d31c79SAmireddy Mallikarjuna reddy #define DMA_CDBA_MSB GENMASK(7, 4) 6332d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL_DIR_TX BIT(8) 6432d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL_CLASS GENMASK(11, 9) 6532d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL_CLASSH GENMASK(19, 18) 6632d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL_WR_NP_EN BIT(21) 6732d31c79SAmireddy Mallikarjuna reddy #define DMA_CCTRL_PDEN BIT(23) 6832d31c79SAmireddy Mallikarjuna reddy #define DMA_MAX_CLASS (SZ_32 - 1) 6932d31c79SAmireddy Mallikarjuna reddy 7032d31c79SAmireddy Mallikarjuna reddy #define DMA_CDBA 0x0020 7132d31c79SAmireddy Mallikarjuna reddy #define DMA_CDLEN 0x0024 7232d31c79SAmireddy Mallikarjuna reddy #define DMA_CIS 0x0028 7332d31c79SAmireddy Mallikarjuna reddy #define DMA_CIE 0x002C 7432d31c79SAmireddy Mallikarjuna reddy #define DMA_CI_EOP BIT(1) 7532d31c79SAmireddy Mallikarjuna reddy #define DMA_CI_DUR BIT(2) 7632d31c79SAmireddy Mallikarjuna reddy #define DMA_CI_DESCPT BIT(3) 7732d31c79SAmireddy Mallikarjuna reddy #define DMA_CI_CHOFF BIT(4) 7832d31c79SAmireddy Mallikarjuna reddy #define DMA_CI_RDERR BIT(5) 7932d31c79SAmireddy Mallikarjuna reddy #define DMA_CI_ALL \ 8032d31c79SAmireddy Mallikarjuna reddy (DMA_CI_EOP | DMA_CI_DUR | DMA_CI_DESCPT | DMA_CI_CHOFF | DMA_CI_RDERR) 8132d31c79SAmireddy Mallikarjuna reddy 8232d31c79SAmireddy Mallikarjuna reddy #define DMA_PS 0x0040 8332d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL 0x0044 8432d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_RXBL16 BIT(0) 8532d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_TXBL16 BIT(1) 8632d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_RXBL GENMASK(3, 2) 8732d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_RXBL_8 3 8832d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_TXBL GENMASK(5, 4) 8932d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_TXBL_8 3 9032d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_PDEN BIT(6) 9132d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_RXBL32 BIT(7) 9232d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_RXENDI GENMASK(9, 8) 9332d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_TXENDI GENMASK(11, 10) 9432d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_TXBL32 BIT(15) 9532d31c79SAmireddy Mallikarjuna reddy #define DMA_PCTRL_MEM_FLUSH BIT(16) 9632d31c79SAmireddy Mallikarjuna reddy 9732d31c79SAmireddy Mallikarjuna reddy #define DMA_IRNEN1 0x00E8 9832d31c79SAmireddy Mallikarjuna reddy #define DMA_IRNCR1 0x00EC 9932d31c79SAmireddy Mallikarjuna reddy #define DMA_IRNEN 0x00F4 10032d31c79SAmireddy Mallikarjuna reddy #define DMA_IRNCR 0x00F8 10132d31c79SAmireddy Mallikarjuna reddy #define DMA_C_DP_TICK 0x100 10232d31c79SAmireddy Mallikarjuna reddy #define DMA_C_DP_TICK_TIKNARB GENMASK(15, 0) 10332d31c79SAmireddy Mallikarjuna reddy #define DMA_C_DP_TICK_TIKARB GENMASK(31, 16) 10432d31c79SAmireddy Mallikarjuna reddy 10532d31c79SAmireddy Mallikarjuna reddy #define DMA_C_HDRM 0x110 10632d31c79SAmireddy Mallikarjuna reddy /* 10732d31c79SAmireddy Mallikarjuna reddy * If header mode is set in DMA descriptor, 10832d31c79SAmireddy Mallikarjuna reddy * If bit 30 is disabled, HDR_LEN must be configured according to channel 10932d31c79SAmireddy Mallikarjuna reddy * requirement. 11032d31c79SAmireddy Mallikarjuna reddy * If bit 30 is enabled(checksum with heade mode), HDR_LEN has no need to 11132d31c79SAmireddy Mallikarjuna reddy * be configured. It will enable check sum for switch 11232d31c79SAmireddy Mallikarjuna reddy * If header mode is not set in DMA descriptor, 11332d31c79SAmireddy Mallikarjuna reddy * This register setting doesn't matter 11432d31c79SAmireddy Mallikarjuna reddy */ 11532d31c79SAmireddy Mallikarjuna reddy #define DMA_C_HDRM_HDR_SUM BIT(30) 11632d31c79SAmireddy Mallikarjuna reddy 11732d31c79SAmireddy Mallikarjuna reddy #define DMA_C_BOFF 0x120 11832d31c79SAmireddy Mallikarjuna reddy #define DMA_C_BOFF_BOF_LEN GENMASK(7, 0) 11932d31c79SAmireddy Mallikarjuna reddy #define DMA_C_BOFF_EN BIT(31) 12032d31c79SAmireddy Mallikarjuna reddy 12132d31c79SAmireddy Mallikarjuna reddy #define DMA_ORRC 0x190 12232d31c79SAmireddy Mallikarjuna reddy #define DMA_ORRC_ORRCNT GENMASK(8, 4) 12332d31c79SAmireddy Mallikarjuna reddy #define DMA_ORRC_EN BIT(31) 12432d31c79SAmireddy Mallikarjuna reddy 12532d31c79SAmireddy Mallikarjuna reddy #define DMA_C_ENDIAN 0x200 12632d31c79SAmireddy Mallikarjuna reddy #define DMA_C_END_DATAENDI GENMASK(1, 0) 12732d31c79SAmireddy Mallikarjuna reddy #define DMA_C_END_DE_EN BIT(7) 12832d31c79SAmireddy Mallikarjuna reddy #define DMA_C_END_DESENDI GENMASK(9, 8) 12932d31c79SAmireddy Mallikarjuna reddy #define DMA_C_END_DES_EN BIT(16) 13032d31c79SAmireddy Mallikarjuna reddy 13132d31c79SAmireddy Mallikarjuna reddy /* DMA controller capability */ 13232d31c79SAmireddy Mallikarjuna reddy #define DMA_ADDR_36BIT BIT(0) 13332d31c79SAmireddy Mallikarjuna reddy #define DMA_DATA_128BIT BIT(1) 13432d31c79SAmireddy Mallikarjuna reddy #define DMA_CHAN_FLOW_CTL BIT(2) 13532d31c79SAmireddy Mallikarjuna reddy #define DMA_DESC_FOD BIT(3) 13632d31c79SAmireddy Mallikarjuna reddy #define DMA_DESC_IN_SRAM BIT(4) 13732d31c79SAmireddy Mallikarjuna reddy #define DMA_EN_BYTE_EN BIT(5) 13832d31c79SAmireddy Mallikarjuna reddy #define DMA_DBURST_WR BIT(6) 13932d31c79SAmireddy Mallikarjuna reddy #define DMA_VALID_DESC_FETCH_ACK BIT(7) 14032d31c79SAmireddy Mallikarjuna reddy #define DMA_DFT_DRB BIT(8) 14132d31c79SAmireddy Mallikarjuna reddy 14232d31c79SAmireddy Mallikarjuna reddy #define DMA_ORRC_MAX_CNT (SZ_32 - 1) 14332d31c79SAmireddy Mallikarjuna reddy #define DMA_DFT_POLL_CNT SZ_4 14432d31c79SAmireddy Mallikarjuna reddy #define DMA_DFT_BURST_V22 SZ_2 14532d31c79SAmireddy Mallikarjuna reddy #define DMA_BURSTL_8DW SZ_8 14632d31c79SAmireddy Mallikarjuna reddy #define DMA_BURSTL_16DW SZ_16 14732d31c79SAmireddy Mallikarjuna reddy #define DMA_BURSTL_32DW SZ_32 14832d31c79SAmireddy Mallikarjuna reddy #define DMA_DFT_BURST DMA_BURSTL_16DW 14932d31c79SAmireddy Mallikarjuna reddy #define DMA_MAX_DESC_NUM (SZ_8K - 1) 15032d31c79SAmireddy Mallikarjuna reddy #define DMA_CHAN_BOFF_MAX (SZ_256 - 1) 15132d31c79SAmireddy Mallikarjuna reddy #define DMA_DFT_ENDIAN 0 15232d31c79SAmireddy Mallikarjuna reddy 15332d31c79SAmireddy Mallikarjuna reddy #define DMA_DFT_DESC_TCNT 50 15432d31c79SAmireddy Mallikarjuna reddy #define DMA_HDR_LEN_MAX (SZ_16K - 1) 15532d31c79SAmireddy Mallikarjuna reddy 15632d31c79SAmireddy Mallikarjuna reddy /* DMA flags */ 15732d31c79SAmireddy Mallikarjuna reddy #define DMA_TX_CH BIT(0) 15832d31c79SAmireddy Mallikarjuna reddy #define DMA_RX_CH BIT(1) 15932d31c79SAmireddy Mallikarjuna reddy #define DEVICE_ALLOC_DESC BIT(2) 16032d31c79SAmireddy Mallikarjuna reddy #define CHAN_IN_USE BIT(3) 16132d31c79SAmireddy Mallikarjuna reddy #define DMA_HW_DESC BIT(4) 16232d31c79SAmireddy Mallikarjuna reddy 16332d31c79SAmireddy Mallikarjuna reddy /* Descriptor fields */ 16432d31c79SAmireddy Mallikarjuna reddy #define DESC_DATA_LEN GENMASK(15, 0) 16532d31c79SAmireddy Mallikarjuna reddy #define DESC_BYTE_OFF GENMASK(25, 23) 16632d31c79SAmireddy Mallikarjuna reddy #define DESC_EOP BIT(28) 16732d31c79SAmireddy Mallikarjuna reddy #define DESC_SOP BIT(29) 16832d31c79SAmireddy Mallikarjuna reddy #define DESC_C BIT(30) 16932d31c79SAmireddy Mallikarjuna reddy #define DESC_OWN BIT(31) 17032d31c79SAmireddy Mallikarjuna reddy 17132d31c79SAmireddy Mallikarjuna reddy #define DMA_CHAN_RST 1 17232d31c79SAmireddy Mallikarjuna reddy #define DMA_MAX_SIZE (BIT(16) - 1) 17332d31c79SAmireddy Mallikarjuna reddy #define MAX_LOWER_CHANS 32 17432d31c79SAmireddy Mallikarjuna reddy #define MASK_LOWER_CHANS GENMASK(4, 0) 17532d31c79SAmireddy Mallikarjuna reddy #define DMA_OWN 1 17632d31c79SAmireddy Mallikarjuna reddy #define HIGH_4_BITS GENMASK(3, 0) 17732d31c79SAmireddy Mallikarjuna reddy #define DMA_DFT_DESC_NUM 1 17832d31c79SAmireddy Mallikarjuna reddy #define DMA_PKT_DROP_DIS 0 17932d31c79SAmireddy Mallikarjuna reddy 18032d31c79SAmireddy Mallikarjuna reddy enum ldma_chan_on_off { 18132d31c79SAmireddy Mallikarjuna reddy DMA_CH_OFF = 0, 18232d31c79SAmireddy Mallikarjuna reddy DMA_CH_ON = 1, 18332d31c79SAmireddy Mallikarjuna reddy }; 18432d31c79SAmireddy Mallikarjuna reddy 18532d31c79SAmireddy Mallikarjuna reddy enum { 18632d31c79SAmireddy Mallikarjuna reddy DMA_TYPE_TX = 0, 18732d31c79SAmireddy Mallikarjuna reddy DMA_TYPE_RX, 18832d31c79SAmireddy Mallikarjuna reddy DMA_TYPE_MCPY, 18932d31c79SAmireddy Mallikarjuna reddy }; 19032d31c79SAmireddy Mallikarjuna reddy 19132d31c79SAmireddy Mallikarjuna reddy struct ldma_dev; 19232d31c79SAmireddy Mallikarjuna reddy struct ldma_port; 19332d31c79SAmireddy Mallikarjuna reddy 19432d31c79SAmireddy Mallikarjuna reddy struct ldma_chan { 19532d31c79SAmireddy Mallikarjuna reddy struct virt_dma_chan vchan; 19632d31c79SAmireddy Mallikarjuna reddy struct ldma_port *port; /* back pointer */ 19732d31c79SAmireddy Mallikarjuna reddy char name[8]; /* Channel name */ 19832d31c79SAmireddy Mallikarjuna reddy int nr; /* Channel id in hardware */ 19932d31c79SAmireddy Mallikarjuna reddy u32 flags; /* central way or channel based way */ 20032d31c79SAmireddy Mallikarjuna reddy enum ldma_chan_on_off onoff; 20132d31c79SAmireddy Mallikarjuna reddy dma_addr_t desc_phys; 20232d31c79SAmireddy Mallikarjuna reddy void *desc_base; /* Virtual address */ 20332d31c79SAmireddy Mallikarjuna reddy u32 desc_cnt; /* Number of descriptors */ 20432d31c79SAmireddy Mallikarjuna reddy int rst; 20532d31c79SAmireddy Mallikarjuna reddy u32 hdrm_len; 20632d31c79SAmireddy Mallikarjuna reddy bool hdrm_csum; 20732d31c79SAmireddy Mallikarjuna reddy u32 boff_len; 20832d31c79SAmireddy Mallikarjuna reddy u32 data_endian; 20932d31c79SAmireddy Mallikarjuna reddy u32 desc_endian; 21032d31c79SAmireddy Mallikarjuna reddy bool pden; 21132d31c79SAmireddy Mallikarjuna reddy bool desc_rx_np; 21232d31c79SAmireddy Mallikarjuna reddy bool data_endian_en; 21332d31c79SAmireddy Mallikarjuna reddy bool desc_endian_en; 21432d31c79SAmireddy Mallikarjuna reddy bool abc_en; 21532d31c79SAmireddy Mallikarjuna reddy bool desc_init; 21632d31c79SAmireddy Mallikarjuna reddy struct dma_pool *desc_pool; /* Descriptors pool */ 21732d31c79SAmireddy Mallikarjuna reddy u32 desc_num; 21832d31c79SAmireddy Mallikarjuna reddy struct dw2_desc_sw *ds; 21932d31c79SAmireddy Mallikarjuna reddy struct work_struct work; 22032d31c79SAmireddy Mallikarjuna reddy struct dma_slave_config config; 22132d31c79SAmireddy Mallikarjuna reddy }; 22232d31c79SAmireddy Mallikarjuna reddy 22332d31c79SAmireddy Mallikarjuna reddy struct ldma_port { 22432d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *ldev; /* back pointer */ 22532d31c79SAmireddy Mallikarjuna reddy u32 portid; 22632d31c79SAmireddy Mallikarjuna reddy u32 rxbl; 22732d31c79SAmireddy Mallikarjuna reddy u32 txbl; 22832d31c79SAmireddy Mallikarjuna reddy u32 rxendi; 22932d31c79SAmireddy Mallikarjuna reddy u32 txendi; 23032d31c79SAmireddy Mallikarjuna reddy u32 pkt_drop; 23132d31c79SAmireddy Mallikarjuna reddy }; 23232d31c79SAmireddy Mallikarjuna reddy 23332d31c79SAmireddy Mallikarjuna reddy /* Instance specific data */ 23432d31c79SAmireddy Mallikarjuna reddy struct ldma_inst_data { 23532d31c79SAmireddy Mallikarjuna reddy bool desc_in_sram; 23632d31c79SAmireddy Mallikarjuna reddy bool chan_fc; 23732d31c79SAmireddy Mallikarjuna reddy bool desc_fod; /* Fetch On Demand */ 23832d31c79SAmireddy Mallikarjuna reddy bool valid_desc_fetch_ack; 23932d31c79SAmireddy Mallikarjuna reddy u32 orrc; /* Outstanding read count */ 24032d31c79SAmireddy Mallikarjuna reddy const char *name; 24132d31c79SAmireddy Mallikarjuna reddy u32 type; 24232d31c79SAmireddy Mallikarjuna reddy }; 24332d31c79SAmireddy Mallikarjuna reddy 24432d31c79SAmireddy Mallikarjuna reddy struct ldma_dev { 24532d31c79SAmireddy Mallikarjuna reddy struct device *dev; 24632d31c79SAmireddy Mallikarjuna reddy void __iomem *base; 24732d31c79SAmireddy Mallikarjuna reddy struct reset_control *rst; 24832d31c79SAmireddy Mallikarjuna reddy struct clk *core_clk; 24932d31c79SAmireddy Mallikarjuna reddy struct dma_device dma_dev; 25032d31c79SAmireddy Mallikarjuna reddy u32 ver; 25132d31c79SAmireddy Mallikarjuna reddy int irq; 25232d31c79SAmireddy Mallikarjuna reddy struct ldma_port *ports; 25332d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *chans; /* channel list on this DMA or port */ 25432d31c79SAmireddy Mallikarjuna reddy spinlock_t dev_lock; /* Controller register exclusive */ 25532d31c79SAmireddy Mallikarjuna reddy u32 chan_nrs; 25632d31c79SAmireddy Mallikarjuna reddy u32 port_nrs; 25732d31c79SAmireddy Mallikarjuna reddy u32 channels_mask; 25832d31c79SAmireddy Mallikarjuna reddy u32 flags; 25932d31c79SAmireddy Mallikarjuna reddy u32 pollcnt; 26032d31c79SAmireddy Mallikarjuna reddy const struct ldma_inst_data *inst; 26132d31c79SAmireddy Mallikarjuna reddy struct workqueue_struct *wq; 26232d31c79SAmireddy Mallikarjuna reddy }; 26332d31c79SAmireddy Mallikarjuna reddy 26432d31c79SAmireddy Mallikarjuna reddy struct dw2_desc { 26532d31c79SAmireddy Mallikarjuna reddy u32 field; 26632d31c79SAmireddy Mallikarjuna reddy u32 addr; 26732d31c79SAmireddy Mallikarjuna reddy } __packed __aligned(8); 26832d31c79SAmireddy Mallikarjuna reddy 26932d31c79SAmireddy Mallikarjuna reddy struct dw2_desc_sw { 27032d31c79SAmireddy Mallikarjuna reddy struct virt_dma_desc vdesc; 27132d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *chan; 27232d31c79SAmireddy Mallikarjuna reddy dma_addr_t desc_phys; 27332d31c79SAmireddy Mallikarjuna reddy size_t desc_cnt; 27432d31c79SAmireddy Mallikarjuna reddy size_t size; 27532d31c79SAmireddy Mallikarjuna reddy struct dw2_desc *desc_hw; 27632d31c79SAmireddy Mallikarjuna reddy }; 27732d31c79SAmireddy Mallikarjuna reddy 27832d31c79SAmireddy Mallikarjuna reddy static inline void 27932d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(struct ldma_dev *d, u32 mask, u32 val, u32 ofs) 28032d31c79SAmireddy Mallikarjuna reddy { 28132d31c79SAmireddy Mallikarjuna reddy u32 old_val, new_val; 28232d31c79SAmireddy Mallikarjuna reddy 28332d31c79SAmireddy Mallikarjuna reddy old_val = readl(d->base + ofs); 28432d31c79SAmireddy Mallikarjuna reddy new_val = (old_val & ~mask) | (val & mask); 28532d31c79SAmireddy Mallikarjuna reddy 28632d31c79SAmireddy Mallikarjuna reddy if (new_val != old_val) 28732d31c79SAmireddy Mallikarjuna reddy writel(new_val, d->base + ofs); 28832d31c79SAmireddy Mallikarjuna reddy } 28932d31c79SAmireddy Mallikarjuna reddy 29032d31c79SAmireddy Mallikarjuna reddy static inline struct ldma_chan *to_ldma_chan(struct dma_chan *chan) 29132d31c79SAmireddy Mallikarjuna reddy { 29232d31c79SAmireddy Mallikarjuna reddy return container_of(chan, struct ldma_chan, vchan.chan); 29332d31c79SAmireddy Mallikarjuna reddy } 29432d31c79SAmireddy Mallikarjuna reddy 29532d31c79SAmireddy Mallikarjuna reddy static inline struct ldma_dev *to_ldma_dev(struct dma_device *dma_dev) 29632d31c79SAmireddy Mallikarjuna reddy { 29732d31c79SAmireddy Mallikarjuna reddy return container_of(dma_dev, struct ldma_dev, dma_dev); 29832d31c79SAmireddy Mallikarjuna reddy } 29932d31c79SAmireddy Mallikarjuna reddy 30032d31c79SAmireddy Mallikarjuna reddy static inline struct dw2_desc_sw *to_lgm_dma_desc(struct virt_dma_desc *vdesc) 30132d31c79SAmireddy Mallikarjuna reddy { 30232d31c79SAmireddy Mallikarjuna reddy return container_of(vdesc, struct dw2_desc_sw, vdesc); 30332d31c79SAmireddy Mallikarjuna reddy } 30432d31c79SAmireddy Mallikarjuna reddy 30532d31c79SAmireddy Mallikarjuna reddy static inline bool ldma_chan_tx(struct ldma_chan *c) 30632d31c79SAmireddy Mallikarjuna reddy { 30732d31c79SAmireddy Mallikarjuna reddy return !!(c->flags & DMA_TX_CH); 30832d31c79SAmireddy Mallikarjuna reddy } 30932d31c79SAmireddy Mallikarjuna reddy 31032d31c79SAmireddy Mallikarjuna reddy static inline bool ldma_chan_is_hw_desc(struct ldma_chan *c) 31132d31c79SAmireddy Mallikarjuna reddy { 31232d31c79SAmireddy Mallikarjuna reddy return !!(c->flags & DMA_HW_DESC); 31332d31c79SAmireddy Mallikarjuna reddy } 31432d31c79SAmireddy Mallikarjuna reddy 31532d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_reset(struct ldma_dev *d) 31632d31c79SAmireddy Mallikarjuna reddy 31732d31c79SAmireddy Mallikarjuna reddy { 31832d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 31932d31c79SAmireddy Mallikarjuna reddy 32032d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 32132d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CTRL_RST, DMA_CTRL_RST, DMA_CTRL); 32232d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 32332d31c79SAmireddy Mallikarjuna reddy } 32432d31c79SAmireddy Mallikarjuna reddy 32532d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_pkt_arb_cfg(struct ldma_dev *d, bool enable) 32632d31c79SAmireddy Mallikarjuna reddy { 32732d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 32832d31c79SAmireddy Mallikarjuna reddy u32 mask = DMA_CTRL_PKTARB; 32932d31c79SAmireddy Mallikarjuna reddy u32 val = enable ? DMA_CTRL_PKTARB : 0; 33032d31c79SAmireddy Mallikarjuna reddy 33132d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 33232d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CTRL); 33332d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 33432d31c79SAmireddy Mallikarjuna reddy } 33532d31c79SAmireddy Mallikarjuna reddy 33632d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_sram_desc_cfg(struct ldma_dev *d, bool enable) 33732d31c79SAmireddy Mallikarjuna reddy { 33832d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 33932d31c79SAmireddy Mallikarjuna reddy u32 mask = DMA_CTRL_DSRAM_PATH; 34032d31c79SAmireddy Mallikarjuna reddy u32 val = enable ? DMA_CTRL_DSRAM_PATH : 0; 34132d31c79SAmireddy Mallikarjuna reddy 34232d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 34332d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CTRL); 34432d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 34532d31c79SAmireddy Mallikarjuna reddy } 34632d31c79SAmireddy Mallikarjuna reddy 34732d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_chan_flow_ctl_cfg(struct ldma_dev *d, bool enable) 34832d31c79SAmireddy Mallikarjuna reddy { 34932d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 35032d31c79SAmireddy Mallikarjuna reddy u32 mask, val; 35132d31c79SAmireddy Mallikarjuna reddy 35232d31c79SAmireddy Mallikarjuna reddy if (d->inst->type != DMA_TYPE_TX) 35332d31c79SAmireddy Mallikarjuna reddy return; 35432d31c79SAmireddy Mallikarjuna reddy 35532d31c79SAmireddy Mallikarjuna reddy mask = DMA_CTRL_CH_FL; 35632d31c79SAmireddy Mallikarjuna reddy val = enable ? DMA_CTRL_CH_FL : 0; 35732d31c79SAmireddy Mallikarjuna reddy 35832d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 35932d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CTRL); 36032d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 36132d31c79SAmireddy Mallikarjuna reddy } 36232d31c79SAmireddy Mallikarjuna reddy 36332d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_global_polling_enable(struct ldma_dev *d) 36432d31c79SAmireddy Mallikarjuna reddy { 36532d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 36632d31c79SAmireddy Mallikarjuna reddy u32 mask = DMA_CPOLL_EN | DMA_CPOLL_CNT; 36732d31c79SAmireddy Mallikarjuna reddy u32 val = DMA_CPOLL_EN; 36832d31c79SAmireddy Mallikarjuna reddy 36932d31c79SAmireddy Mallikarjuna reddy val |= FIELD_PREP(DMA_CPOLL_CNT, d->pollcnt); 37032d31c79SAmireddy Mallikarjuna reddy 37132d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 37232d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CPOLL); 37332d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 37432d31c79SAmireddy Mallikarjuna reddy } 37532d31c79SAmireddy Mallikarjuna reddy 37632d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_desc_fetch_on_demand_cfg(struct ldma_dev *d, bool enable) 37732d31c79SAmireddy Mallikarjuna reddy { 37832d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 37932d31c79SAmireddy Mallikarjuna reddy u32 mask, val; 38032d31c79SAmireddy Mallikarjuna reddy 38132d31c79SAmireddy Mallikarjuna reddy if (d->inst->type == DMA_TYPE_MCPY) 38232d31c79SAmireddy Mallikarjuna reddy return; 38332d31c79SAmireddy Mallikarjuna reddy 38432d31c79SAmireddy Mallikarjuna reddy mask = DMA_CTRL_DS_FOD; 38532d31c79SAmireddy Mallikarjuna reddy val = enable ? DMA_CTRL_DS_FOD : 0; 38632d31c79SAmireddy Mallikarjuna reddy 38732d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 38832d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CTRL); 38932d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 39032d31c79SAmireddy Mallikarjuna reddy } 39132d31c79SAmireddy Mallikarjuna reddy 39232d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_byte_enable_cfg(struct ldma_dev *d, bool enable) 39332d31c79SAmireddy Mallikarjuna reddy { 39432d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 39532d31c79SAmireddy Mallikarjuna reddy u32 mask = DMA_CTRL_ENBE; 39632d31c79SAmireddy Mallikarjuna reddy u32 val = enable ? DMA_CTRL_ENBE : 0; 39732d31c79SAmireddy Mallikarjuna reddy 39832d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 39932d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CTRL); 40032d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 40132d31c79SAmireddy Mallikarjuna reddy } 40232d31c79SAmireddy Mallikarjuna reddy 40332d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_orrc_cfg(struct ldma_dev *d) 40432d31c79SAmireddy Mallikarjuna reddy { 40532d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 40632d31c79SAmireddy Mallikarjuna reddy u32 val = 0; 40732d31c79SAmireddy Mallikarjuna reddy u32 mask; 40832d31c79SAmireddy Mallikarjuna reddy 40932d31c79SAmireddy Mallikarjuna reddy if (d->inst->type == DMA_TYPE_RX) 41032d31c79SAmireddy Mallikarjuna reddy return; 41132d31c79SAmireddy Mallikarjuna reddy 41232d31c79SAmireddy Mallikarjuna reddy mask = DMA_ORRC_EN | DMA_ORRC_ORRCNT; 41332d31c79SAmireddy Mallikarjuna reddy if (d->inst->orrc > 0 && d->inst->orrc <= DMA_ORRC_MAX_CNT) 41432d31c79SAmireddy Mallikarjuna reddy val = DMA_ORRC_EN | FIELD_PREP(DMA_ORRC_ORRCNT, d->inst->orrc); 41532d31c79SAmireddy Mallikarjuna reddy 41632d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 41732d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_ORRC); 41832d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 41932d31c79SAmireddy Mallikarjuna reddy } 42032d31c79SAmireddy Mallikarjuna reddy 42132d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_df_tout_cfg(struct ldma_dev *d, bool enable, int tcnt) 42232d31c79SAmireddy Mallikarjuna reddy { 42332d31c79SAmireddy Mallikarjuna reddy u32 mask = DMA_CTRL_DESC_TMOUT_CNT_V31; 42432d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 42532d31c79SAmireddy Mallikarjuna reddy u32 val; 42632d31c79SAmireddy Mallikarjuna reddy 42732d31c79SAmireddy Mallikarjuna reddy if (enable) 42832d31c79SAmireddy Mallikarjuna reddy val = DMA_CTRL_DESC_TMOUT_EN_V31 | FIELD_PREP(DMA_CTRL_DESC_TMOUT_CNT_V31, tcnt); 42932d31c79SAmireddy Mallikarjuna reddy else 43032d31c79SAmireddy Mallikarjuna reddy val = 0; 43132d31c79SAmireddy Mallikarjuna reddy 43232d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 43332d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CTRL); 43432d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 43532d31c79SAmireddy Mallikarjuna reddy } 43632d31c79SAmireddy Mallikarjuna reddy 43732d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_dburst_wr_cfg(struct ldma_dev *d, bool enable) 43832d31c79SAmireddy Mallikarjuna reddy { 43932d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 44032d31c79SAmireddy Mallikarjuna reddy u32 mask, val; 44132d31c79SAmireddy Mallikarjuna reddy 44232d31c79SAmireddy Mallikarjuna reddy if (d->inst->type != DMA_TYPE_RX && d->inst->type != DMA_TYPE_MCPY) 44332d31c79SAmireddy Mallikarjuna reddy return; 44432d31c79SAmireddy Mallikarjuna reddy 44532d31c79SAmireddy Mallikarjuna reddy mask = DMA_CTRL_DBURST_WR; 44632d31c79SAmireddy Mallikarjuna reddy val = enable ? DMA_CTRL_DBURST_WR : 0; 44732d31c79SAmireddy Mallikarjuna reddy 44832d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 44932d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CTRL); 45032d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 45132d31c79SAmireddy Mallikarjuna reddy } 45232d31c79SAmireddy Mallikarjuna reddy 45332d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_vld_fetch_ack_cfg(struct ldma_dev *d, bool enable) 45432d31c79SAmireddy Mallikarjuna reddy { 45532d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 45632d31c79SAmireddy Mallikarjuna reddy u32 mask, val; 45732d31c79SAmireddy Mallikarjuna reddy 45832d31c79SAmireddy Mallikarjuna reddy if (d->inst->type != DMA_TYPE_TX) 45932d31c79SAmireddy Mallikarjuna reddy return; 46032d31c79SAmireddy Mallikarjuna reddy 46132d31c79SAmireddy Mallikarjuna reddy mask = DMA_CTRL_VLD_DF_ACK; 46232d31c79SAmireddy Mallikarjuna reddy val = enable ? DMA_CTRL_VLD_DF_ACK : 0; 46332d31c79SAmireddy Mallikarjuna reddy 46432d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 46532d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CTRL); 46632d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 46732d31c79SAmireddy Mallikarjuna reddy } 46832d31c79SAmireddy Mallikarjuna reddy 46932d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_drb_cfg(struct ldma_dev *d, int enable) 47032d31c79SAmireddy Mallikarjuna reddy { 47132d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 47232d31c79SAmireddy Mallikarjuna reddy u32 mask = DMA_CTRL_DRB; 47332d31c79SAmireddy Mallikarjuna reddy u32 val = enable ? DMA_CTRL_DRB : 0; 47432d31c79SAmireddy Mallikarjuna reddy 47532d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 47632d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CTRL); 47732d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 47832d31c79SAmireddy Mallikarjuna reddy } 47932d31c79SAmireddy Mallikarjuna reddy 48032d31c79SAmireddy Mallikarjuna reddy static int ldma_dev_cfg(struct ldma_dev *d) 48132d31c79SAmireddy Mallikarjuna reddy { 48232d31c79SAmireddy Mallikarjuna reddy bool enable; 48332d31c79SAmireddy Mallikarjuna reddy 48432d31c79SAmireddy Mallikarjuna reddy ldma_dev_pkt_arb_cfg(d, true); 48532d31c79SAmireddy Mallikarjuna reddy ldma_dev_global_polling_enable(d); 48632d31c79SAmireddy Mallikarjuna reddy 48732d31c79SAmireddy Mallikarjuna reddy enable = !!(d->flags & DMA_DFT_DRB); 48832d31c79SAmireddy Mallikarjuna reddy ldma_dev_drb_cfg(d, enable); 48932d31c79SAmireddy Mallikarjuna reddy 49032d31c79SAmireddy Mallikarjuna reddy enable = !!(d->flags & DMA_EN_BYTE_EN); 49132d31c79SAmireddy Mallikarjuna reddy ldma_dev_byte_enable_cfg(d, enable); 49232d31c79SAmireddy Mallikarjuna reddy 49332d31c79SAmireddy Mallikarjuna reddy enable = !!(d->flags & DMA_CHAN_FLOW_CTL); 49432d31c79SAmireddy Mallikarjuna reddy ldma_dev_chan_flow_ctl_cfg(d, enable); 49532d31c79SAmireddy Mallikarjuna reddy 49632d31c79SAmireddy Mallikarjuna reddy enable = !!(d->flags & DMA_DESC_FOD); 49732d31c79SAmireddy Mallikarjuna reddy ldma_dev_desc_fetch_on_demand_cfg(d, enable); 49832d31c79SAmireddy Mallikarjuna reddy 49932d31c79SAmireddy Mallikarjuna reddy enable = !!(d->flags & DMA_DESC_IN_SRAM); 50032d31c79SAmireddy Mallikarjuna reddy ldma_dev_sram_desc_cfg(d, enable); 50132d31c79SAmireddy Mallikarjuna reddy 50232d31c79SAmireddy Mallikarjuna reddy enable = !!(d->flags & DMA_DBURST_WR); 50332d31c79SAmireddy Mallikarjuna reddy ldma_dev_dburst_wr_cfg(d, enable); 50432d31c79SAmireddy Mallikarjuna reddy 50532d31c79SAmireddy Mallikarjuna reddy enable = !!(d->flags & DMA_VALID_DESC_FETCH_ACK); 50632d31c79SAmireddy Mallikarjuna reddy ldma_dev_vld_fetch_ack_cfg(d, enable); 50732d31c79SAmireddy Mallikarjuna reddy 50832d31c79SAmireddy Mallikarjuna reddy if (d->ver > DMA_VER22) { 50932d31c79SAmireddy Mallikarjuna reddy ldma_dev_orrc_cfg(d); 51032d31c79SAmireddy Mallikarjuna reddy ldma_dev_df_tout_cfg(d, true, DMA_DFT_DESC_TCNT); 51132d31c79SAmireddy Mallikarjuna reddy } 51232d31c79SAmireddy Mallikarjuna reddy 51332d31c79SAmireddy Mallikarjuna reddy dev_dbg(d->dev, "%s Controller 0x%08x configuration done\n", 51432d31c79SAmireddy Mallikarjuna reddy d->inst->name, readl(d->base + DMA_CTRL)); 51532d31c79SAmireddy Mallikarjuna reddy 51632d31c79SAmireddy Mallikarjuna reddy return 0; 51732d31c79SAmireddy Mallikarjuna reddy } 51832d31c79SAmireddy Mallikarjuna reddy 51932d31c79SAmireddy Mallikarjuna reddy static int ldma_chan_cctrl_cfg(struct ldma_chan *c, u32 val) 52032d31c79SAmireddy Mallikarjuna reddy { 52132d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 52232d31c79SAmireddy Mallikarjuna reddy u32 class_low, class_high; 52332d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 52432d31c79SAmireddy Mallikarjuna reddy u32 reg; 52532d31c79SAmireddy Mallikarjuna reddy 52632d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 52732d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 52832d31c79SAmireddy Mallikarjuna reddy reg = readl(d->base + DMA_CCTRL); 52932d31c79SAmireddy Mallikarjuna reddy /* Read from hardware */ 53032d31c79SAmireddy Mallikarjuna reddy if (reg & DMA_CCTRL_DIR_TX) 53132d31c79SAmireddy Mallikarjuna reddy c->flags |= DMA_TX_CH; 53232d31c79SAmireddy Mallikarjuna reddy else 53332d31c79SAmireddy Mallikarjuna reddy c->flags |= DMA_RX_CH; 53432d31c79SAmireddy Mallikarjuna reddy 53532d31c79SAmireddy Mallikarjuna reddy /* Keep the class value unchanged */ 53632d31c79SAmireddy Mallikarjuna reddy class_low = FIELD_GET(DMA_CCTRL_CLASS, reg); 53732d31c79SAmireddy Mallikarjuna reddy class_high = FIELD_GET(DMA_CCTRL_CLASSH, reg); 53832d31c79SAmireddy Mallikarjuna reddy val &= ~DMA_CCTRL_CLASS; 53932d31c79SAmireddy Mallikarjuna reddy val |= FIELD_PREP(DMA_CCTRL_CLASS, class_low); 54032d31c79SAmireddy Mallikarjuna reddy val &= ~DMA_CCTRL_CLASSH; 54132d31c79SAmireddy Mallikarjuna reddy val |= FIELD_PREP(DMA_CCTRL_CLASSH, class_high); 54232d31c79SAmireddy Mallikarjuna reddy writel(val, d->base + DMA_CCTRL); 54332d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 54432d31c79SAmireddy Mallikarjuna reddy 54532d31c79SAmireddy Mallikarjuna reddy return 0; 54632d31c79SAmireddy Mallikarjuna reddy } 54732d31c79SAmireddy Mallikarjuna reddy 54832d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_irq_init(struct ldma_chan *c) 54932d31c79SAmireddy Mallikarjuna reddy { 55032d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 55132d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 55232d31c79SAmireddy Mallikarjuna reddy u32 enofs, crofs; 55332d31c79SAmireddy Mallikarjuna reddy u32 cn_bit; 55432d31c79SAmireddy Mallikarjuna reddy 55532d31c79SAmireddy Mallikarjuna reddy if (c->nr < MAX_LOWER_CHANS) { 55632d31c79SAmireddy Mallikarjuna reddy enofs = DMA_IRNEN; 55732d31c79SAmireddy Mallikarjuna reddy crofs = DMA_IRNCR; 55832d31c79SAmireddy Mallikarjuna reddy } else { 55932d31c79SAmireddy Mallikarjuna reddy enofs = DMA_IRNEN1; 56032d31c79SAmireddy Mallikarjuna reddy crofs = DMA_IRNCR1; 56132d31c79SAmireddy Mallikarjuna reddy } 56232d31c79SAmireddy Mallikarjuna reddy 56332d31c79SAmireddy Mallikarjuna reddy cn_bit = BIT(c->nr & MASK_LOWER_CHANS); 56432d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 56532d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 56632d31c79SAmireddy Mallikarjuna reddy 56732d31c79SAmireddy Mallikarjuna reddy /* Clear all interrupts and disabled it */ 56832d31c79SAmireddy Mallikarjuna reddy writel(0, d->base + DMA_CIE); 56932d31c79SAmireddy Mallikarjuna reddy writel(DMA_CI_ALL, d->base + DMA_CIS); 57032d31c79SAmireddy Mallikarjuna reddy 57132d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, cn_bit, 0, enofs); 57232d31c79SAmireddy Mallikarjuna reddy writel(cn_bit, d->base + crofs); 57332d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 57432d31c79SAmireddy Mallikarjuna reddy } 57532d31c79SAmireddy Mallikarjuna reddy 57632d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_set_class(struct ldma_chan *c, u32 val) 57732d31c79SAmireddy Mallikarjuna reddy { 57832d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 57932d31c79SAmireddy Mallikarjuna reddy u32 class_val; 58032d31c79SAmireddy Mallikarjuna reddy 58132d31c79SAmireddy Mallikarjuna reddy if (d->inst->type == DMA_TYPE_MCPY || val > DMA_MAX_CLASS) 58232d31c79SAmireddy Mallikarjuna reddy return; 58332d31c79SAmireddy Mallikarjuna reddy 58432d31c79SAmireddy Mallikarjuna reddy /* 3 bits low */ 58532d31c79SAmireddy Mallikarjuna reddy class_val = FIELD_PREP(DMA_CCTRL_CLASS, val & 0x7); 58632d31c79SAmireddy Mallikarjuna reddy /* 2 bits high */ 58732d31c79SAmireddy Mallikarjuna reddy class_val |= FIELD_PREP(DMA_CCTRL_CLASSH, (val >> 3) & 0x3); 58832d31c79SAmireddy Mallikarjuna reddy 58932d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 59032d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CCTRL_CLASS | DMA_CCTRL_CLASSH, class_val, 59132d31c79SAmireddy Mallikarjuna reddy DMA_CCTRL); 59232d31c79SAmireddy Mallikarjuna reddy } 59332d31c79SAmireddy Mallikarjuna reddy 59432d31c79SAmireddy Mallikarjuna reddy static int ldma_chan_on(struct ldma_chan *c) 59532d31c79SAmireddy Mallikarjuna reddy { 59632d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 59732d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 59832d31c79SAmireddy Mallikarjuna reddy 59932d31c79SAmireddy Mallikarjuna reddy /* If descriptors not configured, not allow to turn on channel */ 60032d31c79SAmireddy Mallikarjuna reddy if (WARN_ON(!c->desc_init)) 60132d31c79SAmireddy Mallikarjuna reddy return -EINVAL; 60232d31c79SAmireddy Mallikarjuna reddy 60332d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 60432d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 60532d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CCTRL_ON, DMA_CCTRL_ON, DMA_CCTRL); 60632d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 60732d31c79SAmireddy Mallikarjuna reddy 60832d31c79SAmireddy Mallikarjuna reddy c->onoff = DMA_CH_ON; 60932d31c79SAmireddy Mallikarjuna reddy 61032d31c79SAmireddy Mallikarjuna reddy return 0; 61132d31c79SAmireddy Mallikarjuna reddy } 61232d31c79SAmireddy Mallikarjuna reddy 61332d31c79SAmireddy Mallikarjuna reddy static int ldma_chan_off(struct ldma_chan *c) 61432d31c79SAmireddy Mallikarjuna reddy { 61532d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 61632d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 61732d31c79SAmireddy Mallikarjuna reddy u32 val; 61832d31c79SAmireddy Mallikarjuna reddy int ret; 61932d31c79SAmireddy Mallikarjuna reddy 62032d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 62132d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 62232d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CCTRL_ON, 0, DMA_CCTRL); 62332d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 62432d31c79SAmireddy Mallikarjuna reddy 62532d31c79SAmireddy Mallikarjuna reddy ret = readl_poll_timeout_atomic(d->base + DMA_CCTRL, val, 62632d31c79SAmireddy Mallikarjuna reddy !(val & DMA_CCTRL_ON), 0, 10000); 62732d31c79SAmireddy Mallikarjuna reddy if (ret) 62832d31c79SAmireddy Mallikarjuna reddy return ret; 62932d31c79SAmireddy Mallikarjuna reddy 63032d31c79SAmireddy Mallikarjuna reddy c->onoff = DMA_CH_OFF; 63132d31c79SAmireddy Mallikarjuna reddy 63232d31c79SAmireddy Mallikarjuna reddy return 0; 63332d31c79SAmireddy Mallikarjuna reddy } 63432d31c79SAmireddy Mallikarjuna reddy 63532d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_desc_hw_cfg(struct ldma_chan *c, dma_addr_t desc_base, 63632d31c79SAmireddy Mallikarjuna reddy int desc_num) 63732d31c79SAmireddy Mallikarjuna reddy { 63832d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 63932d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 64032d31c79SAmireddy Mallikarjuna reddy 64132d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 64232d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 64332d31c79SAmireddy Mallikarjuna reddy writel(lower_32_bits(desc_base), d->base + DMA_CDBA); 64432d31c79SAmireddy Mallikarjuna reddy 64532d31c79SAmireddy Mallikarjuna reddy /* Higher 4 bits of 36 bit addressing */ 64632d31c79SAmireddy Mallikarjuna reddy if (IS_ENABLED(CONFIG_64BIT)) { 64732d31c79SAmireddy Mallikarjuna reddy u32 hi = upper_32_bits(desc_base) & HIGH_4_BITS; 64832d31c79SAmireddy Mallikarjuna reddy 64932d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CDBA_MSB, 65032d31c79SAmireddy Mallikarjuna reddy FIELD_PREP(DMA_CDBA_MSB, hi), DMA_CCTRL); 65132d31c79SAmireddy Mallikarjuna reddy } 65232d31c79SAmireddy Mallikarjuna reddy writel(desc_num, d->base + DMA_CDLEN); 65332d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 65432d31c79SAmireddy Mallikarjuna reddy 65532d31c79SAmireddy Mallikarjuna reddy c->desc_init = true; 65632d31c79SAmireddy Mallikarjuna reddy } 65732d31c79SAmireddy Mallikarjuna reddy 65832d31c79SAmireddy Mallikarjuna reddy static struct dma_async_tx_descriptor * 65932d31c79SAmireddy Mallikarjuna reddy ldma_chan_desc_cfg(struct dma_chan *chan, dma_addr_t desc_base, int desc_num) 66032d31c79SAmireddy Mallikarjuna reddy { 66132d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 66232d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 66332d31c79SAmireddy Mallikarjuna reddy struct dma_async_tx_descriptor *tx; 66432d31c79SAmireddy Mallikarjuna reddy struct dw2_desc_sw *ds; 66532d31c79SAmireddy Mallikarjuna reddy 66632d31c79SAmireddy Mallikarjuna reddy if (!desc_num) { 66732d31c79SAmireddy Mallikarjuna reddy dev_err(d->dev, "Channel %d must allocate descriptor first\n", 66832d31c79SAmireddy Mallikarjuna reddy c->nr); 66932d31c79SAmireddy Mallikarjuna reddy return NULL; 67032d31c79SAmireddy Mallikarjuna reddy } 67132d31c79SAmireddy Mallikarjuna reddy 67232d31c79SAmireddy Mallikarjuna reddy if (desc_num > DMA_MAX_DESC_NUM) { 67332d31c79SAmireddy Mallikarjuna reddy dev_err(d->dev, "Channel %d descriptor number out of range %d\n", 67432d31c79SAmireddy Mallikarjuna reddy c->nr, desc_num); 67532d31c79SAmireddy Mallikarjuna reddy return NULL; 67632d31c79SAmireddy Mallikarjuna reddy } 67732d31c79SAmireddy Mallikarjuna reddy 67832d31c79SAmireddy Mallikarjuna reddy ldma_chan_desc_hw_cfg(c, desc_base, desc_num); 67932d31c79SAmireddy Mallikarjuna reddy 68032d31c79SAmireddy Mallikarjuna reddy c->flags |= DMA_HW_DESC; 68132d31c79SAmireddy Mallikarjuna reddy c->desc_cnt = desc_num; 68232d31c79SAmireddy Mallikarjuna reddy c->desc_phys = desc_base; 68332d31c79SAmireddy Mallikarjuna reddy 68432d31c79SAmireddy Mallikarjuna reddy ds = kzalloc(sizeof(*ds), GFP_NOWAIT); 68532d31c79SAmireddy Mallikarjuna reddy if (!ds) 68632d31c79SAmireddy Mallikarjuna reddy return NULL; 68732d31c79SAmireddy Mallikarjuna reddy 68832d31c79SAmireddy Mallikarjuna reddy tx = &ds->vdesc.tx; 68932d31c79SAmireddy Mallikarjuna reddy dma_async_tx_descriptor_init(tx, chan); 69032d31c79SAmireddy Mallikarjuna reddy 69132d31c79SAmireddy Mallikarjuna reddy return tx; 69232d31c79SAmireddy Mallikarjuna reddy } 69332d31c79SAmireddy Mallikarjuna reddy 69432d31c79SAmireddy Mallikarjuna reddy static int ldma_chan_reset(struct ldma_chan *c) 69532d31c79SAmireddy Mallikarjuna reddy { 69632d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 69732d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 69832d31c79SAmireddy Mallikarjuna reddy u32 val; 69932d31c79SAmireddy Mallikarjuna reddy int ret; 70032d31c79SAmireddy Mallikarjuna reddy 70132d31c79SAmireddy Mallikarjuna reddy ret = ldma_chan_off(c); 70232d31c79SAmireddy Mallikarjuna reddy if (ret) 70332d31c79SAmireddy Mallikarjuna reddy return ret; 70432d31c79SAmireddy Mallikarjuna reddy 70532d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 70632d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 70732d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CCTRL_RST, DMA_CCTRL_RST, DMA_CCTRL); 70832d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 70932d31c79SAmireddy Mallikarjuna reddy 71032d31c79SAmireddy Mallikarjuna reddy ret = readl_poll_timeout_atomic(d->base + DMA_CCTRL, val, 71132d31c79SAmireddy Mallikarjuna reddy !(val & DMA_CCTRL_RST), 0, 10000); 71232d31c79SAmireddy Mallikarjuna reddy if (ret) 71332d31c79SAmireddy Mallikarjuna reddy return ret; 71432d31c79SAmireddy Mallikarjuna reddy 71532d31c79SAmireddy Mallikarjuna reddy c->rst = 1; 71632d31c79SAmireddy Mallikarjuna reddy c->desc_init = false; 71732d31c79SAmireddy Mallikarjuna reddy 71832d31c79SAmireddy Mallikarjuna reddy return 0; 71932d31c79SAmireddy Mallikarjuna reddy } 72032d31c79SAmireddy Mallikarjuna reddy 72132d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_byte_offset_cfg(struct ldma_chan *c, u32 boff_len) 72232d31c79SAmireddy Mallikarjuna reddy { 72332d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 72432d31c79SAmireddy Mallikarjuna reddy u32 mask = DMA_C_BOFF_EN | DMA_C_BOFF_BOF_LEN; 72532d31c79SAmireddy Mallikarjuna reddy u32 val; 72632d31c79SAmireddy Mallikarjuna reddy 72732d31c79SAmireddy Mallikarjuna reddy if (boff_len > 0 && boff_len <= DMA_CHAN_BOFF_MAX) 72832d31c79SAmireddy Mallikarjuna reddy val = FIELD_PREP(DMA_C_BOFF_BOF_LEN, boff_len) | DMA_C_BOFF_EN; 72932d31c79SAmireddy Mallikarjuna reddy else 73032d31c79SAmireddy Mallikarjuna reddy val = 0; 73132d31c79SAmireddy Mallikarjuna reddy 73232d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 73332d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_C_BOFF); 73432d31c79SAmireddy Mallikarjuna reddy } 73532d31c79SAmireddy Mallikarjuna reddy 73632d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_data_endian_cfg(struct ldma_chan *c, bool enable, 73732d31c79SAmireddy Mallikarjuna reddy u32 endian_type) 73832d31c79SAmireddy Mallikarjuna reddy { 73932d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 74032d31c79SAmireddy Mallikarjuna reddy u32 mask = DMA_C_END_DE_EN | DMA_C_END_DATAENDI; 74132d31c79SAmireddy Mallikarjuna reddy u32 val; 74232d31c79SAmireddy Mallikarjuna reddy 74332d31c79SAmireddy Mallikarjuna reddy if (enable) 74432d31c79SAmireddy Mallikarjuna reddy val = DMA_C_END_DE_EN | FIELD_PREP(DMA_C_END_DATAENDI, endian_type); 74532d31c79SAmireddy Mallikarjuna reddy else 74632d31c79SAmireddy Mallikarjuna reddy val = 0; 74732d31c79SAmireddy Mallikarjuna reddy 74832d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 74932d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_C_ENDIAN); 75032d31c79SAmireddy Mallikarjuna reddy } 75132d31c79SAmireddy Mallikarjuna reddy 75232d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_desc_endian_cfg(struct ldma_chan *c, bool enable, 75332d31c79SAmireddy Mallikarjuna reddy u32 endian_type) 75432d31c79SAmireddy Mallikarjuna reddy { 75532d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 75632d31c79SAmireddy Mallikarjuna reddy u32 mask = DMA_C_END_DES_EN | DMA_C_END_DESENDI; 75732d31c79SAmireddy Mallikarjuna reddy u32 val; 75832d31c79SAmireddy Mallikarjuna reddy 75932d31c79SAmireddy Mallikarjuna reddy if (enable) 76032d31c79SAmireddy Mallikarjuna reddy val = DMA_C_END_DES_EN | FIELD_PREP(DMA_C_END_DESENDI, endian_type); 76132d31c79SAmireddy Mallikarjuna reddy else 76232d31c79SAmireddy Mallikarjuna reddy val = 0; 76332d31c79SAmireddy Mallikarjuna reddy 76432d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 76532d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_C_ENDIAN); 76632d31c79SAmireddy Mallikarjuna reddy } 76732d31c79SAmireddy Mallikarjuna reddy 76832d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_hdr_mode_cfg(struct ldma_chan *c, u32 hdr_len, bool csum) 76932d31c79SAmireddy Mallikarjuna reddy { 77032d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 77132d31c79SAmireddy Mallikarjuna reddy u32 mask, val; 77232d31c79SAmireddy Mallikarjuna reddy 77332d31c79SAmireddy Mallikarjuna reddy /* NB, csum disabled, hdr length must be provided */ 77432d31c79SAmireddy Mallikarjuna reddy if (!csum && (!hdr_len || hdr_len > DMA_HDR_LEN_MAX)) 77532d31c79SAmireddy Mallikarjuna reddy return; 77632d31c79SAmireddy Mallikarjuna reddy 77732d31c79SAmireddy Mallikarjuna reddy mask = DMA_C_HDRM_HDR_SUM; 77832d31c79SAmireddy Mallikarjuna reddy val = DMA_C_HDRM_HDR_SUM; 77932d31c79SAmireddy Mallikarjuna reddy 78032d31c79SAmireddy Mallikarjuna reddy if (!csum && hdr_len) 78132d31c79SAmireddy Mallikarjuna reddy val = hdr_len; 78232d31c79SAmireddy Mallikarjuna reddy 78332d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 78432d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_C_HDRM); 78532d31c79SAmireddy Mallikarjuna reddy } 78632d31c79SAmireddy Mallikarjuna reddy 78732d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_rxwr_np_cfg(struct ldma_chan *c, bool enable) 78832d31c79SAmireddy Mallikarjuna reddy { 78932d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 79032d31c79SAmireddy Mallikarjuna reddy u32 mask, val; 79132d31c79SAmireddy Mallikarjuna reddy 79232d31c79SAmireddy Mallikarjuna reddy /* Only valid for RX channel */ 79332d31c79SAmireddy Mallikarjuna reddy if (ldma_chan_tx(c)) 79432d31c79SAmireddy Mallikarjuna reddy return; 79532d31c79SAmireddy Mallikarjuna reddy 79632d31c79SAmireddy Mallikarjuna reddy mask = DMA_CCTRL_WR_NP_EN; 79732d31c79SAmireddy Mallikarjuna reddy val = enable ? DMA_CCTRL_WR_NP_EN : 0; 79832d31c79SAmireddy Mallikarjuna reddy 79932d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 80032d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CCTRL); 80132d31c79SAmireddy Mallikarjuna reddy } 80232d31c79SAmireddy Mallikarjuna reddy 80332d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_abc_cfg(struct ldma_chan *c, bool enable) 80432d31c79SAmireddy Mallikarjuna reddy { 80532d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 80632d31c79SAmireddy Mallikarjuna reddy u32 mask, val; 80732d31c79SAmireddy Mallikarjuna reddy 80832d31c79SAmireddy Mallikarjuna reddy if (d->ver < DMA_VER32 || ldma_chan_tx(c)) 80932d31c79SAmireddy Mallikarjuna reddy return; 81032d31c79SAmireddy Mallikarjuna reddy 81132d31c79SAmireddy Mallikarjuna reddy mask = DMA_CCTRL_CH_ABC; 81232d31c79SAmireddy Mallikarjuna reddy val = enable ? DMA_CCTRL_CH_ABC : 0; 81332d31c79SAmireddy Mallikarjuna reddy 81432d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, DMA_CS_MASK, c->nr, DMA_CS); 81532d31c79SAmireddy Mallikarjuna reddy ldma_update_bits(d, mask, val, DMA_CCTRL); 81632d31c79SAmireddy Mallikarjuna reddy } 81732d31c79SAmireddy Mallikarjuna reddy 81832d31c79SAmireddy Mallikarjuna reddy static int ldma_port_cfg(struct ldma_port *p) 81932d31c79SAmireddy Mallikarjuna reddy { 82032d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 82132d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d; 82232d31c79SAmireddy Mallikarjuna reddy u32 reg; 82332d31c79SAmireddy Mallikarjuna reddy 82432d31c79SAmireddy Mallikarjuna reddy d = p->ldev; 82532d31c79SAmireddy Mallikarjuna reddy reg = FIELD_PREP(DMA_PCTRL_TXENDI, p->txendi); 82632d31c79SAmireddy Mallikarjuna reddy reg |= FIELD_PREP(DMA_PCTRL_RXENDI, p->rxendi); 82732d31c79SAmireddy Mallikarjuna reddy 82832d31c79SAmireddy Mallikarjuna reddy if (d->ver == DMA_VER22) { 82932d31c79SAmireddy Mallikarjuna reddy reg |= FIELD_PREP(DMA_PCTRL_TXBL, p->txbl); 83032d31c79SAmireddy Mallikarjuna reddy reg |= FIELD_PREP(DMA_PCTRL_RXBL, p->rxbl); 83132d31c79SAmireddy Mallikarjuna reddy } else { 83232d31c79SAmireddy Mallikarjuna reddy reg |= FIELD_PREP(DMA_PCTRL_PDEN, p->pkt_drop); 83332d31c79SAmireddy Mallikarjuna reddy 83432d31c79SAmireddy Mallikarjuna reddy if (p->txbl == DMA_BURSTL_32DW) 83532d31c79SAmireddy Mallikarjuna reddy reg |= DMA_PCTRL_TXBL32; 83632d31c79SAmireddy Mallikarjuna reddy else if (p->txbl == DMA_BURSTL_16DW) 83732d31c79SAmireddy Mallikarjuna reddy reg |= DMA_PCTRL_TXBL16; 83832d31c79SAmireddy Mallikarjuna reddy else 83932d31c79SAmireddy Mallikarjuna reddy reg |= FIELD_PREP(DMA_PCTRL_TXBL, DMA_PCTRL_TXBL_8); 84032d31c79SAmireddy Mallikarjuna reddy 84132d31c79SAmireddy Mallikarjuna reddy if (p->rxbl == DMA_BURSTL_32DW) 84232d31c79SAmireddy Mallikarjuna reddy reg |= DMA_PCTRL_RXBL32; 84332d31c79SAmireddy Mallikarjuna reddy else if (p->rxbl == DMA_BURSTL_16DW) 84432d31c79SAmireddy Mallikarjuna reddy reg |= DMA_PCTRL_RXBL16; 84532d31c79SAmireddy Mallikarjuna reddy else 84632d31c79SAmireddy Mallikarjuna reddy reg |= FIELD_PREP(DMA_PCTRL_RXBL, DMA_PCTRL_RXBL_8); 84732d31c79SAmireddy Mallikarjuna reddy } 84832d31c79SAmireddy Mallikarjuna reddy 84932d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 85032d31c79SAmireddy Mallikarjuna reddy writel(p->portid, d->base + DMA_PS); 85132d31c79SAmireddy Mallikarjuna reddy writel(reg, d->base + DMA_PCTRL); 85232d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 85332d31c79SAmireddy Mallikarjuna reddy 85432d31c79SAmireddy Mallikarjuna reddy reg = readl(d->base + DMA_PCTRL); /* read back */ 85532d31c79SAmireddy Mallikarjuna reddy dev_dbg(d->dev, "Port Control 0x%08x configuration done\n", reg); 85632d31c79SAmireddy Mallikarjuna reddy 85732d31c79SAmireddy Mallikarjuna reddy return 0; 85832d31c79SAmireddy Mallikarjuna reddy } 85932d31c79SAmireddy Mallikarjuna reddy 86032d31c79SAmireddy Mallikarjuna reddy static int ldma_chan_cfg(struct ldma_chan *c) 86132d31c79SAmireddy Mallikarjuna reddy { 86232d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 86332d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 86432d31c79SAmireddy Mallikarjuna reddy u32 reg; 86532d31c79SAmireddy Mallikarjuna reddy 86632d31c79SAmireddy Mallikarjuna reddy reg = c->pden ? DMA_CCTRL_PDEN : 0; 86732d31c79SAmireddy Mallikarjuna reddy reg |= c->onoff ? DMA_CCTRL_ON : 0; 86832d31c79SAmireddy Mallikarjuna reddy reg |= c->rst ? DMA_CCTRL_RST : 0; 86932d31c79SAmireddy Mallikarjuna reddy 87032d31c79SAmireddy Mallikarjuna reddy ldma_chan_cctrl_cfg(c, reg); 87132d31c79SAmireddy Mallikarjuna reddy ldma_chan_irq_init(c); 87232d31c79SAmireddy Mallikarjuna reddy 87332d31c79SAmireddy Mallikarjuna reddy if (d->ver <= DMA_VER22) 87432d31c79SAmireddy Mallikarjuna reddy return 0; 87532d31c79SAmireddy Mallikarjuna reddy 87632d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 87732d31c79SAmireddy Mallikarjuna reddy ldma_chan_set_class(c, c->nr); 87832d31c79SAmireddy Mallikarjuna reddy ldma_chan_byte_offset_cfg(c, c->boff_len); 87932d31c79SAmireddy Mallikarjuna reddy ldma_chan_data_endian_cfg(c, c->data_endian_en, c->data_endian); 88032d31c79SAmireddy Mallikarjuna reddy ldma_chan_desc_endian_cfg(c, c->desc_endian_en, c->desc_endian); 88132d31c79SAmireddy Mallikarjuna reddy ldma_chan_hdr_mode_cfg(c, c->hdrm_len, c->hdrm_csum); 88232d31c79SAmireddy Mallikarjuna reddy ldma_chan_rxwr_np_cfg(c, c->desc_rx_np); 88332d31c79SAmireddy Mallikarjuna reddy ldma_chan_abc_cfg(c, c->abc_en); 88432d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 88532d31c79SAmireddy Mallikarjuna reddy 88632d31c79SAmireddy Mallikarjuna reddy if (ldma_chan_is_hw_desc(c)) 88732d31c79SAmireddy Mallikarjuna reddy ldma_chan_desc_hw_cfg(c, c->desc_phys, c->desc_cnt); 88832d31c79SAmireddy Mallikarjuna reddy 88932d31c79SAmireddy Mallikarjuna reddy return 0; 89032d31c79SAmireddy Mallikarjuna reddy } 89132d31c79SAmireddy Mallikarjuna reddy 89232d31c79SAmireddy Mallikarjuna reddy static void ldma_dev_init(struct ldma_dev *d) 89332d31c79SAmireddy Mallikarjuna reddy { 89432d31c79SAmireddy Mallikarjuna reddy unsigned long ch_mask = (unsigned long)d->channels_mask; 89532d31c79SAmireddy Mallikarjuna reddy struct ldma_port *p; 89632d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c; 89732d31c79SAmireddy Mallikarjuna reddy int i; 89832d31c79SAmireddy Mallikarjuna reddy u32 j; 89932d31c79SAmireddy Mallikarjuna reddy 90032d31c79SAmireddy Mallikarjuna reddy spin_lock_init(&d->dev_lock); 90132d31c79SAmireddy Mallikarjuna reddy ldma_dev_reset(d); 90232d31c79SAmireddy Mallikarjuna reddy ldma_dev_cfg(d); 90332d31c79SAmireddy Mallikarjuna reddy 90432d31c79SAmireddy Mallikarjuna reddy /* DMA port initialization */ 90532d31c79SAmireddy Mallikarjuna reddy for (i = 0; i < d->port_nrs; i++) { 90632d31c79SAmireddy Mallikarjuna reddy p = &d->ports[i]; 90732d31c79SAmireddy Mallikarjuna reddy ldma_port_cfg(p); 90832d31c79SAmireddy Mallikarjuna reddy } 90932d31c79SAmireddy Mallikarjuna reddy 91032d31c79SAmireddy Mallikarjuna reddy /* DMA channel initialization */ 91132d31c79SAmireddy Mallikarjuna reddy for_each_set_bit(j, &ch_mask, d->chan_nrs) { 91232d31c79SAmireddy Mallikarjuna reddy c = &d->chans[j]; 91332d31c79SAmireddy Mallikarjuna reddy ldma_chan_cfg(c); 91432d31c79SAmireddy Mallikarjuna reddy } 91532d31c79SAmireddy Mallikarjuna reddy } 91632d31c79SAmireddy Mallikarjuna reddy 91732d31c79SAmireddy Mallikarjuna reddy static int ldma_cfg_init(struct ldma_dev *d) 91832d31c79SAmireddy Mallikarjuna reddy { 91932d31c79SAmireddy Mallikarjuna reddy struct fwnode_handle *fwnode = dev_fwnode(d->dev); 92032d31c79SAmireddy Mallikarjuna reddy struct ldma_port *p; 92132d31c79SAmireddy Mallikarjuna reddy int i; 92232d31c79SAmireddy Mallikarjuna reddy 92332d31c79SAmireddy Mallikarjuna reddy if (fwnode_property_read_bool(fwnode, "intel,dma-byte-en")) 92432d31c79SAmireddy Mallikarjuna reddy d->flags |= DMA_EN_BYTE_EN; 92532d31c79SAmireddy Mallikarjuna reddy 92632d31c79SAmireddy Mallikarjuna reddy if (fwnode_property_read_bool(fwnode, "intel,dma-dburst-wr")) 92732d31c79SAmireddy Mallikarjuna reddy d->flags |= DMA_DBURST_WR; 92832d31c79SAmireddy Mallikarjuna reddy 92932d31c79SAmireddy Mallikarjuna reddy if (fwnode_property_read_bool(fwnode, "intel,dma-drb")) 93032d31c79SAmireddy Mallikarjuna reddy d->flags |= DMA_DFT_DRB; 93132d31c79SAmireddy Mallikarjuna reddy 93232d31c79SAmireddy Mallikarjuna reddy if (fwnode_property_read_u32(fwnode, "intel,dma-poll-cnt", 93332d31c79SAmireddy Mallikarjuna reddy &d->pollcnt)) 93432d31c79SAmireddy Mallikarjuna reddy d->pollcnt = DMA_DFT_POLL_CNT; 93532d31c79SAmireddy Mallikarjuna reddy 93632d31c79SAmireddy Mallikarjuna reddy if (d->inst->chan_fc) 93732d31c79SAmireddy Mallikarjuna reddy d->flags |= DMA_CHAN_FLOW_CTL; 93832d31c79SAmireddy Mallikarjuna reddy 93932d31c79SAmireddy Mallikarjuna reddy if (d->inst->desc_fod) 94032d31c79SAmireddy Mallikarjuna reddy d->flags |= DMA_DESC_FOD; 94132d31c79SAmireddy Mallikarjuna reddy 94232d31c79SAmireddy Mallikarjuna reddy if (d->inst->desc_in_sram) 94332d31c79SAmireddy Mallikarjuna reddy d->flags |= DMA_DESC_IN_SRAM; 94432d31c79SAmireddy Mallikarjuna reddy 94532d31c79SAmireddy Mallikarjuna reddy if (d->inst->valid_desc_fetch_ack) 94632d31c79SAmireddy Mallikarjuna reddy d->flags |= DMA_VALID_DESC_FETCH_ACK; 94732d31c79SAmireddy Mallikarjuna reddy 94832d31c79SAmireddy Mallikarjuna reddy if (d->ver > DMA_VER22) { 94932d31c79SAmireddy Mallikarjuna reddy if (!d->port_nrs) 95032d31c79SAmireddy Mallikarjuna reddy return -EINVAL; 95132d31c79SAmireddy Mallikarjuna reddy 95232d31c79SAmireddy Mallikarjuna reddy for (i = 0; i < d->port_nrs; i++) { 95332d31c79SAmireddy Mallikarjuna reddy p = &d->ports[i]; 95432d31c79SAmireddy Mallikarjuna reddy p->rxendi = DMA_DFT_ENDIAN; 95532d31c79SAmireddy Mallikarjuna reddy p->txendi = DMA_DFT_ENDIAN; 95632d31c79SAmireddy Mallikarjuna reddy p->rxbl = DMA_DFT_BURST; 95732d31c79SAmireddy Mallikarjuna reddy p->txbl = DMA_DFT_BURST; 95832d31c79SAmireddy Mallikarjuna reddy p->pkt_drop = DMA_PKT_DROP_DIS; 95932d31c79SAmireddy Mallikarjuna reddy } 96032d31c79SAmireddy Mallikarjuna reddy } 96132d31c79SAmireddy Mallikarjuna reddy 96232d31c79SAmireddy Mallikarjuna reddy return 0; 96332d31c79SAmireddy Mallikarjuna reddy } 96432d31c79SAmireddy Mallikarjuna reddy 96532d31c79SAmireddy Mallikarjuna reddy static void dma_free_desc_resource(struct virt_dma_desc *vdesc) 96632d31c79SAmireddy Mallikarjuna reddy { 96732d31c79SAmireddy Mallikarjuna reddy struct dw2_desc_sw *ds = to_lgm_dma_desc(vdesc); 96832d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = ds->chan; 96932d31c79SAmireddy Mallikarjuna reddy 97032d31c79SAmireddy Mallikarjuna reddy dma_pool_free(c->desc_pool, ds->desc_hw, ds->desc_phys); 97132d31c79SAmireddy Mallikarjuna reddy kfree(ds); 97232d31c79SAmireddy Mallikarjuna reddy } 97332d31c79SAmireddy Mallikarjuna reddy 97432d31c79SAmireddy Mallikarjuna reddy static struct dw2_desc_sw * 97532d31c79SAmireddy Mallikarjuna reddy dma_alloc_desc_resource(int num, struct ldma_chan *c) 97632d31c79SAmireddy Mallikarjuna reddy { 97732d31c79SAmireddy Mallikarjuna reddy struct device *dev = c->vchan.chan.device->dev; 97832d31c79SAmireddy Mallikarjuna reddy struct dw2_desc_sw *ds; 97932d31c79SAmireddy Mallikarjuna reddy 98032d31c79SAmireddy Mallikarjuna reddy if (num > c->desc_num) { 98132d31c79SAmireddy Mallikarjuna reddy dev_err(dev, "sg num %d exceed max %d\n", num, c->desc_num); 98232d31c79SAmireddy Mallikarjuna reddy return NULL; 98332d31c79SAmireddy Mallikarjuna reddy } 98432d31c79SAmireddy Mallikarjuna reddy 98532d31c79SAmireddy Mallikarjuna reddy ds = kzalloc(sizeof(*ds), GFP_NOWAIT); 98632d31c79SAmireddy Mallikarjuna reddy if (!ds) 98732d31c79SAmireddy Mallikarjuna reddy return NULL; 98832d31c79SAmireddy Mallikarjuna reddy 98932d31c79SAmireddy Mallikarjuna reddy ds->chan = c; 99032d31c79SAmireddy Mallikarjuna reddy ds->desc_hw = dma_pool_zalloc(c->desc_pool, GFP_ATOMIC, 99132d31c79SAmireddy Mallikarjuna reddy &ds->desc_phys); 99232d31c79SAmireddy Mallikarjuna reddy if (!ds->desc_hw) { 99332d31c79SAmireddy Mallikarjuna reddy dev_dbg(dev, "out of memory for link descriptor\n"); 99432d31c79SAmireddy Mallikarjuna reddy kfree(ds); 99532d31c79SAmireddy Mallikarjuna reddy return NULL; 99632d31c79SAmireddy Mallikarjuna reddy } 99732d31c79SAmireddy Mallikarjuna reddy ds->desc_cnt = num; 99832d31c79SAmireddy Mallikarjuna reddy 99932d31c79SAmireddy Mallikarjuna reddy return ds; 100032d31c79SAmireddy Mallikarjuna reddy } 100132d31c79SAmireddy Mallikarjuna reddy 100232d31c79SAmireddy Mallikarjuna reddy static void ldma_chan_irq_en(struct ldma_chan *c) 100332d31c79SAmireddy Mallikarjuna reddy { 100432d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 100532d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 100632d31c79SAmireddy Mallikarjuna reddy 100732d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&d->dev_lock, flags); 100832d31c79SAmireddy Mallikarjuna reddy writel(c->nr, d->base + DMA_CS); 100932d31c79SAmireddy Mallikarjuna reddy writel(DMA_CI_EOP, d->base + DMA_CIE); 101032d31c79SAmireddy Mallikarjuna reddy writel(BIT(c->nr), d->base + DMA_IRNEN); 101132d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&d->dev_lock, flags); 101232d31c79SAmireddy Mallikarjuna reddy } 101332d31c79SAmireddy Mallikarjuna reddy 101432d31c79SAmireddy Mallikarjuna reddy static void ldma_issue_pending(struct dma_chan *chan) 101532d31c79SAmireddy Mallikarjuna reddy { 101632d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 101732d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 101832d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 101932d31c79SAmireddy Mallikarjuna reddy 102032d31c79SAmireddy Mallikarjuna reddy if (d->ver == DMA_VER22) { 102132d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&c->vchan.lock, flags); 102232d31c79SAmireddy Mallikarjuna reddy if (vchan_issue_pending(&c->vchan)) { 102332d31c79SAmireddy Mallikarjuna reddy struct virt_dma_desc *vdesc; 102432d31c79SAmireddy Mallikarjuna reddy 102532d31c79SAmireddy Mallikarjuna reddy /* Get the next descriptor */ 102632d31c79SAmireddy Mallikarjuna reddy vdesc = vchan_next_desc(&c->vchan); 102732d31c79SAmireddy Mallikarjuna reddy if (!vdesc) { 102832d31c79SAmireddy Mallikarjuna reddy c->ds = NULL; 102932d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&c->vchan.lock, flags); 103032d31c79SAmireddy Mallikarjuna reddy return; 103132d31c79SAmireddy Mallikarjuna reddy } 103232d31c79SAmireddy Mallikarjuna reddy list_del(&vdesc->node); 103332d31c79SAmireddy Mallikarjuna reddy c->ds = to_lgm_dma_desc(vdesc); 103432d31c79SAmireddy Mallikarjuna reddy ldma_chan_desc_hw_cfg(c, c->ds->desc_phys, c->ds->desc_cnt); 103532d31c79SAmireddy Mallikarjuna reddy ldma_chan_irq_en(c); 103632d31c79SAmireddy Mallikarjuna reddy } 103732d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&c->vchan.lock, flags); 103832d31c79SAmireddy Mallikarjuna reddy } 103932d31c79SAmireddy Mallikarjuna reddy ldma_chan_on(c); 104032d31c79SAmireddy Mallikarjuna reddy } 104132d31c79SAmireddy Mallikarjuna reddy 104232d31c79SAmireddy Mallikarjuna reddy static void ldma_synchronize(struct dma_chan *chan) 104332d31c79SAmireddy Mallikarjuna reddy { 104432d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 104532d31c79SAmireddy Mallikarjuna reddy 104632d31c79SAmireddy Mallikarjuna reddy /* 104732d31c79SAmireddy Mallikarjuna reddy * clear any pending work if any. In that 104832d31c79SAmireddy Mallikarjuna reddy * case the resource needs to be free here. 104932d31c79SAmireddy Mallikarjuna reddy */ 105032d31c79SAmireddy Mallikarjuna reddy cancel_work_sync(&c->work); 105132d31c79SAmireddy Mallikarjuna reddy vchan_synchronize(&c->vchan); 105232d31c79SAmireddy Mallikarjuna reddy if (c->ds) 105332d31c79SAmireddy Mallikarjuna reddy dma_free_desc_resource(&c->ds->vdesc); 105432d31c79SAmireddy Mallikarjuna reddy } 105532d31c79SAmireddy Mallikarjuna reddy 105632d31c79SAmireddy Mallikarjuna reddy static int ldma_terminate_all(struct dma_chan *chan) 105732d31c79SAmireddy Mallikarjuna reddy { 105832d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 105932d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 106032d31c79SAmireddy Mallikarjuna reddy LIST_HEAD(head); 106132d31c79SAmireddy Mallikarjuna reddy 106232d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&c->vchan.lock, flags); 106332d31c79SAmireddy Mallikarjuna reddy vchan_get_all_descriptors(&c->vchan, &head); 106432d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&c->vchan.lock, flags); 106532d31c79SAmireddy Mallikarjuna reddy vchan_dma_desc_free_list(&c->vchan, &head); 106632d31c79SAmireddy Mallikarjuna reddy 106732d31c79SAmireddy Mallikarjuna reddy return ldma_chan_reset(c); 106832d31c79SAmireddy Mallikarjuna reddy } 106932d31c79SAmireddy Mallikarjuna reddy 107032d31c79SAmireddy Mallikarjuna reddy static int ldma_resume_chan(struct dma_chan *chan) 107132d31c79SAmireddy Mallikarjuna reddy { 107232d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 107332d31c79SAmireddy Mallikarjuna reddy 107432d31c79SAmireddy Mallikarjuna reddy ldma_chan_on(c); 107532d31c79SAmireddy Mallikarjuna reddy 107632d31c79SAmireddy Mallikarjuna reddy return 0; 107732d31c79SAmireddy Mallikarjuna reddy } 107832d31c79SAmireddy Mallikarjuna reddy 107932d31c79SAmireddy Mallikarjuna reddy static int ldma_pause_chan(struct dma_chan *chan) 108032d31c79SAmireddy Mallikarjuna reddy { 108132d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 108232d31c79SAmireddy Mallikarjuna reddy 108332d31c79SAmireddy Mallikarjuna reddy return ldma_chan_off(c); 108432d31c79SAmireddy Mallikarjuna reddy } 108532d31c79SAmireddy Mallikarjuna reddy 108632d31c79SAmireddy Mallikarjuna reddy static enum dma_status 108732d31c79SAmireddy Mallikarjuna reddy ldma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, 108832d31c79SAmireddy Mallikarjuna reddy struct dma_tx_state *txstate) 108932d31c79SAmireddy Mallikarjuna reddy { 109032d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 109132d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 109232d31c79SAmireddy Mallikarjuna reddy enum dma_status status = DMA_COMPLETE; 109332d31c79SAmireddy Mallikarjuna reddy 109432d31c79SAmireddy Mallikarjuna reddy if (d->ver == DMA_VER22) 109532d31c79SAmireddy Mallikarjuna reddy status = dma_cookie_status(chan, cookie, txstate); 109632d31c79SAmireddy Mallikarjuna reddy 109732d31c79SAmireddy Mallikarjuna reddy return status; 109832d31c79SAmireddy Mallikarjuna reddy } 109932d31c79SAmireddy Mallikarjuna reddy 110032d31c79SAmireddy Mallikarjuna reddy static void dma_chan_irq(int irq, void *data) 110132d31c79SAmireddy Mallikarjuna reddy { 110232d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = data; 110332d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 110432d31c79SAmireddy Mallikarjuna reddy u32 stat; 110532d31c79SAmireddy Mallikarjuna reddy 110632d31c79SAmireddy Mallikarjuna reddy /* Disable channel interrupts */ 110732d31c79SAmireddy Mallikarjuna reddy writel(c->nr, d->base + DMA_CS); 110832d31c79SAmireddy Mallikarjuna reddy stat = readl(d->base + DMA_CIS); 110932d31c79SAmireddy Mallikarjuna reddy if (!stat) 111032d31c79SAmireddy Mallikarjuna reddy return; 111132d31c79SAmireddy Mallikarjuna reddy 111232d31c79SAmireddy Mallikarjuna reddy writel(readl(d->base + DMA_CIE) & ~DMA_CI_ALL, d->base + DMA_CIE); 111332d31c79SAmireddy Mallikarjuna reddy writel(stat, d->base + DMA_CIS); 111432d31c79SAmireddy Mallikarjuna reddy queue_work(d->wq, &c->work); 111532d31c79SAmireddy Mallikarjuna reddy } 111632d31c79SAmireddy Mallikarjuna reddy 111732d31c79SAmireddy Mallikarjuna reddy static irqreturn_t dma_interrupt(int irq, void *dev_id) 111832d31c79SAmireddy Mallikarjuna reddy { 111932d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = dev_id; 112032d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c; 112132d31c79SAmireddy Mallikarjuna reddy unsigned long irncr; 112232d31c79SAmireddy Mallikarjuna reddy u32 cid; 112332d31c79SAmireddy Mallikarjuna reddy 112432d31c79SAmireddy Mallikarjuna reddy irncr = readl(d->base + DMA_IRNCR); 112532d31c79SAmireddy Mallikarjuna reddy if (!irncr) { 112632d31c79SAmireddy Mallikarjuna reddy dev_err(d->dev, "dummy interrupt\n"); 112732d31c79SAmireddy Mallikarjuna reddy return IRQ_NONE; 112832d31c79SAmireddy Mallikarjuna reddy } 112932d31c79SAmireddy Mallikarjuna reddy 113032d31c79SAmireddy Mallikarjuna reddy for_each_set_bit(cid, &irncr, d->chan_nrs) { 113132d31c79SAmireddy Mallikarjuna reddy /* Mask */ 113232d31c79SAmireddy Mallikarjuna reddy writel(readl(d->base + DMA_IRNEN) & ~BIT(cid), d->base + DMA_IRNEN); 113332d31c79SAmireddy Mallikarjuna reddy /* Ack */ 113432d31c79SAmireddy Mallikarjuna reddy writel(readl(d->base + DMA_IRNCR) | BIT(cid), d->base + DMA_IRNCR); 113532d31c79SAmireddy Mallikarjuna reddy 113632d31c79SAmireddy Mallikarjuna reddy c = &d->chans[cid]; 113732d31c79SAmireddy Mallikarjuna reddy dma_chan_irq(irq, c); 113832d31c79SAmireddy Mallikarjuna reddy } 113932d31c79SAmireddy Mallikarjuna reddy 114032d31c79SAmireddy Mallikarjuna reddy return IRQ_HANDLED; 114132d31c79SAmireddy Mallikarjuna reddy } 114232d31c79SAmireddy Mallikarjuna reddy 114332d31c79SAmireddy Mallikarjuna reddy static void prep_slave_burst_len(struct ldma_chan *c) 114432d31c79SAmireddy Mallikarjuna reddy { 114532d31c79SAmireddy Mallikarjuna reddy struct ldma_port *p = c->port; 114632d31c79SAmireddy Mallikarjuna reddy struct dma_slave_config *cfg = &c->config; 114732d31c79SAmireddy Mallikarjuna reddy 114832d31c79SAmireddy Mallikarjuna reddy if (cfg->dst_maxburst) 114932d31c79SAmireddy Mallikarjuna reddy cfg->src_maxburst = cfg->dst_maxburst; 115032d31c79SAmireddy Mallikarjuna reddy 115132d31c79SAmireddy Mallikarjuna reddy /* TX and RX has the same burst length */ 115232d31c79SAmireddy Mallikarjuna reddy p->txbl = ilog2(cfg->src_maxburst); 115332d31c79SAmireddy Mallikarjuna reddy p->rxbl = p->txbl; 115432d31c79SAmireddy Mallikarjuna reddy } 115532d31c79SAmireddy Mallikarjuna reddy 115632d31c79SAmireddy Mallikarjuna reddy static struct dma_async_tx_descriptor * 115732d31c79SAmireddy Mallikarjuna reddy ldma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, 115832d31c79SAmireddy Mallikarjuna reddy unsigned int sglen, enum dma_transfer_direction dir, 115932d31c79SAmireddy Mallikarjuna reddy unsigned long flags, void *context) 116032d31c79SAmireddy Mallikarjuna reddy { 116132d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 116232d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 116332d31c79SAmireddy Mallikarjuna reddy size_t len, avail, total = 0; 116432d31c79SAmireddy Mallikarjuna reddy struct dw2_desc *hw_ds; 116532d31c79SAmireddy Mallikarjuna reddy struct dw2_desc_sw *ds; 116632d31c79SAmireddy Mallikarjuna reddy struct scatterlist *sg; 116732d31c79SAmireddy Mallikarjuna reddy int num = sglen, i; 116832d31c79SAmireddy Mallikarjuna reddy dma_addr_t addr; 116932d31c79SAmireddy Mallikarjuna reddy 117032d31c79SAmireddy Mallikarjuna reddy if (!sgl) 117132d31c79SAmireddy Mallikarjuna reddy return NULL; 117232d31c79SAmireddy Mallikarjuna reddy 117332d31c79SAmireddy Mallikarjuna reddy if (d->ver > DMA_VER22) 117432d31c79SAmireddy Mallikarjuna reddy return ldma_chan_desc_cfg(chan, sgl->dma_address, sglen); 117532d31c79SAmireddy Mallikarjuna reddy 117632d31c79SAmireddy Mallikarjuna reddy for_each_sg(sgl, sg, sglen, i) { 117732d31c79SAmireddy Mallikarjuna reddy avail = sg_dma_len(sg); 117832d31c79SAmireddy Mallikarjuna reddy if (avail > DMA_MAX_SIZE) 117932d31c79SAmireddy Mallikarjuna reddy num += DIV_ROUND_UP(avail, DMA_MAX_SIZE) - 1; 118032d31c79SAmireddy Mallikarjuna reddy } 118132d31c79SAmireddy Mallikarjuna reddy 118232d31c79SAmireddy Mallikarjuna reddy ds = dma_alloc_desc_resource(num, c); 118332d31c79SAmireddy Mallikarjuna reddy if (!ds) 118432d31c79SAmireddy Mallikarjuna reddy return NULL; 118532d31c79SAmireddy Mallikarjuna reddy 118632d31c79SAmireddy Mallikarjuna reddy c->ds = ds; 118732d31c79SAmireddy Mallikarjuna reddy 118832d31c79SAmireddy Mallikarjuna reddy num = 0; 118932d31c79SAmireddy Mallikarjuna reddy /* sop and eop has to be handled nicely */ 119032d31c79SAmireddy Mallikarjuna reddy for_each_sg(sgl, sg, sglen, i) { 119132d31c79SAmireddy Mallikarjuna reddy addr = sg_dma_address(sg); 119232d31c79SAmireddy Mallikarjuna reddy avail = sg_dma_len(sg); 119332d31c79SAmireddy Mallikarjuna reddy total += avail; 119432d31c79SAmireddy Mallikarjuna reddy 119532d31c79SAmireddy Mallikarjuna reddy do { 119632d31c79SAmireddy Mallikarjuna reddy len = min_t(size_t, avail, DMA_MAX_SIZE); 119732d31c79SAmireddy Mallikarjuna reddy 119832d31c79SAmireddy Mallikarjuna reddy hw_ds = &ds->desc_hw[num]; 119932d31c79SAmireddy Mallikarjuna reddy switch (sglen) { 120032d31c79SAmireddy Mallikarjuna reddy case 1: 120132d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_SOP; 120232d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_SOP, 1); 120332d31c79SAmireddy Mallikarjuna reddy 120432d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_EOP; 120532d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_EOP, 1); 120632d31c79SAmireddy Mallikarjuna reddy break; 120732d31c79SAmireddy Mallikarjuna reddy default: 120832d31c79SAmireddy Mallikarjuna reddy if (num == 0) { 120932d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_SOP; 121032d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_SOP, 1); 121132d31c79SAmireddy Mallikarjuna reddy 121232d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_EOP; 121332d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_EOP, 0); 121432d31c79SAmireddy Mallikarjuna reddy } else if (num == (sglen - 1)) { 121532d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_SOP; 121632d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_SOP, 0); 121732d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_EOP; 121832d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_EOP, 1); 121932d31c79SAmireddy Mallikarjuna reddy } else { 122032d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_SOP; 122132d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_SOP, 0); 122232d31c79SAmireddy Mallikarjuna reddy 122332d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_EOP; 122432d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_EOP, 0); 122532d31c79SAmireddy Mallikarjuna reddy } 122632d31c79SAmireddy Mallikarjuna reddy break; 122732d31c79SAmireddy Mallikarjuna reddy } 122832d31c79SAmireddy Mallikarjuna reddy /* Only 32 bit address supported */ 122932d31c79SAmireddy Mallikarjuna reddy hw_ds->addr = (u32)addr; 123032d31c79SAmireddy Mallikarjuna reddy 123132d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_DATA_LEN; 123232d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_DATA_LEN, len); 123332d31c79SAmireddy Mallikarjuna reddy 123432d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_C; 123532d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_C, 0); 123632d31c79SAmireddy Mallikarjuna reddy 123732d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_BYTE_OFF; 123832d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_BYTE_OFF, addr & 0x3); 123932d31c79SAmireddy Mallikarjuna reddy 124032d31c79SAmireddy Mallikarjuna reddy /* Ensure data ready before ownership change */ 124132d31c79SAmireddy Mallikarjuna reddy wmb(); 124232d31c79SAmireddy Mallikarjuna reddy hw_ds->field &= ~DESC_OWN; 124332d31c79SAmireddy Mallikarjuna reddy hw_ds->field |= FIELD_PREP(DESC_OWN, DMA_OWN); 124432d31c79SAmireddy Mallikarjuna reddy 124532d31c79SAmireddy Mallikarjuna reddy /* Ensure ownership changed before moving forward */ 124632d31c79SAmireddy Mallikarjuna reddy wmb(); 124732d31c79SAmireddy Mallikarjuna reddy num++; 124832d31c79SAmireddy Mallikarjuna reddy addr += len; 124932d31c79SAmireddy Mallikarjuna reddy avail -= len; 125032d31c79SAmireddy Mallikarjuna reddy } while (avail); 125132d31c79SAmireddy Mallikarjuna reddy } 125232d31c79SAmireddy Mallikarjuna reddy 125332d31c79SAmireddy Mallikarjuna reddy ds->size = total; 125432d31c79SAmireddy Mallikarjuna reddy prep_slave_burst_len(c); 125532d31c79SAmireddy Mallikarjuna reddy 125632d31c79SAmireddy Mallikarjuna reddy return vchan_tx_prep(&c->vchan, &ds->vdesc, DMA_CTRL_ACK); 125732d31c79SAmireddy Mallikarjuna reddy } 125832d31c79SAmireddy Mallikarjuna reddy 125932d31c79SAmireddy Mallikarjuna reddy static int 126032d31c79SAmireddy Mallikarjuna reddy ldma_slave_config(struct dma_chan *chan, struct dma_slave_config *cfg) 126132d31c79SAmireddy Mallikarjuna reddy { 126232d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 126332d31c79SAmireddy Mallikarjuna reddy 126432d31c79SAmireddy Mallikarjuna reddy memcpy(&c->config, cfg, sizeof(c->config)); 126532d31c79SAmireddy Mallikarjuna reddy 126632d31c79SAmireddy Mallikarjuna reddy return 0; 126732d31c79SAmireddy Mallikarjuna reddy } 126832d31c79SAmireddy Mallikarjuna reddy 126932d31c79SAmireddy Mallikarjuna reddy static int ldma_alloc_chan_resources(struct dma_chan *chan) 127032d31c79SAmireddy Mallikarjuna reddy { 127132d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 127232d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 127332d31c79SAmireddy Mallikarjuna reddy struct device *dev = c->vchan.chan.device->dev; 127432d31c79SAmireddy Mallikarjuna reddy size_t desc_sz; 127532d31c79SAmireddy Mallikarjuna reddy 127632d31c79SAmireddy Mallikarjuna reddy if (d->ver > DMA_VER22) { 127732d31c79SAmireddy Mallikarjuna reddy c->flags |= CHAN_IN_USE; 127832d31c79SAmireddy Mallikarjuna reddy return 0; 127932d31c79SAmireddy Mallikarjuna reddy } 128032d31c79SAmireddy Mallikarjuna reddy 128132d31c79SAmireddy Mallikarjuna reddy if (c->desc_pool) 128232d31c79SAmireddy Mallikarjuna reddy return c->desc_num; 128332d31c79SAmireddy Mallikarjuna reddy 128432d31c79SAmireddy Mallikarjuna reddy desc_sz = c->desc_num * sizeof(struct dw2_desc); 128532d31c79SAmireddy Mallikarjuna reddy c->desc_pool = dma_pool_create(c->name, dev, desc_sz, 128632d31c79SAmireddy Mallikarjuna reddy __alignof__(struct dw2_desc), 0); 128732d31c79SAmireddy Mallikarjuna reddy 128832d31c79SAmireddy Mallikarjuna reddy if (!c->desc_pool) { 128932d31c79SAmireddy Mallikarjuna reddy dev_err(dev, "unable to allocate descriptor pool\n"); 129032d31c79SAmireddy Mallikarjuna reddy return -ENOMEM; 129132d31c79SAmireddy Mallikarjuna reddy } 129232d31c79SAmireddy Mallikarjuna reddy 129332d31c79SAmireddy Mallikarjuna reddy return c->desc_num; 129432d31c79SAmireddy Mallikarjuna reddy } 129532d31c79SAmireddy Mallikarjuna reddy 129632d31c79SAmireddy Mallikarjuna reddy static void ldma_free_chan_resources(struct dma_chan *chan) 129732d31c79SAmireddy Mallikarjuna reddy { 129832d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = to_ldma_chan(chan); 129932d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = to_ldma_dev(c->vchan.chan.device); 130032d31c79SAmireddy Mallikarjuna reddy 130132d31c79SAmireddy Mallikarjuna reddy if (d->ver == DMA_VER22) { 130232d31c79SAmireddy Mallikarjuna reddy dma_pool_destroy(c->desc_pool); 130332d31c79SAmireddy Mallikarjuna reddy c->desc_pool = NULL; 130432d31c79SAmireddy Mallikarjuna reddy vchan_free_chan_resources(to_virt_chan(chan)); 130532d31c79SAmireddy Mallikarjuna reddy ldma_chan_reset(c); 130632d31c79SAmireddy Mallikarjuna reddy } else { 130732d31c79SAmireddy Mallikarjuna reddy c->flags &= ~CHAN_IN_USE; 130832d31c79SAmireddy Mallikarjuna reddy } 130932d31c79SAmireddy Mallikarjuna reddy } 131032d31c79SAmireddy Mallikarjuna reddy 131132d31c79SAmireddy Mallikarjuna reddy static void dma_work(struct work_struct *work) 131232d31c79SAmireddy Mallikarjuna reddy { 131332d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c = container_of(work, struct ldma_chan, work); 131432d31c79SAmireddy Mallikarjuna reddy struct dma_async_tx_descriptor *tx = &c->ds->vdesc.tx; 131532d31c79SAmireddy Mallikarjuna reddy struct virt_dma_chan *vc = &c->vchan; 131632d31c79SAmireddy Mallikarjuna reddy struct dmaengine_desc_callback cb; 131732d31c79SAmireddy Mallikarjuna reddy struct virt_dma_desc *vd, *_vd; 131832d31c79SAmireddy Mallikarjuna reddy unsigned long flags; 131932d31c79SAmireddy Mallikarjuna reddy LIST_HEAD(head); 132032d31c79SAmireddy Mallikarjuna reddy 132132d31c79SAmireddy Mallikarjuna reddy spin_lock_irqsave(&c->vchan.lock, flags); 132232d31c79SAmireddy Mallikarjuna reddy list_splice_tail_init(&vc->desc_completed, &head); 132332d31c79SAmireddy Mallikarjuna reddy spin_unlock_irqrestore(&c->vchan.lock, flags); 132432d31c79SAmireddy Mallikarjuna reddy dmaengine_desc_get_callback(tx, &cb); 132532d31c79SAmireddy Mallikarjuna reddy dma_cookie_complete(tx); 132632d31c79SAmireddy Mallikarjuna reddy dmaengine_desc_callback_invoke(&cb, NULL); 132732d31c79SAmireddy Mallikarjuna reddy 132832d31c79SAmireddy Mallikarjuna reddy list_for_each_entry_safe(vd, _vd, &head, node) { 132932d31c79SAmireddy Mallikarjuna reddy dmaengine_desc_get_callback(tx, &cb); 133032d31c79SAmireddy Mallikarjuna reddy dma_cookie_complete(tx); 133132d31c79SAmireddy Mallikarjuna reddy list_del(&vd->node); 133232d31c79SAmireddy Mallikarjuna reddy dmaengine_desc_callback_invoke(&cb, NULL); 133332d31c79SAmireddy Mallikarjuna reddy 133432d31c79SAmireddy Mallikarjuna reddy vchan_vdesc_fini(vd); 133532d31c79SAmireddy Mallikarjuna reddy } 133632d31c79SAmireddy Mallikarjuna reddy c->ds = NULL; 133732d31c79SAmireddy Mallikarjuna reddy } 133832d31c79SAmireddy Mallikarjuna reddy 133932d31c79SAmireddy Mallikarjuna reddy static void 134032d31c79SAmireddy Mallikarjuna reddy update_burst_len_v22(struct ldma_chan *c, struct ldma_port *p, u32 burst) 134132d31c79SAmireddy Mallikarjuna reddy { 134232d31c79SAmireddy Mallikarjuna reddy if (ldma_chan_tx(c)) 134332d31c79SAmireddy Mallikarjuna reddy p->txbl = ilog2(burst); 134432d31c79SAmireddy Mallikarjuna reddy else 134532d31c79SAmireddy Mallikarjuna reddy p->rxbl = ilog2(burst); 134632d31c79SAmireddy Mallikarjuna reddy } 134732d31c79SAmireddy Mallikarjuna reddy 134832d31c79SAmireddy Mallikarjuna reddy static void 134932d31c79SAmireddy Mallikarjuna reddy update_burst_len_v3X(struct ldma_chan *c, struct ldma_port *p, u32 burst) 135032d31c79SAmireddy Mallikarjuna reddy { 135132d31c79SAmireddy Mallikarjuna reddy if (ldma_chan_tx(c)) 135232d31c79SAmireddy Mallikarjuna reddy p->txbl = burst; 135332d31c79SAmireddy Mallikarjuna reddy else 135432d31c79SAmireddy Mallikarjuna reddy p->rxbl = burst; 135532d31c79SAmireddy Mallikarjuna reddy } 135632d31c79SAmireddy Mallikarjuna reddy 135732d31c79SAmireddy Mallikarjuna reddy static int 135832d31c79SAmireddy Mallikarjuna reddy update_client_configs(struct of_dma *ofdma, struct of_phandle_args *spec) 135932d31c79SAmireddy Mallikarjuna reddy { 136032d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = ofdma->of_dma_data; 136132d31c79SAmireddy Mallikarjuna reddy u32 chan_id = spec->args[0]; 136232d31c79SAmireddy Mallikarjuna reddy u32 port_id = spec->args[1]; 136332d31c79SAmireddy Mallikarjuna reddy u32 burst = spec->args[2]; 136432d31c79SAmireddy Mallikarjuna reddy struct ldma_port *p; 136532d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c; 136632d31c79SAmireddy Mallikarjuna reddy 136732d31c79SAmireddy Mallikarjuna reddy if (chan_id >= d->chan_nrs || port_id >= d->port_nrs) 136832d31c79SAmireddy Mallikarjuna reddy return 0; 136932d31c79SAmireddy Mallikarjuna reddy 137032d31c79SAmireddy Mallikarjuna reddy p = &d->ports[port_id]; 137132d31c79SAmireddy Mallikarjuna reddy c = &d->chans[chan_id]; 137232d31c79SAmireddy Mallikarjuna reddy c->port = p; 137332d31c79SAmireddy Mallikarjuna reddy 137432d31c79SAmireddy Mallikarjuna reddy if (d->ver == DMA_VER22) 137532d31c79SAmireddy Mallikarjuna reddy update_burst_len_v22(c, p, burst); 137632d31c79SAmireddy Mallikarjuna reddy else 137732d31c79SAmireddy Mallikarjuna reddy update_burst_len_v3X(c, p, burst); 137832d31c79SAmireddy Mallikarjuna reddy 137932d31c79SAmireddy Mallikarjuna reddy ldma_port_cfg(p); 138032d31c79SAmireddy Mallikarjuna reddy 138132d31c79SAmireddy Mallikarjuna reddy return 1; 138232d31c79SAmireddy Mallikarjuna reddy } 138332d31c79SAmireddy Mallikarjuna reddy 138432d31c79SAmireddy Mallikarjuna reddy static struct dma_chan *ldma_xlate(struct of_phandle_args *spec, 138532d31c79SAmireddy Mallikarjuna reddy struct of_dma *ofdma) 138632d31c79SAmireddy Mallikarjuna reddy { 138732d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = ofdma->of_dma_data; 138832d31c79SAmireddy Mallikarjuna reddy u32 chan_id = spec->args[0]; 138932d31c79SAmireddy Mallikarjuna reddy int ret; 139032d31c79SAmireddy Mallikarjuna reddy 139132d31c79SAmireddy Mallikarjuna reddy if (!spec->args_count) 139232d31c79SAmireddy Mallikarjuna reddy return NULL; 139332d31c79SAmireddy Mallikarjuna reddy 139432d31c79SAmireddy Mallikarjuna reddy /* if args_count is 1 driver use default settings */ 139532d31c79SAmireddy Mallikarjuna reddy if (spec->args_count > 1) { 139632d31c79SAmireddy Mallikarjuna reddy ret = update_client_configs(ofdma, spec); 139732d31c79SAmireddy Mallikarjuna reddy if (!ret) 139832d31c79SAmireddy Mallikarjuna reddy return NULL; 139932d31c79SAmireddy Mallikarjuna reddy } 140032d31c79SAmireddy Mallikarjuna reddy 140132d31c79SAmireddy Mallikarjuna reddy return dma_get_slave_channel(&d->chans[chan_id].vchan.chan); 140232d31c79SAmireddy Mallikarjuna reddy } 140332d31c79SAmireddy Mallikarjuna reddy 140432d31c79SAmireddy Mallikarjuna reddy static void ldma_dma_init_v22(int i, struct ldma_dev *d) 140532d31c79SAmireddy Mallikarjuna reddy { 140632d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c; 140732d31c79SAmireddy Mallikarjuna reddy 140832d31c79SAmireddy Mallikarjuna reddy c = &d->chans[i]; 140932d31c79SAmireddy Mallikarjuna reddy c->nr = i; /* Real channel number */ 141032d31c79SAmireddy Mallikarjuna reddy c->rst = DMA_CHAN_RST; 141132d31c79SAmireddy Mallikarjuna reddy c->desc_num = DMA_DFT_DESC_NUM; 141232d31c79SAmireddy Mallikarjuna reddy snprintf(c->name, sizeof(c->name), "chan%d", c->nr); 141332d31c79SAmireddy Mallikarjuna reddy INIT_WORK(&c->work, dma_work); 141432d31c79SAmireddy Mallikarjuna reddy c->vchan.desc_free = dma_free_desc_resource; 141532d31c79SAmireddy Mallikarjuna reddy vchan_init(&c->vchan, &d->dma_dev); 141632d31c79SAmireddy Mallikarjuna reddy } 141732d31c79SAmireddy Mallikarjuna reddy 141832d31c79SAmireddy Mallikarjuna reddy static void ldma_dma_init_v3X(int i, struct ldma_dev *d) 141932d31c79SAmireddy Mallikarjuna reddy { 142032d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c; 142132d31c79SAmireddy Mallikarjuna reddy 142232d31c79SAmireddy Mallikarjuna reddy c = &d->chans[i]; 142332d31c79SAmireddy Mallikarjuna reddy c->data_endian = DMA_DFT_ENDIAN; 142432d31c79SAmireddy Mallikarjuna reddy c->desc_endian = DMA_DFT_ENDIAN; 142532d31c79SAmireddy Mallikarjuna reddy c->data_endian_en = false; 142632d31c79SAmireddy Mallikarjuna reddy c->desc_endian_en = false; 142732d31c79SAmireddy Mallikarjuna reddy c->desc_rx_np = false; 142832d31c79SAmireddy Mallikarjuna reddy c->flags |= DEVICE_ALLOC_DESC; 142932d31c79SAmireddy Mallikarjuna reddy c->onoff = DMA_CH_OFF; 143032d31c79SAmireddy Mallikarjuna reddy c->rst = DMA_CHAN_RST; 143132d31c79SAmireddy Mallikarjuna reddy c->abc_en = true; 143232d31c79SAmireddy Mallikarjuna reddy c->hdrm_csum = false; 143332d31c79SAmireddy Mallikarjuna reddy c->boff_len = 0; 143432d31c79SAmireddy Mallikarjuna reddy c->nr = i; 143532d31c79SAmireddy Mallikarjuna reddy c->vchan.desc_free = dma_free_desc_resource; 143632d31c79SAmireddy Mallikarjuna reddy vchan_init(&c->vchan, &d->dma_dev); 143732d31c79SAmireddy Mallikarjuna reddy } 143832d31c79SAmireddy Mallikarjuna reddy 143932d31c79SAmireddy Mallikarjuna reddy static int ldma_init_v22(struct ldma_dev *d, struct platform_device *pdev) 144032d31c79SAmireddy Mallikarjuna reddy { 144132d31c79SAmireddy Mallikarjuna reddy int ret; 144232d31c79SAmireddy Mallikarjuna reddy 144332d31c79SAmireddy Mallikarjuna reddy ret = device_property_read_u32(d->dev, "dma-channels", &d->chan_nrs); 144432d31c79SAmireddy Mallikarjuna reddy if (ret < 0) { 144532d31c79SAmireddy Mallikarjuna reddy dev_err(d->dev, "unable to read dma-channels property\n"); 144632d31c79SAmireddy Mallikarjuna reddy return ret; 144732d31c79SAmireddy Mallikarjuna reddy } 144832d31c79SAmireddy Mallikarjuna reddy 144932d31c79SAmireddy Mallikarjuna reddy d->irq = platform_get_irq(pdev, 0); 145032d31c79SAmireddy Mallikarjuna reddy if (d->irq < 0) 145132d31c79SAmireddy Mallikarjuna reddy return d->irq; 145232d31c79SAmireddy Mallikarjuna reddy 145332d31c79SAmireddy Mallikarjuna reddy ret = devm_request_irq(&pdev->dev, d->irq, dma_interrupt, 0, 145432d31c79SAmireddy Mallikarjuna reddy DRIVER_NAME, d); 145532d31c79SAmireddy Mallikarjuna reddy if (ret) 145632d31c79SAmireddy Mallikarjuna reddy return ret; 145732d31c79SAmireddy Mallikarjuna reddy 145832d31c79SAmireddy Mallikarjuna reddy d->wq = alloc_ordered_workqueue("dma_wq", WQ_MEM_RECLAIM | 145932d31c79SAmireddy Mallikarjuna reddy WQ_HIGHPRI); 146032d31c79SAmireddy Mallikarjuna reddy if (!d->wq) 146132d31c79SAmireddy Mallikarjuna reddy return -ENOMEM; 146232d31c79SAmireddy Mallikarjuna reddy 146332d31c79SAmireddy Mallikarjuna reddy return 0; 146432d31c79SAmireddy Mallikarjuna reddy } 146532d31c79SAmireddy Mallikarjuna reddy 146632d31c79SAmireddy Mallikarjuna reddy static void ldma_clk_disable(void *data) 146732d31c79SAmireddy Mallikarjuna reddy { 146832d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d = data; 146932d31c79SAmireddy Mallikarjuna reddy 147032d31c79SAmireddy Mallikarjuna reddy clk_disable_unprepare(d->core_clk); 147132d31c79SAmireddy Mallikarjuna reddy reset_control_assert(d->rst); 147232d31c79SAmireddy Mallikarjuna reddy } 147332d31c79SAmireddy Mallikarjuna reddy 147432d31c79SAmireddy Mallikarjuna reddy static const struct ldma_inst_data dma0 = { 147532d31c79SAmireddy Mallikarjuna reddy .name = "dma0", 147632d31c79SAmireddy Mallikarjuna reddy .chan_fc = false, 147732d31c79SAmireddy Mallikarjuna reddy .desc_fod = false, 147832d31c79SAmireddy Mallikarjuna reddy .desc_in_sram = false, 147932d31c79SAmireddy Mallikarjuna reddy .valid_desc_fetch_ack = false, 148032d31c79SAmireddy Mallikarjuna reddy }; 148132d31c79SAmireddy Mallikarjuna reddy 148232d31c79SAmireddy Mallikarjuna reddy static const struct ldma_inst_data dma2tx = { 148332d31c79SAmireddy Mallikarjuna reddy .name = "dma2tx", 148432d31c79SAmireddy Mallikarjuna reddy .type = DMA_TYPE_TX, 148532d31c79SAmireddy Mallikarjuna reddy .orrc = 16, 148632d31c79SAmireddy Mallikarjuna reddy .chan_fc = true, 148732d31c79SAmireddy Mallikarjuna reddy .desc_fod = true, 148832d31c79SAmireddy Mallikarjuna reddy .desc_in_sram = true, 148932d31c79SAmireddy Mallikarjuna reddy .valid_desc_fetch_ack = true, 149032d31c79SAmireddy Mallikarjuna reddy }; 149132d31c79SAmireddy Mallikarjuna reddy 149232d31c79SAmireddy Mallikarjuna reddy static const struct ldma_inst_data dma1rx = { 149332d31c79SAmireddy Mallikarjuna reddy .name = "dma1rx", 149432d31c79SAmireddy Mallikarjuna reddy .type = DMA_TYPE_RX, 149532d31c79SAmireddy Mallikarjuna reddy .orrc = 16, 149632d31c79SAmireddy Mallikarjuna reddy .chan_fc = false, 149732d31c79SAmireddy Mallikarjuna reddy .desc_fod = true, 149832d31c79SAmireddy Mallikarjuna reddy .desc_in_sram = true, 149932d31c79SAmireddy Mallikarjuna reddy .valid_desc_fetch_ack = false, 150032d31c79SAmireddy Mallikarjuna reddy }; 150132d31c79SAmireddy Mallikarjuna reddy 150232d31c79SAmireddy Mallikarjuna reddy static const struct ldma_inst_data dma1tx = { 150332d31c79SAmireddy Mallikarjuna reddy .name = "dma1tx", 150432d31c79SAmireddy Mallikarjuna reddy .type = DMA_TYPE_TX, 150532d31c79SAmireddy Mallikarjuna reddy .orrc = 16, 150632d31c79SAmireddy Mallikarjuna reddy .chan_fc = true, 150732d31c79SAmireddy Mallikarjuna reddy .desc_fod = true, 150832d31c79SAmireddy Mallikarjuna reddy .desc_in_sram = true, 150932d31c79SAmireddy Mallikarjuna reddy .valid_desc_fetch_ack = true, 151032d31c79SAmireddy Mallikarjuna reddy }; 151132d31c79SAmireddy Mallikarjuna reddy 151232d31c79SAmireddy Mallikarjuna reddy static const struct ldma_inst_data dma0tx = { 151332d31c79SAmireddy Mallikarjuna reddy .name = "dma0tx", 151432d31c79SAmireddy Mallikarjuna reddy .type = DMA_TYPE_TX, 151532d31c79SAmireddy Mallikarjuna reddy .orrc = 16, 151632d31c79SAmireddy Mallikarjuna reddy .chan_fc = true, 151732d31c79SAmireddy Mallikarjuna reddy .desc_fod = true, 151832d31c79SAmireddy Mallikarjuna reddy .desc_in_sram = true, 151932d31c79SAmireddy Mallikarjuna reddy .valid_desc_fetch_ack = true, 152032d31c79SAmireddy Mallikarjuna reddy }; 152132d31c79SAmireddy Mallikarjuna reddy 152232d31c79SAmireddy Mallikarjuna reddy static const struct ldma_inst_data dma3 = { 152332d31c79SAmireddy Mallikarjuna reddy .name = "dma3", 152432d31c79SAmireddy Mallikarjuna reddy .type = DMA_TYPE_MCPY, 152532d31c79SAmireddy Mallikarjuna reddy .orrc = 16, 152632d31c79SAmireddy Mallikarjuna reddy .chan_fc = false, 152732d31c79SAmireddy Mallikarjuna reddy .desc_fod = false, 152832d31c79SAmireddy Mallikarjuna reddy .desc_in_sram = true, 152932d31c79SAmireddy Mallikarjuna reddy .valid_desc_fetch_ack = false, 153032d31c79SAmireddy Mallikarjuna reddy }; 153132d31c79SAmireddy Mallikarjuna reddy 153232d31c79SAmireddy Mallikarjuna reddy static const struct ldma_inst_data toe_dma30 = { 153332d31c79SAmireddy Mallikarjuna reddy .name = "toe_dma30", 153432d31c79SAmireddy Mallikarjuna reddy .type = DMA_TYPE_MCPY, 153532d31c79SAmireddy Mallikarjuna reddy .orrc = 16, 153632d31c79SAmireddy Mallikarjuna reddy .chan_fc = false, 153732d31c79SAmireddy Mallikarjuna reddy .desc_fod = false, 153832d31c79SAmireddy Mallikarjuna reddy .desc_in_sram = true, 153932d31c79SAmireddy Mallikarjuna reddy .valid_desc_fetch_ack = true, 154032d31c79SAmireddy Mallikarjuna reddy }; 154132d31c79SAmireddy Mallikarjuna reddy 154232d31c79SAmireddy Mallikarjuna reddy static const struct ldma_inst_data toe_dma31 = { 154332d31c79SAmireddy Mallikarjuna reddy .name = "toe_dma31", 154432d31c79SAmireddy Mallikarjuna reddy .type = DMA_TYPE_MCPY, 154532d31c79SAmireddy Mallikarjuna reddy .orrc = 16, 154632d31c79SAmireddy Mallikarjuna reddy .chan_fc = false, 154732d31c79SAmireddy Mallikarjuna reddy .desc_fod = false, 154832d31c79SAmireddy Mallikarjuna reddy .desc_in_sram = true, 154932d31c79SAmireddy Mallikarjuna reddy .valid_desc_fetch_ack = true, 155032d31c79SAmireddy Mallikarjuna reddy }; 155132d31c79SAmireddy Mallikarjuna reddy 155232d31c79SAmireddy Mallikarjuna reddy static const struct of_device_id intel_ldma_match[] = { 155332d31c79SAmireddy Mallikarjuna reddy { .compatible = "intel,lgm-cdma", .data = &dma0}, 155432d31c79SAmireddy Mallikarjuna reddy { .compatible = "intel,lgm-dma2tx", .data = &dma2tx}, 155532d31c79SAmireddy Mallikarjuna reddy { .compatible = "intel,lgm-dma1rx", .data = &dma1rx}, 155632d31c79SAmireddy Mallikarjuna reddy { .compatible = "intel,lgm-dma1tx", .data = &dma1tx}, 155732d31c79SAmireddy Mallikarjuna reddy { .compatible = "intel,lgm-dma0tx", .data = &dma0tx}, 155832d31c79SAmireddy Mallikarjuna reddy { .compatible = "intel,lgm-dma3", .data = &dma3}, 155932d31c79SAmireddy Mallikarjuna reddy { .compatible = "intel,lgm-toe-dma30", .data = &toe_dma30}, 156032d31c79SAmireddy Mallikarjuna reddy { .compatible = "intel,lgm-toe-dma31", .data = &toe_dma31}, 156132d31c79SAmireddy Mallikarjuna reddy {} 156232d31c79SAmireddy Mallikarjuna reddy }; 156332d31c79SAmireddy Mallikarjuna reddy 156432d31c79SAmireddy Mallikarjuna reddy static int intel_ldma_probe(struct platform_device *pdev) 156532d31c79SAmireddy Mallikarjuna reddy { 156632d31c79SAmireddy Mallikarjuna reddy struct device *dev = &pdev->dev; 156732d31c79SAmireddy Mallikarjuna reddy struct dma_device *dma_dev; 156832d31c79SAmireddy Mallikarjuna reddy unsigned long ch_mask; 156932d31c79SAmireddy Mallikarjuna reddy struct ldma_chan *c; 157032d31c79SAmireddy Mallikarjuna reddy struct ldma_port *p; 157132d31c79SAmireddy Mallikarjuna reddy struct ldma_dev *d; 157232d31c79SAmireddy Mallikarjuna reddy u32 id, bitn = 32, j; 157332d31c79SAmireddy Mallikarjuna reddy int i, ret; 157432d31c79SAmireddy Mallikarjuna reddy 157532d31c79SAmireddy Mallikarjuna reddy d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL); 157632d31c79SAmireddy Mallikarjuna reddy if (!d) 157732d31c79SAmireddy Mallikarjuna reddy return -ENOMEM; 157832d31c79SAmireddy Mallikarjuna reddy 157932d31c79SAmireddy Mallikarjuna reddy /* Link controller to platform device */ 158032d31c79SAmireddy Mallikarjuna reddy d->dev = &pdev->dev; 158132d31c79SAmireddy Mallikarjuna reddy 158232d31c79SAmireddy Mallikarjuna reddy d->inst = device_get_match_data(dev); 158332d31c79SAmireddy Mallikarjuna reddy if (!d->inst) { 158432d31c79SAmireddy Mallikarjuna reddy dev_err(dev, "No device match found\n"); 158532d31c79SAmireddy Mallikarjuna reddy return -ENODEV; 158632d31c79SAmireddy Mallikarjuna reddy } 158732d31c79SAmireddy Mallikarjuna reddy 158832d31c79SAmireddy Mallikarjuna reddy d->base = devm_platform_ioremap_resource(pdev, 0); 158932d31c79SAmireddy Mallikarjuna reddy if (IS_ERR(d->base)) 159032d31c79SAmireddy Mallikarjuna reddy return PTR_ERR(d->base); 159132d31c79SAmireddy Mallikarjuna reddy 159232d31c79SAmireddy Mallikarjuna reddy /* Power up and reset the dma engine, some DMAs always on?? */ 159332d31c79SAmireddy Mallikarjuna reddy d->core_clk = devm_clk_get_optional(dev, NULL); 159432d31c79SAmireddy Mallikarjuna reddy if (IS_ERR(d->core_clk)) 159532d31c79SAmireddy Mallikarjuna reddy return PTR_ERR(d->core_clk); 159632d31c79SAmireddy Mallikarjuna reddy 159732d31c79SAmireddy Mallikarjuna reddy d->rst = devm_reset_control_get_optional(dev, NULL); 159832d31c79SAmireddy Mallikarjuna reddy if (IS_ERR(d->rst)) 159932d31c79SAmireddy Mallikarjuna reddy return PTR_ERR(d->rst); 1600*1dbe67b9SChristophe JAILLET 1601*1dbe67b9SChristophe JAILLET clk_prepare_enable(d->core_clk); 160232d31c79SAmireddy Mallikarjuna reddy reset_control_deassert(d->rst); 160332d31c79SAmireddy Mallikarjuna reddy 160432d31c79SAmireddy Mallikarjuna reddy ret = devm_add_action_or_reset(dev, ldma_clk_disable, d); 160532d31c79SAmireddy Mallikarjuna reddy if (ret) { 160632d31c79SAmireddy Mallikarjuna reddy dev_err(dev, "Failed to devm_add_action_or_reset, %d\n", ret); 160732d31c79SAmireddy Mallikarjuna reddy return ret; 160832d31c79SAmireddy Mallikarjuna reddy } 160932d31c79SAmireddy Mallikarjuna reddy 161032d31c79SAmireddy Mallikarjuna reddy id = readl(d->base + DMA_ID); 161132d31c79SAmireddy Mallikarjuna reddy d->chan_nrs = FIELD_GET(DMA_ID_CHNR, id); 161232d31c79SAmireddy Mallikarjuna reddy d->port_nrs = FIELD_GET(DMA_ID_PNR, id); 161332d31c79SAmireddy Mallikarjuna reddy d->ver = FIELD_GET(DMA_ID_REV, id); 161432d31c79SAmireddy Mallikarjuna reddy 161532d31c79SAmireddy Mallikarjuna reddy if (id & DMA_ID_AW_36B) 161632d31c79SAmireddy Mallikarjuna reddy d->flags |= DMA_ADDR_36BIT; 161732d31c79SAmireddy Mallikarjuna reddy 161832d31c79SAmireddy Mallikarjuna reddy if (IS_ENABLED(CONFIG_64BIT) && (id & DMA_ID_AW_36B)) 161932d31c79SAmireddy Mallikarjuna reddy bitn = 36; 162032d31c79SAmireddy Mallikarjuna reddy 162132d31c79SAmireddy Mallikarjuna reddy if (id & DMA_ID_DW_128B) 162232d31c79SAmireddy Mallikarjuna reddy d->flags |= DMA_DATA_128BIT; 162332d31c79SAmireddy Mallikarjuna reddy 162432d31c79SAmireddy Mallikarjuna reddy ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(bitn)); 162532d31c79SAmireddy Mallikarjuna reddy if (ret) { 162632d31c79SAmireddy Mallikarjuna reddy dev_err(dev, "No usable DMA configuration\n"); 162732d31c79SAmireddy Mallikarjuna reddy return ret; 162832d31c79SAmireddy Mallikarjuna reddy } 162932d31c79SAmireddy Mallikarjuna reddy 163032d31c79SAmireddy Mallikarjuna reddy if (d->ver == DMA_VER22) { 163132d31c79SAmireddy Mallikarjuna reddy ret = ldma_init_v22(d, pdev); 163232d31c79SAmireddy Mallikarjuna reddy if (ret) 163332d31c79SAmireddy Mallikarjuna reddy return ret; 163432d31c79SAmireddy Mallikarjuna reddy } 163532d31c79SAmireddy Mallikarjuna reddy 163632d31c79SAmireddy Mallikarjuna reddy ret = device_property_read_u32(dev, "dma-channel-mask", &d->channels_mask); 163732d31c79SAmireddy Mallikarjuna reddy if (ret < 0) 163832d31c79SAmireddy Mallikarjuna reddy d->channels_mask = GENMASK(d->chan_nrs - 1, 0); 163932d31c79SAmireddy Mallikarjuna reddy 164032d31c79SAmireddy Mallikarjuna reddy dma_dev = &d->dma_dev; 164132d31c79SAmireddy Mallikarjuna reddy 164232d31c79SAmireddy Mallikarjuna reddy dma_cap_zero(dma_dev->cap_mask); 164332d31c79SAmireddy Mallikarjuna reddy dma_cap_set(DMA_SLAVE, dma_dev->cap_mask); 164432d31c79SAmireddy Mallikarjuna reddy 164532d31c79SAmireddy Mallikarjuna reddy /* Channel initializations */ 164632d31c79SAmireddy Mallikarjuna reddy INIT_LIST_HEAD(&dma_dev->channels); 164732d31c79SAmireddy Mallikarjuna reddy 164832d31c79SAmireddy Mallikarjuna reddy /* Port Initializations */ 164932d31c79SAmireddy Mallikarjuna reddy d->ports = devm_kcalloc(dev, d->port_nrs, sizeof(*p), GFP_KERNEL); 165032d31c79SAmireddy Mallikarjuna reddy if (!d->ports) 165132d31c79SAmireddy Mallikarjuna reddy return -ENOMEM; 165232d31c79SAmireddy Mallikarjuna reddy 165332d31c79SAmireddy Mallikarjuna reddy /* Channels Initializations */ 165432d31c79SAmireddy Mallikarjuna reddy d->chans = devm_kcalloc(d->dev, d->chan_nrs, sizeof(*c), GFP_KERNEL); 165532d31c79SAmireddy Mallikarjuna reddy if (!d->chans) 165632d31c79SAmireddy Mallikarjuna reddy return -ENOMEM; 165732d31c79SAmireddy Mallikarjuna reddy 165832d31c79SAmireddy Mallikarjuna reddy for (i = 0; i < d->port_nrs; i++) { 165932d31c79SAmireddy Mallikarjuna reddy p = &d->ports[i]; 166032d31c79SAmireddy Mallikarjuna reddy p->portid = i; 166132d31c79SAmireddy Mallikarjuna reddy p->ldev = d; 166232d31c79SAmireddy Mallikarjuna reddy } 166332d31c79SAmireddy Mallikarjuna reddy 166432d31c79SAmireddy Mallikarjuna reddy ret = ldma_cfg_init(d); 166532d31c79SAmireddy Mallikarjuna reddy if (ret) 166632d31c79SAmireddy Mallikarjuna reddy return ret; 166732d31c79SAmireddy Mallikarjuna reddy 166832d31c79SAmireddy Mallikarjuna reddy dma_dev->dev = &pdev->dev; 166932d31c79SAmireddy Mallikarjuna reddy 167032d31c79SAmireddy Mallikarjuna reddy ch_mask = (unsigned long)d->channels_mask; 167132d31c79SAmireddy Mallikarjuna reddy for_each_set_bit(j, &ch_mask, d->chan_nrs) { 167232d31c79SAmireddy Mallikarjuna reddy if (d->ver == DMA_VER22) 167332d31c79SAmireddy Mallikarjuna reddy ldma_dma_init_v22(j, d); 167432d31c79SAmireddy Mallikarjuna reddy else 167532d31c79SAmireddy Mallikarjuna reddy ldma_dma_init_v3X(j, d); 167632d31c79SAmireddy Mallikarjuna reddy } 167732d31c79SAmireddy Mallikarjuna reddy 167832d31c79SAmireddy Mallikarjuna reddy dma_dev->device_alloc_chan_resources = ldma_alloc_chan_resources; 167932d31c79SAmireddy Mallikarjuna reddy dma_dev->device_free_chan_resources = ldma_free_chan_resources; 168032d31c79SAmireddy Mallikarjuna reddy dma_dev->device_terminate_all = ldma_terminate_all; 168132d31c79SAmireddy Mallikarjuna reddy dma_dev->device_issue_pending = ldma_issue_pending; 168232d31c79SAmireddy Mallikarjuna reddy dma_dev->device_tx_status = ldma_tx_status; 168332d31c79SAmireddy Mallikarjuna reddy dma_dev->device_resume = ldma_resume_chan; 168432d31c79SAmireddy Mallikarjuna reddy dma_dev->device_pause = ldma_pause_chan; 168532d31c79SAmireddy Mallikarjuna reddy dma_dev->device_prep_slave_sg = ldma_prep_slave_sg; 168632d31c79SAmireddy Mallikarjuna reddy 168732d31c79SAmireddy Mallikarjuna reddy if (d->ver == DMA_VER22) { 168832d31c79SAmireddy Mallikarjuna reddy dma_dev->device_config = ldma_slave_config; 168932d31c79SAmireddy Mallikarjuna reddy dma_dev->device_synchronize = ldma_synchronize; 169032d31c79SAmireddy Mallikarjuna reddy dma_dev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); 169132d31c79SAmireddy Mallikarjuna reddy dma_dev->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); 169232d31c79SAmireddy Mallikarjuna reddy dma_dev->directions = BIT(DMA_MEM_TO_DEV) | 169332d31c79SAmireddy Mallikarjuna reddy BIT(DMA_DEV_TO_MEM); 169432d31c79SAmireddy Mallikarjuna reddy dma_dev->residue_granularity = 169532d31c79SAmireddy Mallikarjuna reddy DMA_RESIDUE_GRANULARITY_DESCRIPTOR; 169632d31c79SAmireddy Mallikarjuna reddy } 169732d31c79SAmireddy Mallikarjuna reddy 169832d31c79SAmireddy Mallikarjuna reddy platform_set_drvdata(pdev, d); 169932d31c79SAmireddy Mallikarjuna reddy 170032d31c79SAmireddy Mallikarjuna reddy ldma_dev_init(d); 170132d31c79SAmireddy Mallikarjuna reddy 170232d31c79SAmireddy Mallikarjuna reddy ret = dma_async_device_register(dma_dev); 170332d31c79SAmireddy Mallikarjuna reddy if (ret) { 170432d31c79SAmireddy Mallikarjuna reddy dev_err(dev, "Failed to register slave DMA engine device\n"); 170532d31c79SAmireddy Mallikarjuna reddy return ret; 170632d31c79SAmireddy Mallikarjuna reddy } 170732d31c79SAmireddy Mallikarjuna reddy 170832d31c79SAmireddy Mallikarjuna reddy ret = of_dma_controller_register(pdev->dev.of_node, ldma_xlate, d); 170932d31c79SAmireddy Mallikarjuna reddy if (ret) { 171032d31c79SAmireddy Mallikarjuna reddy dev_err(dev, "Failed to register of DMA controller\n"); 171132d31c79SAmireddy Mallikarjuna reddy dma_async_device_unregister(dma_dev); 171232d31c79SAmireddy Mallikarjuna reddy return ret; 171332d31c79SAmireddy Mallikarjuna reddy } 171432d31c79SAmireddy Mallikarjuna reddy 171532d31c79SAmireddy Mallikarjuna reddy dev_info(dev, "Init done - rev: %x, ports: %d channels: %d\n", d->ver, 171632d31c79SAmireddy Mallikarjuna reddy d->port_nrs, d->chan_nrs); 171732d31c79SAmireddy Mallikarjuna reddy 171832d31c79SAmireddy Mallikarjuna reddy return 0; 171932d31c79SAmireddy Mallikarjuna reddy } 172032d31c79SAmireddy Mallikarjuna reddy 172132d31c79SAmireddy Mallikarjuna reddy static struct platform_driver intel_ldma_driver = { 172232d31c79SAmireddy Mallikarjuna reddy .probe = intel_ldma_probe, 172332d31c79SAmireddy Mallikarjuna reddy .driver = { 172432d31c79SAmireddy Mallikarjuna reddy .name = DRIVER_NAME, 172532d31c79SAmireddy Mallikarjuna reddy .of_match_table = intel_ldma_match, 172632d31c79SAmireddy Mallikarjuna reddy }, 172732d31c79SAmireddy Mallikarjuna reddy }; 172832d31c79SAmireddy Mallikarjuna reddy 172932d31c79SAmireddy Mallikarjuna reddy /* 173032d31c79SAmireddy Mallikarjuna reddy * Perform this driver as device_initcall to make sure initialization happens 173132d31c79SAmireddy Mallikarjuna reddy * before its DMA clients of some are platform specific and also to provide 173232d31c79SAmireddy Mallikarjuna reddy * registered DMA channels and DMA capabilities to clients before their 173332d31c79SAmireddy Mallikarjuna reddy * initialization. 173432d31c79SAmireddy Mallikarjuna reddy */ 173532d31c79SAmireddy Mallikarjuna reddy static int __init intel_ldma_init(void) 173632d31c79SAmireddy Mallikarjuna reddy { 173732d31c79SAmireddy Mallikarjuna reddy return platform_driver_register(&intel_ldma_driver); 173832d31c79SAmireddy Mallikarjuna reddy } 173932d31c79SAmireddy Mallikarjuna reddy 174032d31c79SAmireddy Mallikarjuna reddy device_initcall(intel_ldma_init); 1741