1*d7bff893SBaolin Wang // SPDX-License-Identifier: GPL-2.0 2*d7bff893SBaolin Wang // Copyright (C) 2019 Spreadtrum Communications Inc. 3*d7bff893SBaolin Wang 4*d7bff893SBaolin Wang #include <linux/errno.h> 5*d7bff893SBaolin Wang #include <linux/interrupt.h> 6*d7bff893SBaolin Wang #include <linux/io.h> 7*d7bff893SBaolin Wang #include <linux/kernel.h> 8*d7bff893SBaolin Wang #include <linux/module.h> 9*d7bff893SBaolin Wang #include <linux/mutex.h> 10*d7bff893SBaolin Wang #include <linux/of.h> 11*d7bff893SBaolin Wang #include <linux/platform_device.h> 12*d7bff893SBaolin Wang #include <linux/spinlock.h> 13*d7bff893SBaolin Wang 14*d7bff893SBaolin Wang #include "sprd-mcdt.h" 15*d7bff893SBaolin Wang 16*d7bff893SBaolin Wang /* MCDT registers definition */ 17*d7bff893SBaolin Wang #define MCDT_CH0_TXD 0x0 18*d7bff893SBaolin Wang #define MCDT_CH0_RXD 0x28 19*d7bff893SBaolin Wang #define MCDT_DAC0_WTMK 0x60 20*d7bff893SBaolin Wang #define MCDT_ADC0_WTMK 0x88 21*d7bff893SBaolin Wang #define MCDT_DMA_EN 0xb0 22*d7bff893SBaolin Wang 23*d7bff893SBaolin Wang #define MCDT_INT_EN0 0xb4 24*d7bff893SBaolin Wang #define MCDT_INT_EN1 0xb8 25*d7bff893SBaolin Wang #define MCDT_INT_EN2 0xbc 26*d7bff893SBaolin Wang 27*d7bff893SBaolin Wang #define MCDT_INT_CLR0 0xc0 28*d7bff893SBaolin Wang #define MCDT_INT_CLR1 0xc4 29*d7bff893SBaolin Wang #define MCDT_INT_CLR2 0xc8 30*d7bff893SBaolin Wang 31*d7bff893SBaolin Wang #define MCDT_INT_RAW1 0xcc 32*d7bff893SBaolin Wang #define MCDT_INT_RAW2 0xd0 33*d7bff893SBaolin Wang #define MCDT_INT_RAW3 0xd4 34*d7bff893SBaolin Wang 35*d7bff893SBaolin Wang #define MCDT_INT_MSK1 0xd8 36*d7bff893SBaolin Wang #define MCDT_INT_MSK2 0xdc 37*d7bff893SBaolin Wang #define MCDT_INT_MSK3 0xe0 38*d7bff893SBaolin Wang 39*d7bff893SBaolin Wang #define MCDT_DAC0_FIFO_ADDR_ST 0xe4 40*d7bff893SBaolin Wang #define MCDT_ADC0_FIFO_ADDR_ST 0xe8 41*d7bff893SBaolin Wang 42*d7bff893SBaolin Wang #define MCDT_CH_FIFO_ST0 0x134 43*d7bff893SBaolin Wang #define MCDT_CH_FIFO_ST1 0x138 44*d7bff893SBaolin Wang #define MCDT_CH_FIFO_ST2 0x13c 45*d7bff893SBaolin Wang 46*d7bff893SBaolin Wang #define MCDT_INT_MSK_CFG0 0x140 47*d7bff893SBaolin Wang #define MCDT_INT_MSK_CFG1 0x144 48*d7bff893SBaolin Wang 49*d7bff893SBaolin Wang #define MCDT_DMA_CFG0 0x148 50*d7bff893SBaolin Wang #define MCDT_FIFO_CLR 0x14c 51*d7bff893SBaolin Wang #define MCDT_DMA_CFG1 0x150 52*d7bff893SBaolin Wang #define MCDT_DMA_CFG2 0x154 53*d7bff893SBaolin Wang #define MCDT_DMA_CFG3 0x158 54*d7bff893SBaolin Wang #define MCDT_DMA_CFG4 0x15c 55*d7bff893SBaolin Wang #define MCDT_DMA_CFG5 0x160 56*d7bff893SBaolin Wang 57*d7bff893SBaolin Wang /* Channel water mark definition */ 58*d7bff893SBaolin Wang #define MCDT_CH_FIFO_AE_SHIFT 16 59*d7bff893SBaolin Wang #define MCDT_CH_FIFO_AE_MASK GENMASK(24, 16) 60*d7bff893SBaolin Wang #define MCDT_CH_FIFO_AF_MASK GENMASK(8, 0) 61*d7bff893SBaolin Wang 62*d7bff893SBaolin Wang /* DMA channel select definition */ 63*d7bff893SBaolin Wang #define MCDT_DMA_CH0_SEL_MASK GENMASK(3, 0) 64*d7bff893SBaolin Wang #define MCDT_DMA_CH0_SEL_SHIFT 0 65*d7bff893SBaolin Wang #define MCDT_DMA_CH1_SEL_MASK GENMASK(7, 4) 66*d7bff893SBaolin Wang #define MCDT_DMA_CH1_SEL_SHIFT 4 67*d7bff893SBaolin Wang #define MCDT_DMA_CH2_SEL_MASK GENMASK(11, 8) 68*d7bff893SBaolin Wang #define MCDT_DMA_CH2_SEL_SHIFT 8 69*d7bff893SBaolin Wang #define MCDT_DMA_CH3_SEL_MASK GENMASK(15, 12) 70*d7bff893SBaolin Wang #define MCDT_DMA_CH3_SEL_SHIFT 12 71*d7bff893SBaolin Wang #define MCDT_DMA_CH4_SEL_MASK GENMASK(19, 16) 72*d7bff893SBaolin Wang #define MCDT_DMA_CH4_SEL_SHIFT 16 73*d7bff893SBaolin Wang #define MCDT_DAC_DMA_SHIFT 16 74*d7bff893SBaolin Wang 75*d7bff893SBaolin Wang /* DMA channel ACK select definition */ 76*d7bff893SBaolin Wang #define MCDT_DMA_ACK_SEL_MASK GENMASK(3, 0) 77*d7bff893SBaolin Wang 78*d7bff893SBaolin Wang /* Channel FIFO definition */ 79*d7bff893SBaolin Wang #define MCDT_CH_FIFO_ADDR_SHIFT 16 80*d7bff893SBaolin Wang #define MCDT_CH_FIFO_ADDR_MASK GENMASK(9, 0) 81*d7bff893SBaolin Wang #define MCDT_ADC_FIFO_SHIFT 16 82*d7bff893SBaolin Wang #define MCDT_FIFO_LENGTH 512 83*d7bff893SBaolin Wang 84*d7bff893SBaolin Wang #define MCDT_ADC_CHANNEL_NUM 10 85*d7bff893SBaolin Wang #define MCDT_DAC_CHANNEL_NUM 10 86*d7bff893SBaolin Wang #define MCDT_CHANNEL_NUM (MCDT_ADC_CHANNEL_NUM + MCDT_DAC_CHANNEL_NUM) 87*d7bff893SBaolin Wang 88*d7bff893SBaolin Wang enum sprd_mcdt_fifo_int { 89*d7bff893SBaolin Wang MCDT_ADC_FIFO_AE_INT, 90*d7bff893SBaolin Wang MCDT_ADC_FIFO_AF_INT, 91*d7bff893SBaolin Wang MCDT_DAC_FIFO_AE_INT, 92*d7bff893SBaolin Wang MCDT_DAC_FIFO_AF_INT, 93*d7bff893SBaolin Wang MCDT_ADC_FIFO_OV_INT, 94*d7bff893SBaolin Wang MCDT_DAC_FIFO_OV_INT 95*d7bff893SBaolin Wang }; 96*d7bff893SBaolin Wang 97*d7bff893SBaolin Wang enum sprd_mcdt_fifo_sts { 98*d7bff893SBaolin Wang MCDT_ADC_FIFO_REAL_FULL, 99*d7bff893SBaolin Wang MCDT_ADC_FIFO_REAL_EMPTY, 100*d7bff893SBaolin Wang MCDT_ADC_FIFO_AF, 101*d7bff893SBaolin Wang MCDT_ADC_FIFO_AE, 102*d7bff893SBaolin Wang MCDT_DAC_FIFO_REAL_FULL, 103*d7bff893SBaolin Wang MCDT_DAC_FIFO_REAL_EMPTY, 104*d7bff893SBaolin Wang MCDT_DAC_FIFO_AF, 105*d7bff893SBaolin Wang MCDT_DAC_FIFO_AE 106*d7bff893SBaolin Wang }; 107*d7bff893SBaolin Wang 108*d7bff893SBaolin Wang struct sprd_mcdt_dev { 109*d7bff893SBaolin Wang struct device *dev; 110*d7bff893SBaolin Wang void __iomem *base; 111*d7bff893SBaolin Wang spinlock_t lock; 112*d7bff893SBaolin Wang struct sprd_mcdt_chan chan[MCDT_CHANNEL_NUM]; 113*d7bff893SBaolin Wang }; 114*d7bff893SBaolin Wang 115*d7bff893SBaolin Wang static LIST_HEAD(sprd_mcdt_chan_list); 116*d7bff893SBaolin Wang static DEFINE_MUTEX(sprd_mcdt_list_mutex); 117*d7bff893SBaolin Wang 118*d7bff893SBaolin Wang static void sprd_mcdt_update(struct sprd_mcdt_dev *mcdt, u32 reg, u32 val, 119*d7bff893SBaolin Wang u32 mask) 120*d7bff893SBaolin Wang { 121*d7bff893SBaolin Wang u32 orig = readl_relaxed(mcdt->base + reg); 122*d7bff893SBaolin Wang u32 tmp; 123*d7bff893SBaolin Wang 124*d7bff893SBaolin Wang tmp = (orig & ~mask) | val; 125*d7bff893SBaolin Wang writel_relaxed(tmp, mcdt->base + reg); 126*d7bff893SBaolin Wang } 127*d7bff893SBaolin Wang 128*d7bff893SBaolin Wang static void sprd_mcdt_dac_set_watermark(struct sprd_mcdt_dev *mcdt, u8 channel, 129*d7bff893SBaolin Wang u32 full, u32 empty) 130*d7bff893SBaolin Wang { 131*d7bff893SBaolin Wang u32 reg = MCDT_DAC0_WTMK + channel * 4; 132*d7bff893SBaolin Wang u32 water_mark = 133*d7bff893SBaolin Wang (empty << MCDT_CH_FIFO_AE_SHIFT) & MCDT_CH_FIFO_AE_MASK; 134*d7bff893SBaolin Wang 135*d7bff893SBaolin Wang water_mark |= full & MCDT_CH_FIFO_AF_MASK; 136*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, reg, water_mark, 137*d7bff893SBaolin Wang MCDT_CH_FIFO_AE_MASK | MCDT_CH_FIFO_AF_MASK); 138*d7bff893SBaolin Wang } 139*d7bff893SBaolin Wang 140*d7bff893SBaolin Wang static void sprd_mcdt_adc_set_watermark(struct sprd_mcdt_dev *mcdt, u8 channel, 141*d7bff893SBaolin Wang u32 full, u32 empty) 142*d7bff893SBaolin Wang { 143*d7bff893SBaolin Wang u32 reg = MCDT_ADC0_WTMK + channel * 4; 144*d7bff893SBaolin Wang u32 water_mark = 145*d7bff893SBaolin Wang (empty << MCDT_CH_FIFO_AE_SHIFT) & MCDT_CH_FIFO_AE_MASK; 146*d7bff893SBaolin Wang 147*d7bff893SBaolin Wang water_mark |= full & MCDT_CH_FIFO_AF_MASK; 148*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, reg, water_mark, 149*d7bff893SBaolin Wang MCDT_CH_FIFO_AE_MASK | MCDT_CH_FIFO_AF_MASK); 150*d7bff893SBaolin Wang } 151*d7bff893SBaolin Wang 152*d7bff893SBaolin Wang static void sprd_mcdt_dac_dma_enable(struct sprd_mcdt_dev *mcdt, u8 channel, 153*d7bff893SBaolin Wang bool enable) 154*d7bff893SBaolin Wang { 155*d7bff893SBaolin Wang u32 shift = MCDT_DAC_DMA_SHIFT + channel; 156*d7bff893SBaolin Wang 157*d7bff893SBaolin Wang if (enable) 158*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_EN, BIT(shift), BIT(shift)); 159*d7bff893SBaolin Wang else 160*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_EN, 0, BIT(shift)); 161*d7bff893SBaolin Wang } 162*d7bff893SBaolin Wang 163*d7bff893SBaolin Wang static void sprd_mcdt_adc_dma_enable(struct sprd_mcdt_dev *mcdt, u8 channel, 164*d7bff893SBaolin Wang bool enable) 165*d7bff893SBaolin Wang { 166*d7bff893SBaolin Wang if (enable) 167*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_EN, BIT(channel), BIT(channel)); 168*d7bff893SBaolin Wang else 169*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_EN, 0, BIT(channel)); 170*d7bff893SBaolin Wang } 171*d7bff893SBaolin Wang 172*d7bff893SBaolin Wang static void sprd_mcdt_ap_int_enable(struct sprd_mcdt_dev *mcdt, u8 channel, 173*d7bff893SBaolin Wang bool enable) 174*d7bff893SBaolin Wang { 175*d7bff893SBaolin Wang if (enable) 176*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_INT_MSK_CFG0, BIT(channel), 177*d7bff893SBaolin Wang BIT(channel)); 178*d7bff893SBaolin Wang else 179*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_INT_MSK_CFG0, 0, BIT(channel)); 180*d7bff893SBaolin Wang } 181*d7bff893SBaolin Wang 182*d7bff893SBaolin Wang static void sprd_mcdt_dac_write_fifo(struct sprd_mcdt_dev *mcdt, u8 channel, 183*d7bff893SBaolin Wang u32 val) 184*d7bff893SBaolin Wang { 185*d7bff893SBaolin Wang u32 reg = MCDT_CH0_TXD + channel * 4; 186*d7bff893SBaolin Wang 187*d7bff893SBaolin Wang writel_relaxed(val, mcdt->base + reg); 188*d7bff893SBaolin Wang } 189*d7bff893SBaolin Wang 190*d7bff893SBaolin Wang static void sprd_mcdt_adc_read_fifo(struct sprd_mcdt_dev *mcdt, u8 channel, 191*d7bff893SBaolin Wang u32 *val) 192*d7bff893SBaolin Wang { 193*d7bff893SBaolin Wang u32 reg = MCDT_CH0_RXD + channel * 4; 194*d7bff893SBaolin Wang 195*d7bff893SBaolin Wang *val = readl_relaxed(mcdt->base + reg); 196*d7bff893SBaolin Wang } 197*d7bff893SBaolin Wang 198*d7bff893SBaolin Wang static void sprd_mcdt_dac_dma_chn_select(struct sprd_mcdt_dev *mcdt, u8 channel, 199*d7bff893SBaolin Wang enum sprd_mcdt_dma_chan dma_chan) 200*d7bff893SBaolin Wang { 201*d7bff893SBaolin Wang switch (dma_chan) { 202*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH0: 203*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG0, 204*d7bff893SBaolin Wang channel << MCDT_DMA_CH0_SEL_SHIFT, 205*d7bff893SBaolin Wang MCDT_DMA_CH0_SEL_MASK); 206*d7bff893SBaolin Wang break; 207*d7bff893SBaolin Wang 208*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH1: 209*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG0, 210*d7bff893SBaolin Wang channel << MCDT_DMA_CH1_SEL_SHIFT, 211*d7bff893SBaolin Wang MCDT_DMA_CH1_SEL_MASK); 212*d7bff893SBaolin Wang break; 213*d7bff893SBaolin Wang 214*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH2: 215*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG0, 216*d7bff893SBaolin Wang channel << MCDT_DMA_CH2_SEL_SHIFT, 217*d7bff893SBaolin Wang MCDT_DMA_CH2_SEL_MASK); 218*d7bff893SBaolin Wang break; 219*d7bff893SBaolin Wang 220*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH3: 221*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG0, 222*d7bff893SBaolin Wang channel << MCDT_DMA_CH3_SEL_SHIFT, 223*d7bff893SBaolin Wang MCDT_DMA_CH3_SEL_MASK); 224*d7bff893SBaolin Wang break; 225*d7bff893SBaolin Wang 226*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH4: 227*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG0, 228*d7bff893SBaolin Wang channel << MCDT_DMA_CH4_SEL_SHIFT, 229*d7bff893SBaolin Wang MCDT_DMA_CH4_SEL_MASK); 230*d7bff893SBaolin Wang break; 231*d7bff893SBaolin Wang } 232*d7bff893SBaolin Wang } 233*d7bff893SBaolin Wang 234*d7bff893SBaolin Wang static void sprd_mcdt_adc_dma_chn_select(struct sprd_mcdt_dev *mcdt, u8 channel, 235*d7bff893SBaolin Wang enum sprd_mcdt_dma_chan dma_chan) 236*d7bff893SBaolin Wang { 237*d7bff893SBaolin Wang switch (dma_chan) { 238*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH0: 239*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG1, 240*d7bff893SBaolin Wang channel << MCDT_DMA_CH0_SEL_SHIFT, 241*d7bff893SBaolin Wang MCDT_DMA_CH0_SEL_MASK); 242*d7bff893SBaolin Wang break; 243*d7bff893SBaolin Wang 244*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH1: 245*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG1, 246*d7bff893SBaolin Wang channel << MCDT_DMA_CH1_SEL_SHIFT, 247*d7bff893SBaolin Wang MCDT_DMA_CH1_SEL_MASK); 248*d7bff893SBaolin Wang break; 249*d7bff893SBaolin Wang 250*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH2: 251*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG1, 252*d7bff893SBaolin Wang channel << MCDT_DMA_CH2_SEL_SHIFT, 253*d7bff893SBaolin Wang MCDT_DMA_CH2_SEL_MASK); 254*d7bff893SBaolin Wang break; 255*d7bff893SBaolin Wang 256*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH3: 257*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG1, 258*d7bff893SBaolin Wang channel << MCDT_DMA_CH3_SEL_SHIFT, 259*d7bff893SBaolin Wang MCDT_DMA_CH3_SEL_MASK); 260*d7bff893SBaolin Wang break; 261*d7bff893SBaolin Wang 262*d7bff893SBaolin Wang case SPRD_MCDT_DMA_CH4: 263*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_DMA_CFG1, 264*d7bff893SBaolin Wang channel << MCDT_DMA_CH4_SEL_SHIFT, 265*d7bff893SBaolin Wang MCDT_DMA_CH4_SEL_MASK); 266*d7bff893SBaolin Wang break; 267*d7bff893SBaolin Wang } 268*d7bff893SBaolin Wang } 269*d7bff893SBaolin Wang 270*d7bff893SBaolin Wang static u32 sprd_mcdt_dma_ack_shift(u8 channel) 271*d7bff893SBaolin Wang { 272*d7bff893SBaolin Wang switch (channel) { 273*d7bff893SBaolin Wang default: 274*d7bff893SBaolin Wang case 0: 275*d7bff893SBaolin Wang case 8: 276*d7bff893SBaolin Wang return 0; 277*d7bff893SBaolin Wang case 1: 278*d7bff893SBaolin Wang case 9: 279*d7bff893SBaolin Wang return 4; 280*d7bff893SBaolin Wang case 2: 281*d7bff893SBaolin Wang return 8; 282*d7bff893SBaolin Wang case 3: 283*d7bff893SBaolin Wang return 12; 284*d7bff893SBaolin Wang case 4: 285*d7bff893SBaolin Wang return 16; 286*d7bff893SBaolin Wang case 5: 287*d7bff893SBaolin Wang return 20; 288*d7bff893SBaolin Wang case 6: 289*d7bff893SBaolin Wang return 24; 290*d7bff893SBaolin Wang case 7: 291*d7bff893SBaolin Wang return 28; 292*d7bff893SBaolin Wang } 293*d7bff893SBaolin Wang } 294*d7bff893SBaolin Wang 295*d7bff893SBaolin Wang static void sprd_mcdt_dac_dma_ack_select(struct sprd_mcdt_dev *mcdt, u8 channel, 296*d7bff893SBaolin Wang enum sprd_mcdt_dma_chan dma_chan) 297*d7bff893SBaolin Wang { 298*d7bff893SBaolin Wang u32 reg, shift = sprd_mcdt_dma_ack_shift(channel), ack = dma_chan; 299*d7bff893SBaolin Wang 300*d7bff893SBaolin Wang switch (channel) { 301*d7bff893SBaolin Wang case 0 ... 7: 302*d7bff893SBaolin Wang reg = MCDT_DMA_CFG2; 303*d7bff893SBaolin Wang break; 304*d7bff893SBaolin Wang 305*d7bff893SBaolin Wang case 8 ... 9: 306*d7bff893SBaolin Wang reg = MCDT_DMA_CFG3; 307*d7bff893SBaolin Wang break; 308*d7bff893SBaolin Wang 309*d7bff893SBaolin Wang default: 310*d7bff893SBaolin Wang return; 311*d7bff893SBaolin Wang } 312*d7bff893SBaolin Wang 313*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, reg, ack << shift, 314*d7bff893SBaolin Wang MCDT_DMA_ACK_SEL_MASK << shift); 315*d7bff893SBaolin Wang } 316*d7bff893SBaolin Wang 317*d7bff893SBaolin Wang static void sprd_mcdt_adc_dma_ack_select(struct sprd_mcdt_dev *mcdt, u8 channel, 318*d7bff893SBaolin Wang enum sprd_mcdt_dma_chan dma_chan) 319*d7bff893SBaolin Wang { 320*d7bff893SBaolin Wang u32 reg, shift = sprd_mcdt_dma_ack_shift(channel), ack = dma_chan; 321*d7bff893SBaolin Wang 322*d7bff893SBaolin Wang switch (channel) { 323*d7bff893SBaolin Wang case 0 ... 7: 324*d7bff893SBaolin Wang reg = MCDT_DMA_CFG4; 325*d7bff893SBaolin Wang break; 326*d7bff893SBaolin Wang 327*d7bff893SBaolin Wang case 8 ... 9: 328*d7bff893SBaolin Wang reg = MCDT_DMA_CFG5; 329*d7bff893SBaolin Wang break; 330*d7bff893SBaolin Wang 331*d7bff893SBaolin Wang default: 332*d7bff893SBaolin Wang return; 333*d7bff893SBaolin Wang } 334*d7bff893SBaolin Wang 335*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, reg, ack << shift, 336*d7bff893SBaolin Wang MCDT_DMA_ACK_SEL_MASK << shift); 337*d7bff893SBaolin Wang } 338*d7bff893SBaolin Wang 339*d7bff893SBaolin Wang static bool sprd_mcdt_chan_fifo_sts(struct sprd_mcdt_dev *mcdt, u8 channel, 340*d7bff893SBaolin Wang enum sprd_mcdt_fifo_sts fifo_sts) 341*d7bff893SBaolin Wang { 342*d7bff893SBaolin Wang u32 reg, shift; 343*d7bff893SBaolin Wang 344*d7bff893SBaolin Wang switch (channel) { 345*d7bff893SBaolin Wang case 0 ... 3: 346*d7bff893SBaolin Wang reg = MCDT_CH_FIFO_ST0; 347*d7bff893SBaolin Wang break; 348*d7bff893SBaolin Wang case 4 ... 7: 349*d7bff893SBaolin Wang reg = MCDT_CH_FIFO_ST1; 350*d7bff893SBaolin Wang break; 351*d7bff893SBaolin Wang case 8 ... 9: 352*d7bff893SBaolin Wang reg = MCDT_CH_FIFO_ST2; 353*d7bff893SBaolin Wang break; 354*d7bff893SBaolin Wang default: 355*d7bff893SBaolin Wang return false; 356*d7bff893SBaolin Wang } 357*d7bff893SBaolin Wang 358*d7bff893SBaolin Wang switch (channel) { 359*d7bff893SBaolin Wang case 0: 360*d7bff893SBaolin Wang case 4: 361*d7bff893SBaolin Wang case 8: 362*d7bff893SBaolin Wang shift = fifo_sts; 363*d7bff893SBaolin Wang break; 364*d7bff893SBaolin Wang 365*d7bff893SBaolin Wang case 1: 366*d7bff893SBaolin Wang case 5: 367*d7bff893SBaolin Wang case 9: 368*d7bff893SBaolin Wang shift = 8 + fifo_sts; 369*d7bff893SBaolin Wang break; 370*d7bff893SBaolin Wang 371*d7bff893SBaolin Wang case 2: 372*d7bff893SBaolin Wang case 6: 373*d7bff893SBaolin Wang shift = 16 + fifo_sts; 374*d7bff893SBaolin Wang break; 375*d7bff893SBaolin Wang 376*d7bff893SBaolin Wang case 3: 377*d7bff893SBaolin Wang case 7: 378*d7bff893SBaolin Wang shift = 24 + fifo_sts; 379*d7bff893SBaolin Wang break; 380*d7bff893SBaolin Wang 381*d7bff893SBaolin Wang default: 382*d7bff893SBaolin Wang return false; 383*d7bff893SBaolin Wang } 384*d7bff893SBaolin Wang 385*d7bff893SBaolin Wang return !!(readl_relaxed(mcdt->base + reg) & BIT(shift)); 386*d7bff893SBaolin Wang } 387*d7bff893SBaolin Wang 388*d7bff893SBaolin Wang static void sprd_mcdt_dac_fifo_clear(struct sprd_mcdt_dev *mcdt, u8 channel) 389*d7bff893SBaolin Wang { 390*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_FIFO_CLR, BIT(channel), BIT(channel)); 391*d7bff893SBaolin Wang } 392*d7bff893SBaolin Wang 393*d7bff893SBaolin Wang static void sprd_mcdt_adc_fifo_clear(struct sprd_mcdt_dev *mcdt, u8 channel) 394*d7bff893SBaolin Wang { 395*d7bff893SBaolin Wang u32 shift = MCDT_ADC_FIFO_SHIFT + channel; 396*d7bff893SBaolin Wang 397*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, MCDT_FIFO_CLR, BIT(shift), BIT(shift)); 398*d7bff893SBaolin Wang } 399*d7bff893SBaolin Wang 400*d7bff893SBaolin Wang static u32 sprd_mcdt_dac_fifo_avail(struct sprd_mcdt_dev *mcdt, u8 channel) 401*d7bff893SBaolin Wang { 402*d7bff893SBaolin Wang u32 reg = MCDT_DAC0_FIFO_ADDR_ST + channel * 8; 403*d7bff893SBaolin Wang u32 r_addr = (readl_relaxed(mcdt->base + reg) >> 404*d7bff893SBaolin Wang MCDT_CH_FIFO_ADDR_SHIFT) & MCDT_CH_FIFO_ADDR_MASK; 405*d7bff893SBaolin Wang u32 w_addr = readl_relaxed(mcdt->base + reg) & MCDT_CH_FIFO_ADDR_MASK; 406*d7bff893SBaolin Wang 407*d7bff893SBaolin Wang if (w_addr >= r_addr) 408*d7bff893SBaolin Wang return 4 * (MCDT_FIFO_LENGTH - w_addr + r_addr); 409*d7bff893SBaolin Wang else 410*d7bff893SBaolin Wang return 4 * (r_addr - w_addr); 411*d7bff893SBaolin Wang } 412*d7bff893SBaolin Wang 413*d7bff893SBaolin Wang static u32 sprd_mcdt_adc_fifo_avail(struct sprd_mcdt_dev *mcdt, u8 channel) 414*d7bff893SBaolin Wang { 415*d7bff893SBaolin Wang u32 reg = MCDT_ADC0_FIFO_ADDR_ST + channel * 8; 416*d7bff893SBaolin Wang u32 r_addr = (readl_relaxed(mcdt->base + reg) >> 417*d7bff893SBaolin Wang MCDT_CH_FIFO_ADDR_SHIFT) & MCDT_CH_FIFO_ADDR_MASK; 418*d7bff893SBaolin Wang u32 w_addr = readl_relaxed(mcdt->base + reg) & MCDT_CH_FIFO_ADDR_MASK; 419*d7bff893SBaolin Wang 420*d7bff893SBaolin Wang if (w_addr >= r_addr) 421*d7bff893SBaolin Wang return 4 * (w_addr - r_addr); 422*d7bff893SBaolin Wang else 423*d7bff893SBaolin Wang return 4 * (MCDT_FIFO_LENGTH - r_addr + w_addr); 424*d7bff893SBaolin Wang } 425*d7bff893SBaolin Wang 426*d7bff893SBaolin Wang static u32 sprd_mcdt_int_type_shift(u8 channel, 427*d7bff893SBaolin Wang enum sprd_mcdt_fifo_int int_type) 428*d7bff893SBaolin Wang { 429*d7bff893SBaolin Wang switch (channel) { 430*d7bff893SBaolin Wang case 0: 431*d7bff893SBaolin Wang case 4: 432*d7bff893SBaolin Wang case 8: 433*d7bff893SBaolin Wang return int_type; 434*d7bff893SBaolin Wang 435*d7bff893SBaolin Wang case 1: 436*d7bff893SBaolin Wang case 5: 437*d7bff893SBaolin Wang case 9: 438*d7bff893SBaolin Wang return 8 + int_type; 439*d7bff893SBaolin Wang 440*d7bff893SBaolin Wang case 2: 441*d7bff893SBaolin Wang case 6: 442*d7bff893SBaolin Wang return 16 + int_type; 443*d7bff893SBaolin Wang 444*d7bff893SBaolin Wang case 3: 445*d7bff893SBaolin Wang case 7: 446*d7bff893SBaolin Wang return 24 + int_type; 447*d7bff893SBaolin Wang 448*d7bff893SBaolin Wang default: 449*d7bff893SBaolin Wang return 0; 450*d7bff893SBaolin Wang } 451*d7bff893SBaolin Wang } 452*d7bff893SBaolin Wang 453*d7bff893SBaolin Wang static void sprd_mcdt_chan_int_en(struct sprd_mcdt_dev *mcdt, u8 channel, 454*d7bff893SBaolin Wang enum sprd_mcdt_fifo_int int_type, bool enable) 455*d7bff893SBaolin Wang { 456*d7bff893SBaolin Wang u32 reg, shift = sprd_mcdt_int_type_shift(channel, int_type); 457*d7bff893SBaolin Wang 458*d7bff893SBaolin Wang switch (channel) { 459*d7bff893SBaolin Wang case 0 ... 3: 460*d7bff893SBaolin Wang reg = MCDT_INT_EN0; 461*d7bff893SBaolin Wang break; 462*d7bff893SBaolin Wang case 4 ... 7: 463*d7bff893SBaolin Wang reg = MCDT_INT_EN1; 464*d7bff893SBaolin Wang break; 465*d7bff893SBaolin Wang case 8 ... 9: 466*d7bff893SBaolin Wang reg = MCDT_INT_EN2; 467*d7bff893SBaolin Wang break; 468*d7bff893SBaolin Wang default: 469*d7bff893SBaolin Wang return; 470*d7bff893SBaolin Wang } 471*d7bff893SBaolin Wang 472*d7bff893SBaolin Wang if (enable) 473*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, reg, BIT(shift), BIT(shift)); 474*d7bff893SBaolin Wang else 475*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, reg, 0, BIT(shift)); 476*d7bff893SBaolin Wang } 477*d7bff893SBaolin Wang 478*d7bff893SBaolin Wang static void sprd_mcdt_chan_int_clear(struct sprd_mcdt_dev *mcdt, u8 channel, 479*d7bff893SBaolin Wang enum sprd_mcdt_fifo_int int_type) 480*d7bff893SBaolin Wang { 481*d7bff893SBaolin Wang u32 reg, shift = sprd_mcdt_int_type_shift(channel, int_type); 482*d7bff893SBaolin Wang 483*d7bff893SBaolin Wang switch (channel) { 484*d7bff893SBaolin Wang case 0 ... 3: 485*d7bff893SBaolin Wang reg = MCDT_INT_CLR0; 486*d7bff893SBaolin Wang break; 487*d7bff893SBaolin Wang case 4 ... 7: 488*d7bff893SBaolin Wang reg = MCDT_INT_CLR1; 489*d7bff893SBaolin Wang break; 490*d7bff893SBaolin Wang case 8 ... 9: 491*d7bff893SBaolin Wang reg = MCDT_INT_CLR2; 492*d7bff893SBaolin Wang break; 493*d7bff893SBaolin Wang default: 494*d7bff893SBaolin Wang return; 495*d7bff893SBaolin Wang } 496*d7bff893SBaolin Wang 497*d7bff893SBaolin Wang sprd_mcdt_update(mcdt, reg, BIT(shift), BIT(shift)); 498*d7bff893SBaolin Wang } 499*d7bff893SBaolin Wang 500*d7bff893SBaolin Wang static bool sprd_mcdt_chan_int_sts(struct sprd_mcdt_dev *mcdt, u8 channel, 501*d7bff893SBaolin Wang enum sprd_mcdt_fifo_int int_type) 502*d7bff893SBaolin Wang { 503*d7bff893SBaolin Wang u32 reg, shift = sprd_mcdt_int_type_shift(channel, int_type); 504*d7bff893SBaolin Wang 505*d7bff893SBaolin Wang switch (channel) { 506*d7bff893SBaolin Wang case 0 ... 3: 507*d7bff893SBaolin Wang reg = MCDT_INT_MSK1; 508*d7bff893SBaolin Wang break; 509*d7bff893SBaolin Wang case 4 ... 7: 510*d7bff893SBaolin Wang reg = MCDT_INT_MSK2; 511*d7bff893SBaolin Wang break; 512*d7bff893SBaolin Wang case 8 ... 9: 513*d7bff893SBaolin Wang reg = MCDT_INT_MSK3; 514*d7bff893SBaolin Wang break; 515*d7bff893SBaolin Wang default: 516*d7bff893SBaolin Wang return false; 517*d7bff893SBaolin Wang } 518*d7bff893SBaolin Wang 519*d7bff893SBaolin Wang return !!(readl_relaxed(mcdt->base + reg) & BIT(shift)); 520*d7bff893SBaolin Wang } 521*d7bff893SBaolin Wang 522*d7bff893SBaolin Wang static irqreturn_t sprd_mcdt_irq_handler(int irq, void *dev_id) 523*d7bff893SBaolin Wang { 524*d7bff893SBaolin Wang struct sprd_mcdt_dev *mcdt = (struct sprd_mcdt_dev *)dev_id; 525*d7bff893SBaolin Wang int i; 526*d7bff893SBaolin Wang 527*d7bff893SBaolin Wang spin_lock(&mcdt->lock); 528*d7bff893SBaolin Wang 529*d7bff893SBaolin Wang for (i = 0; i < MCDT_ADC_CHANNEL_NUM; i++) { 530*d7bff893SBaolin Wang if (sprd_mcdt_chan_int_sts(mcdt, i, MCDT_ADC_FIFO_AF_INT)) { 531*d7bff893SBaolin Wang struct sprd_mcdt_chan *chan = &mcdt->chan[i]; 532*d7bff893SBaolin Wang 533*d7bff893SBaolin Wang sprd_mcdt_chan_int_clear(mcdt, i, MCDT_ADC_FIFO_AF_INT); 534*d7bff893SBaolin Wang if (chan->cb) 535*d7bff893SBaolin Wang chan->cb->notify(chan->cb->data); 536*d7bff893SBaolin Wang } 537*d7bff893SBaolin Wang } 538*d7bff893SBaolin Wang 539*d7bff893SBaolin Wang for (i = 0; i < MCDT_DAC_CHANNEL_NUM; i++) { 540*d7bff893SBaolin Wang if (sprd_mcdt_chan_int_sts(mcdt, i, MCDT_DAC_FIFO_AE_INT)) { 541*d7bff893SBaolin Wang struct sprd_mcdt_chan *chan = 542*d7bff893SBaolin Wang &mcdt->chan[i + MCDT_ADC_CHANNEL_NUM]; 543*d7bff893SBaolin Wang 544*d7bff893SBaolin Wang sprd_mcdt_chan_int_clear(mcdt, i, MCDT_DAC_FIFO_AE_INT); 545*d7bff893SBaolin Wang if (chan->cb) 546*d7bff893SBaolin Wang chan->cb->notify(chan->cb->data); 547*d7bff893SBaolin Wang } 548*d7bff893SBaolin Wang } 549*d7bff893SBaolin Wang 550*d7bff893SBaolin Wang spin_unlock(&mcdt->lock); 551*d7bff893SBaolin Wang 552*d7bff893SBaolin Wang return IRQ_HANDLED; 553*d7bff893SBaolin Wang } 554*d7bff893SBaolin Wang 555*d7bff893SBaolin Wang /** 556*d7bff893SBaolin Wang * sprd_mcdt_chan_write - write data to the MCDT channel's fifo 557*d7bff893SBaolin Wang * @chan: the MCDT channel 558*d7bff893SBaolin Wang * @tx_buf: send buffer 559*d7bff893SBaolin Wang * @size: data size 560*d7bff893SBaolin Wang * 561*d7bff893SBaolin Wang * Note: We can not write data to the channel fifo when enabling the DMA mode, 562*d7bff893SBaolin Wang * otherwise the channel fifo data will be invalid. 563*d7bff893SBaolin Wang * 564*d7bff893SBaolin Wang * If there are not enough space of the channel fifo, it will return errors 565*d7bff893SBaolin Wang * to users. 566*d7bff893SBaolin Wang * 567*d7bff893SBaolin Wang * Returns 0 on success, or an appropriate error code on failure. 568*d7bff893SBaolin Wang */ 569*d7bff893SBaolin Wang int sprd_mcdt_chan_write(struct sprd_mcdt_chan *chan, char *tx_buf, u32 size) 570*d7bff893SBaolin Wang { 571*d7bff893SBaolin Wang struct sprd_mcdt_dev *mcdt = chan->mcdt; 572*d7bff893SBaolin Wang unsigned long flags; 573*d7bff893SBaolin Wang int avail, i = 0, words = size / 4; 574*d7bff893SBaolin Wang u32 *buf = (u32 *)tx_buf; 575*d7bff893SBaolin Wang 576*d7bff893SBaolin Wang spin_lock_irqsave(&mcdt->lock, flags); 577*d7bff893SBaolin Wang 578*d7bff893SBaolin Wang if (chan->dma_enable) { 579*d7bff893SBaolin Wang dev_err(mcdt->dev, 580*d7bff893SBaolin Wang "Can not write data when DMA mode enabled\n"); 581*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 582*d7bff893SBaolin Wang return -EINVAL; 583*d7bff893SBaolin Wang } 584*d7bff893SBaolin Wang 585*d7bff893SBaolin Wang if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_DAC_FIFO_REAL_FULL)) { 586*d7bff893SBaolin Wang dev_err(mcdt->dev, "Channel fifo is full now\n"); 587*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 588*d7bff893SBaolin Wang return -EBUSY; 589*d7bff893SBaolin Wang } 590*d7bff893SBaolin Wang 591*d7bff893SBaolin Wang avail = sprd_mcdt_dac_fifo_avail(mcdt, chan->id); 592*d7bff893SBaolin Wang if (size > avail) { 593*d7bff893SBaolin Wang dev_err(mcdt->dev, 594*d7bff893SBaolin Wang "Data size is larger than the available fifo size\n"); 595*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 596*d7bff893SBaolin Wang return -EBUSY; 597*d7bff893SBaolin Wang } 598*d7bff893SBaolin Wang 599*d7bff893SBaolin Wang while (i++ < words) 600*d7bff893SBaolin Wang sprd_mcdt_dac_write_fifo(mcdt, chan->id, *buf++); 601*d7bff893SBaolin Wang 602*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 603*d7bff893SBaolin Wang return 0; 604*d7bff893SBaolin Wang } 605*d7bff893SBaolin Wang EXPORT_SYMBOL_GPL(sprd_mcdt_chan_write); 606*d7bff893SBaolin Wang 607*d7bff893SBaolin Wang /** 608*d7bff893SBaolin Wang * sprd_mcdt_chan_read - read data from the MCDT channel's fifo 609*d7bff893SBaolin Wang * @chan: the MCDT channel 610*d7bff893SBaolin Wang * @rx_buf: receive buffer 611*d7bff893SBaolin Wang * @size: data size 612*d7bff893SBaolin Wang * 613*d7bff893SBaolin Wang * Note: We can not read data from the channel fifo when enabling the DMA mode, 614*d7bff893SBaolin Wang * otherwise the reading data will be invalid. 615*d7bff893SBaolin Wang * 616*d7bff893SBaolin Wang * Usually user need start to read data once receiving the fifo full interrupt. 617*d7bff893SBaolin Wang * 618*d7bff893SBaolin Wang * Returns data size of reading successfully, or an error code on failure. 619*d7bff893SBaolin Wang */ 620*d7bff893SBaolin Wang int sprd_mcdt_chan_read(struct sprd_mcdt_chan *chan, char *rx_buf, u32 size) 621*d7bff893SBaolin Wang { 622*d7bff893SBaolin Wang struct sprd_mcdt_dev *mcdt = chan->mcdt; 623*d7bff893SBaolin Wang unsigned long flags; 624*d7bff893SBaolin Wang int i = 0, avail, words = size / 4; 625*d7bff893SBaolin Wang u32 *buf = (u32 *)rx_buf; 626*d7bff893SBaolin Wang 627*d7bff893SBaolin Wang spin_lock_irqsave(&mcdt->lock, flags); 628*d7bff893SBaolin Wang 629*d7bff893SBaolin Wang if (chan->dma_enable) { 630*d7bff893SBaolin Wang dev_err(mcdt->dev, "Can not read data when DMA mode enabled\n"); 631*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 632*d7bff893SBaolin Wang return -EINVAL; 633*d7bff893SBaolin Wang } 634*d7bff893SBaolin Wang 635*d7bff893SBaolin Wang if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_ADC_FIFO_REAL_EMPTY)) { 636*d7bff893SBaolin Wang dev_err(mcdt->dev, "Channel fifo is empty\n"); 637*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 638*d7bff893SBaolin Wang return -EBUSY; 639*d7bff893SBaolin Wang } 640*d7bff893SBaolin Wang 641*d7bff893SBaolin Wang avail = sprd_mcdt_adc_fifo_avail(mcdt, chan->id); 642*d7bff893SBaolin Wang if (size > avail) 643*d7bff893SBaolin Wang words = avail / 4; 644*d7bff893SBaolin Wang 645*d7bff893SBaolin Wang while (i++ < words) 646*d7bff893SBaolin Wang sprd_mcdt_adc_read_fifo(mcdt, chan->id, buf++); 647*d7bff893SBaolin Wang 648*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 649*d7bff893SBaolin Wang return words * 4; 650*d7bff893SBaolin Wang } 651*d7bff893SBaolin Wang EXPORT_SYMBOL_GPL(sprd_mcdt_chan_read); 652*d7bff893SBaolin Wang 653*d7bff893SBaolin Wang /** 654*d7bff893SBaolin Wang * sprd_mcdt_chan_int_enable - enable the interrupt mode for the MCDT channel 655*d7bff893SBaolin Wang * @chan: the MCDT channel 656*d7bff893SBaolin Wang * @water_mark: water mark to trigger a interrupt 657*d7bff893SBaolin Wang * @cb: callback when a interrupt happened 658*d7bff893SBaolin Wang * 659*d7bff893SBaolin Wang * Now it only can enable fifo almost full interrupt for ADC channel and fifo 660*d7bff893SBaolin Wang * almost empty interrupt for DAC channel. Morevoer for interrupt mode, user 661*d7bff893SBaolin Wang * should use sprd_mcdt_chan_read() or sprd_mcdt_chan_write() to read or write 662*d7bff893SBaolin Wang * data manually. 663*d7bff893SBaolin Wang * 664*d7bff893SBaolin Wang * For ADC channel, user can start to read data once receiving one fifo full 665*d7bff893SBaolin Wang * interrupt. For DAC channel, user can start to write data once receiving one 666*d7bff893SBaolin Wang * fifo empty interrupt or just call sprd_mcdt_chan_write() to write data 667*d7bff893SBaolin Wang * directly. 668*d7bff893SBaolin Wang * 669*d7bff893SBaolin Wang * Returns 0 on success, or an error code on failure. 670*d7bff893SBaolin Wang */ 671*d7bff893SBaolin Wang int sprd_mcdt_chan_int_enable(struct sprd_mcdt_chan *chan, u32 water_mark, 672*d7bff893SBaolin Wang struct sprd_mcdt_chan_callback *cb) 673*d7bff893SBaolin Wang { 674*d7bff893SBaolin Wang struct sprd_mcdt_dev *mcdt = chan->mcdt; 675*d7bff893SBaolin Wang unsigned long flags; 676*d7bff893SBaolin Wang int ret = 0; 677*d7bff893SBaolin Wang 678*d7bff893SBaolin Wang spin_lock_irqsave(&mcdt->lock, flags); 679*d7bff893SBaolin Wang 680*d7bff893SBaolin Wang if (chan->dma_enable || chan->int_enable) { 681*d7bff893SBaolin Wang dev_err(mcdt->dev, "Failed to set interrupt mode.\n"); 682*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 683*d7bff893SBaolin Wang return -EINVAL; 684*d7bff893SBaolin Wang } 685*d7bff893SBaolin Wang 686*d7bff893SBaolin Wang switch (chan->type) { 687*d7bff893SBaolin Wang case SPRD_MCDT_ADC_CHAN: 688*d7bff893SBaolin Wang sprd_mcdt_adc_fifo_clear(mcdt, chan->id); 689*d7bff893SBaolin Wang sprd_mcdt_adc_set_watermark(mcdt, chan->id, water_mark, 690*d7bff893SBaolin Wang MCDT_FIFO_LENGTH - 1); 691*d7bff893SBaolin Wang sprd_mcdt_chan_int_en(mcdt, chan->id, 692*d7bff893SBaolin Wang MCDT_ADC_FIFO_AF_INT, true); 693*d7bff893SBaolin Wang sprd_mcdt_ap_int_enable(mcdt, chan->id, true); 694*d7bff893SBaolin Wang break; 695*d7bff893SBaolin Wang 696*d7bff893SBaolin Wang case SPRD_MCDT_DAC_CHAN: 697*d7bff893SBaolin Wang sprd_mcdt_dac_fifo_clear(mcdt, chan->id); 698*d7bff893SBaolin Wang sprd_mcdt_dac_set_watermark(mcdt, chan->id, 699*d7bff893SBaolin Wang MCDT_FIFO_LENGTH - 1, water_mark); 700*d7bff893SBaolin Wang sprd_mcdt_chan_int_en(mcdt, chan->id, 701*d7bff893SBaolin Wang MCDT_DAC_FIFO_AE_INT, true); 702*d7bff893SBaolin Wang sprd_mcdt_ap_int_enable(mcdt, chan->id, true); 703*d7bff893SBaolin Wang break; 704*d7bff893SBaolin Wang 705*d7bff893SBaolin Wang default: 706*d7bff893SBaolin Wang dev_err(mcdt->dev, "Unsupported channel type\n"); 707*d7bff893SBaolin Wang ret = -EINVAL; 708*d7bff893SBaolin Wang } 709*d7bff893SBaolin Wang 710*d7bff893SBaolin Wang if (!ret) { 711*d7bff893SBaolin Wang chan->cb = cb; 712*d7bff893SBaolin Wang chan->int_enable = true; 713*d7bff893SBaolin Wang } 714*d7bff893SBaolin Wang 715*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 716*d7bff893SBaolin Wang 717*d7bff893SBaolin Wang return ret; 718*d7bff893SBaolin Wang } 719*d7bff893SBaolin Wang EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_enable); 720*d7bff893SBaolin Wang 721*d7bff893SBaolin Wang /** 722*d7bff893SBaolin Wang * sprd_mcdt_chan_int_disable - disable the interrupt mode for the MCDT channel 723*d7bff893SBaolin Wang * @chan: the MCDT channel 724*d7bff893SBaolin Wang */ 725*d7bff893SBaolin Wang void sprd_mcdt_chan_int_disable(struct sprd_mcdt_chan *chan) 726*d7bff893SBaolin Wang { 727*d7bff893SBaolin Wang struct sprd_mcdt_dev *mcdt = chan->mcdt; 728*d7bff893SBaolin Wang unsigned long flags; 729*d7bff893SBaolin Wang 730*d7bff893SBaolin Wang spin_lock_irqsave(&mcdt->lock, flags); 731*d7bff893SBaolin Wang 732*d7bff893SBaolin Wang if (!chan->int_enable) { 733*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 734*d7bff893SBaolin Wang return; 735*d7bff893SBaolin Wang } 736*d7bff893SBaolin Wang 737*d7bff893SBaolin Wang switch (chan->type) { 738*d7bff893SBaolin Wang case SPRD_MCDT_ADC_CHAN: 739*d7bff893SBaolin Wang sprd_mcdt_chan_int_en(mcdt, chan->id, 740*d7bff893SBaolin Wang MCDT_ADC_FIFO_AF_INT, false); 741*d7bff893SBaolin Wang sprd_mcdt_chan_int_clear(mcdt, chan->id, MCDT_ADC_FIFO_AF_INT); 742*d7bff893SBaolin Wang sprd_mcdt_ap_int_enable(mcdt, chan->id, false); 743*d7bff893SBaolin Wang break; 744*d7bff893SBaolin Wang 745*d7bff893SBaolin Wang case SPRD_MCDT_DAC_CHAN: 746*d7bff893SBaolin Wang sprd_mcdt_chan_int_en(mcdt, chan->id, 747*d7bff893SBaolin Wang MCDT_DAC_FIFO_AE_INT, false); 748*d7bff893SBaolin Wang sprd_mcdt_chan_int_clear(mcdt, chan->id, MCDT_DAC_FIFO_AE_INT); 749*d7bff893SBaolin Wang sprd_mcdt_ap_int_enable(mcdt, chan->id, false); 750*d7bff893SBaolin Wang break; 751*d7bff893SBaolin Wang 752*d7bff893SBaolin Wang default: 753*d7bff893SBaolin Wang break; 754*d7bff893SBaolin Wang } 755*d7bff893SBaolin Wang 756*d7bff893SBaolin Wang chan->int_enable = false; 757*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 758*d7bff893SBaolin Wang } 759*d7bff893SBaolin Wang EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_disable); 760*d7bff893SBaolin Wang 761*d7bff893SBaolin Wang /** 762*d7bff893SBaolin Wang * sprd_mcdt_chan_dma_enable - enable the DMA mode for the MCDT channel 763*d7bff893SBaolin Wang * @chan: the MCDT channel 764*d7bff893SBaolin Wang * @dma_chan: specify which DMA channel will be used for this MCDT channel 765*d7bff893SBaolin Wang * @water_mark: water mark to trigger a DMA request 766*d7bff893SBaolin Wang * 767*d7bff893SBaolin Wang * Enable the DMA mode for the MCDT channel, that means we can use DMA to 768*d7bff893SBaolin Wang * transfer data to the channel fifo and do not need reading/writing data 769*d7bff893SBaolin Wang * manually. 770*d7bff893SBaolin Wang * 771*d7bff893SBaolin Wang * Returns 0 on success, or an error code on failure. 772*d7bff893SBaolin Wang */ 773*d7bff893SBaolin Wang int sprd_mcdt_chan_dma_enable(struct sprd_mcdt_chan *chan, 774*d7bff893SBaolin Wang enum sprd_mcdt_dma_chan dma_chan, 775*d7bff893SBaolin Wang u32 water_mark) 776*d7bff893SBaolin Wang { 777*d7bff893SBaolin Wang struct sprd_mcdt_dev *mcdt = chan->mcdt; 778*d7bff893SBaolin Wang unsigned long flags; 779*d7bff893SBaolin Wang int ret = 0; 780*d7bff893SBaolin Wang 781*d7bff893SBaolin Wang spin_lock_irqsave(&mcdt->lock, flags); 782*d7bff893SBaolin Wang 783*d7bff893SBaolin Wang if (chan->dma_enable || chan->int_enable || 784*d7bff893SBaolin Wang dma_chan > SPRD_MCDT_DMA_CH4) { 785*d7bff893SBaolin Wang dev_err(mcdt->dev, "Failed to set DMA mode\n"); 786*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 787*d7bff893SBaolin Wang return -EINVAL; 788*d7bff893SBaolin Wang } 789*d7bff893SBaolin Wang 790*d7bff893SBaolin Wang switch (chan->type) { 791*d7bff893SBaolin Wang case SPRD_MCDT_ADC_CHAN: 792*d7bff893SBaolin Wang sprd_mcdt_adc_fifo_clear(mcdt, chan->id); 793*d7bff893SBaolin Wang sprd_mcdt_adc_set_watermark(mcdt, chan->id, 794*d7bff893SBaolin Wang water_mark, MCDT_FIFO_LENGTH - 1); 795*d7bff893SBaolin Wang sprd_mcdt_adc_dma_enable(mcdt, chan->id, true); 796*d7bff893SBaolin Wang sprd_mcdt_adc_dma_chn_select(mcdt, chan->id, dma_chan); 797*d7bff893SBaolin Wang sprd_mcdt_adc_dma_ack_select(mcdt, chan->id, dma_chan); 798*d7bff893SBaolin Wang break; 799*d7bff893SBaolin Wang 800*d7bff893SBaolin Wang case SPRD_MCDT_DAC_CHAN: 801*d7bff893SBaolin Wang sprd_mcdt_dac_fifo_clear(mcdt, chan->id); 802*d7bff893SBaolin Wang sprd_mcdt_dac_set_watermark(mcdt, chan->id, 803*d7bff893SBaolin Wang MCDT_FIFO_LENGTH - 1, water_mark); 804*d7bff893SBaolin Wang sprd_mcdt_dac_dma_enable(mcdt, chan->id, true); 805*d7bff893SBaolin Wang sprd_mcdt_dac_dma_chn_select(mcdt, chan->id, dma_chan); 806*d7bff893SBaolin Wang sprd_mcdt_dac_dma_ack_select(mcdt, chan->id, dma_chan); 807*d7bff893SBaolin Wang break; 808*d7bff893SBaolin Wang 809*d7bff893SBaolin Wang default: 810*d7bff893SBaolin Wang dev_err(mcdt->dev, "Unsupported channel type\n"); 811*d7bff893SBaolin Wang ret = -EINVAL; 812*d7bff893SBaolin Wang } 813*d7bff893SBaolin Wang 814*d7bff893SBaolin Wang if (!ret) 815*d7bff893SBaolin Wang chan->dma_enable = true; 816*d7bff893SBaolin Wang 817*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 818*d7bff893SBaolin Wang 819*d7bff893SBaolin Wang return ret; 820*d7bff893SBaolin Wang } 821*d7bff893SBaolin Wang EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_enable); 822*d7bff893SBaolin Wang 823*d7bff893SBaolin Wang /** 824*d7bff893SBaolin Wang * sprd_mcdt_chan_dma_disable - disable the DMA mode for the MCDT channel 825*d7bff893SBaolin Wang * @chan: the MCDT channel 826*d7bff893SBaolin Wang */ 827*d7bff893SBaolin Wang void sprd_mcdt_chan_dma_disable(struct sprd_mcdt_chan *chan) 828*d7bff893SBaolin Wang { 829*d7bff893SBaolin Wang struct sprd_mcdt_dev *mcdt = chan->mcdt; 830*d7bff893SBaolin Wang unsigned long flags; 831*d7bff893SBaolin Wang 832*d7bff893SBaolin Wang spin_lock_irqsave(&mcdt->lock, flags); 833*d7bff893SBaolin Wang 834*d7bff893SBaolin Wang if (!chan->dma_enable) { 835*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 836*d7bff893SBaolin Wang return; 837*d7bff893SBaolin Wang } 838*d7bff893SBaolin Wang 839*d7bff893SBaolin Wang switch (chan->type) { 840*d7bff893SBaolin Wang case SPRD_MCDT_ADC_CHAN: 841*d7bff893SBaolin Wang sprd_mcdt_adc_dma_enable(mcdt, chan->id, false); 842*d7bff893SBaolin Wang sprd_mcdt_adc_fifo_clear(mcdt, chan->id); 843*d7bff893SBaolin Wang break; 844*d7bff893SBaolin Wang 845*d7bff893SBaolin Wang case SPRD_MCDT_DAC_CHAN: 846*d7bff893SBaolin Wang sprd_mcdt_dac_dma_enable(mcdt, chan->id, false); 847*d7bff893SBaolin Wang sprd_mcdt_dac_fifo_clear(mcdt, chan->id); 848*d7bff893SBaolin Wang break; 849*d7bff893SBaolin Wang 850*d7bff893SBaolin Wang default: 851*d7bff893SBaolin Wang break; 852*d7bff893SBaolin Wang } 853*d7bff893SBaolin Wang 854*d7bff893SBaolin Wang chan->dma_enable = false; 855*d7bff893SBaolin Wang spin_unlock_irqrestore(&mcdt->lock, flags); 856*d7bff893SBaolin Wang } 857*d7bff893SBaolin Wang EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_disable); 858*d7bff893SBaolin Wang 859*d7bff893SBaolin Wang /** 860*d7bff893SBaolin Wang * sprd_mcdt_request_chan - request one MCDT channel 861*d7bff893SBaolin Wang * @channel: channel id 862*d7bff893SBaolin Wang * @type: channel type, it can be one ADC channel or DAC channel 863*d7bff893SBaolin Wang * 864*d7bff893SBaolin Wang * Rreturn NULL if no available channel. 865*d7bff893SBaolin Wang */ 866*d7bff893SBaolin Wang struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel, 867*d7bff893SBaolin Wang enum sprd_mcdt_channel_type type) 868*d7bff893SBaolin Wang { 869*d7bff893SBaolin Wang struct sprd_mcdt_chan *temp, *chan = NULL; 870*d7bff893SBaolin Wang 871*d7bff893SBaolin Wang mutex_lock(&sprd_mcdt_list_mutex); 872*d7bff893SBaolin Wang 873*d7bff893SBaolin Wang list_for_each_entry(temp, &sprd_mcdt_chan_list, list) { 874*d7bff893SBaolin Wang if (temp->type == type && temp->id == channel) { 875*d7bff893SBaolin Wang chan = temp; 876*d7bff893SBaolin Wang break; 877*d7bff893SBaolin Wang } 878*d7bff893SBaolin Wang } 879*d7bff893SBaolin Wang 880*d7bff893SBaolin Wang if (chan) 881*d7bff893SBaolin Wang list_del(&chan->list); 882*d7bff893SBaolin Wang 883*d7bff893SBaolin Wang mutex_unlock(&sprd_mcdt_list_mutex); 884*d7bff893SBaolin Wang 885*d7bff893SBaolin Wang return chan; 886*d7bff893SBaolin Wang } 887*d7bff893SBaolin Wang EXPORT_SYMBOL_GPL(sprd_mcdt_request_chan); 888*d7bff893SBaolin Wang 889*d7bff893SBaolin Wang /** 890*d7bff893SBaolin Wang * sprd_mcdt_free_chan - free one MCDT channel 891*d7bff893SBaolin Wang * @chan: the channel to be freed 892*d7bff893SBaolin Wang */ 893*d7bff893SBaolin Wang void sprd_mcdt_free_chan(struct sprd_mcdt_chan *chan) 894*d7bff893SBaolin Wang { 895*d7bff893SBaolin Wang struct sprd_mcdt_chan *temp; 896*d7bff893SBaolin Wang 897*d7bff893SBaolin Wang sprd_mcdt_chan_dma_disable(chan); 898*d7bff893SBaolin Wang sprd_mcdt_chan_int_disable(chan); 899*d7bff893SBaolin Wang 900*d7bff893SBaolin Wang mutex_lock(&sprd_mcdt_list_mutex); 901*d7bff893SBaolin Wang 902*d7bff893SBaolin Wang list_for_each_entry(temp, &sprd_mcdt_chan_list, list) { 903*d7bff893SBaolin Wang if (temp == chan) { 904*d7bff893SBaolin Wang mutex_unlock(&sprd_mcdt_list_mutex); 905*d7bff893SBaolin Wang return; 906*d7bff893SBaolin Wang } 907*d7bff893SBaolin Wang } 908*d7bff893SBaolin Wang 909*d7bff893SBaolin Wang list_add_tail(&chan->list, &sprd_mcdt_chan_list); 910*d7bff893SBaolin Wang mutex_unlock(&sprd_mcdt_list_mutex); 911*d7bff893SBaolin Wang } 912*d7bff893SBaolin Wang EXPORT_SYMBOL_GPL(sprd_mcdt_free_chan); 913*d7bff893SBaolin Wang 914*d7bff893SBaolin Wang static void sprd_mcdt_init_chans(struct sprd_mcdt_dev *mcdt, 915*d7bff893SBaolin Wang struct resource *res) 916*d7bff893SBaolin Wang { 917*d7bff893SBaolin Wang int i; 918*d7bff893SBaolin Wang 919*d7bff893SBaolin Wang for (i = 0; i < MCDT_CHANNEL_NUM; i++) { 920*d7bff893SBaolin Wang struct sprd_mcdt_chan *chan = &mcdt->chan[i]; 921*d7bff893SBaolin Wang 922*d7bff893SBaolin Wang if (i < MCDT_ADC_CHANNEL_NUM) { 923*d7bff893SBaolin Wang chan->id = i; 924*d7bff893SBaolin Wang chan->type = SPRD_MCDT_ADC_CHAN; 925*d7bff893SBaolin Wang chan->fifo_phys = res->start + MCDT_CH0_RXD + i * 4; 926*d7bff893SBaolin Wang } else { 927*d7bff893SBaolin Wang chan->id = i - MCDT_ADC_CHANNEL_NUM; 928*d7bff893SBaolin Wang chan->type = SPRD_MCDT_DAC_CHAN; 929*d7bff893SBaolin Wang chan->fifo_phys = res->start + MCDT_CH0_TXD + 930*d7bff893SBaolin Wang (i - MCDT_ADC_CHANNEL_NUM) * 4; 931*d7bff893SBaolin Wang } 932*d7bff893SBaolin Wang 933*d7bff893SBaolin Wang chan->mcdt = mcdt; 934*d7bff893SBaolin Wang INIT_LIST_HEAD(&chan->list); 935*d7bff893SBaolin Wang 936*d7bff893SBaolin Wang mutex_lock(&sprd_mcdt_list_mutex); 937*d7bff893SBaolin Wang list_add_tail(&chan->list, &sprd_mcdt_chan_list); 938*d7bff893SBaolin Wang mutex_unlock(&sprd_mcdt_list_mutex); 939*d7bff893SBaolin Wang } 940*d7bff893SBaolin Wang } 941*d7bff893SBaolin Wang 942*d7bff893SBaolin Wang static int sprd_mcdt_probe(struct platform_device *pdev) 943*d7bff893SBaolin Wang { 944*d7bff893SBaolin Wang struct sprd_mcdt_dev *mcdt; 945*d7bff893SBaolin Wang struct resource *res; 946*d7bff893SBaolin Wang int ret, irq; 947*d7bff893SBaolin Wang 948*d7bff893SBaolin Wang mcdt = devm_kzalloc(&pdev->dev, sizeof(*mcdt), GFP_KERNEL); 949*d7bff893SBaolin Wang if (!mcdt) 950*d7bff893SBaolin Wang return -ENOMEM; 951*d7bff893SBaolin Wang 952*d7bff893SBaolin Wang res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 953*d7bff893SBaolin Wang mcdt->base = devm_ioremap_resource(&pdev->dev, res); 954*d7bff893SBaolin Wang if (!mcdt->base) 955*d7bff893SBaolin Wang return -ENOMEM; 956*d7bff893SBaolin Wang 957*d7bff893SBaolin Wang mcdt->dev = &pdev->dev; 958*d7bff893SBaolin Wang spin_lock_init(&mcdt->lock); 959*d7bff893SBaolin Wang platform_set_drvdata(pdev, mcdt); 960*d7bff893SBaolin Wang 961*d7bff893SBaolin Wang irq = platform_get_irq(pdev, 0); 962*d7bff893SBaolin Wang if (irq < 0) { 963*d7bff893SBaolin Wang dev_err(&pdev->dev, "Failed to get MCDT interrupt\n"); 964*d7bff893SBaolin Wang return irq; 965*d7bff893SBaolin Wang } 966*d7bff893SBaolin Wang 967*d7bff893SBaolin Wang ret = devm_request_irq(&pdev->dev, irq, sprd_mcdt_irq_handler, 968*d7bff893SBaolin Wang 0, "sprd-mcdt", mcdt); 969*d7bff893SBaolin Wang if (ret) { 970*d7bff893SBaolin Wang dev_err(&pdev->dev, "Failed to request MCDT IRQ\n"); 971*d7bff893SBaolin Wang return ret; 972*d7bff893SBaolin Wang } 973*d7bff893SBaolin Wang 974*d7bff893SBaolin Wang sprd_mcdt_init_chans(mcdt, res); 975*d7bff893SBaolin Wang 976*d7bff893SBaolin Wang return 0; 977*d7bff893SBaolin Wang } 978*d7bff893SBaolin Wang 979*d7bff893SBaolin Wang static int sprd_mcdt_remove(struct platform_device *pdev) 980*d7bff893SBaolin Wang { 981*d7bff893SBaolin Wang struct sprd_mcdt_chan *temp; 982*d7bff893SBaolin Wang 983*d7bff893SBaolin Wang mutex_lock(&sprd_mcdt_list_mutex); 984*d7bff893SBaolin Wang 985*d7bff893SBaolin Wang list_for_each_entry(temp, &sprd_mcdt_chan_list, list) 986*d7bff893SBaolin Wang list_del(&temp->list); 987*d7bff893SBaolin Wang 988*d7bff893SBaolin Wang mutex_unlock(&sprd_mcdt_list_mutex); 989*d7bff893SBaolin Wang 990*d7bff893SBaolin Wang return 0; 991*d7bff893SBaolin Wang } 992*d7bff893SBaolin Wang 993*d7bff893SBaolin Wang static const struct of_device_id sprd_mcdt_of_match[] = { 994*d7bff893SBaolin Wang { .compatible = "sprd,sc9860-mcdt", }, 995*d7bff893SBaolin Wang { } 996*d7bff893SBaolin Wang }; 997*d7bff893SBaolin Wang MODULE_DEVICE_TABLE(of, sprd_mcdt_of_match); 998*d7bff893SBaolin Wang 999*d7bff893SBaolin Wang static struct platform_driver sprd_mcdt_driver = { 1000*d7bff893SBaolin Wang .probe = sprd_mcdt_probe, 1001*d7bff893SBaolin Wang .remove = sprd_mcdt_remove, 1002*d7bff893SBaolin Wang .driver = { 1003*d7bff893SBaolin Wang .name = "sprd-mcdt", 1004*d7bff893SBaolin Wang .of_match_table = sprd_mcdt_of_match, 1005*d7bff893SBaolin Wang }, 1006*d7bff893SBaolin Wang }; 1007*d7bff893SBaolin Wang 1008*d7bff893SBaolin Wang module_platform_driver(sprd_mcdt_driver); 1009*d7bff893SBaolin Wang 1010*d7bff893SBaolin Wang MODULE_DESCRIPTION("Spreadtrum Multi-Channel Data Transfer Driver"); 1011*d7bff893SBaolin Wang MODULE_LICENSE("GPL v2"); 1012