Commit | Line | Data |
---|---|---|
c4144247 YS |
1 | /* |
2 | * R8A66597 UDC | |
3 | * | |
4 | * Copyright (C) 2007-2009 Renesas Solutions Corp. | |
5 | * | |
5db05c09 | 6 | * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
c4144247 YS |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; version 2 of the License. | |
c4144247 YS |
11 | */ |
12 | ||
13 | #ifndef __R8A66597_H__ | |
14 | #define __R8A66597_H__ | |
15 | ||
d2e27bdf | 16 | #include <linux/clk.h> |
c4144247 YS |
17 | #include <linux/usb/r8a66597.h> |
18 | ||
19 | #define R8A66597_MAX_SAMPLING 10 | |
20 | ||
21 | #define R8A66597_MAX_NUM_PIPE 8 | |
22 | #define R8A66597_MAX_NUM_BULK 3 | |
23 | #define R8A66597_MAX_NUM_ISOC 2 | |
24 | #define R8A66597_MAX_NUM_INT 2 | |
25 | ||
26 | #define R8A66597_BASE_PIPENUM_BULK 3 | |
27 | #define R8A66597_BASE_PIPENUM_ISOC 1 | |
28 | #define R8A66597_BASE_PIPENUM_INT 6 | |
29 | ||
30 | #define R8A66597_BASE_BUFNUM 6 | |
31 | #define R8A66597_MAX_BUFNUM 0x4F | |
32 | ||
33 | #define is_bulk_pipe(pipenum) \ | |
34 | ((pipenum >= R8A66597_BASE_PIPENUM_BULK) && \ | |
35 | (pipenum < (R8A66597_BASE_PIPENUM_BULK + R8A66597_MAX_NUM_BULK))) | |
36 | #define is_interrupt_pipe(pipenum) \ | |
37 | ((pipenum >= R8A66597_BASE_PIPENUM_INT) && \ | |
38 | (pipenum < (R8A66597_BASE_PIPENUM_INT + R8A66597_MAX_NUM_INT))) | |
39 | #define is_isoc_pipe(pipenum) \ | |
40 | ((pipenum >= R8A66597_BASE_PIPENUM_ISOC) && \ | |
41 | (pipenum < (R8A66597_BASE_PIPENUM_ISOC + R8A66597_MAX_NUM_ISOC))) | |
42 | ||
b8a56e17 | 43 | #define r8a66597_is_sudmac(r8a66597) (r8a66597->pdata->sudmac) |
c4144247 YS |
44 | struct r8a66597_pipe_info { |
45 | u16 pipe; | |
46 | u16 epnum; | |
47 | u16 maxpacket; | |
48 | u16 type; | |
49 | u16 interval; | |
50 | u16 dir_in; | |
51 | }; | |
52 | ||
53 | struct r8a66597_request { | |
54 | struct usb_request req; | |
55 | struct list_head queue; | |
56 | }; | |
57 | ||
58 | struct r8a66597_ep { | |
59 | struct usb_ep ep; | |
60 | struct r8a66597 *r8a66597; | |
b8a56e17 | 61 | struct r8a66597_dma *dma; |
c4144247 YS |
62 | |
63 | struct list_head queue; | |
64 | unsigned busy:1; | |
9e7291c1 | 65 | unsigned wedge:1; |
c4144247 YS |
66 | unsigned internal_ccpl:1; /* use only control */ |
67 | ||
68 | /* this member can able to after r8a66597_enable */ | |
69 | unsigned use_dma:1; | |
70 | u16 pipenum; | |
71 | u16 type; | |
9e658f26 | 72 | |
c4144247 YS |
73 | /* register address */ |
74 | unsigned char fifoaddr; | |
75 | unsigned char fifosel; | |
76 | unsigned char fifoctr; | |
c4144247 | 77 | unsigned char pipectr; |
b8a56e17 YS |
78 | unsigned char pipetre; |
79 | unsigned char pipetrn; | |
80 | }; | |
81 | ||
82 | struct r8a66597_dma { | |
83 | unsigned used:1; | |
84 | unsigned dir:1; /* 1 = IN(write), 0 = OUT(read) */ | |
c4144247 YS |
85 | }; |
86 | ||
87 | struct r8a66597 { | |
88 | spinlock_t lock; | |
e8b48669 | 89 | void __iomem *reg; |
b8a56e17 | 90 | void __iomem *sudmac_reg; |
c4144247 | 91 | |
d2e27bdf | 92 | struct clk *clk; |
c4144247 YS |
93 | struct r8a66597_platdata *pdata; |
94 | ||
95 | struct usb_gadget gadget; | |
96 | struct usb_gadget_driver *driver; | |
97 | ||
98 | struct r8a66597_ep ep[R8A66597_MAX_NUM_PIPE]; | |
99 | struct r8a66597_ep *pipenum2ep[R8A66597_MAX_NUM_PIPE]; | |
100 | struct r8a66597_ep *epaddr2ep[16]; | |
b8a56e17 | 101 | struct r8a66597_dma dma; |
c4144247 YS |
102 | |
103 | struct timer_list timer; | |
104 | struct usb_request *ep0_req; /* for internal request */ | |
105 | u16 ep0_data; /* for internal request */ | |
106 | u16 old_vbus; | |
107 | u16 scount; | |
108 | u16 old_dvsq; | |
1ec9c8a2 | 109 | u16 device_status; /* for GET_STATUS */ |
c4144247 YS |
110 | |
111 | /* pipe config */ | |
c4144247 YS |
112 | unsigned char bulk; |
113 | unsigned char interrupt; | |
114 | unsigned char isochronous; | |
115 | unsigned char num_dma; | |
116 | ||
117 | unsigned irq_sense_low:1; | |
118 | }; | |
119 | ||
120 | #define gadget_to_r8a66597(_gadget) \ | |
121 | container_of(_gadget, struct r8a66597, gadget) | |
122 | #define r8a66597_to_gadget(r8a66597) (&r8a66597->gadget) | |
12158f42 | 123 | #define r8a66597_to_dev(r8a66597) (r8a66597->gadget.dev.parent) |
c4144247 YS |
124 | |
125 | static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) | |
126 | { | |
e8b48669 | 127 | return ioread16(r8a66597->reg + offset); |
c4144247 YS |
128 | } |
129 | ||
130 | static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, | |
59c82d12 MD |
131 | unsigned long offset, |
132 | unsigned char *buf, | |
c4144247 YS |
133 | int len) |
134 | { | |
e8b48669 | 135 | void __iomem *fifoaddr = r8a66597->reg + offset; |
92d3489e | 136 | unsigned int data = 0; |
59c82d12 MD |
137 | int i; |
138 | ||
c4144247 | 139 | if (r8a66597->pdata->on_chip) { |
59c82d12 MD |
140 | /* 32-bit accesses for on_chip controllers */ |
141 | ||
142 | /* aligned buf case */ | |
143 | if (len >= 4 && !((unsigned long)buf & 0x03)) { | |
e8b48669 | 144 | ioread32_rep(fifoaddr, buf, len / 4); |
59c82d12 MD |
145 | buf += len & ~0x03; |
146 | len &= 0x03; | |
147 | } | |
148 | ||
149 | /* unaligned buf case */ | |
150 | for (i = 0; i < len; i++) { | |
151 | if (!(i & 0x03)) | |
e8b48669 | 152 | data = ioread32(fifoaddr); |
59c82d12 MD |
153 | |
154 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; | |
c4144247 YS |
155 | } |
156 | } else { | |
59c82d12 MD |
157 | /* 16-bit accesses for external controllers */ |
158 | ||
159 | /* aligned buf case */ | |
160 | if (len >= 2 && !((unsigned long)buf & 0x01)) { | |
e8b48669 | 161 | ioread16_rep(fifoaddr, buf, len / 2); |
59c82d12 MD |
162 | buf += len & ~0x01; |
163 | len &= 0x01; | |
164 | } | |
165 | ||
166 | /* unaligned buf case */ | |
167 | for (i = 0; i < len; i++) { | |
168 | if (!(i & 0x01)) | |
e8b48669 | 169 | data = ioread16(fifoaddr); |
59c82d12 MD |
170 | |
171 | buf[i] = (data >> ((i & 0x01) * 8)) & 0xff; | |
172 | } | |
c4144247 YS |
173 | } |
174 | } | |
175 | ||
176 | static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, | |
177 | unsigned long offset) | |
178 | { | |
e8b48669 | 179 | iowrite16(val, r8a66597->reg + offset); |
c4144247 YS |
180 | } |
181 | ||
5c481a63 YS |
182 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, |
183 | u16 val, u16 pat, unsigned long offset) | |
184 | { | |
185 | u16 tmp; | |
186 | tmp = r8a66597_read(r8a66597, offset); | |
187 | tmp = tmp & (~pat); | |
188 | tmp = tmp | val; | |
189 | r8a66597_write(r8a66597, tmp, offset); | |
190 | } | |
191 | ||
192 | #define r8a66597_bclr(r8a66597, val, offset) \ | |
193 | r8a66597_mdfy(r8a66597, 0, val, offset) | |
194 | #define r8a66597_bset(r8a66597, val, offset) \ | |
195 | r8a66597_mdfy(r8a66597, val, 0, offset) | |
196 | ||
c4144247 | 197 | static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, |
0a855776 | 198 | struct r8a66597_ep *ep, |
59c82d12 | 199 | unsigned char *buf, |
c4144247 YS |
200 | int len) |
201 | { | |
0a855776 | 202 | void __iomem *fifoaddr = r8a66597->reg + ep->fifoaddr; |
59c82d12 MD |
203 | int adj = 0; |
204 | int i; | |
c4144247 YS |
205 | |
206 | if (r8a66597->pdata->on_chip) { | |
59c82d12 MD |
207 | /* 32-bit access only if buf is 32-bit aligned */ |
208 | if (len >= 4 && !((unsigned long)buf & 0x03)) { | |
e8b48669 | 209 | iowrite32_rep(fifoaddr, buf, len / 4); |
59c82d12 MD |
210 | buf += len & ~0x03; |
211 | len &= 0x03; | |
c4144247 YS |
212 | } |
213 | } else { | |
59c82d12 MD |
214 | /* 16-bit access only if buf is 16-bit aligned */ |
215 | if (len >= 2 && !((unsigned long)buf & 0x01)) { | |
e8b48669 | 216 | iowrite16_rep(fifoaddr, buf, len / 2); |
59c82d12 MD |
217 | buf += len & ~0x01; |
218 | len &= 0x01; | |
c4144247 YS |
219 | } |
220 | } | |
59c82d12 MD |
221 | |
222 | /* adjust fifo address in the little endian case */ | |
223 | if (!(r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)) { | |
224 | if (r8a66597->pdata->on_chip) | |
225 | adj = 0x03; /* 32-bit wide */ | |
226 | else | |
227 | adj = 0x01; /* 16-bit wide */ | |
228 | } | |
229 | ||
5c481a63 YS |
230 | if (r8a66597->pdata->wr0_shorted_to_wr1) |
231 | r8a66597_bclr(r8a66597, MBW_16, ep->fifosel); | |
59c82d12 | 232 | for (i = 0; i < len; i++) |
e8b48669 | 233 | iowrite8(buf[i], fifoaddr + adj - (i & adj)); |
5c481a63 YS |
234 | if (r8a66597->pdata->wr0_shorted_to_wr1) |
235 | r8a66597_bclr(r8a66597, MBW_16, ep->fifosel); | |
c4144247 YS |
236 | } |
237 | ||
238 | static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata) | |
239 | { | |
240 | u16 clock = 0; | |
241 | ||
242 | switch (pdata->xtal) { | |
243 | case R8A66597_PLATDATA_XTAL_12MHZ: | |
244 | clock = XTAL12; | |
245 | break; | |
246 | case R8A66597_PLATDATA_XTAL_24MHZ: | |
247 | clock = XTAL24; | |
248 | break; | |
249 | case R8A66597_PLATDATA_XTAL_48MHZ: | |
250 | clock = XTAL48; | |
251 | break; | |
252 | default: | |
253 | printk(KERN_ERR "r8a66597: platdata clock is wrong.\n"); | |
254 | break; | |
255 | } | |
256 | ||
257 | return clock; | |
258 | } | |
259 | ||
b8a56e17 YS |
260 | static inline u32 r8a66597_sudmac_read(struct r8a66597 *r8a66597, |
261 | unsigned long offset) | |
262 | { | |
263 | return ioread32(r8a66597->sudmac_reg + offset); | |
264 | } | |
265 | ||
266 | static inline void r8a66597_sudmac_write(struct r8a66597 *r8a66597, u32 val, | |
267 | unsigned long offset) | |
268 | { | |
269 | iowrite32(val, r8a66597->sudmac_reg + offset); | |
270 | } | |
271 | ||
c4144247 | 272 | #define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2) |
b8a56e17 YS |
273 | #define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4) |
274 | #define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4) | |
c4144247 YS |
275 | |
276 | #define enable_irq_ready(r8a66597, pipenum) \ | |
277 | enable_pipe_irq(r8a66597, pipenum, BRDYENB) | |
278 | #define disable_irq_ready(r8a66597, pipenum) \ | |
279 | disable_pipe_irq(r8a66597, pipenum, BRDYENB) | |
280 | #define enable_irq_empty(r8a66597, pipenum) \ | |
281 | enable_pipe_irq(r8a66597, pipenum, BEMPENB) | |
282 | #define disable_irq_empty(r8a66597, pipenum) \ | |
283 | disable_pipe_irq(r8a66597, pipenum, BEMPENB) | |
284 | #define enable_irq_nrdy(r8a66597, pipenum) \ | |
285 | enable_pipe_irq(r8a66597, pipenum, NRDYENB) | |
286 | #define disable_irq_nrdy(r8a66597, pipenum) \ | |
287 | disable_pipe_irq(r8a66597, pipenum, NRDYENB) | |
288 | ||
289 | #endif /* __R8A66597_H__ */ | |
290 |