aboutsummaryrefslogtreecommitdiff
path: root/include/linux/musb/mtk_qmu.h
blob: 4eea9cdfe278854025048c58c829e3a7908bc78f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#ifndef _MTK_QMU_H_
#define _MTK_QMU_H_

#ifdef MUSB_QMU_SUPPORT

/* for musb_read/write api */
#include "mtk_musb.h"
#include "musb_debug.h"
#include "musb_io.h"

#include <linux/dmapool.h>

/* CUSTOM SETTING */
#define GPD_LEN_ALIGNED (64)  	/* > gpd len (16) and cache line size aligned */
#define GPD_EXT_LEN (48)		/* GPD_LEN_ALIGNED - 16(should be sizeof(TGPD) */
#define GPD_SZ (16)
#define MAX_GPD_NUM 36
#define RXQ_NUM 8
#define TXQ_NUM 8
#define MAX_QMU_EP RXQ_NUM
#define TXQ	0
#define RXQ	1

/* QMU SETTING */
#define NO_ZLP 0
#define HW_MODE 1
#define GPD_MODE 2
//#define TXZLP GPD_MODE
//#define TXZLP HW_MODE
#define TXZLP NO_ZLP

//#define CFG_RX_ZLP_EN
//#define CFG_RX_COZ_EN

#define CFG_CS_CHECK
//#define CFG_EMPTY_CHECK

/* TGPD */
typedef struct _TGPD
{
    u8	flag;
    u8	chksum;
    u16	DataBufferLen; /*Rx Allow Length*/

	/* address field, 32-bit long */
    u32				pNext;
    u32				pBuf;

    u16	bufLen;
    u8 	ExtLength;
    u8 ZTepFlag;
}TGPD, *PGPD;

typedef struct _GPD_RANGE {
	PGPD    pNext;
	PGPD    pStart;
	PGPD    pEnd;
}GPD_R, *RGPD;

extern int mtk_qmu_dbg_level;	/* refer to musb_core.c */
static inline int mtk_dbg_level(unsigned level)
{
	return mtk_qmu_dbg_level >= level;
}

#define LOG_EMERG 		0
#define LOG_ALERT  		1
#define LOG_CRIT   		2
#define LOG_ERR    		3
#define LOG_WARN    	4
#define LOG_NOTICE 		5
#define LOG_INFO   		6
#define LOG_DBG  		7

#define QMU_DBG_ON

#ifdef QMU_DBG_ON
#define QMU_ERR(format, args...) do {if(mtk_dbg_level(LOG_ERR)){printk(KERN_WARNING "QMU_ERR,<%s %d>, " format , __func__, __LINE__ , ## args);}}while(0)
#define QMU_WARN(format, args...) do {if(mtk_dbg_level(LOG_WARN)){printk(KERN_WARNING "QMU_WARN,<%s %d>, " format , __func__, __LINE__ , ## args);}}while(0)
#define QMU_INFO(format, args...) do {if(mtk_dbg_level(LOG_INFO)){printk(KERN_WARNING "QMU_INFO,<%s %d>, " format , __func__, __LINE__ , ## args);}}while(0)
#define QMU_DBG(format, args...) do {if(mtk_dbg_level(LOG_DBG)){printk(KERN_WARNING "QMU_DBG,<%s %d>, " format , __func__, __LINE__ , ## args);}}while(0)
#else
#define QMU_ERR(format, args...) do {}while(0)
#define QMU_WARN(format, args...) do {}while(0)
#define QMU_INFO(format, args...) do {}while(0)
#define QMU_DBG(format, args...) do {}while(0)
#endif



/* QMU macros */
#define USB_HW_QMU_OFF	0x0000
#define USB_HW_QUCS_OFF	0x0300
#define USB_HW_QIRQ_OFF	0x0400
#define USB_HW_QDBG_OFF	0x04F0

#define MGC_O_QMU_QCR0	0x0000
#define MGC_O_QMU_QCR2	0x0008
#define MGC_O_QMU_QCR3	0x000C

