xref: /openbmc/linux/sound/soc/sprd/sprd-mcdt.c (revision d7bff893e04f4e7b4a0789486da1435df5920f5a)
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