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