#define MGC_O_QMU_RQCSR0	0x0010
#define MGC_O_QMU_RQSAR0	0x0014
#define MGC_O_QMU_RQCPR0	0x0018
#define MGC_O_QMU_RQCSR(n) (MGC_O_QMU_RQCSR0+0x0010*((n)-1))
#define MGC_O_QMU_RQSAR(n) (MGC_O_QMU_RQSAR0+0x0010*((n)-1))
#define MGC_O_QMU_RQCPR(n) (MGC_O_QMU_RQCPR0+0x0010*((n)-1))

#define MGC_O_QMU_RQTR_BASE	0x0090
#define MGC_O_QMU_RQTR(n)		(MGC_O_QMU_RQTR_BASE+0x4*((n)-1))
#define MGC_O_QMU_RQLDPR0		0x0100
#define MGC_O_QMU_RQLDPR(n) 	(MGC_O_QMU_RQLDPR0+0x4*((n)-1))

#define MGC_O_QMU_TQCSR0	0x0200
#define MGC_O_QMU_TQSAR0	0x0204
#define MGC_O_QMU_TQCPR0	0x0208
#define MGC_O_QMU_TQCSR(n) (MGC_O_QMU_TQCSR0+0x0010*((n)-1))
#define MGC_O_QMU_TQSAR(n) (MGC_O_QMU_TQSAR0+0x0010*((n)-1))
#define MGC_O_QMU_TQCPR(n) (MGC_O_QMU_TQCPR0+0x0010*((n)-1))

#define MGC_O_QMU_QAR		0x0300
#define MGC_O_QUCS_USBGCSR	0x0000
#define MGC_O_QIRQ_QISAR		0x0000
#define MGC_O_QIRQ_QIMR		0x0004
#define MGC_O_QIRQ_QIMCR		0x0008
#define MGC_O_QIRQ_QIMSR		0x000C
#define MGC_O_QIRQ_IOCDISR    0x0030
#define MGC_O_QIRQ_TEPEMPR	0x0060
#define MGC_O_QIRQ_TEPEMPMR	0x0064
#define MGC_O_QIRQ_TEPEMPMCR	0x0068
#define MGC_O_QIRQ_TEPEMPMSR	0x006C
#define MGC_O_QIRQ_REPEMPR	0x0070
#define MGC_O_QIRQ_REPEMPMR	0x0074
#define MGC_O_QIRQ_REPEMPMCR	0x0078
#define MGC_O_QIRQ_REPEMPMSR	0x007C

#define MGC_O_QIRQ_RQEIR		0x0090
#define MGC_O_QIRQ_RQEIMR		0x0094
#define MGC_O_QIRQ_RQEIMCR	0x0098
#define MGC_O_QIRQ_RQEIMSR	0x009C
#define MGC_O_QIRQ_REPEIR		0x00A0
#define MGC_O_QIRQ_REPEIMR	0x00A4
#define MGC_O_QIRQ_REPEIMCR	0x00A8
#define MGC_O_QIRQ_REPEIMSR	0x00AC
#define MGC_O_QIRQ_TQEIR		0x00B0
#define MGC_O_QIRQ_TQEIMR		0x00B4
#define MGC_O_QIRQ_TQEIMCR	0x00B8
#define MGC_O_QIRQ_TQEIMSR	0x00BC
#define MGC_O_QIRQ_TEPEIR		0x00C0
#define MGC_O_QIRQ_TEPEIMR	0x00C4
#define MGC_O_QIRQ_TEPEIMCR	0x00C8
#define MGC_O_QIRQ_TEPEIMSR	0x00CC

#define MGC_O_QDBG_DFCR	0x0000
#define MGC_O_QDBG_DFMR	0x0004

/* brief Queue Control value Definition */
#define DQMU_QUE_START	0x00000001
#define DQMU_QUE_RESUME	0x00000002
#define DQMU_QUE_STOP		0x00000004
#define DQMU_QUE_ACTIVE	0x00008000

