diff options
author | Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | 2009-08-19 00:59:39 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-08-19 21:25:30 -0400 |
commit | c41442474a26984abaa094e96e42182868eab658 (patch) | |
tree | 729f53db686fe5539f07e9aec623936e686f8ab9 /drivers/usb/gadget | |
parent | 24d76195d124986b7702821b8b6cc85942b13146 (diff) |
usb: gadget: R8A66597 peripheral controller support.
While in-tree support for the R8A66597 host side has been supported for
some time, the peripheral side has so far been unsupported. This adds a
new USB gadget driver which bridges the gap and finally wires up the
peripheral side as well.
Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
Tested-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/Kconfig | 18 | ||||
-rw-r--r-- | drivers/usb/gadget/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/gadget_chips.h | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/r8a66597-udc.c | 1635 | ||||
-rw-r--r-- | drivers/usb/gadget/r8a66597-udc.h | 249 |
5 files changed, 1911 insertions, 0 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index b7f10bc25c2c..9f986b417c5b 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -251,6 +251,24 @@ config USB_PXA25X_SMALL | |||
251 | default y if USB_ETH | 251 | default y if USB_ETH |
252 | default y if USB_G_SERIAL | 252 | default y if USB_G_SERIAL |
253 | 253 | ||
254 | config USB_GADGET_R8A66597 | ||
255 | boolean "Renesas R8A66597 USB Peripheral Controller" | ||
256 | select USB_GADGET_DUALSPEED | ||
257 | help | ||
258 | R8A66597 is a discrete USB host and peripheral controller chip that | ||
259 | supports both full and high speed USB 2.0 data transfers. | ||
260 | It has nine configurable endpoints, and endpoint zero. | ||
261 | |||
262 | Say "y" to link the driver statically, or "m" to build a | ||
263 | dynamically linked module called "r8a66597_udc" and force all | ||
264 | gadget drivers to also be dynamically linked. | ||
265 | |||
266 | config USB_R8A66597 | ||
267 | tristate | ||
268 | depends on USB_GADGET_R8A66597 | ||
269 | default USB_GADGET | ||
270 | select USB_GADGET_SELECTED | ||
271 | |||
254 | config USB_GADGET_PXA27X | 272 | config USB_GADGET_PXA27X |
255 | boolean "PXA 27x" | 273 | boolean "PXA 27x" |
256 | depends on ARCH_PXA && (PXA27x || PXA3xx) | 274 | depends on ARCH_PXA && (PXA27x || PXA3xx) |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index e6017e6bf6da..9d7b87c52e9f 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -23,6 +23,7 @@ ifeq ($(CONFIG_ARCH_MXC),y) | |||
23 | fsl_usb2_udc-objs += fsl_mx3_udc.o | 23 | fsl_usb2_udc-objs += fsl_mx3_udc.o |
24 | endif | 24 | endif |
25 | obj-$(CONFIG_USB_M66592) += m66592-udc.o | 25 | obj-$(CONFIG_USB_M66592) += m66592-udc.o |
26 | obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o | ||
26 | obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o | 27 | obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o |
27 | obj-$(CONFIG_USB_CI13XXX) += ci13xxx_udc.o | 28 | obj-$(CONFIG_USB_CI13XXX) += ci13xxx_udc.o |
28 | obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o | 29 | obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o |
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 8e0e9a0b7364..f2d270b202f2 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h | |||
@@ -173,6 +173,12 @@ | |||
173 | // CONFIG_USB_GADGET_AU1X00 | 173 | // CONFIG_USB_GADGET_AU1X00 |
174 | // ... | 174 | // ... |
175 | 175 | ||
176 | #ifdef CONFIG_USB_GADGET_R8A66597 | ||
177 | #define gadget_is_r8a66597(g) !strcmp("r8a66597_udc", (g)->name) | ||
178 | #else | ||
179 | #define gadget_is_r8a66597(g) 0 | ||
180 | #endif | ||
181 | |||
176 | 182 | ||
177 | /** | 183 | /** |
178 | * usb_gadget_controller_number - support bcdDevice id convention | 184 | * usb_gadget_controller_number - support bcdDevice id convention |
@@ -239,6 +245,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) | |||
239 | return 0x23; | 245 | return 0x23; |
240 | else if (gadget_is_langwell(gadget)) | 246 | else if (gadget_is_langwell(gadget)) |
241 | return 0x24; | 247 | return 0x24; |
248 | else if (gadget_is_r8a66597(gadget)) | ||
249 | return 0x25; | ||
242 | return -ENOENT; | 250 | return -ENOENT; |
243 | } | 251 | } |
244 | 252 | ||
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c new file mode 100644 index 000000000000..cc0ba68efa55 --- /dev/null +++ b/drivers/usb/gadget/r8a66597-udc.c | |||
@@ -0,0 +1,1635 @@ | |||
1 | /* | ||
2 | * R8A66597 UDC (USB gadget) | ||
3 | * | ||
4 | * Copyright (C) 2006-2009 Renesas Solutions Corp. | ||
5 | * | ||
6 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | ||
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. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | |||
29 | #include <linux/usb/ch9.h> | ||
30 | #include <linux/usb/gadget.h> | ||
31 | |||
32 | #include "r8a66597-udc.h" | ||
33 | |||
34 | #define DRIVER_VERSION "2009-08-18" | ||
35 | |||
36 | static const char udc_name[] = "r8a66597_udc"; | ||
37 | static const char *r8a66597_ep_name[] = { | ||
38 | "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7", | ||
39 | "ep8", "ep9", | ||
40 | }; | ||
41 | |||
42 | static void disable_controller(struct r8a66597 *r8a66597); | ||
43 | static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req); | ||
44 | static void irq_packet_write(struct r8a66597_ep *ep, | ||
45 | struct r8a66597_request *req); | ||
46 | static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req, | ||
47 | gfp_t gfp_flags); | ||
48 | |||
49 | static void transfer_complete(struct r8a66597_ep *ep, | ||
50 | struct r8a66597_request *req, int status); | ||
51 | |||
52 | /*-------------------------------------------------------------------------*/ | ||
53 | static inline u16 get_usb_speed(struct r8a66597 *r8a66597) | ||
54 | { | ||
55 | return r8a66597_read(r8a66597, DVSTCTR0) & RHST; | ||
56 | } | ||
57 | |||
58 | static void enable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum, | ||
59 | unsigned long reg) | ||
60 | { | ||
61 | u16 tmp; | ||
62 | |||
63 | tmp = r8a66597_read(r8a66597, INTENB0); | ||
64 | r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, | ||
65 | INTENB0); | ||
66 | r8a66597_bset(r8a66597, (1 << pipenum), reg); | ||
67 | r8a66597_write(r8a66597, tmp, INTENB0); | ||
68 | } | ||
69 | |||
70 | static void disable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum, | ||
71 | unsigned long reg) | ||
72 | { | ||
73 | u16 tmp; | ||
74 | |||
75 | tmp = r8a66597_read(r8a66597, INTENB0); | ||
76 | r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, | ||
77 | INTENB0); | ||
78 | r8a66597_bclr(r8a66597, (1 << pipenum), reg); | ||
79 | r8a66597_write(r8a66597, tmp, INTENB0); | ||
80 | } | ||
81 | |||
82 | static void r8a66597_usb_connect(struct r8a66597 *r8a66597) | ||
83 | { | ||
84 | r8a66597_bset(r8a66597, CTRE, INTENB0); | ||
85 | r8a66597_bset(r8a66597, BEMPE | BRDYE, INTENB0); | ||
86 | |||
87 | r8a66597_bset(r8a66597, DPRPU, SYSCFG0); | ||
88 | } | ||
89 | |||
90 | static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597) | ||
91 | __releases(r8a66597->lock) | ||
92 | __acquires(r8a66597->lock) | ||
93 | { | ||
94 | r8a66597_bclr(r8a66597, CTRE, INTENB0); | ||
95 | r8a66597_bclr(r8a66597, BEMPE | BRDYE, INTENB0); | ||
96 | r8a66597_bclr(r8a66597, DPRPU, SYSCFG0); | ||
97 | |||
98 | r8a66597->gadget.speed = USB_SPEED_UNKNOWN; | ||
99 | spin_unlock(&r8a66597->lock); | ||
100 | r8a66597->driver->disconnect(&r8a66597->gadget); | ||
101 | spin_lock(&r8a66597->lock); | ||
102 | |||
103 | disable_controller(r8a66597); | ||
104 | INIT_LIST_HEAD(&r8a66597->ep[0].queue); | ||
105 | } | ||
106 | |||
107 | static inline u16 control_reg_get_pid(struct r8a66597 *r8a66597, u16 pipenum) | ||
108 | { | ||
109 | u16 pid = 0; | ||
110 | unsigned long offset; | ||
111 | |||
112 | if (pipenum == 0) | ||
113 | pid = r8a66597_read(r8a66597, DCPCTR) & PID; | ||
114 | else if (pipenum < R8A66597_MAX_NUM_PIPE) { | ||
115 | offset = get_pipectr_addr(pipenum); | ||
116 | pid = r8a66597_read(r8a66597, offset) & PID; | ||
117 | } else | ||
118 | printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum); | ||
119 | |||
120 | return pid; | ||
121 | } | ||
122 | |||
123 | static inline void control_reg_set_pid(struct r8a66597 *r8a66597, u16 pipenum, | ||
124 | u16 pid) | ||
125 | { | ||
126 | unsigned long offset; | ||
127 | |||
128 | if (pipenum == 0) | ||
129 | r8a66597_mdfy(r8a66597, pid, PID, DCPCTR); | ||
130 | else if (pipenum < R8A66597_MAX_NUM_PIPE) { | ||
131 | offset = get_pipectr_addr(pipenum); | ||
132 | r8a66597_mdfy(r8a66597, pid, PID, offset); | ||
133 | } else | ||
134 | printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum); | ||
135 | } | ||
136 | |||
137 | static inline void pipe_start(struct r8a66597 *r8a66597, u16 pipenum) | ||
138 | { | ||
139 | control_reg_set_pid(r8a66597, pipenum, PID_BUF); | ||
140 | } | ||
141 | |||
142 | static inline void pipe_stop(struct r8a66597 *r8a66597, u16 pipenum) | ||
143 | { | ||
144 | control_reg_set_pid(r8a66597, pipenum, PID_NAK); | ||
145 | } | ||
146 | |||
147 | static inline void pipe_stall(struct r8a66597 *r8a66597, u16 pipenum) | ||
148 | { | ||
149 | control_reg_set_pid(r8a66597, pipenum, PID_STALL); | ||
150 | } | ||
151 | |||
152 | static inline u16 control_reg_get(struct r8a66597 *r8a66597, u16 pipenum) | ||
153 | { | ||
154 | u16 ret = 0; | ||
155 | unsigned long offset; | ||
156 | |||
157 | if (pipenum == 0) | ||
158 | ret = r8a66597_read(r8a66597, DCPCTR); | ||
159 | else if (pipenum < R8A66597_MAX_NUM_PIPE) { | ||
160 | offset = get_pipectr_addr(pipenum); | ||
161 | ret = r8a66597_read(r8a66597, offset); | ||
162 | } else | ||
163 | printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum); | ||
164 | |||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum) | ||
169 | { | ||
170 | unsigned long offset; | ||
171 | |||
172 | pipe_stop(r8a66597, pipenum); | ||
173 | |||
174 | if (pipenum == 0) | ||
175 | r8a66597_bset(r8a66597, SQCLR, DCPCTR); | ||
176 | else if (pipenum < R8A66597_MAX_NUM_PIPE) { | ||
177 | offset = get_pipectr_addr(pipenum); | ||
178 | r8a66597_bset(r8a66597, SQCLR, offset); | ||
179 | } else | ||
180 | printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum); | ||
181 | } | ||
182 | |||
183 | static inline int get_buffer_size(struct r8a66597 *r8a66597, u16 pipenum) | ||
184 | { | ||
185 | u16 tmp; | ||
186 | int size; | ||
187 | |||
188 | if (pipenum == 0) { | ||
189 | tmp = r8a66597_read(r8a66597, DCPCFG); | ||
190 | if ((tmp & R8A66597_CNTMD) != 0) | ||
191 | size = 256; | ||
192 | else { | ||
193 | tmp = r8a66597_read(r8a66597, DCPMAXP); | ||
194 | size = tmp & MAXP; | ||
195 | } | ||
196 | } else { | ||
197 | r8a66597_write(r8a66597, pipenum, PIPESEL); | ||
198 | tmp = r8a66597_read(r8a66597, PIPECFG); | ||
199 | if ((tmp & R8A66597_CNTMD) != 0) { | ||
200 | tmp = r8a66597_read(r8a66597, PIPEBUF); | ||
201 | size = ((tmp >> 10) + 1) * 64; | ||
202 | } else { | ||
203 | tmp = r8a66597_read(r8a66597, PIPEMAXP); | ||
204 | size = tmp & MXPS; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | return size; | ||
209 | } | ||
210 | |||
211 | static inline unsigned short mbw_value(struct r8a66597 *r8a66597) | ||
212 | { | ||
213 | if (r8a66597->pdata->on_chip) | ||
214 | return MBW_32; | ||
215 | else | ||
216 | return MBW_16; | ||
217 | } | ||
218 | |||
219 | static inline void pipe_change(struct r8a66597 *r8a66597, u16 pipenum) | ||
220 | { | ||
221 | struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum]; | ||
222 | |||
223 | if (ep->use_dma) | ||
224 | return; | ||
225 | |||
226 | r8a66597_mdfy(r8a66597, pipenum, CURPIPE, ep->fifosel); | ||
227 | |||
228 | ndelay(450); | ||
229 | |||
230 | r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel); | ||
231 | } | ||
232 | |||
233 | static int pipe_buffer_setting(struct r8a66597 *r8a66597, | ||
234 | struct r8a66597_pipe_info *info) | ||
235 | { | ||
236 | u16 bufnum = 0, buf_bsize = 0; | ||
237 | u16 pipecfg = 0; | ||
238 | |||
239 | if (info->pipe == 0) | ||
240 | return -EINVAL; | ||
241 | |||
242 | r8a66597_write(r8a66597, info->pipe, PIPESEL); | ||
243 | |||
244 | if (info->dir_in) | ||
245 | pipecfg |= R8A66597_DIR; | ||
246 | pipecfg |= info->type; | ||
247 | pipecfg |= info->epnum; | ||
248 | switch (info->type) { | ||
249 | case R8A66597_INT: | ||
250 | bufnum = 4 + (info->pipe - R8A66597_BASE_PIPENUM_INT); | ||
251 | buf_bsize = 0; | ||
252 | break; | ||
253 | case R8A66597_BULK: | ||
254 | bufnum = r8a66597->bi_bufnum + | ||
255 | (info->pipe - R8A66597_BASE_PIPENUM_BULK) * 16; | ||
256 | r8a66597->bi_bufnum += 16; | ||
257 | buf_bsize = 7; | ||
258 | pipecfg |= R8A66597_DBLB; | ||
259 | if (!info->dir_in) | ||
260 | pipecfg |= R8A66597_SHTNAK; | ||
261 | break; | ||
262 | case R8A66597_ISO: | ||
263 | bufnum = r8a66597->bi_bufnum + | ||
264 | (info->pipe - R8A66597_BASE_PIPENUM_ISOC) * 16; | ||
265 | r8a66597->bi_bufnum += 16; | ||
266 | buf_bsize = 7; | ||
267 | break; | ||
268 | } | ||
269 | if (r8a66597->bi_bufnum > R8A66597_MAX_BUFNUM) { | ||
270 | printk(KERN_ERR "r8a66597 pipe memory is insufficient(%d)\n", | ||
271 | r8a66597->bi_bufnum); | ||
272 | return -ENOMEM; | ||
273 | } | ||
274 | |||
275 | r8a66597_write(r8a66597, pipecfg, PIPECFG); | ||
276 | r8a66597_write(r8a66597, (buf_bsize << 10) | (bufnum), PIPEBUF); | ||
277 | r8a66597_write(r8a66597, info->maxpacket, PIPEMAXP); | ||
278 | if (info->interval) | ||
279 | info->interval--; | ||
280 | r8a66597_write(r8a66597, info->interval, PIPEPERI); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static void pipe_buffer_release(struct r8a66597 *r8a66597, | ||
286 | struct r8a66597_pipe_info *info) | ||
287 | { | ||
288 | if (info->pipe == 0) | ||
289 | return; | ||
290 | |||
291 | switch (info->type) { | ||
292 | case R8A66597_BULK: | ||
293 | if (is_bulk_pipe(info->pipe)) | ||
294 | r8a66597->bi_bufnum -= 16; | ||
295 | break; | ||
296 | case R8A66597_ISO: | ||
297 | if (is_isoc_pipe(info->pipe)) | ||
298 | r8a66597->bi_bufnum -= 16; | ||
299 | break; | ||
300 | } | ||
301 | |||
302 | if (is_bulk_pipe(info->pipe)) | ||
303 | r8a66597->bulk--; | ||
304 | else if (is_interrupt_pipe(info->pipe)) | ||
305 | r8a66597->interrupt--; | ||
306 | else if (is_isoc_pipe(info->pipe)) { | ||
307 | r8a66597->isochronous--; | ||
308 | if (info->type == R8A66597_BULK) | ||
309 | r8a66597->bulk--; | ||
310 | } else | ||
311 | printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n", | ||
312 | info->pipe); | ||
313 | } | ||
314 | |||
315 | static void pipe_initialize(struct r8a66597_ep *ep) | ||
316 | { | ||
317 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
318 | |||
319 | r8a66597_mdfy(r8a66597, 0, CURPIPE, ep->fifosel); | ||
320 | |||
321 | r8a66597_write(r8a66597, ACLRM, ep->pipectr); | ||
322 | r8a66597_write(r8a66597, 0, ep->pipectr); | ||
323 | r8a66597_write(r8a66597, SQCLR, ep->pipectr); | ||
324 | if (ep->use_dma) { | ||
325 | r8a66597_mdfy(r8a66597, ep->pipenum, CURPIPE, ep->fifosel); | ||
326 | |||
327 | ndelay(450); | ||
328 | |||
329 | r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static void r8a66597_ep_setting(struct r8a66597 *r8a66597, | ||
334 | struct r8a66597_ep *ep, | ||
335 | const struct usb_endpoint_descriptor *desc, | ||
336 | u16 pipenum, int dma) | ||
337 | { | ||
338 | ep->use_dma = 0; | ||
339 | ep->fifoaddr = CFIFO; | ||
340 | ep->fifosel = CFIFOSEL; | ||
341 | ep->fifoctr = CFIFOCTR; | ||
342 | ep->fifotrn = 0; | ||
343 | |||
344 | ep->pipectr = get_pipectr_addr(pipenum); | ||
345 | ep->pipenum = pipenum; | ||
346 | ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); | ||
347 | r8a66597->pipenum2ep[pipenum] = ep; | ||
348 | r8a66597->epaddr2ep[desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK] | ||
349 | = ep; | ||
350 | INIT_LIST_HEAD(&ep->queue); | ||
351 | } | ||
352 | |||
353 | static void r8a66597_ep_release(struct r8a66597_ep *ep) | ||
354 | { | ||
355 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
356 | u16 pipenum = ep->pipenum; | ||
357 | |||
358 | if (pipenum == 0) | ||
359 | return; | ||
360 | |||
361 | if (ep->use_dma) | ||
362 | r8a66597->num_dma--; | ||
363 | ep->pipenum = 0; | ||
364 | ep->busy = 0; | ||
365 | ep->use_dma = 0; | ||
366 | } | ||
367 | |||
368 | static int alloc_pipe_config(struct r8a66597_ep *ep, | ||
369 | const struct usb_endpoint_descriptor *desc) | ||
370 | { | ||
371 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
372 | struct r8a66597_pipe_info info; | ||
373 | int dma = 0; | ||
374 | unsigned char *counter; | ||
375 | int ret; | ||
376 | |||
377 | ep->desc = desc; | ||
378 | |||
379 | if (ep->pipenum) /* already allocated pipe */ | ||
380 | return 0; | ||
381 | |||
382 | switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
383 | case USB_ENDPOINT_XFER_BULK: | ||
384 | if (r8a66597->bulk >= R8A66597_MAX_NUM_BULK) { | ||
385 | if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) { | ||
386 | printk(KERN_ERR "bulk pipe is insufficient\n"); | ||
387 | return -ENODEV; | ||
388 | } else { | ||
389 | info.pipe = R8A66597_BASE_PIPENUM_ISOC | ||
390 | + r8a66597->isochronous; | ||
391 | counter = &r8a66597->isochronous; | ||
392 | } | ||
393 | } else { | ||
394 | info.pipe = R8A66597_BASE_PIPENUM_BULK + r8a66597->bulk; | ||
395 | counter = &r8a66597->bulk; | ||
396 | } | ||
397 | info.type = R8A66597_BULK; | ||
398 | dma = 1; | ||
399 | break; | ||
400 | case USB_ENDPOINT_XFER_INT: | ||
401 | if (r8a66597->interrupt >= R8A66597_MAX_NUM_INT) { | ||
402 | printk(KERN_ERR "interrupt pipe is insufficient\n"); | ||
403 | return -ENODEV; | ||
404 | } | ||
405 | info.pipe = R8A66597_BASE_PIPENUM_INT + r8a66597->interrupt; | ||
406 | info.type = R8A66597_INT; | ||
407 | counter = &r8a66597->interrupt; | ||
408 | break; | ||
409 | case USB_ENDPOINT_XFER_ISOC: | ||
410 | if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) { | ||
411 | printk(KERN_ERR "isochronous pipe is insufficient\n"); | ||
412 | return -ENODEV; | ||
413 | } | ||
414 | info.pipe = R8A66597_BASE_PIPENUM_ISOC + r8a66597->isochronous; | ||
415 | info.type = R8A66597_ISO; | ||
416 | counter = &r8a66597->isochronous; | ||
417 | break; | ||
418 | default: | ||
419 | printk(KERN_ERR "unexpect xfer type\n"); | ||
420 | return -EINVAL; | ||
421 | } | ||
422 | ep->type = info.type; | ||
423 | |||
424 | info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | ||
425 | info.maxpacket = le16_to_cpu(desc->wMaxPacketSize); | ||
426 | info.interval = desc->bInterval; | ||
427 | if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | ||
428 | info.dir_in = 1; | ||
429 | else | ||
430 | info.dir_in = 0; | ||
431 | |||
432 | ret = pipe_buffer_setting(r8a66597, &info); | ||
433 | if (ret < 0) { | ||
434 | printk(KERN_ERR "pipe_buffer_setting fail\n"); | ||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | (*counter)++; | ||
439 | if ((counter == &r8a66597->isochronous) && info.type == R8A66597_BULK) | ||
440 | r8a66597->bulk++; | ||
441 | |||
442 | r8a66597_ep_setting(r8a66597, ep, desc, info.pipe, dma); | ||
443 | pipe_initialize(ep); | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static int free_pipe_config(struct r8a66597_ep *ep) | ||
449 | { | ||
450 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
451 | struct r8a66597_pipe_info info; | ||
452 | |||
453 | info.pipe = ep->pipenum; | ||
454 | info.type = ep->type; | ||
455 | pipe_buffer_release(r8a66597, &info); | ||
456 | r8a66597_ep_release(ep); | ||
457 | |||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | /*-------------------------------------------------------------------------*/ | ||
462 | static void pipe_irq_enable(struct r8a66597 *r8a66597, u16 pipenum) | ||
463 | { | ||
464 | enable_irq_ready(r8a66597, pipenum); | ||
465 | enable_irq_nrdy(r8a66597, pipenum); | ||
466 | } | ||
467 | |||
468 | static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum) | ||
469 | { | ||
470 | disable_irq_ready(r8a66597, pipenum); | ||
471 | disable_irq_nrdy(r8a66597, pipenum); | ||
472 | } | ||
473 | |||
474 | /* if complete is true, gadget driver complete function is not call */ | ||
475 | static void control_end(struct r8a66597 *r8a66597, unsigned ccpl) | ||
476 | { | ||
477 | r8a66597->ep[0].internal_ccpl = ccpl; | ||
478 | pipe_start(r8a66597, 0); | ||
479 | r8a66597_bset(r8a66597, CCPL, DCPCTR); | ||
480 | } | ||
481 | |||
482 | static void start_ep0_write(struct r8a66597_ep *ep, | ||
483 | struct r8a66597_request *req) | ||
484 | { | ||
485 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
486 | |||
487 | pipe_change(r8a66597, ep->pipenum); | ||
488 | r8a66597_mdfy(r8a66597, ISEL, (ISEL | CURPIPE), CFIFOSEL); | ||
489 | r8a66597_write(r8a66597, BCLR, ep->fifoctr); | ||
490 | if (req->req.length == 0) { | ||
491 | r8a66597_bset(r8a66597, BVAL, ep->fifoctr); | ||
492 | pipe_start(r8a66597, 0); | ||
493 | transfer_complete(ep, req, 0); | ||
494 | } else { | ||
495 | r8a66597_write(r8a66597, ~BEMP0, BEMPSTS); | ||
496 | irq_ep0_write(ep, req); | ||
497 | } | ||
498 | } | ||
499 | |||
500 | static void start_packet_write(struct r8a66597_ep *ep, | ||
501 | struct r8a66597_request *req) | ||
502 | { | ||
503 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
504 | u16 tmp; | ||
505 | |||
506 | pipe_change(r8a66597, ep->pipenum); | ||
507 | disable_irq_empty(r8a66597, ep->pipenum); | ||
508 | pipe_start(r8a66597, ep->pipenum); | ||
509 | |||
510 | tmp = r8a66597_read(r8a66597, ep->fifoctr); | ||
511 | if (unlikely((tmp & FRDY) == 0)) | ||
512 | pipe_irq_enable(r8a66597, ep->pipenum); | ||
513 | else | ||
514 | irq_packet_write(ep, req); | ||
515 | } | ||
516 | |||
517 | static void start_packet_read(struct r8a66597_ep *ep, | ||
518 | struct r8a66597_request *req) | ||
519 | { | ||
520 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
521 | u16 pipenum = ep->pipenum; | ||
522 | |||
523 | if (ep->pipenum == 0) { | ||
524 | r8a66597_mdfy(r8a66597, 0, (ISEL | CURPIPE), CFIFOSEL); | ||
525 | r8a66597_write(r8a66597, BCLR, ep->fifoctr); | ||
526 | pipe_start(r8a66597, pipenum); | ||
527 | pipe_irq_enable(r8a66597, pipenum); | ||
528 | } else { | ||
529 | if (ep->use_dma) { | ||
530 | r8a66597_bset(r8a66597, TRCLR, ep->fifosel); | ||
531 | pipe_change(r8a66597, pipenum); | ||
532 | r8a66597_bset(r8a66597, TRENB, ep->fifosel); | ||
533 | r8a66597_write(r8a66597, | ||
534 | (req->req.length + ep->ep.maxpacket - 1) | ||
535 | / ep->ep.maxpacket, | ||
536 | ep->fifotrn); | ||
537 | } | ||
538 | pipe_start(r8a66597, pipenum); /* trigger once */ | ||
539 | pipe_irq_enable(r8a66597, pipenum); | ||
540 | } | ||
541 | } | ||
542 | |||
543 | static void start_packet(struct r8a66597_ep *ep, struct r8a66597_request *req) | ||
544 | { | ||
545 | if (ep->desc->bEndpointAddress & USB_DIR_IN) | ||
546 | start_packet_write(ep, req); | ||
547 | else | ||
548 | start_packet_read(ep, req); | ||
549 | } | ||
550 | |||
551 | static void start_ep0(struct r8a66597_ep *ep, struct r8a66597_request *req) | ||
552 | { | ||
553 | u16 ctsq; | ||
554 | |||
555 | ctsq = r8a66597_read(ep->r8a66597, INTSTS0) & CTSQ; | ||
556 | |||
557 | switch (ctsq) { | ||
558 | case CS_RDDS: | ||
559 | start_ep0_write(ep, req); | ||
560 | break; | ||
561 | case CS_WRDS: | ||
562 | start_packet_read(ep, req); | ||
563 | break; | ||
564 | |||
565 | case CS_WRND: | ||
566 | control_end(ep->r8a66597, 0); | ||
567 | break; | ||
568 | default: | ||
569 | printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq); | ||
570 | break; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | static void init_controller(struct r8a66597 *r8a66597) | ||
575 | { | ||
576 | u16 vif = r8a66597->pdata->vif ? LDRV : 0; | ||
577 | u16 irq_sense = r8a66597->irq_sense_low ? INTL : 0; | ||
578 | u16 endian = r8a66597->pdata->endian ? BIGEND : 0; | ||
579 | |||
580 | if (r8a66597->pdata->on_chip) { | ||
581 | r8a66597_bset(r8a66597, 0x04, SYSCFG1); | ||
582 | r8a66597_bset(r8a66597, HSE, SYSCFG0); | ||
583 | |||
584 | r8a66597_bclr(r8a66597, USBE, SYSCFG0); | ||
585 | r8a66597_bclr(r8a66597, DPRPU, SYSCFG0); | ||
586 | r8a66597_bset(r8a66597, USBE, SYSCFG0); | ||
587 | |||
588 | r8a66597_bset(r8a66597, SCKE, SYSCFG0); | ||
589 | |||
590 | r8a66597_bset(r8a66597, irq_sense, INTENB1); | ||
591 | r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, | ||
592 | DMA0CFG); | ||
593 | } else { | ||
594 | r8a66597_bset(r8a66597, vif | endian, PINCFG); | ||
595 | r8a66597_bset(r8a66597, HSE, SYSCFG0); /* High spd */ | ||
596 | r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata), | ||
597 | XTAL, SYSCFG0); | ||
598 | |||
599 | r8a66597_bclr(r8a66597, USBE, SYSCFG0); | ||
600 | r8a66597_bclr(r8a66597, DPRPU, SYSCFG0); | ||
601 | r8a66597_bset(r8a66597, USBE, SYSCFG0); | ||
602 | |||
603 | r8a66597_bset(r8a66597, XCKE, SYSCFG0); | ||
604 | |||
605 | msleep(3); | ||
606 | |||
607 | r8a66597_bset(r8a66597, PLLC, SYSCFG0); | ||
608 | |||
609 | msleep(1); | ||
610 | |||
611 | r8a66597_bset(r8a66597, SCKE, SYSCFG0); | ||
612 | |||
613 | r8a66597_bset(r8a66597, irq_sense, INTENB1); | ||
614 | r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, | ||
615 | DMA0CFG); | ||
616 | } | ||
617 | } | ||
618 | |||
619 | static void disable_controller(struct r8a66597 *r8a66597) | ||
620 | { | ||
621 | if (r8a66597->pdata->on_chip) { | ||
622 | r8a66597_bset(r8a66597, SCKE, SYSCFG0); | ||
623 | |||
624 | r8a66597_write(r8a66597, 0, INTENB0); | ||
625 | r8a66597_write(r8a66597, 0, INTENB1); | ||
626 | |||
627 | r8a66597_bclr(r8a66597, USBE, SYSCFG0); | ||
628 | r8a66597_bclr(r8a66597, SCKE, SYSCFG0); | ||
629 | |||
630 | } else { | ||
631 | r8a66597_bclr(r8a66597, SCKE, SYSCFG0); | ||
632 | udelay(1); | ||
633 | r8a66597_bclr(r8a66597, PLLC, SYSCFG0); | ||
634 | udelay(1); | ||
635 | udelay(1); | ||
636 | r8a66597_bclr(r8a66597, XCKE, SYSCFG0); | ||
637 | } | ||
638 | } | ||
639 | |||
640 | static void r8a66597_start_xclock(struct r8a66597 *r8a66597) | ||
641 | { | ||
642 | u16 tmp; | ||
643 | |||
644 | if (!r8a66597->pdata->on_chip) { | ||
645 | tmp = r8a66597_read(r8a66597, SYSCFG0); | ||
646 | if (!(tmp & XCKE)) | ||
647 | r8a66597_bset(r8a66597, XCKE, SYSCFG0); | ||
648 | } | ||
649 | } | ||
650 | |||
651 | static struct r8a66597_request *get_request_from_ep(struct r8a66597_ep *ep) | ||
652 | { | ||
653 | return list_entry(ep->queue.next, struct r8a66597_request, queue); | ||
654 | } | ||
655 | |||
656 | /*-------------------------------------------------------------------------*/ | ||
657 | static void transfer_complete(struct r8a66597_ep *ep, | ||
658 | struct r8a66597_request *req, int status) | ||
659 | __releases(r8a66597->lock) | ||
660 | __acquires(r8a66597->lock) | ||
661 | { | ||
662 | int restart = 0; | ||
663 | |||
664 | if (unlikely(ep->pipenum == 0)) { | ||
665 | if (ep->internal_ccpl) { | ||
666 | ep->internal_ccpl = 0; | ||
667 | return; | ||
668 | } | ||
669 | } | ||
670 | |||
671 | list_del_init(&req->queue); | ||
672 | if (ep->r8a66597->gadget.speed == USB_SPEED_UNKNOWN) | ||
673 | req->req.status = -ESHUTDOWN; | ||
674 | else | ||
675 | req->req.status = status; | ||
676 | |||
677 | if (!list_empty(&ep->queue)) | ||
678 | restart = 1; | ||
679 | |||
680 | spin_unlock(&ep->r8a66597->lock); | ||
681 | req->req.complete(&ep->ep, &req->req); | ||
682 | spin_lock(&ep->r8a66597->lock); | ||
683 | |||
684 | if (restart) { | ||
685 | req = get_request_from_ep(ep); | ||
686 | if (ep->desc) | ||
687 | start_packet(ep, req); | ||
688 | } | ||
689 | } | ||
690 | |||
691 | static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req) | ||
692 | { | ||
693 | int i; | ||
694 | u16 tmp; | ||
695 | unsigned bufsize; | ||
696 | size_t size; | ||
697 | void *buf; | ||
698 | u16 pipenum = ep->pipenum; | ||
699 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
700 | |||
701 | pipe_change(r8a66597, pipenum); | ||
702 | r8a66597_bset(r8a66597, ISEL, ep->fifosel); | ||
703 | |||
704 | i = 0; | ||
705 | do { | ||
706 | tmp = r8a66597_read(r8a66597, ep->fifoctr); | ||
707 | if (i++ > 100000) { | ||
708 | printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus" | ||
709 | "conflict. please power off this controller."); | ||
710 | return; | ||
711 | } | ||
712 | ndelay(1); | ||
713 | } while ((tmp & FRDY) == 0); | ||
714 | |||
715 | /* prepare parameters */ | ||
716 | bufsize = get_buffer_size(r8a66597, pipenum); | ||
717 | buf = req->req.buf + req->req.actual; | ||
718 | size = min(bufsize, req->req.length - req->req.actual); | ||
719 | |||
720 | /* write fifo */ | ||
721 | if (req->req.buf) { | ||
722 | if (size > 0) | ||
723 | r8a66597_write_fifo(r8a66597, ep->fifoaddr, buf, size); | ||
724 | if ((size == 0) || ((size % ep->ep.maxpacket) != 0)) | ||
725 | r8a66597_bset(r8a66597, BVAL, ep->fifoctr); | ||
726 | } | ||
727 | |||
728 | /* update parameters */ | ||
729 | req->req.actual += size; | ||
730 | |||
731 | /* check transfer finish */ | ||
732 | if ((!req->req.zero && (req->req.actual == req->req.length)) | ||
733 | || (size % ep->ep.maxpacket) | ||
734 | || (size == 0)) { | ||
735 | disable_irq_ready(r8a66597, pipenum); | ||
736 | disable_irq_empty(r8a66597, pipenum); | ||
737 | } else { | ||
738 | disable_irq_ready(r8a66597, pipenum); | ||
739 | enable_irq_empty(r8a66597, pipenum); | ||
740 | } | ||
741 | pipe_start(r8a66597, pipenum); | ||
742 | } | ||
743 | |||
744 | static void irq_packet_write(struct r8a66597_ep *ep, | ||
745 | struct r8a66597_request *req) | ||
746 | { | ||
747 | u16 tmp; | ||
748 | unsigned bufsize; | ||
749 | size_t size; | ||
750 | void *buf; | ||
751 | u16 pipenum = ep->pipenum; | ||
752 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
753 | |||
754 | pipe_change(r8a66597, pipenum); | ||
755 | tmp = r8a66597_read(r8a66597, ep->fifoctr); | ||
756 | if (unlikely((tmp & FRDY) == 0)) { | ||
757 | pipe_stop(r8a66597, pipenum); | ||
758 | pipe_irq_disable(r8a66597, pipenum); | ||
759 | printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum); | ||
760 | return; | ||
761 | } | ||
762 | |||
763 | /* prepare parameters */ | ||
764 | bufsize = get_buffer_size(r8a66597, pipenum); | ||
765 | buf = req->req.buf + req->req.actual; | ||
766 | size = min(bufsize, req->req.length - req->req.actual); | ||
767 | |||
768 | /* write fifo */ | ||
769 | if (req->req.buf) { | ||
770 | r8a66597_write_fifo(r8a66597, ep->fifoaddr, buf, size); | ||
771 | if ((size == 0) | ||
772 | || ((size % ep->ep.maxpacket) != 0) | ||
773 | || ((bufsize != ep->ep.maxpacket) | ||
774 | && (bufsize > size))) | ||
775 | r8a66597_bset(r8a66597, BVAL, ep->fifoctr); | ||
776 | } | ||
777 | |||
778 | /* update parameters */ | ||
779 | req->req.actual += size; | ||
780 | /* check transfer finish */ | ||
781 | if ((!req->req.zero && (req->req.actual == req->req.length)) | ||
782 | || (size % ep->ep.maxpacket) | ||
783 | || (size == 0)) { | ||
784 | disable_irq_ready(r8a66597, pipenum); | ||
785 | enable_irq_empty(r8a66597, pipenum); | ||
786 | } else { | ||
787 | disable_irq_empty(r8a66597, pipenum); | ||
788 | pipe_irq_enable(r8a66597, pipenum); | ||
789 | } | ||
790 | } | ||
791 | |||
792 | static void irq_packet_read(struct r8a66597_ep *ep, | ||
793 | struct r8a66597_request *req) | ||
794 | { | ||
795 | u16 tmp; | ||
796 | int rcv_len, bufsize, req_len; | ||
797 | int size; | ||
798 | void *buf; | ||
799 | u16 pipenum = ep->pipenum; | ||
800 | struct r8a66597 *r8a66597 = ep->r8a66597; | ||
801 | int finish = 0; | ||
802 | |||
803 | pipe_change(r8a66597, pipenum); | ||
804 | tmp = r8a66597_read(r8a66597, ep->fifoctr); | ||
805 | if (unlikely((tmp & FRDY) == 0)) { | ||
806 | req->req.status = -EPIPE; | ||
807 | pipe_stop(r8a66597, pipenum); | ||
808 | pipe_irq_disable(r8a66597, pipenum); | ||
809 | printk(KERN_ERR "read fifo not ready"); | ||
810 | return; | ||
811 | } | ||
812 | |||
813 | /* prepare parameters */ | ||
814 | rcv_len = tmp & DTLN; | ||
815 | bufsize = get_buffer_size(r8a66597, pipenum); | ||
816 | |||
817 | buf = req->req.buf + req->req.actual; | ||
818 | req_len = req->req.length - req->req.actual; | ||
819 | if (rcv_len < bufsize) | ||
820 | size = min(rcv_len, req_len); | ||
821 | else | ||
822 | size = min(bufsize, req_len); | ||
823 | |||
824 | /* update parameters */ | ||
825 | req->req.actual += size; | ||
826 | |||
827 | /* check transfer finish */ | ||
828 | if ((!req->req.zero && (req->req.actual == req->req.length)) | ||
829 | || (size % ep->ep.maxpacket) | ||
830 | || (size == 0)) { | ||
831 | pipe_stop(r8a66597, pipenum); | ||
832 | pipe_irq_disable(r8a66597, pipenum); | ||
833 | finish = 1; | ||
834 | } | ||
835 | |||
836 | /* read fifo */ | ||
837 | if (req->req.buf) { | ||
838 | if (size == 0) | ||
839 | r8a66597_write(r8a66597, BCLR, ep->fifoctr); | ||
840 | else | ||
841 | r8a66597_read_fifo(r8a66597, ep->fifoaddr, buf, size); | ||
842 | |||
843 | } | ||
844 | |||
845 | if ((ep->pipenum != 0) && finish) | ||
846 | transfer_complete(ep, req, 0); | ||
847 | } | ||
848 | |||
849 | static void irq_pipe_ready(struct r8a66597 *r8a66597, u16 status, u16 enb) | ||
850 | { | ||
851 | u16 check; | ||
852 | u16 pipenum; | ||
853 | struct r8a66597_ep *ep; | ||
854 | struct r8a66597_request *req; | ||
855 | |||
856 | if ((status & BRDY0) && (enb & BRDY0)) { | ||
857 | r8a66597_write(r8a66597, ~BRDY0, BRDYSTS); | ||
858 | r8a66597_mdfy(r8a66597, 0, CURPIPE, CFIFOSEL); | ||
859 | |||
860 | ep = &r8a66597->ep[0]; | ||
861 | req = get_request_from_ep(ep); | ||
862 | irq_packet_read(ep, req); | ||
863 | } else { | ||
864 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | ||
865 | check = 1 << pipenum; | ||
866 | if ((status & check) && (enb & check)) { | ||
867 | r8a66597_write(r8a66597, ~check, BRDYSTS); | ||
868 | ep = r8a66597->pipenum2ep[pipenum]; | ||
869 | req = get_request_from_ep(ep); | ||
870 | if (ep->desc->bEndpointAddress & USB_DIR_IN) | ||
871 | irq_packet_write(ep, req); | ||
872 | else | ||
873 | irq_packet_read(ep, req); | ||
874 | } | ||
875 | } | ||
876 | } | ||
877 | } | ||
878 | |||
879 | static void irq_pipe_empty(struct r8a66597 *r8a66597, u16 status, u16 enb) | ||
880 | { | ||
881 | u16 tmp; | ||
882 | u16 check; | ||
883 | u16 pipenum; | ||
884 | struct r8a66597_ep *ep; | ||
885 | struct r8a66597_request *req; | ||
886 | |||
887 | if ((status & BEMP0) && (enb & BEMP0)) { | ||
888 | r8a66597_write(r8a66597, ~BEMP0, BEMPSTS); | ||
889 | |||
890 | ep = &r8a66597->ep[0]; | ||
891 | req = get_request_from_ep(ep); | ||
892 | irq_ep0_write(ep, req); | ||
893 | } else { | ||
894 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | ||
895 | check = 1 << pipenum; | ||
896 | if ((status & check) && (enb & check)) { | ||
897 | r8a66597_write(r8a66597, ~check, BEMPSTS); | ||
898 | tmp = control_reg_get(r8a66597, pipenum); | ||
899 | if ((tmp & INBUFM) == 0) { | ||
900 | disable_irq_empty(r8a66597, pipenum); | ||
901 | pipe_irq_disable(r8a66597, pipenum); | ||
902 | pipe_stop(r8a66597, pipenum); | ||
903 | ep = r8a66597->pipenum2ep[pipenum]; | ||
904 | req = get_request_from_ep(ep); | ||
905 | if (!list_empty(&ep->queue)) | ||
906 | transfer_complete(ep, req, 0); | ||
907 | } | ||
908 | } | ||
909 | } | ||
910 | } | ||
911 | } | ||
912 | |||
913 | static void get_status(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl) | ||
914 | __releases(r8a66597->lock) | ||
915 | __acquires(r8a66597->lock) | ||
916 | { | ||
917 | struct r8a66597_ep *ep; | ||
918 | u16 pid; | ||
919 | u16 status = 0; | ||
920 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
921 | |||
922 | switch (ctrl->bRequestType & USB_RECIP_MASK) { | ||
923 | case USB_RECIP_DEVICE: | ||
924 | status = 1 << USB_DEVICE_SELF_POWERED; | ||
925 | break; | ||
926 | case USB_RECIP_INTERFACE: | ||
927 | status = 0; | ||
928 | break; | ||
929 | case USB_RECIP_ENDPOINT: | ||
930 | ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK]; | ||
931 | pid = control_reg_get_pid(r8a66597, ep->pipenum); | ||
932 | if (pid == PID_STALL) | ||
933 | status = 1 << USB_ENDPOINT_HALT; | ||
934 | else | ||
935 | status = 0; | ||
936 | break; | ||
937 | default: | ||
938 | pipe_stall(r8a66597, 0); | ||
939 | return; /* exit */ | ||
940 | } | ||
941 | |||
942 | r8a66597->ep0_data = cpu_to_le16(status); | ||
943 | r8a66597->ep0_req->buf = &r8a66597->ep0_data; | ||
944 | r8a66597->ep0_req->length = 2; | ||
945 | /* AV: what happens if we get called again before that gets through? */ | ||
946 | spin_unlock(&r8a66597->lock); | ||
947 | r8a66597_queue(r8a66597->gadget.ep0, r8a66597->ep0_req, GFP_KERNEL); | ||
948 | spin_lock(&r8a66597->lock); | ||
949 | } | ||
950 | |||
951 | static void clear_feature(struct r8a66597 *r8a66597, | ||
952 | struct usb_ctrlrequest *ctrl) | ||
953 | { | ||
954 | switch (ctrl->bRequestType & USB_RECIP_MASK) { | ||
955 | case USB_RECIP_DEVICE: | ||
956 | control_end(r8a66597, 1); | ||
957 | break; | ||
958 | case USB_RECIP_INTERFACE: | ||
959 | control_end(r8a66597, 1); | ||
960 | break; | ||
961 | case USB_RECIP_ENDPOINT: { | ||
962 | struct r8a66597_ep *ep; | ||
963 | struct r8a66597_request *req; | ||
964 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
965 | |||
966 | ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK]; | ||
967 | pipe_stop(r8a66597, ep->pipenum); | ||
968 | control_reg_sqclr(r8a66597, ep->pipenum); | ||
969 | |||
970 | control_end(r8a66597, 1); | ||
971 | |||
972 | req = get_request_from_ep(ep); | ||
973 | if (ep->busy) { | ||
974 | ep->busy = 0; | ||
975 | if (list_empty(&ep->queue)) | ||
976 | break; | ||
977 | start_packet(ep, req); | ||
978 | } else if (!list_empty(&ep->queue)) | ||
979 | pipe_start(r8a66597, ep->pipenum); | ||
980 | } | ||
981 | break; | ||
982 | default: | ||
983 | pipe_stall(r8a66597, 0); | ||
984 | break; | ||
985 | } | ||
986 | } | ||
987 | |||
988 | static void set_feature(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl) | ||
989 | { | ||
990 | |||
991 | switch (ctrl->bRequestType & USB_RECIP_MASK) { | ||
992 | case USB_RECIP_DEVICE: | ||
993 | control_end(r8a66597, 1); | ||
994 | break; | ||
995 | case USB_RECIP_INTERFACE: | ||
996 | control_end(r8a66597, 1); | ||
997 | break; | ||
998 | case USB_RECIP_ENDPOINT: { | ||
999 | struct r8a66597_ep *ep; | ||
1000 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
1001 | |||
1002 | ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK]; | ||
1003 | pipe_stall(r8a66597, ep->pipenum); | ||
1004 | |||
1005 | control_end(r8a66597, 1); | ||
1006 | } | ||
1007 | break; | ||
1008 | default: | ||
1009 | pipe_stall(r8a66597, 0); | ||
1010 | break; | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | /* if return value is true, call class driver's setup() */ | ||
1015 | static int setup_packet(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl) | ||
1016 | { | ||
1017 | u16 *p = (u16 *)ctrl; | ||
1018 | unsigned long offset = USBREQ; | ||
1019 | int i, ret = 0; | ||
1020 | |||
1021 | /* read fifo */ | ||
1022 | r8a66597_write(r8a66597, ~VALID, INTSTS0); | ||
1023 | |||
1024 | for (i = 0; i < 4; i++) | ||
1025 | p[i] = r8a66597_read(r8a66597, offset + i*2); | ||
1026 | |||
1027 | /* check request */ | ||
1028 | if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { | ||
1029 | switch (ctrl->bRequest) { | ||
1030 | case USB_REQ_GET_STATUS: | ||
1031 | get_status(r8a66597, ctrl); | ||
1032 | break; | ||
1033 | case USB_REQ_CLEAR_FEATURE: | ||
1034 | clear_feature(r8a66597, ctrl); | ||
1035 | break; | ||
1036 | case USB_REQ_SET_FEATURE: | ||
1037 | set_feature(r8a66597, ctrl); | ||
1038 | break; | ||
1039 | default: | ||
1040 | ret = 1; | ||
1041 | break; | ||
1042 | } | ||
1043 | } else | ||
1044 | ret = 1; | ||
1045 | return ret; | ||
1046 | } | ||
1047 | |||
1048 | static void r8a66597_update_usb_speed(struct r8a66597 *r8a66597) | ||
1049 | { | ||
1050 | u16 speed = get_usb_speed(r8a66597); | ||
1051 | |||
1052 | switch (speed) { | ||
1053 | case HSMODE: | ||
1054 | r8a66597->gadget.speed = USB_SPEED_HIGH; | ||
1055 | break; | ||
1056 | case FSMODE: | ||
1057 | r8a66597->gadget.speed = USB_SPEED_FULL; | ||
1058 | break; | ||
1059 | default: | ||
1060 | r8a66597->gadget.speed = USB_SPEED_UNKNOWN; | ||
1061 | printk(KERN_ERR "USB speed unknown\n"); | ||
1062 | } | ||
1063 | } | ||
1064 | |||
1065 | static void irq_device_state(struct r8a66597 *r8a66597) | ||
1066 | { | ||
1067 | u16 dvsq; | ||
1068 | |||
1069 | dvsq = r8a66597_read(r8a66597, INTSTS0) & DVSQ; | ||
1070 | r8a66597_write(r8a66597, ~DVST, INTSTS0); | ||
1071 | |||
1072 | if (dvsq == DS_DFLT) { | ||
1073 | /* bus reset */ | ||
1074 | r8a66597->driver->disconnect(&r8a66597->gadget); | ||
1075 | r8a66597_update_usb_speed(r8a66597); | ||
1076 | } | ||
1077 | if (r8a66597->old_dvsq == DS_CNFG && dvsq != DS_CNFG) | ||
1078 | r8a66597_update_usb_speed(r8a66597); | ||
1079 | if ((dvsq == DS_CNFG || dvsq == DS_ADDS) | ||
1080 | && r8a66597->gadget.speed == USB_SPEED_UNKNOWN) | ||
1081 | r8a66597_update_usb_speed(r8a66597); | ||
1082 | |||
1083 | r8a66597->old_dvsq = dvsq; | ||
1084 | } | ||
1085 | |||
1086 | static void irq_control_stage(struct r8a66597 *r8a66597) | ||
1087 | __releases(r8a66597->lock) | ||
1088 | __acquires(r8a66597->lock) | ||
1089 | { | ||
1090 | struct usb_ctrlrequest ctrl; | ||
1091 | u16 ctsq; | ||
1092 | |||
1093 | ctsq = r8a66597_read(r8a66597, INTSTS0) & CTSQ; | ||
1094 | r8a66597_write(r8a66597, ~CTRT, INTSTS0); | ||
1095 | |||
1096 | switch (ctsq) { | ||
1097 | case CS_IDST: { | ||
1098 | struct r8a66597_ep *ep; | ||
1099 | struct r8a66597_request *req; | ||
1100 | ep = &r8a66597->ep[0]; | ||
1101 | req = get_request_from_ep(ep); | ||
1102 | transfer_complete(ep, req, 0); | ||
1103 | } | ||
1104 | break; | ||
1105 | |||
1106 | case CS_RDDS: | ||
1107 | case CS_WRDS: | ||
1108 | case CS_WRND: | ||
1109 | if (setup_packet(r8a66597, &ctrl)) { | ||
1110 | spin_unlock(&r8a66597->lock); | ||
1111 | if (r8a66597->driver->setup(&r8a66597->gadget, &ctrl) | ||
1112 | < 0) | ||
1113 | pipe_stall(r8a66597, 0); | ||
1114 | spin_lock(&r8a66597->lock); | ||
1115 | } | ||
1116 | break; | ||
1117 | case CS_RDSS: | ||
1118 | case CS_WRSS: | ||
1119 | control_end(r8a66597, 0); | ||
1120 | break; | ||
1121 | default: | ||
1122 | printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq); | ||
1123 | break; | ||
1124 | } | ||
1125 | } | ||
1126 | |||
1127 | static irqreturn_t r8a66597_irq(int irq, void *_r8a66597) | ||
1128 | { | ||
1129 | struct r8a66597 *r8a66597 = _r8a66597; | ||
1130 | u16 intsts0; | ||
1131 | u16 intenb0; | ||
1132 | u16 brdysts, nrdysts, bempsts; | ||
1133 | u16 brdyenb, nrdyenb, bempenb; | ||
1134 | u16 savepipe; | ||
1135 | u16 mask0; | ||
1136 | |||
1137 | spin_lock(&r8a66597->lock); | ||
1138 | |||
1139 | intsts0 = r8a66597_read(r8a66597, INTSTS0); | ||
1140 | intenb0 = r8a66597_read(r8a66597, INTENB0); | ||
1141 | |||
1142 | savepipe = r8a66597_read(r8a66597, CFIFOSEL); | ||
1143 | |||
1144 | mask0 = intsts0 & intenb0; | ||
1145 | if (mask0) { | ||
1146 | brdysts = r8a66597_read(r8a66597, BRDYSTS); | ||
1147 | nrdysts = r8a66597_read(r8a66597, NRDYSTS); | ||
1148 | bempsts = r8a66597_read(r8a66597, BEMPSTS); | ||
1149 | brdyenb = r8a66597_read(r8a66597, BRDYENB); | ||
1150 | nrdyenb = r8a66597_read(r8a66597, NRDYENB); | ||
1151 | bempenb = r8a66597_read(r8a66597, BEMPENB); | ||
1152 | |||
1153 | if (mask0 & VBINT) { | ||
1154 | r8a66597_write(r8a66597, 0xffff & ~VBINT, | ||
1155 | INTSTS0); | ||
1156 | r8a66597_start_xclock(r8a66597); | ||
1157 | |||
1158 | /* start vbus sampling */ | ||
1159 | r8a66597->old_vbus = r8a66597_read(r8a66597, INTSTS0) | ||
1160 | & VBSTS; | ||
1161 | r8a66597->scount = R8A66597_MAX_SAMPLING; | ||
1162 | |||
1163 | mod_timer(&r8a66597->timer, | ||
1164 | jiffies + msecs_to_jiffies(50)); | ||
1165 | } | ||
1166 | if (intsts0 & DVSQ) | ||
1167 | irq_device_state(r8a66597); | ||
1168 | |||
1169 | if ((intsts0 & BRDY) && (intenb0 & BRDYE) | ||
1170 | && (brdysts & brdyenb)) | ||
1171 | irq_pipe_ready(r8a66597, brdysts, brdyenb); | ||
1172 | if ((intsts0 & BEMP) && (intenb0 & BEMPE) | ||
1173 | && (bempsts & bempenb)) | ||
1174 | irq_pipe_empty(r8a66597, bempsts, bempenb); | ||
1175 | |||
1176 | if (intsts0 & CTRT) | ||
1177 | irq_control_stage(r8a66597); | ||
1178 | } | ||
1179 | |||
1180 | r8a66597_write(r8a66597, savepipe, CFIFOSEL); | ||
1181 | |||
1182 | spin_unlock(&r8a66597->lock); | ||
1183 | return IRQ_HANDLED; | ||
1184 | } | ||
1185 | |||
1186 | static void r8a66597_timer(unsigned long _r8a66597) | ||
1187 | { | ||
1188 | struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; | ||
1189 | unsigned long flags; | ||
1190 | u16 tmp; | ||
1191 | |||
1192 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1193 | tmp = r8a66597_read(r8a66597, SYSCFG0); | ||
1194 | if (r8a66597->scount > 0) { | ||
1195 | tmp = r8a66597_read(r8a66597, INTSTS0) & VBSTS; | ||
1196 | if (tmp == r8a66597->old_vbus) { | ||
1197 | r8a66597->scount--; | ||
1198 | if (r8a66597->scount == 0) { | ||
1199 | if (tmp == VBSTS) | ||
1200 | r8a66597_usb_connect(r8a66597); | ||
1201 | else | ||
1202 | r8a66597_usb_disconnect(r8a66597); | ||
1203 | } else { | ||
1204 | mod_timer(&r8a66597->timer, | ||
1205 | jiffies + msecs_to_jiffies(50)); | ||
1206 | } | ||
1207 | } else { | ||
1208 | r8a66597->scount = R8A66597_MAX_SAMPLING; | ||
1209 | r8a66597->old_vbus = tmp; | ||
1210 | mod_timer(&r8a66597->timer, | ||
1211 | jiffies + msecs_to_jiffies(50)); | ||
1212 | } | ||
1213 | } | ||
1214 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1215 | } | ||
1216 | |||
1217 | /*-------------------------------------------------------------------------*/ | ||
1218 | static int r8a66597_enable(struct usb_ep *_ep, | ||
1219 | const struct usb_endpoint_descriptor *desc) | ||
1220 | { | ||
1221 | struct r8a66597_ep *ep; | ||
1222 | |||
1223 | ep = container_of(_ep, struct r8a66597_ep, ep); | ||
1224 | return alloc_pipe_config(ep, desc); | ||
1225 | } | ||
1226 | |||
1227 | static int r8a66597_disable(struct usb_ep *_ep) | ||
1228 | { | ||
1229 | struct r8a66597_ep *ep; | ||
1230 | struct r8a66597_request *req; | ||
1231 | unsigned long flags; | ||
1232 | |||
1233 | ep = container_of(_ep, struct r8a66597_ep, ep); | ||
1234 | BUG_ON(!ep); | ||
1235 | |||
1236 | while (!list_empty(&ep->queue)) { | ||
1237 | req = get_request_from_ep(ep); | ||
1238 | spin_lock_irqsave(&ep->r8a66597->lock, flags); | ||
1239 | transfer_complete(ep, req, -ECONNRESET); | ||
1240 | spin_unlock_irqrestore(&ep->r8a66597->lock, flags); | ||
1241 | } | ||
1242 | |||
1243 | pipe_irq_disable(ep->r8a66597, ep->pipenum); | ||
1244 | return free_pipe_config(ep); | ||
1245 | } | ||
1246 | |||
1247 | static struct usb_request *r8a66597_alloc_request(struct usb_ep *_ep, | ||
1248 | gfp_t gfp_flags) | ||
1249 | { | ||
1250 | struct r8a66597_request *req; | ||
1251 | |||
1252 | req = kzalloc(sizeof(struct r8a66597_request), gfp_flags); | ||
1253 | if (!req) | ||
1254 | return NULL; | ||
1255 | |||
1256 | INIT_LIST_HEAD(&req->queue); | ||
1257 | |||
1258 | return &req->req; | ||
1259 | } | ||
1260 | |||
1261 | static void r8a66597_free_request(struct usb_ep *_ep, struct usb_request *_req) | ||
1262 | { | ||
1263 | struct r8a66597_request *req; | ||
1264 | |||
1265 | req = container_of(_req, struct r8a66597_request, req); | ||
1266 | kfree(req); | ||
1267 | } | ||
1268 | |||
1269 | static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req, | ||
1270 | gfp_t gfp_flags) | ||
1271 | { | ||
1272 | struct r8a66597_ep *ep; | ||
1273 | struct r8a66597_request *req; | ||
1274 | unsigned long flags; | ||
1275 | int request = 0; | ||
1276 | |||
1277 | ep = container_of(_ep, struct r8a66597_ep, ep); | ||
1278 | req = container_of(_req, struct r8a66597_request, req); | ||
1279 | |||
1280 | if (ep->r8a66597->gadget.speed == USB_SPEED_UNKNOWN) | ||
1281 | return -ESHUTDOWN; | ||
1282 | |||
1283 | spin_lock_irqsave(&ep->r8a66597->lock, flags); | ||
1284 | |||
1285 | if (list_empty(&ep->queue)) | ||
1286 | request = 1; | ||
1287 | |||
1288 | list_add_tail(&req->queue, &ep->queue); | ||
1289 | req->req.actual = 0; | ||
1290 | req->req.status = -EINPROGRESS; | ||
1291 | |||
1292 | if (ep->desc == NULL) /* control */ | ||
1293 | start_ep0(ep, req); | ||
1294 | else { | ||
1295 | if (request && !ep->busy) | ||
1296 | start_packet(ep, req); | ||
1297 | } | ||
1298 | |||
1299 | spin_unlock_irqrestore(&ep->r8a66597->lock, flags); | ||
1300 | |||
1301 | return 0; | ||
1302 | } | ||
1303 | |||
1304 | static int r8a66597_dequeue(struct usb_ep *_ep, struct usb_request *_req) | ||
1305 | { | ||
1306 | struct r8a66597_ep *ep; | ||
1307 | struct r8a66597_request *req; | ||
1308 | unsigned long flags; | ||
1309 | |||
1310 | ep = container_of(_ep, struct r8a66597_ep, ep); | ||
1311 | req = container_of(_req, struct r8a66597_request, req); | ||
1312 | |||
1313 | spin_lock_irqsave(&ep->r8a66597->lock, flags); | ||
1314 | if (!list_empty(&ep->queue)) | ||
1315 | transfer_complete(ep, req, -ECONNRESET); | ||
1316 | spin_unlock_irqrestore(&ep->r8a66597->lock, flags); | ||
1317 | |||
1318 | return 0; | ||
1319 | } | ||
1320 | |||
1321 | static int r8a66597_set_halt(struct usb_ep *_ep, int value) | ||
1322 | { | ||
1323 | struct r8a66597_ep *ep; | ||
1324 | struct r8a66597_request *req; | ||
1325 | unsigned long flags; | ||
1326 | int ret = 0; | ||
1327 | |||
1328 | ep = container_of(_ep, struct r8a66597_ep, ep); | ||
1329 | req = get_request_from_ep(ep); | ||
1330 | |||
1331 | spin_lock_irqsave(&ep->r8a66597->lock, flags); | ||
1332 | if (!list_empty(&ep->queue)) { | ||
1333 | ret = -EAGAIN; | ||
1334 | goto out; | ||
1335 | } | ||
1336 | if (value) { | ||
1337 | ep->busy = 1; | ||
1338 | pipe_stall(ep->r8a66597, ep->pipenum); | ||
1339 | } else { | ||
1340 | ep->busy = 0; | ||
1341 | pipe_stop(ep->r8a66597, ep->pipenum); | ||
1342 | } | ||
1343 | |||
1344 | out: | ||
1345 | spin_unlock_irqrestore(&ep->r8a66597->lock, flags); | ||
1346 | return ret; | ||
1347 | } | ||
1348 | |||
1349 | static void r8a66597_fifo_flush(struct usb_ep *_ep) | ||
1350 | { | ||
1351 | struct r8a66597_ep *ep; | ||
1352 | unsigned long flags; | ||
1353 | |||
1354 | ep = container_of(_ep, struct r8a66597_ep, ep); | ||
1355 | spin_lock_irqsave(&ep->r8a66597->lock, flags); | ||
1356 | if (list_empty(&ep->queue) && !ep->busy) { | ||
1357 | pipe_stop(ep->r8a66597, ep->pipenum); | ||
1358 | r8a66597_bclr(ep->r8a66597, BCLR, ep->fifoctr); | ||
1359 | } | ||
1360 | spin_unlock_irqrestore(&ep->r8a66597->lock, flags); | ||
1361 | } | ||
1362 | |||
1363 | static struct usb_ep_ops r8a66597_ep_ops = { | ||
1364 | .enable = r8a66597_enable, | ||
1365 | .disable = r8a66597_disable, | ||
1366 | |||
1367 | .alloc_request = r8a66597_alloc_request, | ||
1368 | .free_request = r8a66597_free_request, | ||
1369 | |||
1370 | .queue = r8a66597_queue, | ||
1371 | .dequeue = r8a66597_dequeue, | ||
1372 | |||
1373 | .set_halt = r8a66597_set_halt, | ||
1374 | .fifo_flush = r8a66597_fifo_flush, | ||
1375 | }; | ||
1376 | |||
1377 | /*-------------------------------------------------------------------------*/ | ||
1378 | static struct r8a66597 *the_controller; | ||
1379 | |||
1380 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) | ||
1381 | { | ||
1382 | struct r8a66597 *r8a66597 = the_controller; | ||
1383 | int retval; | ||
1384 | |||
1385 | if (!driver | ||
1386 | || driver->speed != USB_SPEED_HIGH | ||
1387 | || !driver->bind | ||
1388 | || !driver->setup) | ||
1389 | return -EINVAL; | ||
1390 | if (!r8a66597) | ||
1391 | return -ENODEV; | ||
1392 | if (r8a66597->driver) | ||
1393 | return -EBUSY; | ||
1394 | |||
1395 | /* hook up the driver */ | ||
1396 | driver->driver.bus = NULL; | ||
1397 | r8a66597->driver = driver; | ||
1398 | r8a66597->gadget.dev.driver = &driver->driver; | ||
1399 | |||
1400 | retval = device_add(&r8a66597->gadget.dev); | ||
1401 | if (retval) { | ||
1402 | printk(KERN_ERR "device_add error (%d)\n", retval); | ||
1403 | goto error; | ||
1404 | } | ||
1405 | |||
1406 | retval = driver->bind(&r8a66597->gadget); | ||
1407 | if (retval) { | ||
1408 | printk(KERN_ERR "bind to driver error (%d)\n", retval); | ||
1409 | device_del(&r8a66597->gadget.dev); | ||
1410 | goto error; | ||
1411 | } | ||
1412 | |||
1413 | r8a66597_bset(r8a66597, VBSE, INTENB0); | ||
1414 | if (r8a66597_read(r8a66597, INTSTS0) & VBSTS) { | ||
1415 | r8a66597_start_xclock(r8a66597); | ||
1416 | /* start vbus sampling */ | ||
1417 | r8a66597->old_vbus = r8a66597_read(r8a66597, | ||
1418 | INTSTS0) & VBSTS; | ||
1419 | r8a66597->scount = R8A66597_MAX_SAMPLING; | ||
1420 | mod_timer(&r8a66597->timer, jiffies + msecs_to_jiffies(50)); | ||
1421 | } | ||
1422 | |||
1423 | return 0; | ||
1424 | |||
1425 | error: | ||
1426 | r8a66597->driver = NULL; | ||
1427 | r8a66597->gadget.dev.driver = NULL; | ||
1428 | |||
1429 | return retval; | ||
1430 | } | ||
1431 | EXPORT_SYMBOL(usb_gadget_register_driver); | ||
1432 | |||
1433 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | ||
1434 | { | ||
1435 | struct r8a66597 *r8a66597 = the_controller; | ||
1436 | unsigned long flags; | ||
1437 | |||
1438 | if (driver != r8a66597->driver || !driver->unbind) | ||
1439 | return -EINVAL; | ||
1440 | |||
1441 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1442 | if (r8a66597->gadget.speed != USB_SPEED_UNKNOWN) | ||
1443 | r8a66597_usb_disconnect(r8a66597); | ||
1444 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1445 | |||
1446 | r8a66597_bclr(r8a66597, VBSE, INTENB0); | ||
1447 | |||
1448 | driver->unbind(&r8a66597->gadget); | ||
1449 | |||
1450 | init_controller(r8a66597); | ||
1451 | disable_controller(r8a66597); | ||
1452 | |||
1453 | device_del(&r8a66597->gadget.dev); | ||
1454 | r8a66597->driver = NULL; | ||
1455 | return 0; | ||
1456 | } | ||
1457 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | ||
1458 | |||
1459 | /*-------------------------------------------------------------------------*/ | ||
1460 | static int r8a66597_get_frame(struct usb_gadget *_gadget) | ||
1461 | { | ||
1462 | struct r8a66597 *r8a66597 = gadget_to_r8a66597(_gadget); | ||
1463 | return r8a66597_read(r8a66597, FRMNUM) & 0x03FF; | ||
1464 | } | ||
1465 | |||
1466 | static struct usb_gadget_ops r8a66597_gadget_ops = { | ||
1467 | .get_frame = r8a66597_get_frame, | ||
1468 | }; | ||
1469 | |||
1470 | static int __exit r8a66597_remove(struct platform_device *pdev) | ||
1471 | { | ||
1472 | struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); | ||
1473 | |||
1474 | del_timer_sync(&r8a66597->timer); | ||
1475 | iounmap((void *)r8a66597->reg); | ||
1476 | free_irq(platform_get_irq(pdev, 0), r8a66597); | ||
1477 | r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req); | ||
1478 | kfree(r8a66597); | ||
1479 | return 0; | ||
1480 | } | ||
1481 | |||
1482 | static void nop_completion(struct usb_ep *ep, struct usb_request *r) | ||
1483 | { | ||
1484 | } | ||
1485 | |||
1486 | static int __init r8a66597_probe(struct platform_device *pdev) | ||
1487 | { | ||
1488 | struct resource *res, *ires; | ||
1489 | int irq; | ||
1490 | void __iomem *reg = NULL; | ||
1491 | struct r8a66597 *r8a66597 = NULL; | ||
1492 | int ret = 0; | ||
1493 | int i; | ||
1494 | unsigned long irq_trigger; | ||
1495 | |||
1496 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1497 | if (!res) { | ||
1498 | ret = -ENODEV; | ||
1499 | printk(KERN_ERR "platform_get_resource error.\n"); | ||
1500 | goto clean_up; | ||
1501 | } | ||
1502 | |||
1503 | ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
1504 | irq = ires->start; | ||
1505 | irq_trigger = ires->flags & IRQF_TRIGGER_MASK; | ||
1506 | |||
1507 | if (irq < 0) { | ||
1508 | ret = -ENODEV; | ||
1509 | printk(KERN_ERR "platform_get_irq error.\n"); | ||
1510 | goto clean_up; | ||
1511 | } | ||
1512 | |||
1513 | reg = ioremap(res->start, resource_size(res)); | ||
1514 | if (reg == NULL) { | ||
1515 | ret = -ENOMEM; | ||
1516 | printk(KERN_ERR "ioremap error.\n"); | ||
1517 | goto clean_up; | ||
1518 | } | ||
1519 | |||
1520 | /* initialize ucd */ | ||
1521 | r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL); | ||
1522 | if (r8a66597 == NULL) { | ||
1523 | printk(KERN_ERR "kzalloc error\n"); | ||
1524 | goto clean_up; | ||
1525 | } | ||
1526 | |||
1527 | spin_lock_init(&r8a66597->lock); | ||
1528 | dev_set_drvdata(&pdev->dev, r8a66597); | ||
1529 | r8a66597->pdata = pdev->dev.platform_data; | ||
1530 | r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW; | ||
1531 | |||
1532 | r8a66597->gadget.ops = &r8a66597_gadget_ops; | ||
1533 | device_initialize(&r8a66597->gadget.dev); | ||
1534 | dev_set_name(&r8a66597->gadget.dev, "gadget"); | ||
1535 | r8a66597->gadget.is_dualspeed = 1; | ||
1536 | r8a66597->gadget.dev.parent = &pdev->dev; | ||
1537 | r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask; | ||
1538 | r8a66597->gadget.dev.release = pdev->dev.release; | ||
1539 | r8a66597->gadget.name = udc_name; | ||
1540 | |||
1541 | init_timer(&r8a66597->timer); | ||
1542 | r8a66597->timer.function = r8a66597_timer; | ||
1543 | r8a66597->timer.data = (unsigned long)r8a66597; | ||
1544 | r8a66597->reg = (unsigned long)reg; | ||
1545 | |||
1546 | r8a66597->bi_bufnum = R8A66597_BASE_BUFNUM; | ||
1547 | |||
1548 | disable_controller(r8a66597); /* make sure controller is disabled */ | ||
1549 | |||
1550 | ret = request_irq(irq, r8a66597_irq, IRQF_DISABLED | IRQF_SHARED, | ||
1551 | udc_name, r8a66597); | ||
1552 | if (ret < 0) { | ||
1553 | printk(KERN_ERR "request_irq error (%d)\n", ret); | ||
1554 | goto clean_up; | ||
1555 | } | ||
1556 | |||
1557 | INIT_LIST_HEAD(&r8a66597->gadget.ep_list); | ||
1558 | r8a66597->gadget.ep0 = &r8a66597->ep[0].ep; | ||
1559 | INIT_LIST_HEAD(&r8a66597->gadget.ep0->ep_list); | ||
1560 | for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) { | ||
1561 | struct r8a66597_ep *ep = &r8a66597->ep[i]; | ||
1562 | |||
1563 | if (i != 0) { | ||
1564 | INIT_LIST_HEAD(&r8a66597->ep[i].ep.ep_list); | ||
1565 | list_add_tail(&r8a66597->ep[i].ep.ep_list, | ||
1566 | &r8a66597->gadget.ep_list); | ||
1567 | } | ||
1568 | ep->r8a66597 = r8a66597; | ||
1569 | INIT_LIST_HEAD(&ep->queue); | ||
1570 | ep->ep.name = r8a66597_ep_name[i]; | ||
1571 | ep->ep.ops = &r8a66597_ep_ops; | ||
1572 | ep->ep.maxpacket = 512; | ||
1573 | } | ||
1574 | r8a66597->ep[0].ep.maxpacket = 64; | ||
1575 | r8a66597->ep[0].pipenum = 0; | ||
1576 | r8a66597->ep[0].fifoaddr = CFIFO; | ||
1577 | r8a66597->ep[0].fifosel = CFIFOSEL; | ||
1578 | r8a66597->ep[0].fifoctr = CFIFOCTR; | ||
1579 | r8a66597->ep[0].fifotrn = 0; | ||
1580 | r8a66597->ep[0].pipectr = get_pipectr_addr(0); | ||
1581 | r8a66597->pipenum2ep[0] = &r8a66597->ep[0]; | ||
1582 | r8a66597->epaddr2ep[0] = &r8a66597->ep[0]; | ||
1583 | |||
1584 | the_controller = r8a66597; | ||
1585 | |||
1586 | r8a66597->ep0_req = r8a66597_alloc_request(&r8a66597->ep[0].ep, | ||
1587 | GFP_KERNEL); | ||
1588 | if (r8a66597->ep0_req == NULL) | ||
1589 | goto clean_up2; | ||
1590 | r8a66597->ep0_req->complete = nop_completion; | ||
1591 | |||
1592 | init_controller(r8a66597); | ||
1593 | |||
1594 | dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION); | ||
1595 | return 0; | ||
1596 | |||
1597 | clean_up2: | ||
1598 | free_irq(irq, r8a66597); | ||
1599 | clean_up: | ||
1600 | if (r8a66597) { | ||
1601 | if (r8a66597->ep0_req) | ||
1602 | r8a66597_free_request(&r8a66597->ep[0].ep, | ||
1603 | r8a66597->ep0_req); | ||
1604 | kfree(r8a66597); | ||
1605 | } | ||
1606 | if (reg) | ||
1607 | iounmap(reg); | ||
1608 | |||
1609 | return ret; | ||
1610 | } | ||
1611 | |||
1612 | /*-------------------------------------------------------------------------*/ | ||
1613 | static struct platform_driver r8a66597_driver = { | ||
1614 | .remove = __exit_p(r8a66597_remove), | ||
1615 | .driver = { | ||
1616 | .name = (char *) udc_name, | ||
1617 | }, | ||
1618 | }; | ||
1619 | |||
1620 | static int __init r8a66597_udc_init(void) | ||
1621 | { | ||
1622 | return platform_driver_probe(&r8a66597_driver, r8a66597_probe); | ||
1623 | } | ||
1624 | module_init(r8a66597_udc_init); | ||
1625 | |||
1626 | static void __exit r8a66597_udc_cleanup(void) | ||
1627 | { | ||
1628 | platform_driver_unregister(&r8a66597_driver); | ||
1629 | } | ||
1630 | module_exit(r8a66597_udc_cleanup); | ||
1631 | |||
1632 | MODULE_DESCRIPTION("R8A66597 USB gadget driver"); | ||
1633 | MODULE_LICENSE("GPL"); | ||
1634 | MODULE_AUTHOR("Yoshihiro Shimoda"); | ||
1635 | |||
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h new file mode 100644 index 000000000000..a2464bf337c8 --- /dev/null +++ b/drivers/usb/gadget/r8a66597-udc.h | |||
@@ -0,0 +1,249 @@ | |||
1 | /* | ||
2 | * R8A66597 UDC | ||
3 | * | ||
4 | * Copyright (C) 2007-2009 Renesas Solutions Corp. | ||
5 | * | ||
6 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | ||
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. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef __R8A66597_H__ | ||
24 | #define __R8A66597_H__ | ||
25 | |||
26 | #include <linux/usb/r8a66597.h> | ||
27 | |||
28 | #define R8A66597_MAX_SAMPLING 10 | ||
29 | |||
30 | #define R8A66597_MAX_NUM_PIPE 8 | ||
31 | #define R8A66597_MAX_NUM_BULK 3 | ||
32 | #define R8A66597_MAX_NUM_ISOC 2 | ||
33 | #define R8A66597_MAX_NUM_INT 2 | ||
34 | |||
35 | #define R8A66597_BASE_PIPENUM_BULK 3 | ||
36 | #define R8A66597_BASE_PIPENUM_ISOC 1 | ||
37 | #define R8A66597_BASE_PIPENUM_INT 6 | ||
38 | |||
39 | #define R8A66597_BASE_BUFNUM 6 | ||
40 | #define R8A66597_MAX_BUFNUM 0x4F | ||
41 | |||
42 | #define is_bulk_pipe(pipenum) \ | ||
43 | ((pipenum >= R8A66597_BASE_PIPENUM_BULK) && \ | ||
44 | (pipenum < (R8A66597_BASE_PIPENUM_BULK + R8A66597_MAX_NUM_BULK))) | ||
45 | #define is_interrupt_pipe(pipenum) \ | ||
46 | ((pipenum >= R8A66597_BASE_PIPENUM_INT) && \ | ||
47 | (pipenum < (R8A66597_BASE_PIPENUM_INT + R8A66597_MAX_NUM_INT))) | ||
48 | #define is_isoc_pipe(pipenum) \ | ||
49 | ((pipenum >= R8A66597_BASE_PIPENUM_ISOC) && \ | ||
50 | (pipenum < (R8A66597_BASE_PIPENUM_ISOC + R8A66597_MAX_NUM_ISOC))) | ||
51 | |||
52 | struct r8a66597_pipe_info { | ||
53 | u16 pipe; | ||
54 | u16 epnum; | ||
55 | u16 maxpacket; | ||
56 | u16 type; | ||
57 | u16 interval; | ||
58 | u16 dir_in; | ||
59 | }; | ||
60 | |||
61 | struct r8a66597_request { | ||
62 | struct usb_request req; | ||
63 | struct list_head queue; | ||
64 | }; | ||
65 | |||
66 | struct r8a66597_ep { | ||
67 | struct usb_ep ep; | ||
68 | struct r8a66597 *r8a66597; | ||
69 | |||
70 | struct list_head queue; | ||
71 | unsigned busy:1; | ||
72 | unsigned internal_ccpl:1; /* use only control */ | ||
73 | |||
74 | /* this member can able to after r8a66597_enable */ | ||
75 | unsigned use_dma:1; | ||
76 | u16 pipenum; | ||
77 | u16 type; | ||
78 | const struct usb_endpoint_descriptor *desc; | ||
79 | /* register address */ | ||
80 | unsigned char fifoaddr; | ||
81 | unsigned char fifosel; | ||
82 | unsigned char fifoctr; | ||
83 | unsigned char fifotrn; | ||
84 | unsigned char pipectr; | ||
85 | }; | ||
86 | |||
87 | struct r8a66597 { | ||
88 | spinlock_t lock; | ||
89 | unsigned long reg; | ||
90 | |||
91 | struct r8a66597_platdata *pdata; | ||
92 | |||
93 | struct usb_gadget gadget; | ||
94 | struct usb_gadget_driver *driver; | ||
95 | |||
96 | struct r8a66597_ep ep[R8A66597_MAX_NUM_PIPE]; | ||
97 | struct r8a66597_ep *pipenum2ep[R8A66597_MAX_NUM_PIPE]; | ||
98 | struct r8a66597_ep *epaddr2ep[16]; | ||
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 | |||
107 | /* pipe config */ | ||
108 | unsigned short bi_bufnum; /* bulk and isochronous's bufnum */ | ||
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 | |||
121 | static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) | ||
122 | { | ||
123 | return inw(r8a66597->reg + offset); | ||
124 | } | ||
125 | |||
126 | static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, | ||
127 | unsigned long offset, u16 *buf, | ||
128 | int len) | ||
129 | { | ||
130 | if (r8a66597->pdata->on_chip) { | ||
131 | unsigned long fifoaddr = r8a66597->reg + offset; | ||
132 | unsigned long count; | ||
133 | union { | ||
134 | unsigned long dword; | ||
135 | unsigned char byte[4]; | ||
136 | } data; | ||
137 | unsigned char *pb; | ||
138 | int i; | ||
139 | |||
140 | count = len / 4; | ||
141 | insl(fifoaddr, buf, count); | ||
142 | |||
143 | if (len & 0x00000003) { | ||
144 | data.dword = inl(fifoaddr); | ||
145 | pb = (unsigned char *)buf + count * 4; | ||
146 | for (i = 0; i < (len & 0x00000003); i++) | ||
147 | pb[i] = data.byte[i]; | ||
148 | } | ||
149 | } else { | ||
150 | len = (len + 1) / 2; | ||
151 | insw(r8a66597->reg + offset, buf, len); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, | ||
156 | unsigned long offset) | ||
157 | { | ||
158 | outw(val, r8a66597->reg + offset); | ||
159 | } | ||
160 | |||
161 | static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, | ||
162 | unsigned long offset, u16 *buf, | ||
163 | int len) | ||
164 | { | ||
165 | unsigned long fifoaddr = r8a66597->reg + offset; | ||
166 | |||
167 | if (r8a66597->pdata->on_chip) { | ||
168 | unsigned long count; | ||
169 | unsigned char *pb; | ||
170 | int i; | ||
171 | |||
172 | count = len / 4; | ||
173 | outsl(fifoaddr, buf, count); | ||
174 | |||
175 | if (len & 0x00000003) { | ||
176 | pb = (unsigned char *)buf + count * 4; | ||
177 | for (i = 0; i < (len & 0x00000003); i++) { | ||
178 | if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND) | ||
179 | outb(pb[i], fifoaddr + i); | ||
180 | else | ||
181 | outb(pb[i], fifoaddr + 3 - i); | ||
182 | } | ||
183 | } | ||
184 | } else { | ||
185 | int odd = len & 0x0001; | ||
186 | |||
187 | len = len / 2; | ||
188 | outsw(fifoaddr, buf, len); | ||
189 | if (unlikely(odd)) { | ||
190 | buf = &buf[len]; | ||
191 | outb((unsigned char)*buf, fifoaddr); | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, | ||
197 | u16 val, u16 pat, unsigned long offset) | ||
198 | { | ||
199 | u16 tmp; | ||
200 | tmp = r8a66597_read(r8a66597, offset); | ||
201 | tmp = tmp & (~pat); | ||
202 | tmp = tmp | val; | ||
203 | r8a66597_write(r8a66597, tmp, offset); | ||
204 | } | ||
205 | |||
206 | static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata) | ||
207 | { | ||
208 | u16 clock = 0; | ||
209 | |||
210 | switch (pdata->xtal) { | ||
211 | case R8A66597_PLATDATA_XTAL_12MHZ: | ||
212 | clock = XTAL12; | ||
213 | break; | ||
214 | case R8A66597_PLATDATA_XTAL_24MHZ: | ||
215 | clock = XTAL24; | ||
216 | break; | ||
217 | case R8A66597_PLATDATA_XTAL_48MHZ: | ||
218 | clock = XTAL48; | ||
219 | break; | ||
220 | default: | ||
221 | printk(KERN_ERR "r8a66597: platdata clock is wrong.\n"); | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | return clock; | ||
226 | } | ||
227 | |||
228 | #define r8a66597_bclr(r8a66597, val, offset) \ | ||
229 | r8a66597_mdfy(r8a66597, 0, val, offset) | ||
230 | #define r8a66597_bset(r8a66597, val, offset) \ | ||
231 | r8a66597_mdfy(r8a66597, val, 0, offset) | ||
232 | |||
233 | #define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2) | ||
234 | |||
235 | #define enable_irq_ready(r8a66597, pipenum) \ | ||
236 | enable_pipe_irq(r8a66597, pipenum, BRDYENB) | ||
237 | #define disable_irq_ready(r8a66597, pipenum) \ | ||
238 | disable_pipe_irq(r8a66597, pipenum, BRDYENB) | ||
239 | #define enable_irq_empty(r8a66597, pipenum) \ | ||
240 | enable_pipe_irq(r8a66597, pipenum, BEMPENB) | ||
241 | #define disable_irq_empty(r8a66597, pipenum) \ | ||
242 | disable_pipe_irq(r8a66597, pipenum, BEMPENB) | ||
243 | #define enable_irq_nrdy(r8a66597, pipenum) \ | ||
244 | enable_pipe_irq(r8a66597, pipenum, NRDYENB) | ||
245 | #define disable_irq_nrdy(r8a66597, pipenum) \ | ||
246 | disable_pipe_irq(r8a66597, pipenum, NRDYENB) | ||
247 | |||
248 | #endif /* __R8A66597_H__ */ | ||
249 | |||