1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * R8A66597 HCD (Host Controller Driver) |
4 | * |
5 | * Copyright (C) 2006-2007 Renesas Solutions Corp. |
6 | * Portions Copyright (C) 2004 Psion Teklogix (for NetBook PRO) |
7 | * Portions Copyright (C) 2004-2005 David Brownell |
8 | * Portions Copyright (C) 1999 Roman Weissgaerber |
9 | * |
10 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> |
11 | */ |
12 | |
13 | #ifndef __R8A66597_H__ |
14 | #define __R8A66597_H__ |
15 | |
16 | #include <linux/clk.h> |
17 | #include <linux/usb/r8a66597.h> |
18 | |
19 | #define R8A66597_MAX_NUM_PIPE 10 |
20 | #define R8A66597_BUF_BSIZE 8 |
21 | #define R8A66597_MAX_DEVICE 10 |
22 | #define R8A66597_MAX_ROOT_HUB 2 |
23 | #define R8A66597_MAX_SAMPLING 5 |
24 | #define R8A66597_RH_POLL_TIME 10 |
25 | #define R8A66597_MAX_DMA_CHANNEL 2 |
26 | #define R8A66597_PIPE_NO_DMA R8A66597_MAX_DMA_CHANNEL |
27 | #define check_bulk_or_isoc(pipenum) ((pipenum >= 1 && pipenum <= 5)) |
28 | #define check_interrupt(pipenum) ((pipenum >= 6 && pipenum <= 9)) |
29 | #define make_devsel(addr) (addr << 12) |
30 | |
31 | struct r8a66597_pipe_info { |
32 | unsigned long timer_interval; |
33 | u16 pipenum; |
34 | u16 address; /* R8A66597 HCD usb address */ |
35 | u16 epnum; |
36 | u16 maxpacket; |
37 | u16 type; |
38 | u16 bufnum; |
39 | u16 buf_bsize; |
40 | u16 interval; |
41 | u16 dir_in; |
42 | }; |
43 | |
44 | struct r8a66597_pipe { |
45 | struct r8a66597_pipe_info info; |
46 | |
47 | unsigned long fifoaddr; |
48 | unsigned long fifosel; |
49 | unsigned long fifoctr; |
50 | unsigned long pipectr; |
51 | unsigned long pipetre; |
52 | unsigned long pipetrn; |
53 | }; |
54 | |
55 | struct r8a66597_td { |
56 | struct r8a66597_pipe *pipe; |
57 | struct urb *urb; |
58 | struct list_head queue; |
59 | |
60 | u16 type; |
61 | u16 pipenum; |
62 | int iso_cnt; |
63 | |
64 | u16 address; /* R8A66597's USB address */ |
65 | u16 maxpacket; |
66 | |
67 | unsigned zero_packet:1; |
68 | unsigned short_packet:1; |
69 | unsigned set_address:1; |
70 | }; |
71 | |
72 | struct r8a66597_device { |
73 | u16 address; /* R8A66597's USB address */ |
74 | u16 hub_port; |
75 | u16 root_port; |
76 | |
77 | unsigned short ep_in_toggle; |
78 | unsigned short ep_out_toggle; |
79 | unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE]; |
80 | unsigned char dma_map; |
81 | |
82 | enum usb_device_state state; |
83 | |
84 | struct usb_device *udev; |
85 | int usb_address; |
86 | struct list_head device_list; |
87 | }; |
88 | |
89 | struct r8a66597_root_hub { |
90 | u32 port; |
91 | u16 old_syssts; |
92 | int scount; |
93 | |
94 | struct r8a66597_device *dev; |
95 | }; |
96 | |
97 | struct r8a66597; |
98 | |
99 | struct r8a66597_timers { |
100 | struct timer_list td; |
101 | struct timer_list interval; |
102 | struct r8a66597 *r8a66597; |
103 | }; |
104 | |
105 | struct r8a66597 { |
106 | spinlock_t lock; |
107 | void __iomem *reg; |
108 | struct clk *clk; |
109 | struct r8a66597_platdata *pdata; |
110 | struct r8a66597_device device0; |
111 | struct r8a66597_root_hub root_hub[R8A66597_MAX_ROOT_HUB]; |
112 | struct list_head pipe_queue[R8A66597_MAX_NUM_PIPE]; |
113 | |
114 | struct timer_list rh_timer; |
115 | struct r8a66597_timers timers[R8A66597_MAX_NUM_PIPE]; |
116 | |
117 | unsigned short address_map; |
118 | unsigned short timeout_map; |
119 | unsigned short interval_map; |
120 | unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE]; |
121 | unsigned char dma_map; |
122 | unsigned int max_root_hub; |
123 | |
124 | struct list_head child_device; |
125 | unsigned long child_connect_map[4]; |
126 | |
127 | unsigned bus_suspended:1; |
128 | unsigned irq_sense_low:1; |
129 | }; |
130 | |
131 | static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd) |
132 | { |
133 | return (struct r8a66597 *)(hcd->hcd_priv); |
134 | } |
135 | |
136 | static inline struct usb_hcd *r8a66597_to_hcd(struct r8a66597 *r8a66597) |
137 | { |
138 | return container_of((void *)r8a66597, struct usb_hcd, hcd_priv); |
139 | } |
140 | |
141 | static inline struct r8a66597_td *r8a66597_get_td(struct r8a66597 *r8a66597, |
142 | u16 pipenum) |
143 | { |
144 | if (unlikely(list_empty(&r8a66597->pipe_queue[pipenum]))) |
145 | return NULL; |
146 | |
147 | return list_entry(r8a66597->pipe_queue[pipenum].next, |
148 | struct r8a66597_td, queue); |
149 | } |
150 | |
151 | static inline struct urb *r8a66597_get_urb(struct r8a66597 *r8a66597, |
152 | u16 pipenum) |
153 | { |
154 | struct r8a66597_td *td; |
155 | |
156 | td = r8a66597_get_td(r8a66597, pipenum); |
157 | return (td ? td->urb : NULL); |
158 | } |
159 | |
160 | static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) |
161 | { |
162 | return ioread16(r8a66597->reg + offset); |
163 | } |
164 | |
165 | static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, |
166 | unsigned long offset, u16 *buf, |
167 | int len) |
168 | { |
169 | void __iomem *fifoaddr = r8a66597->reg + offset; |
170 | unsigned long count; |
171 | |
172 | if (r8a66597->pdata->on_chip) { |
173 | count = len / 4; |
174 | ioread32_rep(port: fifoaddr, buf, count); |
175 | |
176 | if (len & 0x00000003) { |
177 | unsigned long tmp = ioread32(fifoaddr); |
178 | memcpy((unsigned char *)buf + count * 4, &tmp, |
179 | len & 0x03); |
180 | } |
181 | } else { |
182 | len = (len + 1) / 2; |
183 | ioread16_rep(port: fifoaddr, buf, count: len); |
184 | } |
185 | } |
186 | |
187 | static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, |
188 | unsigned long offset) |
189 | { |
190 | iowrite16(val, r8a66597->reg + offset); |
191 | } |
192 | |
193 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, |
194 | u16 val, u16 pat, unsigned long offset) |
195 | { |
196 | u16 tmp; |
197 | tmp = r8a66597_read(r8a66597, offset); |
198 | tmp = tmp & (~pat); |
199 | tmp = tmp | val; |
200 | r8a66597_write(r8a66597, val: tmp, offset); |
201 | } |
202 | |
203 | #define r8a66597_bclr(r8a66597, val, offset) \ |
204 | r8a66597_mdfy(r8a66597, 0, val, offset) |
205 | #define r8a66597_bset(r8a66597, val, offset) \ |
206 | r8a66597_mdfy(r8a66597, val, 0, offset) |
207 | |
208 | static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, |
209 | struct r8a66597_pipe *pipe, u16 *buf, |
210 | int len) |
211 | { |
212 | void __iomem *fifoaddr = r8a66597->reg + pipe->fifoaddr; |
213 | unsigned long count; |
214 | unsigned char *pb; |
215 | int i; |
216 | |
217 | if (r8a66597->pdata->on_chip) { |
218 | count = len / 4; |
219 | iowrite32_rep(port: fifoaddr, buf, count); |
220 | |
221 | if (len & 0x00000003) { |
222 | pb = (unsigned char *)buf + count * 4; |
223 | for (i = 0; i < (len & 0x00000003); i++) { |
224 | if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND) |
225 | iowrite8(pb[i], fifoaddr + i); |
226 | else |
227 | iowrite8(pb[i], fifoaddr + 3 - i); |
228 | } |
229 | } |
230 | } else { |
231 | int odd = len & 0x0001; |
232 | |
233 | len = len / 2; |
234 | iowrite16_rep(port: fifoaddr, buf, count: len); |
235 | if (unlikely(odd)) { |
236 | buf = &buf[len]; |
237 | if (r8a66597->pdata->wr0_shorted_to_wr1) |
238 | r8a66597_bclr(r8a66597, MBW_16, pipe->fifosel); |
239 | iowrite8((unsigned char)*buf, fifoaddr); |
240 | if (r8a66597->pdata->wr0_shorted_to_wr1) |
241 | r8a66597_bset(r8a66597, MBW_16, pipe->fifosel); |
242 | } |
243 | } |
244 | } |
245 | |
246 | static inline unsigned long get_syscfg_reg(int port) |
247 | { |
248 | return port == 0 ? SYSCFG0 : SYSCFG1; |
249 | } |
250 | |
251 | static inline unsigned long get_syssts_reg(int port) |
252 | { |
253 | return port == 0 ? SYSSTS0 : SYSSTS1; |
254 | } |
255 | |
256 | static inline unsigned long get_dvstctr_reg(int port) |
257 | { |
258 | return port == 0 ? DVSTCTR0 : DVSTCTR1; |
259 | } |
260 | |
261 | static inline unsigned long get_dmacfg_reg(int port) |
262 | { |
263 | return port == 0 ? DMA0CFG : DMA1CFG; |
264 | } |
265 | |
266 | static inline unsigned long get_intenb_reg(int port) |
267 | { |
268 | return port == 0 ? INTENB1 : INTENB2; |
269 | } |
270 | |
271 | static inline unsigned long get_intsts_reg(int port) |
272 | { |
273 | return port == 0 ? INTSTS1 : INTSTS2; |
274 | } |
275 | |
276 | static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port) |
277 | { |
278 | unsigned long dvstctr_reg = get_dvstctr_reg(port); |
279 | |
280 | return r8a66597_read(r8a66597, offset: dvstctr_reg) & RHST; |
281 | } |
282 | |
283 | static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port, |
284 | int power) |
285 | { |
286 | unsigned long dvstctr_reg = get_dvstctr_reg(port); |
287 | |
288 | if (r8a66597->pdata->port_power) { |
289 | r8a66597->pdata->port_power(port, power); |
290 | } else { |
291 | if (power) |
292 | r8a66597_bset(r8a66597, VBOUT, dvstctr_reg); |
293 | else |
294 | r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg); |
295 | } |
296 | } |
297 | |
298 | static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata) |
299 | { |
300 | u16 clock = 0; |
301 | |
302 | switch (pdata->xtal) { |
303 | case R8A66597_PLATDATA_XTAL_12MHZ: |
304 | clock = XTAL12; |
305 | break; |
306 | case R8A66597_PLATDATA_XTAL_24MHZ: |
307 | clock = XTAL24; |
308 | break; |
309 | case R8A66597_PLATDATA_XTAL_48MHZ: |
310 | clock = XTAL48; |
311 | break; |
312 | default: |
313 | printk(KERN_ERR "r8a66597: platdata clock is wrong.\n" ); |
314 | break; |
315 | } |
316 | |
317 | return clock; |
318 | } |
319 | |
320 | #define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2) |
321 | #define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4) |
322 | #define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4) |
323 | #define get_devadd_addr(address) (DEVADD0 + address * 2) |
324 | |
325 | #define enable_irq_ready(r8a66597, pipenum) \ |
326 | enable_pipe_irq(r8a66597, pipenum, BRDYENB) |
327 | #define disable_irq_ready(r8a66597, pipenum) \ |
328 | disable_pipe_irq(r8a66597, pipenum, BRDYENB) |
329 | #define enable_irq_empty(r8a66597, pipenum) \ |
330 | enable_pipe_irq(r8a66597, pipenum, BEMPENB) |
331 | #define disable_irq_empty(r8a66597, pipenum) \ |
332 | disable_pipe_irq(r8a66597, pipenum, BEMPENB) |
333 | #define enable_irq_nrdy(r8a66597, pipenum) \ |
334 | enable_pipe_irq(r8a66597, pipenum, NRDYENB) |
335 | #define disable_irq_nrdy(r8a66597, pipenum) \ |
336 | disable_pipe_irq(r8a66597, pipenum, NRDYENB) |
337 | |
338 | #endif /* __R8A66597_H__ */ |
339 | |
340 | |