/*brief USB QMU Special Control USBGCSR value Definition*/
#define USB_QMU_Tx0_EN 			0x00000001
#define USB_QMU_Tx_EN(n) 			(USB_QMU_Tx0_EN<<((n)-1))
#define USB_QMU_Rx0_EN 			0x00010000
#define USB_QMU_Rx_EN(n) 			(USB_QMU_Rx0_EN<<((n)-1))
#define USB_QMU_HIFEVT_EN	 		0x00000100
#define USB_QMU_HIFCMD_EN	 		0x01000000
#define DQMU_SW_RESET		0x00010000
#define DQMU_CS16B_EN		0x80000000
#define DQMU_TQ0CS_EN		0x00010000
#define DQMU_TQCS_EN(n)	(DQMU_TQ0CS_EN<<((n)-1))
#define DQMU_RQ0CS_EN		0x00000001
#define DQMU_RQCS_EN(n)	(DQMU_RQ0CS_EN<<((n)-1))
#define DQMU_TX0_ZLP 		0x01000000
#define DQMU_TX_ZLP(n)		(DQMU_TX0_ZLP<<((n)-1))
#define DQMU_TX0_MULTIPLE	0x00010000
#define DQMU_TX_MULTIPLE(n)	(DQMU_TX0_MULTIPLE<<((n)-1))
#define DQMU_RX0_MULTIPLE	0x00010000
#define DQMU_RX_MULTIPLE(n)	(DQMU_RX0_MULTIPLE<<((n)-1))
#define DQMU_RX0_ZLP 		0x01000000
#define DQMU_RX_ZLP(n)		(DQMU_RX0_ZLP<<((n)-1))
#define DQMU_RX0_COZ 		0x00000100
#define DQMU_RX_COZ(n)		(DQMU_RX0_COZ<<((n)-1))

#define DQMU_M_TXEP_ERR	0x10000000
#define DQMU_M_TXQ_ERR	0x08000000
#define DQMU_M_RXEP_ERR	0x04000000
#define DQMU_M_RXQ_ERR	0x02000000
#define DQMU_M_RQ_EMPTY	0x00020000
#define DQMU_M_TQ_EMPTY	0x00010000
#define DQMU_M_RX0_EMPTY	0x00000001
#define DQMU_M_RX_EMPTY(n) 	(DQMU_M_RX0_EMPTY<<((n)-1))
#define DQMU_M_TX0_EMPTY	0x00000001
#define DQMU_M_TX_EMPTY(n) 	(DQMU_M_TX0_EMPTY<<((n)-1))
#define DQMU_M_RX0_DONE	0x00000100
#define DQMU_M_RX_DONE(n)	(DQMU_M_RX0_DONE<<((n)-1))
#define DQMU_M_TX0_DONE	0x00000001
#define DQMU_M_TX_DONE(n)	(DQMU_M_TX0_DONE<<((n)-1))

#define DQMU_M_RX0_ZLP_ERR	0x01000000
#define DQMU_M_RX_ZLP_ERR(n)	(DQMU_M_RX0_ZLP_ERR<<((n)-1))
#define DQMU_M_RX0_LEN_ERR	0x00000100
#define DQMU_M_RX_LEN_ERR(n)	(DQMU_M_RX0_LEN_ERR<<((n)-1))
#define DQMU_M_RX0_GPDCS_ERR		0x00000001
#define DQMU_M_RX_GPDCS_ERR(n)	(DQMU_M_RX0_GPDCS_ERR<<((n)-1))

#define DQMU_M_TX0_LEN_ERR	0x00010000
#define DQMU_M_TX_LEN_ERR(n)	(DQMU_M_TX0_LEN_ERR<<((n)-1))
#define DQMU_M_TX0_GPDCS_ERR	0x00000100
#define DQMU_M_TX_GPDCS_ERR(n)	(DQMU_M_TX0_GPDCS_ERR<<((n)-1))
#define DQMU_M_TX0_BDCS_ERR		0x00000001
#define DQMU_M_TX_BDCS_ERR(n)	(DQMU_M_TX0_BDCS_ERR<<((n)-1))

#define DQMU_M_TX0_EP_ERR		0x00000001
#define DQMU_M_TX_EP_ERR(n)	(DQMU_M_TX0_EP_ERR<<((n)-1))

#define DQMU_M_RX0_EP_ERR		0x00000001
#define DQMU_M_RX_EP_ERR(n)	(DQMU_M_RX0_EP_ERR<<((n)-1))
#define DQMU_M_RQ_DIS_IOC(n)   (0x100<<((n)-1))

#define MGC_ReadQMU8(base,_offset) \
	musb_readb(base, (USB_HW_QMU_OFF + _offset))

#define MGC_ReadQUCS8(base,_offset) \
	musb_readb(base, (USB_HW_QUCS_OFF + _offset))

#define MGC_ReadQIRQ8(base,_offset) \
	musb_readb(base, (USB_HW_QIRQ_OFF + _offset))

#define MGC_ReadQMU16(base,_offset) \
	musb_readw(base, (USB_HW_QMU_OFF + _offset))

#define MGC_ReadQUCS16(base,_offset) \
	musb_readw(base,(USB_HW_QUCS_OFF + _offset))

#define MGC_ReadQIRQ16(base,_offset) \
	musb_readw(base, (USB_HW_QIRQ_OFF + _offset))
#define MGC_ReadQMU32(base,_offset) \
	musb_readl(base, (USB_HW_QMU_OFF + _offset))

#define MGC_ReadQUCS32(base,_offset) \
	musb_readl(base, (USB_HW_QUCS_OFF + _offset))

#define MGC_ReadQIRQ32(base,_offset) \
	musb_readl(base, (USB_HW_QIRQ_OFF + _offset))

#define MGC_WriteQMU32(base,_offset, _data) \
	musb_writel(base, (USB_HW_QMU_OFF + _offset), _data)

#define MGC_WriteQUCS32(base,_offset, _data) \
	musb_writel(base, (USB_HW_QUCS_OFF + _offset), _data)

#define MGC_WriteQIRQ32(base,_offset, _data) \
	musb_writel(base,(USB_HW_QIRQ_OFF + _offset), _data)

u8 PDU_calcCksum(u8 *data, int len);

/* brief Define DMAQ GPD format */
#define TGPD_FLAGS_HWO              0x01
#define TGPD_IS_FLAGS_HWO(_pd)      (((TGPD *)_pd)->flag & TGPD_FLAGS_HWO)
#define TGPD_SET_FLAGS_HWO(_pd)     (((TGPD *)_pd)->flag |= TGPD_FLAGS_HWO)
#define TGPD_CLR_FLAGS_HWO(_pd)     (((TGPD *)_pd)->flag &= (~TGPD_FLAGS_HWO))
#define TGPD_FORMAT_BDP             0x02
#define TGPD_IS_FORMAT_BDP(_pd)     (((TGPD *)_pd)->flag & TGPD_FORMAT_BDP)
#define TGPD_SET_FORMAT_BDP(_pd)    (((TGPD *)_pd)->flag |= TGPD_FORMAT_BDP)
#define TGPD_CLR_FORMAT_BDP(_pd)    (((TGPD *)_pd)->flag &= (~TGPD_FORMAT_BDP))

#define TGPD_SET_FLAG(_pd, _flag)   ((TGPD *)_pd)->flag = (((TGPD *)_pd)->flag&(~TGPD_FLAGS_HWO))|(_flag)
#define TGPD_GET_FLAG(_pd)             (((TGPD *)_pd)->flag & TGPD_FLAGS_HWO)
#define TGPD_SET_CHKSUM(_pd, _n)    ((TGPD *)_pd)->chksum = PDU_calcCksum((u8 *)_pd, _n)
#define TGPD_SET_CHKSUM_HWO(_pd, _n)    ((TGPD *)_pd)->chksum = PDU_calcCksum((u8 *)_pd, _n)-1
#define TGPD_GET_CHKSUM(_pd)        ((TGPD *)_pd)->chksum
#define TGPD_SET_FORMAT(_pd, _fmt)  ((TGPD *)_pd)->flag = (((TGPD *)_pd)->flag&(~TGPD_FORMAT_BDP))|(_fmt)
#define TGPD_GET_FORMAT(_pd)        ((((TGPD *)_pd)->flag & TGPD_FORMAT_BDP)>>1)
#define TGPD_SET_DataBUF_LEN(_pd, _len) ((TGPD *)_pd)->DataBufferLen = _len
#define TGPD_ADD_DataBUF_LEN(_pd, _len) ((TGPD *)_pd)->DataBufferLen += _len
#define TGPD_GET_DataBUF_LEN(_pd)       ((TGPD *)_pd)->DataBufferLen
#define TGPD_SET_NEXT(_pd, _next)   ((TGPD *)_pd)->pNext = (u32)(unsigned long)((TGPD *)_next)
#define TGPD_GET_NEXT(_pd)			(TGPD *)(unsigned long)((TGPD *)_pd)->pNext

#define TGPD_SET_DATA(_pd, _data)   ((TGPD *)_pd)->pBuf = (u32)(unsigned long)_data
#define TGPD_GET_DATA(_pd)          (u8 *)(unsigned long)((TGPD *)_pd)->pBuf
#define TGPD_SET_BUF_LEN(_pd, _len) ((TGPD *)_pd)->bufLen = _len
#define TGPD_ADD_BUF_LEN(_pd, _len) ((TGPD *)_pd)->bufLen += _len
#define TGPD_GET_BUF_LEN(_pd)       ((TGPD *)_pd)->bufLen
#define TGPD_SET_EXT_LEN(_pd, _len) ((TGPD *)_pd)->ExtLength = _len
#define TGPD_GET_EXT_LEN(_pd)        ((TGPD *)_pd)->ExtLength
#define TGPD_SET_EPaddr(_pd, _EP)  ((TGPD *)_pd)->ZTepFlag =(((TGPD *)_pd)->ZTepFlag&0xF0)|(_EP)
#define TGPD_GET_EPaddr(_pd)        ((TGPD *)_pd)->ZTepFlag & 0x0F

#define TGPD_FORMAT_TGL             0x10
#define TGPD_IS_FORMAT_TGL(_pd)     (((TGPD *)_pd)->ZTepFlag & TGPD_FORMAT_TGL)
#define TGPD_SET_FORMAT_TGL(_pd)    (((TGPD *)_pd)->ZTepFlag |=TGPD_FORMAT_TGL)
#define TGPD_CLR_FORMAT_TGL(_pd)    (((TGPD *)_pd)->ZTepFlag &= (~TGPD_FORMAT_TGL))
#define TGPD_FORMAT_ZLP             0x20
#define TGPD_IS_FORMAT_ZLP(_pd)     (((TGPD *)_pd)->ZTepFlag & TGPD_FORMAT_ZLP)
#define TGPD_SET_FORMAT_ZLP(_pd)    (((TGPD *)_pd)->ZTepFlag |=TGPD_FORMAT_ZLP)
#define TGPD_CLR_FORMAT_ZLP(_pd)    (((TGPD *)_pd)->ZTepFlag &= (~TGPD_FORMAT_ZLP))

#define TGPD_SET_TGL(_pd, _TGL)  ((TGPD *)_pd)->ZTepFlag |=(( _TGL) ? 0x10: 0x00)
#define TGPD_GET_TGL(_pd)        ((TGPD *)_pd)->ZTepFlag & 0x10 ? 1:0
#define TGPD_SET_ZLP(_pd, _ZLP)  ((TGPD *)_pd)->ZTepFlag |= ((_ZLP) ? 0x20: 0x00)
#define TGPD_GET_ZLP(_pd)        ((TGPD *)_pd)->ZTepFlag & 0x20 ? 1:0

#define TGPD_FLAG_IOC				0x80
#define TGPD_SET_IOC(_pd)			(((TGPD *)_pd)->flag |= TGPD_FLAG_IOC)

extern void qmu_destroy_gpd_pool(struct device *dev);
extern int qmu_init_gpd_pool(struct device *dev);
extern void qmu_reset_gpd_pool(u32 ep_num, u8 isRx);
extern bool mtk_is_qmu_enabled(u8 EP_Num, u8 isRx);
extern void mtk_qmu_enable(struct musb *musb, u8 EP_Num, u8 isRx);
extern void mtk_qmu_insert_task(u8 EP_Num, u8 isRx, u8* buf, u32 length, u8 zlp);
extern void mtk_qmu_resume(u8 EP_Num, u8 isRx);
extern void qmu_done_rx(struct musb *musb, u8 ep_num);
extern void qmu_done_tx(struct musb *musb, u8 ep_num);
extern void mtk_disable_q(struct musb *musb, u8 ep_num, u8 isRx);
extern void mtk_qmu_irq_err(struct musb *musb, u32 qisar);
extern void flush_ep_csr(struct musb *musb, u8 ep_num, u8 isRx);
extern void mtk_qmu_stop(u8 ep_num, u8 isRx);

#endif
#endif