blob: e91f11a8e2b181d866d14050765470a99d064788 [file] [log] [blame]
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001/*
2 * Intel Langwell USB Device Controller driver
3 * Copyright (C) 2008-2009, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
Xiaochen Shen5be19a92009-06-04 15:34:49 +08008 */
9
10
11/* #undef DEBUG */
JiebingLi5f81f4b2010-08-05 14:17:54 +010012/* #undef VERBOSE_DEBUG */
Xiaochen Shen5be19a92009-06-04 15:34:49 +080013
14#if defined(CONFIG_USB_LANGWELL_OTG)
15#define OTG_TRANSCEIVER
16#endif
17
18
19#include <linux/module.h>
20#include <linux/pci.h>
21#include <linux/dma-mapping.h>
22#include <linux/kernel.h>
23#include <linux/delay.h>
24#include <linux/ioport.h>
25#include <linux/sched.h>
26#include <linux/slab.h>
Xiaochen Shen5be19a92009-06-04 15:34:49 +080027#include <linux/errno.h>
28#include <linux/init.h>
29#include <linux/timer.h>
30#include <linux/list.h>
31#include <linux/interrupt.h>
32#include <linux/moduleparam.h>
33#include <linux/device.h>
34#include <linux/usb/ch9.h>
35#include <linux/usb/gadget.h>
36#include <linux/usb/otg.h>
37#include <linux/pm.h>
38#include <linux/io.h>
39#include <linux/irq.h>
40#include <asm/system.h>
41#include <asm/unaligned.h>
42
43#include "langwell_udc.h"
44
45
46#define DRIVER_DESC "Intel Langwell USB Device Controller driver"
47#define DRIVER_VERSION "16 May 2009"
48
49static const char driver_name[] = "langwell_udc";
50static const char driver_desc[] = DRIVER_DESC;
51
52
Xiaochen Shen5be19a92009-06-04 15:34:49 +080053/* for endpoint 0 operations */
54static const struct usb_endpoint_descriptor
55langwell_ep0_desc = {
56 .bLength = USB_DT_ENDPOINT_SIZE,
57 .bDescriptorType = USB_DT_ENDPOINT,
58 .bEndpointAddress = 0,
59 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
60 .wMaxPacketSize = EP0_MAX_PKT_SIZE,
61};
62
63
64/*-------------------------------------------------------------------------*/
65/* debugging */
66
JiebingLi5f81f4b2010-08-05 14:17:54 +010067#ifdef VERBOSE_DEBUG
Xiaochen Shen5be19a92009-06-04 15:34:49 +080068static inline void print_all_registers(struct langwell_udc *dev)
69{
70 int i;
71
72 /* Capability Registers */
JiebingLi5f81f4b2010-08-05 14:17:54 +010073 dev_dbg(&dev->pdev->dev,
74 "Capability Registers (offset: 0x%04x, length: 0x%08x)\n",
75 CAP_REG_OFFSET, (u32)sizeof(struct langwell_cap_regs));
76 dev_dbg(&dev->pdev->dev, "caplength=0x%02x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +080077 readb(&dev->cap_regs->caplength));
JiebingLi5f81f4b2010-08-05 14:17:54 +010078 dev_dbg(&dev->pdev->dev, "hciversion=0x%04x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +080079 readw(&dev->cap_regs->hciversion));
JiebingLi5f81f4b2010-08-05 14:17:54 +010080 dev_dbg(&dev->pdev->dev, "hcsparams=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +080081 readl(&dev->cap_regs->hcsparams));
JiebingLi5f81f4b2010-08-05 14:17:54 +010082 dev_dbg(&dev->pdev->dev, "hccparams=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +080083 readl(&dev->cap_regs->hccparams));
JiebingLi5f81f4b2010-08-05 14:17:54 +010084 dev_dbg(&dev->pdev->dev, "dciversion=0x%04x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +080085 readw(&dev->cap_regs->dciversion));
JiebingLi5f81f4b2010-08-05 14:17:54 +010086 dev_dbg(&dev->pdev->dev, "dccparams=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +080087 readl(&dev->cap_regs->dccparams));
88
89 /* Operational Registers */
JiebingLi5f81f4b2010-08-05 14:17:54 +010090 dev_dbg(&dev->pdev->dev,
91 "Operational Registers (offset: 0x%04x, length: 0x%08x)\n",
92 OP_REG_OFFSET, (u32)sizeof(struct langwell_op_regs));
93 dev_dbg(&dev->pdev->dev, "extsts=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +080094 readl(&dev->op_regs->extsts));
JiebingLi5f81f4b2010-08-05 14:17:54 +010095 dev_dbg(&dev->pdev->dev, "extintr=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +080096 readl(&dev->op_regs->extintr));
JiebingLi5f81f4b2010-08-05 14:17:54 +010097 dev_dbg(&dev->pdev->dev, "usbcmd=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +080098 readl(&dev->op_regs->usbcmd));
JiebingLi5f81f4b2010-08-05 14:17:54 +010099 dev_dbg(&dev->pdev->dev, "usbsts=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800100 readl(&dev->op_regs->usbsts));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100101 dev_dbg(&dev->pdev->dev, "usbintr=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800102 readl(&dev->op_regs->usbintr));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100103 dev_dbg(&dev->pdev->dev, "frindex=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800104 readl(&dev->op_regs->frindex));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100105 dev_dbg(&dev->pdev->dev, "ctrldssegment=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800106 readl(&dev->op_regs->ctrldssegment));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100107 dev_dbg(&dev->pdev->dev, "deviceaddr=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800108 readl(&dev->op_regs->deviceaddr));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100109 dev_dbg(&dev->pdev->dev, "endpointlistaddr=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800110 readl(&dev->op_regs->endpointlistaddr));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100111 dev_dbg(&dev->pdev->dev, "ttctrl=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800112 readl(&dev->op_regs->ttctrl));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100113 dev_dbg(&dev->pdev->dev, "burstsize=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800114 readl(&dev->op_regs->burstsize));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100115 dev_dbg(&dev->pdev->dev, "txfilltuning=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800116 readl(&dev->op_regs->txfilltuning));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100117 dev_dbg(&dev->pdev->dev, "txttfilltuning=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800118 readl(&dev->op_regs->txttfilltuning));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100119 dev_dbg(&dev->pdev->dev, "ic_usb=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800120 readl(&dev->op_regs->ic_usb));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100121 dev_dbg(&dev->pdev->dev, "ulpi_viewport=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800122 readl(&dev->op_regs->ulpi_viewport));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100123 dev_dbg(&dev->pdev->dev, "configflag=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800124 readl(&dev->op_regs->configflag));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100125 dev_dbg(&dev->pdev->dev, "portsc1=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800126 readl(&dev->op_regs->portsc1));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100127 dev_dbg(&dev->pdev->dev, "devlc=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800128 readl(&dev->op_regs->devlc));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100129 dev_dbg(&dev->pdev->dev, "otgsc=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800130 readl(&dev->op_regs->otgsc));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100131 dev_dbg(&dev->pdev->dev, "usbmode=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800132 readl(&dev->op_regs->usbmode));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100133 dev_dbg(&dev->pdev->dev, "endptnak=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800134 readl(&dev->op_regs->endptnak));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100135 dev_dbg(&dev->pdev->dev, "endptnaken=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800136 readl(&dev->op_regs->endptnaken));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100137 dev_dbg(&dev->pdev->dev, "endptsetupstat=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800138 readl(&dev->op_regs->endptsetupstat));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100139 dev_dbg(&dev->pdev->dev, "endptprime=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800140 readl(&dev->op_regs->endptprime));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100141 dev_dbg(&dev->pdev->dev, "endptflush=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800142 readl(&dev->op_regs->endptflush));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100143 dev_dbg(&dev->pdev->dev, "endptstat=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800144 readl(&dev->op_regs->endptstat));
JiebingLi5f81f4b2010-08-05 14:17:54 +0100145 dev_dbg(&dev->pdev->dev, "endptcomplete=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800146 readl(&dev->op_regs->endptcomplete));
147
148 for (i = 0; i < dev->ep_max / 2; i++) {
JiebingLi5f81f4b2010-08-05 14:17:54 +0100149 dev_dbg(&dev->pdev->dev, "endptctrl[%d]=0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800150 i, readl(&dev->op_regs->endptctrl[i]));
151 }
152}
JiebingLi5f81f4b2010-08-05 14:17:54 +0100153#else
154
155#define print_all_registers(dev) do { } while (0)
156
157#endif /* VERBOSE_DEBUG */
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800158
159
160/*-------------------------------------------------------------------------*/
161
JiebingLi5f81f4b2010-08-05 14:17:54 +0100162#define is_in(ep) (((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \
163 USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc)))
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800164
JiebingLi5f81f4b2010-08-05 14:17:54 +0100165#define DIR_STRING(ep) (is_in(ep) ? "in" : "out")
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800166
167
JiebingLi5f81f4b2010-08-05 14:17:54 +0100168static char *type_string(const struct usb_endpoint_descriptor *desc)
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800169{
JiebingLi5f81f4b2010-08-05 14:17:54 +0100170 switch (usb_endpoint_type(desc)) {
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800171 case USB_ENDPOINT_XFER_BULK:
172 return "bulk";
173 case USB_ENDPOINT_XFER_ISOC:
174 return "iso";
175 case USB_ENDPOINT_XFER_INT:
176 return "int";
177 };
178
179 return "control";
180}
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800181
182
183/* configure endpoint control registers */
184static void ep_reset(struct langwell_ep *ep, unsigned char ep_num,
185 unsigned char is_in, unsigned char ep_type)
186{
187 struct langwell_udc *dev;
188 u32 endptctrl;
189
190 dev = ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100191 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800192
193 endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
194 if (is_in) { /* TX */
195 if (ep_num)
196 endptctrl |= EPCTRL_TXR;
197 endptctrl |= EPCTRL_TXE;
198 endptctrl |= ep_type << EPCTRL_TXT_SHIFT;
199 } else { /* RX */
200 if (ep_num)
201 endptctrl |= EPCTRL_RXR;
202 endptctrl |= EPCTRL_RXE;
203 endptctrl |= ep_type << EPCTRL_RXT_SHIFT;
204 }
205
206 writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
207
JiebingLi5f81f4b2010-08-05 14:17:54 +0100208 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800209}
210
211
212/* reset ep0 dQH and endptctrl */
213static void ep0_reset(struct langwell_udc *dev)
214{
215 struct langwell_ep *ep;
216 int i;
217
JiebingLi5f81f4b2010-08-05 14:17:54 +0100218 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800219
220 /* ep0 in and out */
221 for (i = 0; i < 2; i++) {
222 ep = &dev->ep[i];
223 ep->dev = dev;
224
225 /* ep0 dQH */
226 ep->dqh = &dev->ep_dqh[i];
227
228 /* configure ep0 endpoint capabilities in dQH */
229 ep->dqh->dqh_ios = 1;
230 ep->dqh->dqh_mpl = EP0_MAX_PKT_SIZE;
231
JiebingLi3eed2982010-08-05 14:18:05 +0100232 /* enable ep0-in HW zero length termination select */
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800233 if (is_in(ep))
234 ep->dqh->dqh_zlt = 0;
235 ep->dqh->dqh_mult = 0;
236
JiebingLi3eed2982010-08-05 14:18:05 +0100237 ep->dqh->dtd_next = DTD_TERM;
238
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800239 /* configure ep0 control registers */
240 ep_reset(&dev->ep[0], 0, i, USB_ENDPOINT_XFER_CONTROL);
241 }
242
JiebingLi5f81f4b2010-08-05 14:17:54 +0100243 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800244}
245
246
247/*-------------------------------------------------------------------------*/
248
249/* endpoints operations */
250
251/* configure endpoint, making it usable */
252static int langwell_ep_enable(struct usb_ep *_ep,
253 const struct usb_endpoint_descriptor *desc)
254{
255 struct langwell_udc *dev;
256 struct langwell_ep *ep;
257 u16 max = 0;
258 unsigned long flags;
JiebingLi3eed2982010-08-05 14:18:05 +0100259 int i, retval = 0;
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800260 unsigned char zlt, ios = 0, mult = 0;
261
262 ep = container_of(_ep, struct langwell_ep, ep);
263 dev = ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100264 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800265
266 if (!_ep || !desc || ep->desc
267 || desc->bDescriptorType != USB_DT_ENDPOINT)
268 return -EINVAL;
269
270 if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
271 return -ESHUTDOWN;
272
Kuninori Morimoto29cc8892011-08-23 03:12:03 -0700273 max = usb_endpoint_maxp(desc);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800274
275 /*
276 * disable HW zero length termination select
277 * driver handles zero length packet through req->req.zero
278 */
279 zlt = 1;
280
281 /*
282 * sanity check type, direction, address, and then
283 * initialize the endpoint capabilities fields in dQH
284 */
JiebingLi5f81f4b2010-08-05 14:17:54 +0100285 switch (usb_endpoint_type(desc)) {
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800286 case USB_ENDPOINT_XFER_CONTROL:
287 ios = 1;
288 break;
289 case USB_ENDPOINT_XFER_BULK:
290 if ((dev->gadget.speed == USB_SPEED_HIGH
291 && max != 512)
292 || (dev->gadget.speed == USB_SPEED_FULL
293 && max > 64)) {
294 goto done;
295 }
296 break;
297 case USB_ENDPOINT_XFER_INT:
298 if (strstr(ep->ep.name, "-iso")) /* bulk is ok */
299 goto done;
300
301 switch (dev->gadget.speed) {
302 case USB_SPEED_HIGH:
303 if (max <= 1024)
304 break;
305 case USB_SPEED_FULL:
306 if (max <= 64)
307 break;
308 default:
309 if (max <= 8)
310 break;
311 goto done;
312 }
313 break;
314 case USB_ENDPOINT_XFER_ISOC:
315 if (strstr(ep->ep.name, "-bulk")
316 || strstr(ep->ep.name, "-int"))
317 goto done;
318
319 switch (dev->gadget.speed) {
320 case USB_SPEED_HIGH:
321 if (max <= 1024)
322 break;
323 case USB_SPEED_FULL:
324 if (max <= 1023)
325 break;
326 default:
327 goto done;
328 }
329 /*
330 * FIXME:
331 * calculate transactions needed for high bandwidth iso
332 */
333 mult = (unsigned char)(1 + ((max >> 11) & 0x03));
334 max = max & 0x8ff; /* bit 0~10 */
335 /* 3 transactions at most */
336 if (mult > 3)
337 goto done;
338 break;
339 default:
340 goto done;
341 }
342
343 spin_lock_irqsave(&dev->lock, flags);
344
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800345 ep->ep.maxpacket = max;
346 ep->desc = desc;
347 ep->stopped = 0;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100348 ep->ep_num = usb_endpoint_num(desc);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800349
350 /* ep_type */
JiebingLi5f81f4b2010-08-05 14:17:54 +0100351 ep->ep_type = usb_endpoint_type(desc);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800352
353 /* configure endpoint control registers */
354 ep_reset(ep, ep->ep_num, is_in(ep), ep->ep_type);
355
JiebingLi3eed2982010-08-05 14:18:05 +0100356 /* configure endpoint capabilities in dQH */
357 i = ep->ep_num * 2 + is_in(ep);
358 ep->dqh = &dev->ep_dqh[i];
359 ep->dqh->dqh_ios = ios;
360 ep->dqh->dqh_mpl = cpu_to_le16(max);
361 ep->dqh->dqh_zlt = zlt;
362 ep->dqh->dqh_mult = mult;
363 ep->dqh->dtd_next = DTD_TERM;
364
JiebingLi5f81f4b2010-08-05 14:17:54 +0100365 dev_dbg(&dev->pdev->dev, "enabled %s (ep%d%s-%s), max %04x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800366 _ep->name,
367 ep->ep_num,
JiebingLi5f81f4b2010-08-05 14:17:54 +0100368 DIR_STRING(ep),
369 type_string(desc),
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800370 max);
371
372 spin_unlock_irqrestore(&dev->lock, flags);
373done:
JiebingLi5f81f4b2010-08-05 14:17:54 +0100374 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800375 return retval;
376}
377
378
379/*-------------------------------------------------------------------------*/
380
381/* retire a request */
382static void done(struct langwell_ep *ep, struct langwell_request *req,
383 int status)
384{
385 struct langwell_udc *dev = ep->dev;
386 unsigned stopped = ep->stopped;
387 struct langwell_dtd *curr_dtd, *next_dtd;
388 int i;
389
JiebingLi5f81f4b2010-08-05 14:17:54 +0100390 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800391
392 /* remove the req from ep->queue */
393 list_del_init(&req->queue);
394
395 if (req->req.status == -EINPROGRESS)
396 req->req.status = status;
397 else
398 status = req->req.status;
399
400 /* free dTD for the request */
401 next_dtd = req->head;
402 for (i = 0; i < req->dtd_count; i++) {
403 curr_dtd = next_dtd;
404 if (i != req->dtd_count - 1)
405 next_dtd = curr_dtd->next_dtd_virt;
406 dma_pool_free(dev->dtd_pool, curr_dtd, curr_dtd->dtd_dma);
407 }
408
Felipe Balbiac8a1382011-12-19 11:48:24 +0200409 usb_gadget_unmap_request(&dev->gadget, &req->req, is_in(ep));
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800410
411 if (status != -ESHUTDOWN)
JiebingLi5f81f4b2010-08-05 14:17:54 +0100412 dev_dbg(&dev->pdev->dev,
413 "complete %s, req %p, stat %d, len %u/%u\n",
414 ep->ep.name, &req->req, status,
415 req->req.actual, req->req.length);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800416
417 /* don't modify queue heads during completion callback */
418 ep->stopped = 1;
419
420 spin_unlock(&dev->lock);
421 /* complete routine from gadget driver */
422 if (req->req.complete)
423 req->req.complete(&ep->ep, &req->req);
424
425 spin_lock(&dev->lock);
426 ep->stopped = stopped;
427
JiebingLi5f81f4b2010-08-05 14:17:54 +0100428 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800429}
430
431
432static void langwell_ep_fifo_flush(struct usb_ep *_ep);
433
434/* delete all endpoint requests, called with spinlock held */
435static void nuke(struct langwell_ep *ep, int status)
436{
437 /* called with spinlock held */
438 ep->stopped = 1;
439
440 /* endpoint fifo flush */
441 if (&ep->ep && ep->desc)
442 langwell_ep_fifo_flush(&ep->ep);
443
444 while (!list_empty(&ep->queue)) {
445 struct langwell_request *req = NULL;
446 req = list_entry(ep->queue.next, struct langwell_request,
447 queue);
448 done(ep, req, status);
449 }
450}
451
452
453/*-------------------------------------------------------------------------*/
454
455/* endpoint is no longer usable */
456static int langwell_ep_disable(struct usb_ep *_ep)
457{
458 struct langwell_ep *ep;
459 unsigned long flags;
460 struct langwell_udc *dev;
461 int ep_num;
462 u32 endptctrl;
463
464 ep = container_of(_ep, struct langwell_ep, ep);
465 dev = ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100466 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800467
468 if (!_ep || !ep->desc)
469 return -EINVAL;
470
471 spin_lock_irqsave(&dev->lock, flags);
472
473 /* disable endpoint control register */
474 ep_num = ep->ep_num;
475 endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
476 if (is_in(ep))
477 endptctrl &= ~EPCTRL_TXE;
478 else
479 endptctrl &= ~EPCTRL_RXE;
480 writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
481
482 /* nuke all pending requests (does flush) */
483 nuke(ep, -ESHUTDOWN);
484
485 ep->desc = NULL;
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +0200486 ep->ep.desc = NULL;
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800487 ep->stopped = 1;
488
489 spin_unlock_irqrestore(&dev->lock, flags);
490
JiebingLi5f81f4b2010-08-05 14:17:54 +0100491 dev_dbg(&dev->pdev->dev, "disabled %s\n", _ep->name);
492 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800493
494 return 0;
495}
496
497
498/* allocate a request object to use with this endpoint */
499static struct usb_request *langwell_alloc_request(struct usb_ep *_ep,
500 gfp_t gfp_flags)
501{
502 struct langwell_ep *ep;
503 struct langwell_udc *dev;
504 struct langwell_request *req = NULL;
505
506 if (!_ep)
507 return NULL;
508
509 ep = container_of(_ep, struct langwell_ep, ep);
510 dev = ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100511 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800512
513 req = kzalloc(sizeof(*req), gfp_flags);
514 if (!req)
515 return NULL;
516
517 req->req.dma = DMA_ADDR_INVALID;
518 INIT_LIST_HEAD(&req->queue);
519
JiebingLi5f81f4b2010-08-05 14:17:54 +0100520 dev_vdbg(&dev->pdev->dev, "alloc request for %s\n", _ep->name);
521 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800522 return &req->req;
523}
524
525
526/* free a request object */
527static void langwell_free_request(struct usb_ep *_ep,
528 struct usb_request *_req)
529{
530 struct langwell_ep *ep;
531 struct langwell_udc *dev;
532 struct langwell_request *req = NULL;
533
534 ep = container_of(_ep, struct langwell_ep, ep);
535 dev = ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100536 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800537
538 if (!_ep || !_req)
539 return;
540
541 req = container_of(_req, struct langwell_request, req);
542 WARN_ON(!list_empty(&req->queue));
543
544 if (_req)
545 kfree(req);
546
JiebingLi5f81f4b2010-08-05 14:17:54 +0100547 dev_vdbg(&dev->pdev->dev, "free request for %s\n", _ep->name);
548 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800549}
550
551
552/*-------------------------------------------------------------------------*/
553
554/* queue dTD and PRIME endpoint */
555static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req)
556{
557 u32 bit_mask, usbcmd, endptstat, dtd_dma;
558 u8 dtd_status;
559 int i;
560 struct langwell_dqh *dqh;
561 struct langwell_udc *dev;
562
563 dev = ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100564 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800565
566 i = ep->ep_num * 2 + is_in(ep);
567 dqh = &dev->ep_dqh[i];
568
569 if (ep->ep_num)
JiebingLi5f81f4b2010-08-05 14:17:54 +0100570 dev_vdbg(&dev->pdev->dev, "%s\n", ep->name);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800571 else
572 /* ep0 */
JiebingLi5f81f4b2010-08-05 14:17:54 +0100573 dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep));
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800574
Felipe Balbib9af9ea2011-07-04 11:12:32 +0300575 dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%p\n",
576 i, &(dev->ep_dqh[i]));
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800577
578 bit_mask = is_in(ep) ?
579 (1 << (ep->ep_num + 16)) : (1 << (ep->ep_num));
580
JiebingLi5f81f4b2010-08-05 14:17:54 +0100581 dev_vdbg(&dev->pdev->dev, "bit_mask = 0x%08x\n", bit_mask);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800582
583 /* check if the pipe is empty */
584 if (!(list_empty(&ep->queue))) {
585 /* add dTD to the end of linked list */
586 struct langwell_request *lastreq;
587 lastreq = list_entry(ep->queue.prev,
588 struct langwell_request, queue);
589
590 lastreq->tail->dtd_next =
591 cpu_to_le32(req->head->dtd_dma & DTD_NEXT_MASK);
592
593 /* read prime bit, if 1 goto out */
594 if (readl(&dev->op_regs->endptprime) & bit_mask)
595 goto out;
596
597 do {
598 /* set ATDTW bit in USBCMD */
599 usbcmd = readl(&dev->op_regs->usbcmd);
600 writel(usbcmd | CMD_ATDTW, &dev->op_regs->usbcmd);
601
602 /* read correct status bit */
603 endptstat = readl(&dev->op_regs->endptstat) & bit_mask;
604
605 } while (!(readl(&dev->op_regs->usbcmd) & CMD_ATDTW));
606
607 /* write ATDTW bit to 0 */
608 usbcmd = readl(&dev->op_regs->usbcmd);
609 writel(usbcmd & ~CMD_ATDTW, &dev->op_regs->usbcmd);
610
611 if (endptstat)
612 goto out;
613 }
614
615 /* write dQH next pointer and terminate bit to 0 */
616 dtd_dma = req->head->dtd_dma & DTD_NEXT_MASK;
617 dqh->dtd_next = cpu_to_le32(dtd_dma);
618
619 /* clear active and halt bit */
620 dtd_status = (u8) ~(DTD_STS_ACTIVE | DTD_STS_HALTED);
621 dqh->dtd_status &= dtd_status;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100622 dev_vdbg(&dev->pdev->dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status);
623
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300624 /* ensure that updates to the dQH will occur before priming */
JiebingLi5f81f4b2010-08-05 14:17:54 +0100625 wmb();
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800626
627 /* write 1 to endptprime register to PRIME endpoint */
628 bit_mask = is_in(ep) ? (1 << (ep->ep_num + 16)) : (1 << ep->ep_num);
JiebingLi5f81f4b2010-08-05 14:17:54 +0100629 dev_vdbg(&dev->pdev->dev, "endprime bit_mask = 0x%08x\n", bit_mask);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800630 writel(bit_mask, &dev->op_regs->endptprime);
631out:
JiebingLi5f81f4b2010-08-05 14:17:54 +0100632 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800633 return 0;
634}
635
636
637/* fill in the dTD structure to build a transfer descriptor */
638static struct langwell_dtd *build_dtd(struct langwell_request *req,
639 unsigned *length, dma_addr_t *dma, int *is_last)
640{
641 u32 buf_ptr;
642 struct langwell_dtd *dtd;
643 struct langwell_udc *dev;
644 int i;
645
646 dev = req->ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100647 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800648
649 /* the maximum transfer length, up to 16k bytes */
650 *length = min(req->req.length - req->req.actual,
651 (unsigned)DTD_MAX_TRANSFER_LENGTH);
652
653 /* create dTD dma_pool resource */
654 dtd = dma_pool_alloc(dev->dtd_pool, GFP_KERNEL, dma);
655 if (dtd == NULL)
656 return dtd;
657 dtd->dtd_dma = *dma;
658
659 /* initialize buffer page pointers */
660 buf_ptr = (u32)(req->req.dma + req->req.actual);
661 for (i = 0; i < 5; i++)
662 dtd->dtd_buf[i] = cpu_to_le32(buf_ptr + i * PAGE_SIZE);
663
664 req->req.actual += *length;
665
666 /* fill in total bytes with transfer size */
667 dtd->dtd_total = cpu_to_le16(*length);
JiebingLi5f81f4b2010-08-05 14:17:54 +0100668 dev_vdbg(&dev->pdev->dev, "dtd->dtd_total = %d\n", dtd->dtd_total);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800669
670 /* set is_last flag if req->req.zero is set or not */
671 if (req->req.zero) {
672 if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
673 *is_last = 1;
674 else
675 *is_last = 0;
676 } else if (req->req.length == req->req.actual) {
677 *is_last = 1;
678 } else
679 *is_last = 0;
680
681 if (*is_last == 0)
JiebingLi5f81f4b2010-08-05 14:17:54 +0100682 dev_vdbg(&dev->pdev->dev, "multi-dtd request!\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800683
684 /* set interrupt on complete bit for the last dTD */
685 if (*is_last && !req->req.no_interrupt)
686 dtd->dtd_ioc = 1;
687
688 /* set multiplier override 0 for non-ISO and non-TX endpoint */
689 dtd->dtd_multo = 0;
690
691 /* set the active bit of status field to 1 */
692 dtd->dtd_status = DTD_STS_ACTIVE;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100693 dev_vdbg(&dev->pdev->dev, "dtd->dtd_status = 0x%02x\n",
694 dtd->dtd_status);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800695
JiebingLi5f81f4b2010-08-05 14:17:54 +0100696 dev_vdbg(&dev->pdev->dev, "length = %d, dma addr= 0x%08x\n",
697 *length, (int)*dma);
698 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800699 return dtd;
700}
701
702
703/* generate dTD linked list for a request */
704static int req_to_dtd(struct langwell_request *req)
705{
706 unsigned count;
707 int is_last, is_first = 1;
708 struct langwell_dtd *dtd, *last_dtd = NULL;
709 struct langwell_udc *dev;
710 dma_addr_t dma;
711
712 dev = req->ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100713 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800714 do {
715 dtd = build_dtd(req, &count, &dma, &is_last);
716 if (dtd == NULL)
717 return -ENOMEM;
718
719 if (is_first) {
720 is_first = 0;
721 req->head = dtd;
722 } else {
723 last_dtd->dtd_next = cpu_to_le32(dma);
724 last_dtd->next_dtd_virt = dtd;
725 }
726 last_dtd = dtd;
727 req->dtd_count++;
728 } while (!is_last);
729
730 /* set terminate bit to 1 for the last dTD */
731 dtd->dtd_next = DTD_TERM;
732
733 req->tail = dtd;
734
JiebingLi5f81f4b2010-08-05 14:17:54 +0100735 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800736 return 0;
737}
738
739/*-------------------------------------------------------------------------*/
740
741/* queue (submits) an I/O requests to an endpoint */
742static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
743 gfp_t gfp_flags)
744{
745 struct langwell_request *req;
746 struct langwell_ep *ep;
747 struct langwell_udc *dev;
748 unsigned long flags;
Felipe Balbiac8a1382011-12-19 11:48:24 +0200749 int is_iso = 0;
750 int ret;
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800751
752 /* always require a cpu-view buffer */
753 req = container_of(_req, struct langwell_request, req);
754 ep = container_of(_ep, struct langwell_ep, ep);
755
756 if (!_req || !_req->complete || !_req->buf
757 || !list_empty(&req->queue)) {
758 return -EINVAL;
759 }
760
761 if (unlikely(!_ep || !ep->desc))
762 return -EINVAL;
763
764 dev = ep->dev;
765 req->ep = ep;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100766 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800767
JiebingLi5f81f4b2010-08-05 14:17:54 +0100768 if (usb_endpoint_xfer_isoc(ep->desc)) {
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800769 if (req->req.length > ep->ep.maxpacket)
770 return -EMSGSIZE;
771 is_iso = 1;
772 }
773
774 if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
775 return -ESHUTDOWN;
776
Felipe Balbiac8a1382011-12-19 11:48:24 +0200777 /* set up dma mapping */
778 ret = usb_gadget_map_request(&dev->gadget, &req->req, is_in(ep));
779 if (ret)
780 return ret;
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800781
JiebingLi5f81f4b2010-08-05 14:17:54 +0100782 dev_dbg(&dev->pdev->dev,
783 "%s queue req %p, len %u, buf %p, dma 0x%08x\n",
784 _ep->name,
785 _req, _req->length, _req->buf, (int)_req->dma);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800786
787 _req->status = -EINPROGRESS;
788 _req->actual = 0;
789 req->dtd_count = 0;
790
791 spin_lock_irqsave(&dev->lock, flags);
792
793 /* build and put dTDs to endpoint queue */
794 if (!req_to_dtd(req)) {
795 queue_dtd(ep, req);
796 } else {
797 spin_unlock_irqrestore(&dev->lock, flags);
798 return -ENOMEM;
799 }
800
801 /* update ep0 state */
802 if (ep->ep_num == 0)
803 dev->ep0_state = DATA_STATE_XMIT;
804
805 if (likely(req != NULL)) {
806 list_add_tail(&req->queue, &ep->queue);
JiebingLi5f81f4b2010-08-05 14:17:54 +0100807 dev_vdbg(&dev->pdev->dev, "list_add_tail()\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800808 }
809
810 spin_unlock_irqrestore(&dev->lock, flags);
811
JiebingLi5f81f4b2010-08-05 14:17:54 +0100812 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800813 return 0;
814}
815
816
817/* dequeue (cancels, unlinks) an I/O request from an endpoint */
818static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
819{
820 struct langwell_ep *ep;
821 struct langwell_udc *dev;
822 struct langwell_request *req;
823 unsigned long flags;
824 int stopped, ep_num, retval = 0;
825 u32 endptctrl;
826
827 ep = container_of(_ep, struct langwell_ep, ep);
828 dev = ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100829 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800830
831 if (!_ep || !ep->desc || !_req)
832 return -EINVAL;
833
834 if (!dev->driver)
835 return -ESHUTDOWN;
836
837 spin_lock_irqsave(&dev->lock, flags);
838 stopped = ep->stopped;
839
840 /* quiesce dma while we patch the queue */
841 ep->stopped = 1;
842 ep_num = ep->ep_num;
843
844 /* disable endpoint control register */
845 endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
846 if (is_in(ep))
847 endptctrl &= ~EPCTRL_TXE;
848 else
849 endptctrl &= ~EPCTRL_RXE;
850 writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
851
852 /* make sure it's still queued on this endpoint */
853 list_for_each_entry(req, &ep->queue, queue) {
854 if (&req->req == _req)
855 break;
856 }
857
858 if (&req->req != _req) {
859 retval = -EINVAL;
860 goto done;
861 }
862
863 /* queue head may be partially complete. */
864 if (ep->queue.next == &req->queue) {
JiebingLi5f81f4b2010-08-05 14:17:54 +0100865 dev_dbg(&dev->pdev->dev, "unlink (%s) dma\n", _ep->name);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800866 _req->status = -ECONNRESET;
867 langwell_ep_fifo_flush(&ep->ep);
868
869 /* not the last request in endpoint queue */
870 if (likely(ep->queue.next == &req->queue)) {
871 struct langwell_dqh *dqh;
872 struct langwell_request *next_req;
873
874 dqh = ep->dqh;
875 next_req = list_entry(req->queue.next,
876 struct langwell_request, queue);
877
878 /* point the dQH to the first dTD of next request */
879 writel((u32) next_req->head, &dqh->dqh_current);
880 }
881 } else {
882 struct langwell_request *prev_req;
883
884 prev_req = list_entry(req->queue.prev,
885 struct langwell_request, queue);
886 writel(readl(&req->tail->dtd_next),
887 &prev_req->tail->dtd_next);
888 }
889
890 done(ep, req, -ECONNRESET);
891
892done:
893 /* enable endpoint again */
894 endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
895 if (is_in(ep))
896 endptctrl |= EPCTRL_TXE;
897 else
898 endptctrl |= EPCTRL_RXE;
899 writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
900
901 ep->stopped = stopped;
902 spin_unlock_irqrestore(&dev->lock, flags);
903
JiebingLi5f81f4b2010-08-05 14:17:54 +0100904 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800905 return retval;
906}
907
908
909/*-------------------------------------------------------------------------*/
910
911/* endpoint set/clear halt */
912static void ep_set_halt(struct langwell_ep *ep, int value)
913{
914 u32 endptctrl = 0;
915 int ep_num;
916 struct langwell_udc *dev = ep->dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +0100917 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800918
919 ep_num = ep->ep_num;
920 endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
921
922 /* value: 1 - set halt, 0 - clear halt */
923 if (value) {
924 /* set the stall bit */
925 if (is_in(ep))
926 endptctrl |= EPCTRL_TXS;
927 else
928 endptctrl |= EPCTRL_RXS;
929 } else {
930 /* clear the stall bit and reset data toggle */
931 if (is_in(ep)) {
932 endptctrl &= ~EPCTRL_TXS;
933 endptctrl |= EPCTRL_TXR;
934 } else {
935 endptctrl &= ~EPCTRL_RXS;
936 endptctrl |= EPCTRL_RXR;
937 }
938 }
939
940 writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
941
JiebingLi5f81f4b2010-08-05 14:17:54 +0100942 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800943}
944
945
946/* set the endpoint halt feature */
947static int langwell_ep_set_halt(struct usb_ep *_ep, int value)
948{
949 struct langwell_ep *ep;
950 struct langwell_udc *dev;
951 unsigned long flags;
952 int retval = 0;
953
954 ep = container_of(_ep, struct langwell_ep, ep);
955 dev = ep->dev;
956
JiebingLi5f81f4b2010-08-05 14:17:54 +0100957 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800958
959 if (!_ep || !ep->desc)
960 return -EINVAL;
961
962 if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
963 return -ESHUTDOWN;
964
JiebingLi5f81f4b2010-08-05 14:17:54 +0100965 if (usb_endpoint_xfer_isoc(ep->desc))
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800966 return -EOPNOTSUPP;
967
968 spin_lock_irqsave(&dev->lock, flags);
969
970 /*
971 * attempt to halt IN ep will fail if any transfer requests
972 * are still queue
973 */
974 if (!list_empty(&ep->queue) && is_in(ep) && value) {
975 /* IN endpoint FIFO holds bytes */
JiebingLi5f81f4b2010-08-05 14:17:54 +0100976 dev_dbg(&dev->pdev->dev, "%s FIFO holds bytes\n", _ep->name);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800977 retval = -EAGAIN;
978 goto done;
979 }
980
981 /* endpoint set/clear halt */
982 if (ep->ep_num) {
983 ep_set_halt(ep, value);
984 } else { /* endpoint 0 */
985 dev->ep0_state = WAIT_FOR_SETUP;
986 dev->ep0_dir = USB_DIR_OUT;
987 }
988done:
989 spin_unlock_irqrestore(&dev->lock, flags);
JiebingLi5f81f4b2010-08-05 14:17:54 +0100990 dev_dbg(&dev->pdev->dev, "%s %s halt\n",
991 _ep->name, value ? "set" : "clear");
992 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +0800993 return retval;
994}
995
996
997/* set the halt feature and ignores clear requests */
998static int langwell_ep_set_wedge(struct usb_ep *_ep)
999{
1000 struct langwell_ep *ep;
1001 struct langwell_udc *dev;
1002
1003 ep = container_of(_ep, struct langwell_ep, ep);
1004 dev = ep->dev;
1005
JiebingLi5f81f4b2010-08-05 14:17:54 +01001006 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001007
1008 if (!_ep || !ep->desc)
1009 return -EINVAL;
1010
JiebingLi5f81f4b2010-08-05 14:17:54 +01001011 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001012 return usb_ep_set_halt(_ep);
1013}
1014
1015
1016/* flush contents of a fifo */
1017static void langwell_ep_fifo_flush(struct usb_ep *_ep)
1018{
1019 struct langwell_ep *ep;
1020 struct langwell_udc *dev;
1021 u32 flush_bit;
1022 unsigned long timeout;
1023
1024 ep = container_of(_ep, struct langwell_ep, ep);
1025 dev = ep->dev;
1026
JiebingLi5f81f4b2010-08-05 14:17:54 +01001027 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001028
1029 if (!_ep || !ep->desc) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01001030 dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n");
1031 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001032 return;
1033 }
1034
JiebingLi5f81f4b2010-08-05 14:17:54 +01001035 dev_vdbg(&dev->pdev->dev, "%s-%s fifo flush\n",
1036 _ep->name, DIR_STRING(ep));
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001037
1038 /* flush endpoint buffer */
1039 if (ep->ep_num == 0)
1040 flush_bit = (1 << 16) | 1;
1041 else if (is_in(ep))
1042 flush_bit = 1 << (ep->ep_num + 16); /* TX */
1043 else
1044 flush_bit = 1 << ep->ep_num; /* RX */
1045
1046 /* wait until flush complete */
1047 timeout = jiffies + FLUSH_TIMEOUT;
1048 do {
1049 writel(flush_bit, &dev->op_regs->endptflush);
1050 while (readl(&dev->op_regs->endptflush)) {
1051 if (time_after(jiffies, timeout)) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01001052 dev_err(&dev->pdev->dev, "ep flush timeout\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001053 goto done;
1054 }
1055 cpu_relax();
1056 }
1057 } while (readl(&dev->op_regs->endptstat) & flush_bit);
1058done:
JiebingLi5f81f4b2010-08-05 14:17:54 +01001059 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001060}
1061
1062
1063/* endpoints operations structure */
1064static const struct usb_ep_ops langwell_ep_ops = {
1065
1066 /* configure endpoint, making it usable */
1067 .enable = langwell_ep_enable,
1068
1069 /* endpoint is no longer usable */
1070 .disable = langwell_ep_disable,
1071
1072 /* allocate a request object to use with this endpoint */
1073 .alloc_request = langwell_alloc_request,
1074
1075 /* free a request object */
1076 .free_request = langwell_free_request,
1077
1078 /* queue (submits) an I/O requests to an endpoint */
1079 .queue = langwell_ep_queue,
1080
1081 /* dequeue (cancels, unlinks) an I/O request from an endpoint */
1082 .dequeue = langwell_ep_dequeue,
1083
1084 /* set the endpoint halt feature */
1085 .set_halt = langwell_ep_set_halt,
1086
1087 /* set the halt feature and ignores clear requests */
1088 .set_wedge = langwell_ep_set_wedge,
1089
1090 /* flush contents of a fifo */
1091 .fifo_flush = langwell_ep_fifo_flush,
1092};
1093
1094
1095/*-------------------------------------------------------------------------*/
1096
1097/* device controller usb_gadget_ops structure */
1098
1099/* returns the current frame number */
1100static int langwell_get_frame(struct usb_gadget *_gadget)
1101{
1102 struct langwell_udc *dev;
1103 u16 retval;
1104
1105 if (!_gadget)
1106 return -ENODEV;
1107
1108 dev = container_of(_gadget, struct langwell_udc, gadget);
JiebingLi5f81f4b2010-08-05 14:17:54 +01001109 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001110
1111 retval = readl(&dev->op_regs->frindex) & FRINDEX_MASK;
1112
JiebingLi5f81f4b2010-08-05 14:17:54 +01001113 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001114 return retval;
1115}
1116
1117
JiebingLi513b91b2010-08-05 14:18:13 +01001118/* enter or exit PHY low power state */
1119static void langwell_phy_low_power(struct langwell_udc *dev, bool flag)
1120{
1121 u32 devlc;
1122 u8 devlc_byte2;
1123 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
1124
1125 devlc = readl(&dev->op_regs->devlc);
1126 dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
1127
1128 if (flag)
1129 devlc |= LPM_PHCD;
1130 else
1131 devlc &= ~LPM_PHCD;
1132
1133 /* FIXME: workaround for Langwell A1/A2/A3 sighting */
1134 devlc_byte2 = (devlc >> 16) & 0xff;
1135 writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
1136
1137 devlc = readl(&dev->op_regs->devlc);
1138 dev_vdbg(&dev->pdev->dev,
1139 "%s PHY low power suspend, devlc = 0x%08x\n",
1140 flag ? "enter" : "exit", devlc);
1141}
1142
1143
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001144/* tries to wake up the host connected to this gadget */
1145static int langwell_wakeup(struct usb_gadget *_gadget)
1146{
1147 struct langwell_udc *dev;
JiebingLi513b91b2010-08-05 14:18:13 +01001148 u32 portsc1;
JiebingLi5f81f4b2010-08-05 14:17:54 +01001149 unsigned long flags;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001150
1151 if (!_gadget)
1152 return 0;
1153
1154 dev = container_of(_gadget, struct langwell_udc, gadget);
JiebingLi5f81f4b2010-08-05 14:17:54 +01001155 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001156
JiebingLi5f81f4b2010-08-05 14:17:54 +01001157 /* remote wakeup feature not enabled by host */
1158 if (!dev->remote_wakeup) {
1159 dev_info(&dev->pdev->dev, "remote wakeup is disabled\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001160 return -ENOTSUPP;
JiebingLi5f81f4b2010-08-05 14:17:54 +01001161 }
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001162
1163 spin_lock_irqsave(&dev->lock, flags);
1164
1165 portsc1 = readl(&dev->op_regs->portsc1);
1166 if (!(portsc1 & PORTS_SUSP)) {
1167 spin_unlock_irqrestore(&dev->lock, flags);
1168 return 0;
1169 }
1170
JiebingLi513b91b2010-08-05 14:18:13 +01001171 /* LPM L1 to L0 or legacy remote wakeup */
1172 if (dev->lpm && dev->lpm_state == LPM_L1)
1173 dev_info(&dev->pdev->dev, "LPM L1 to L0 remote wakeup\n");
1174 else
1175 dev_info(&dev->pdev->dev, "device remote wakeup\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001176
1177 /* exit PHY low power suspend */
JiebingLi513b91b2010-08-05 14:18:13 +01001178 if (dev->pdev->device != 0x0829)
1179 langwell_phy_low_power(dev, 0);
1180
1181 /* force port resume */
1182 portsc1 |= PORTS_FPR;
1183 writel(portsc1, &dev->op_regs->portsc1);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001184
1185 spin_unlock_irqrestore(&dev->lock, flags);
1186
JiebingLi5f81f4b2010-08-05 14:17:54 +01001187 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001188 return 0;
1189}
1190
1191
1192/* notify controller that VBUS is powered or not */
1193static int langwell_vbus_session(struct usb_gadget *_gadget, int is_active)
1194{
1195 struct langwell_udc *dev;
1196 unsigned long flags;
JiebingLi5f81f4b2010-08-05 14:17:54 +01001197 u32 usbcmd;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001198
1199 if (!_gadget)
1200 return -ENODEV;
1201
1202 dev = container_of(_gadget, struct langwell_udc, gadget);
JiebingLi5f81f4b2010-08-05 14:17:54 +01001203 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001204
1205 spin_lock_irqsave(&dev->lock, flags);
JiebingLi5f81f4b2010-08-05 14:17:54 +01001206 dev_vdbg(&dev->pdev->dev, "VBUS status: %s\n",
1207 is_active ? "on" : "off");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001208
1209 dev->vbus_active = (is_active != 0);
1210 if (dev->driver && dev->softconnected && dev->vbus_active) {
1211 usbcmd = readl(&dev->op_regs->usbcmd);
1212 usbcmd |= CMD_RUNSTOP;
1213 writel(usbcmd, &dev->op_regs->usbcmd);
1214 } else {
1215 usbcmd = readl(&dev->op_regs->usbcmd);
1216 usbcmd &= ~CMD_RUNSTOP;
1217 writel(usbcmd, &dev->op_regs->usbcmd);
1218 }
1219
1220 spin_unlock_irqrestore(&dev->lock, flags);
1221
JiebingLi5f81f4b2010-08-05 14:17:54 +01001222 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001223 return 0;
1224}
1225
1226
1227/* constrain controller's VBUS power usage */
1228static int langwell_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
1229{
1230 struct langwell_udc *dev;
1231
1232 if (!_gadget)
1233 return -ENODEV;
1234
1235 dev = container_of(_gadget, struct langwell_udc, gadget);
JiebingLi5f81f4b2010-08-05 14:17:54 +01001236 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001237
1238 if (dev->transceiver) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01001239 dev_vdbg(&dev->pdev->dev, "otg_set_power\n");
1240 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001241 return otg_set_power(dev->transceiver, mA);
1242 }
1243
JiebingLi5f81f4b2010-08-05 14:17:54 +01001244 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001245 return -ENOTSUPP;
1246}
1247
1248
1249/* D+ pullup, software-controlled connect/disconnect to USB host */
1250static int langwell_pullup(struct usb_gadget *_gadget, int is_on)
1251{
1252 struct langwell_udc *dev;
JiebingLi5f81f4b2010-08-05 14:17:54 +01001253 u32 usbcmd;
1254 unsigned long flags;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001255
1256 if (!_gadget)
1257 return -ENODEV;
1258
1259 dev = container_of(_gadget, struct langwell_udc, gadget);
1260
JiebingLi5f81f4b2010-08-05 14:17:54 +01001261 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001262
1263 spin_lock_irqsave(&dev->lock, flags);
1264 dev->softconnected = (is_on != 0);
1265
1266 if (dev->driver && dev->softconnected && dev->vbus_active) {
1267 usbcmd = readl(&dev->op_regs->usbcmd);
1268 usbcmd |= CMD_RUNSTOP;
1269 writel(usbcmd, &dev->op_regs->usbcmd);
1270 } else {
1271 usbcmd = readl(&dev->op_regs->usbcmd);
1272 usbcmd &= ~CMD_RUNSTOP;
1273 writel(usbcmd, &dev->op_regs->usbcmd);
1274 }
1275 spin_unlock_irqrestore(&dev->lock, flags);
1276
JiebingLi5f81f4b2010-08-05 14:17:54 +01001277 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001278 return 0;
1279}
1280
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001281static int langwell_start(struct usb_gadget *g,
1282 struct usb_gadget_driver *driver);
1283
1284static int langwell_stop(struct usb_gadget *g,
1285 struct usb_gadget_driver *driver);
1286
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001287/* device controller usb_gadget_ops structure */
1288static const struct usb_gadget_ops langwell_ops = {
1289
1290 /* returns the current frame number */
1291 .get_frame = langwell_get_frame,
1292
1293 /* tries to wake up the host connected to this gadget */
1294 .wakeup = langwell_wakeup,
1295
1296 /* set the device selfpowered feature, always selfpowered */
1297 /* .set_selfpowered = langwell_set_selfpowered, */
1298
1299 /* notify controller that VBUS is powered or not */
1300 .vbus_session = langwell_vbus_session,
1301
1302 /* constrain controller's VBUS power usage */
1303 .vbus_draw = langwell_vbus_draw,
1304
1305 /* D+ pullup, software-controlled connect/disconnect to USB host */
1306 .pullup = langwell_pullup,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001307
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001308 .udc_start = langwell_start,
1309 .udc_stop = langwell_stop,
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001310};
1311
1312
1313/*-------------------------------------------------------------------------*/
1314
1315/* device controller operations */
1316
1317/* reset device controller */
1318static int langwell_udc_reset(struct langwell_udc *dev)
1319{
1320 u32 usbcmd, usbmode, devlc, endpointlistaddr;
JiebingLi513b91b2010-08-05 14:18:13 +01001321 u8 devlc_byte0, devlc_byte2;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001322 unsigned long timeout;
1323
1324 if (!dev)
1325 return -EINVAL;
1326
JiebingLi5f81f4b2010-08-05 14:17:54 +01001327 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001328
1329 /* set controller to stop state */
1330 usbcmd = readl(&dev->op_regs->usbcmd);
1331 usbcmd &= ~CMD_RUNSTOP;
1332 writel(usbcmd, &dev->op_regs->usbcmd);
1333
1334 /* reset device controller */
1335 usbcmd = readl(&dev->op_regs->usbcmd);
1336 usbcmd |= CMD_RST;
1337 writel(usbcmd, &dev->op_regs->usbcmd);
1338
1339 /* wait for reset to complete */
1340 timeout = jiffies + RESET_TIMEOUT;
1341 while (readl(&dev->op_regs->usbcmd) & CMD_RST) {
1342 if (time_after(jiffies, timeout)) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01001343 dev_err(&dev->pdev->dev, "device reset timeout\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001344 return -ETIMEDOUT;
1345 }
1346 cpu_relax();
1347 }
1348
1349 /* set controller to device mode */
1350 usbmode = readl(&dev->op_regs->usbmode);
1351 usbmode |= MODE_DEVICE;
1352
1353 /* turn setup lockout off, require setup tripwire in usbcmd */
1354 usbmode |= MODE_SLOM;
1355
1356 writel(usbmode, &dev->op_regs->usbmode);
1357 usbmode = readl(&dev->op_regs->usbmode);
JiebingLi5f81f4b2010-08-05 14:17:54 +01001358 dev_vdbg(&dev->pdev->dev, "usbmode=0x%08x\n", usbmode);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001359
1360 /* Write-Clear setup status */
1361 writel(0, &dev->op_regs->usbsts);
1362
1363 /* if support USB LPM, ACK all LPM token */
1364 if (dev->lpm) {
1365 devlc = readl(&dev->op_regs->devlc);
JiebingLi513b91b2010-08-05 14:18:13 +01001366 dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
1367 /* FIXME: workaround for Langwell A1/A2/A3 sighting */
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001368 devlc &= ~LPM_STL; /* don't STALL LPM token */
1369 devlc &= ~LPM_NYT_ACK; /* ACK LPM token */
JiebingLi513b91b2010-08-05 14:18:13 +01001370 devlc_byte0 = devlc & 0xff;
1371 devlc_byte2 = (devlc >> 16) & 0xff;
1372 writeb(devlc_byte0, (u8 *)&dev->op_regs->devlc);
1373 writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
1374 devlc = readl(&dev->op_regs->devlc);
1375 dev_vdbg(&dev->pdev->dev,
1376 "ACK LPM token, devlc = 0x%08x\n", devlc);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001377 }
1378
1379 /* fill endpointlistaddr register */
1380 endpointlistaddr = dev->ep_dqh_dma;
1381 endpointlistaddr &= ENDPOINTLISTADDR_MASK;
1382 writel(endpointlistaddr, &dev->op_regs->endpointlistaddr);
1383
JiebingLi5f81f4b2010-08-05 14:17:54 +01001384 dev_vdbg(&dev->pdev->dev,
1385 "dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n",
1386 dev->ep_dqh, endpointlistaddr,
1387 readl(&dev->op_regs->endpointlistaddr));
1388 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001389 return 0;
1390}
1391
1392
1393/* reinitialize device controller endpoints */
1394static int eps_reinit(struct langwell_udc *dev)
1395{
1396 struct langwell_ep *ep;
1397 char name[14];
1398 int i;
1399
JiebingLi5f81f4b2010-08-05 14:17:54 +01001400 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001401
1402 /* initialize ep0 */
1403 ep = &dev->ep[0];
1404 ep->dev = dev;
1405 strncpy(ep->name, "ep0", sizeof(ep->name));
1406 ep->ep.name = ep->name;
1407 ep->ep.ops = &langwell_ep_ops;
1408 ep->stopped = 0;
1409 ep->ep.maxpacket = EP0_MAX_PKT_SIZE;
1410 ep->ep_num = 0;
1411 ep->desc = &langwell_ep0_desc;
1412 INIT_LIST_HEAD(&ep->queue);
1413
1414 ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
1415
1416 /* initialize other endpoints */
1417 for (i = 2; i < dev->ep_max; i++) {
1418 ep = &dev->ep[i];
1419 if (i % 2)
1420 snprintf(name, sizeof(name), "ep%din", i / 2);
1421 else
1422 snprintf(name, sizeof(name), "ep%dout", i / 2);
1423 ep->dev = dev;
1424 strncpy(ep->name, name, sizeof(ep->name));
1425 ep->ep.name = ep->name;
1426
1427 ep->ep.ops = &langwell_ep_ops;
1428 ep->stopped = 0;
1429 ep->ep.maxpacket = (unsigned short) ~0;
1430 ep->ep_num = i / 2;
1431
1432 INIT_LIST_HEAD(&ep->queue);
1433 list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001434 }
1435
JiebingLi5f81f4b2010-08-05 14:17:54 +01001436 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001437 return 0;
1438}
1439
1440
1441/* enable interrupt and set controller to run state */
1442static void langwell_udc_start(struct langwell_udc *dev)
1443{
1444 u32 usbintr, usbcmd;
JiebingLi5f81f4b2010-08-05 14:17:54 +01001445 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001446
1447 /* enable interrupts */
1448 usbintr = INTR_ULPIE /* ULPI */
1449 | INTR_SLE /* suspend */
1450 /* | INTR_SRE SOF received */
1451 | INTR_URE /* USB reset */
1452 | INTR_AAE /* async advance */
1453 | INTR_SEE /* system error */
1454 | INTR_FRE /* frame list rollover */
1455 | INTR_PCE /* port change detect */
1456 | INTR_UEE /* USB error interrupt */
1457 | INTR_UE; /* USB interrupt */
1458 writel(usbintr, &dev->op_regs->usbintr);
1459
1460 /* clear stopped bit */
1461 dev->stopped = 0;
1462
1463 /* set controller to run */
1464 usbcmd = readl(&dev->op_regs->usbcmd);
1465 usbcmd |= CMD_RUNSTOP;
1466 writel(usbcmd, &dev->op_regs->usbcmd);
1467
JiebingLi5f81f4b2010-08-05 14:17:54 +01001468 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001469}
1470
1471
1472/* disable interrupt and set controller to stop state */
1473static void langwell_udc_stop(struct langwell_udc *dev)
1474{
1475 u32 usbcmd;
1476
JiebingLi5f81f4b2010-08-05 14:17:54 +01001477 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001478
1479 /* disable all interrupts */
1480 writel(0, &dev->op_regs->usbintr);
1481
1482 /* set stopped bit */
1483 dev->stopped = 1;
1484
1485 /* set controller to stop state */
1486 usbcmd = readl(&dev->op_regs->usbcmd);
1487 usbcmd &= ~CMD_RUNSTOP;
1488 writel(usbcmd, &dev->op_regs->usbcmd);
1489
JiebingLi5f81f4b2010-08-05 14:17:54 +01001490 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001491}
1492
1493
1494/* stop all USB activities */
1495static void stop_activity(struct langwell_udc *dev,
1496 struct usb_gadget_driver *driver)
1497{
1498 struct langwell_ep *ep;
JiebingLi5f81f4b2010-08-05 14:17:54 +01001499 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001500
1501 nuke(&dev->ep[0], -ESHUTDOWN);
1502
1503 list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
1504 nuke(ep, -ESHUTDOWN);
1505 }
1506
1507 /* report disconnect; the driver is already quiesced */
1508 if (driver) {
1509 spin_unlock(&dev->lock);
1510 driver->disconnect(&dev->gadget);
1511 spin_lock(&dev->lock);
1512 }
1513
JiebingLi5f81f4b2010-08-05 14:17:54 +01001514 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001515}
1516
1517
1518/*-------------------------------------------------------------------------*/
1519
1520/* device "function" sysfs attribute file */
1521static ssize_t show_function(struct device *_dev,
1522 struct device_attribute *attr, char *buf)
1523{
Felipe Balbi5bc639f2011-10-08 13:08:01 +03001524 struct langwell_udc *dev = dev_get_drvdata(_dev);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001525
1526 if (!dev->driver || !dev->driver->function
1527 || strlen(dev->driver->function) > PAGE_SIZE)
1528 return 0;
1529
1530 return scnprintf(buf, PAGE_SIZE, "%s\n", dev->driver->function);
1531}
1532static DEVICE_ATTR(function, S_IRUGO, show_function, NULL);
1533
1534
Randy Dunlap56526c02011-10-07 13:57:42 -07001535static inline enum usb_device_speed lpm_device_speed(u32 reg)
1536{
1537 switch (LPM_PSPD(reg)) {
1538 case LPM_SPEED_HIGH:
1539 return USB_SPEED_HIGH;
1540 case LPM_SPEED_FULL:
1541 return USB_SPEED_FULL;
1542 case LPM_SPEED_LOW:
1543 return USB_SPEED_LOW;
1544 default:
1545 return USB_SPEED_UNKNOWN;
1546 }
1547}
1548
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001549/* device "langwell_udc" sysfs attribute file */
1550static ssize_t show_langwell_udc(struct device *_dev,
1551 struct device_attribute *attr, char *buf)
1552{
Felipe Balbi5bc639f2011-10-08 13:08:01 +03001553 struct langwell_udc *dev = dev_get_drvdata(_dev);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001554 struct langwell_request *req;
1555 struct langwell_ep *ep = NULL;
1556 char *next;
1557 unsigned size;
1558 unsigned t;
1559 unsigned i;
1560 unsigned long flags;
1561 u32 tmp_reg;
1562
1563 next = buf;
1564 size = PAGE_SIZE;
1565 spin_lock_irqsave(&dev->lock, flags);
1566
1567 /* driver basic information */
1568 t = scnprintf(next, size,
1569 DRIVER_DESC "\n"
1570 "%s version: %s\n"
1571 "Gadget driver: %s\n\n",
1572 driver_name, DRIVER_VERSION,
1573 dev->driver ? dev->driver->driver.name : "(none)");
1574 size -= t;
1575 next += t;
1576
1577 /* device registers */
1578 tmp_reg = readl(&dev->op_regs->usbcmd);
1579 t = scnprintf(next, size,
1580 "USBCMD reg:\n"
1581 "SetupTW: %d\n"
1582 "Run/Stop: %s\n\n",
1583 (tmp_reg & CMD_SUTW) ? 1 : 0,
1584 (tmp_reg & CMD_RUNSTOP) ? "Run" : "Stop");
1585 size -= t;
1586 next += t;
1587
1588 tmp_reg = readl(&dev->op_regs->usbsts);
1589 t = scnprintf(next, size,
1590 "USB Status Reg:\n"
1591 "Device Suspend: %d\n"
1592 "Reset Received: %d\n"
1593 "System Error: %s\n"
1594 "USB Error Interrupt: %s\n\n",
1595 (tmp_reg & STS_SLI) ? 1 : 0,
1596 (tmp_reg & STS_URI) ? 1 : 0,
1597 (tmp_reg & STS_SEI) ? "Error" : "No error",
1598 (tmp_reg & STS_UEI) ? "Error detected" : "No error");
1599 size -= t;
1600 next += t;
1601
1602 tmp_reg = readl(&dev->op_regs->usbintr);
1603 t = scnprintf(next, size,
1604 "USB Intrrupt Enable Reg:\n"
1605 "Sleep Enable: %d\n"
1606 "SOF Received Enable: %d\n"
1607 "Reset Enable: %d\n"
1608 "System Error Enable: %d\n"
1609 "Port Change Dectected Enable: %d\n"
1610 "USB Error Intr Enable: %d\n"
1611 "USB Intr Enable: %d\n\n",
1612 (tmp_reg & INTR_SLE) ? 1 : 0,
1613 (tmp_reg & INTR_SRE) ? 1 : 0,
1614 (tmp_reg & INTR_URE) ? 1 : 0,
1615 (tmp_reg & INTR_SEE) ? 1 : 0,
1616 (tmp_reg & INTR_PCE) ? 1 : 0,
1617 (tmp_reg & INTR_UEE) ? 1 : 0,
1618 (tmp_reg & INTR_UE) ? 1 : 0);
1619 size -= t;
1620 next += t;
1621
1622 tmp_reg = readl(&dev->op_regs->frindex);
1623 t = scnprintf(next, size,
1624 "USB Frame Index Reg:\n"
1625 "Frame Number is 0x%08x\n\n",
1626 (tmp_reg & FRINDEX_MASK));
1627 size -= t;
1628 next += t;
1629
1630 tmp_reg = readl(&dev->op_regs->deviceaddr);
1631 t = scnprintf(next, size,
1632 "USB Device Address Reg:\n"
1633 "Device Addr is 0x%x\n\n",
1634 USBADR(tmp_reg));
1635 size -= t;
1636 next += t;
1637
1638 tmp_reg = readl(&dev->op_regs->endpointlistaddr);
1639 t = scnprintf(next, size,
1640 "USB Endpoint List Address Reg:\n"
1641 "Endpoint List Pointer is 0x%x\n\n",
1642 EPBASE(tmp_reg));
1643 size -= t;
1644 next += t;
1645
1646 tmp_reg = readl(&dev->op_regs->portsc1);
1647 t = scnprintf(next, size,
1648 "USB Port Status & Control Reg:\n"
1649 "Port Reset: %s\n"
1650 "Port Suspend Mode: %s\n"
1651 "Over-current Change: %s\n"
1652 "Port Enable/Disable Change: %s\n"
1653 "Port Enabled/Disabled: %s\n"
JiebingLi5f81f4b2010-08-05 14:17:54 +01001654 "Current Connect Status: %s\n"
1655 "LPM Suspend Status: %s\n\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001656 (tmp_reg & PORTS_PR) ? "Reset" : "Not Reset",
1657 (tmp_reg & PORTS_SUSP) ? "Suspend " : "Not Suspend",
1658 (tmp_reg & PORTS_OCC) ? "Detected" : "No",
1659 (tmp_reg & PORTS_PEC) ? "Changed" : "Not Changed",
1660 (tmp_reg & PORTS_PE) ? "Enable" : "Not Correct",
JiebingLi5f81f4b2010-08-05 14:17:54 +01001661 (tmp_reg & PORTS_CCS) ? "Attached" : "Not Attached",
1662 (tmp_reg & PORTS_SLP) ? "LPM L1" : "LPM L0");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001663 size -= t;
1664 next += t;
1665
1666 tmp_reg = readl(&dev->op_regs->devlc);
1667 t = scnprintf(next, size,
1668 "Device LPM Control Reg:\n"
1669 "Parallel Transceiver : %d\n"
1670 "Serial Transceiver : %d\n"
1671 "Port Speed: %s\n"
1672 "Port Force Full Speed Connenct: %s\n"
JiebingLi5f81f4b2010-08-05 14:17:54 +01001673 "PHY Low Power Suspend Clock: %s\n"
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001674 "BmAttributes: %d\n\n",
1675 LPM_PTS(tmp_reg),
1676 (tmp_reg & LPM_STS) ? 1 : 0,
Michal Nazarewicze538dfd2011-08-30 17:11:19 +02001677 usb_speed_string(lpm_device_speed(tmp_reg)),
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001678 (tmp_reg & LPM_PFSC) ? "Force Full Speed" : "Not Force",
1679 (tmp_reg & LPM_PHCD) ? "Disabled" : "Enabled",
1680 LPM_BA(tmp_reg));
1681 size -= t;
1682 next += t;
1683
1684 tmp_reg = readl(&dev->op_regs->usbmode);
1685 t = scnprintf(next, size,
1686 "USB Mode Reg:\n"
1687 "Controller Mode is : %s\n\n", ({
1688 char *s;
1689 switch (MODE_CM(tmp_reg)) {
1690 case MODE_IDLE:
1691 s = "Idle"; break;
1692 case MODE_DEVICE:
1693 s = "Device Controller"; break;
1694 case MODE_HOST:
1695 s = "Host Controller"; break;
1696 default:
1697 s = "None"; break;
1698 }
1699 s;
1700 }));
1701 size -= t;
1702 next += t;
1703
1704 tmp_reg = readl(&dev->op_regs->endptsetupstat);
1705 t = scnprintf(next, size,
1706 "Endpoint Setup Status Reg:\n"
1707 "SETUP on ep 0x%04x\n\n",
1708 tmp_reg & SETUPSTAT_MASK);
1709 size -= t;
1710 next += t;
1711
1712 for (i = 0; i < dev->ep_max / 2; i++) {
1713 tmp_reg = readl(&dev->op_regs->endptctrl[i]);
1714 t = scnprintf(next, size, "EP Ctrl Reg [%d]: 0x%08x\n",
1715 i, tmp_reg);
1716 size -= t;
1717 next += t;
1718 }
1719 tmp_reg = readl(&dev->op_regs->endptprime);
1720 t = scnprintf(next, size, "EP Prime Reg: 0x%08x\n\n", tmp_reg);
1721 size -= t;
1722 next += t;
1723
1724 /* langwell_udc, langwell_ep, langwell_request structure information */
1725 ep = &dev->ep[0];
1726 t = scnprintf(next, size, "%s MaxPacketSize: 0x%x, ep_num: %d\n",
1727 ep->ep.name, ep->ep.maxpacket, ep->ep_num);
1728 size -= t;
1729 next += t;
1730
1731 if (list_empty(&ep->queue)) {
1732 t = scnprintf(next, size, "its req queue is empty\n\n");
1733 size -= t;
1734 next += t;
1735 } else {
1736 list_for_each_entry(req, &ep->queue, queue) {
1737 t = scnprintf(next, size,
1738 "req %p actual 0x%x length 0x%x buf %p\n",
1739 &req->req, req->req.actual,
1740 req->req.length, req->req.buf);
1741 size -= t;
1742 next += t;
1743 }
1744 }
1745 /* other gadget->eplist ep */
1746 list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
1747 if (ep->desc) {
1748 t = scnprintf(next, size,
1749 "\n%s MaxPacketSize: 0x%x, "
1750 "ep_num: %d\n",
1751 ep->ep.name, ep->ep.maxpacket,
1752 ep->ep_num);
1753 size -= t;
1754 next += t;
1755
1756 if (list_empty(&ep->queue)) {
1757 t = scnprintf(next, size,
1758 "its req queue is empty\n\n");
1759 size -= t;
1760 next += t;
1761 } else {
1762 list_for_each_entry(req, &ep->queue, queue) {
1763 t = scnprintf(next, size,
1764 "req %p actual 0x%x length "
1765 "0x%x buf %p\n",
1766 &req->req, req->req.actual,
1767 req->req.length, req->req.buf);
1768 size -= t;
1769 next += t;
1770 }
1771 }
1772 }
1773 }
1774
1775 spin_unlock_irqrestore(&dev->lock, flags);
1776 return PAGE_SIZE - size;
1777}
1778static DEVICE_ATTR(langwell_udc, S_IRUGO, show_langwell_udc, NULL);
1779
1780
JiebingLi3211cbc2010-08-05 14:18:21 +01001781/* device "remote_wakeup" sysfs attribute file */
1782static ssize_t store_remote_wakeup(struct device *_dev,
1783 struct device_attribute *attr, const char *buf, size_t count)
1784{
Felipe Balbi5bc639f2011-10-08 13:08:01 +03001785 struct langwell_udc *dev = dev_get_drvdata(_dev);
JiebingLi3211cbc2010-08-05 14:18:21 +01001786 unsigned long flags;
1787 ssize_t rc = count;
1788
1789 if (count > 2)
1790 return -EINVAL;
1791
1792 if (count > 0 && buf[count-1] == '\n')
1793 ((char *) buf)[count-1] = 0;
1794
1795 if (buf[0] != '1')
1796 return -EINVAL;
1797
1798 /* force remote wakeup enabled in case gadget driver doesn't support */
1799 spin_lock_irqsave(&dev->lock, flags);
1800 dev->remote_wakeup = 1;
1801 dev->dev_status |= (1 << USB_DEVICE_REMOTE_WAKEUP);
1802 spin_unlock_irqrestore(&dev->lock, flags);
1803
1804 langwell_wakeup(&dev->gadget);
1805
1806 return rc;
1807}
1808static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup);
1809
1810
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001811/*-------------------------------------------------------------------------*/
1812
1813/*
1814 * when a driver is successfully registered, it will receive
1815 * control requests including set_configuration(), which enables
1816 * non-control requests. then usb traffic follows until a
1817 * disconnect is reported. then a host may connect again, or
1818 * the driver might get unbound.
1819 */
1820
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001821static int langwell_start(struct usb_gadget *g,
1822 struct usb_gadget_driver *driver)
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001823{
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001824 struct langwell_udc *dev = gadget_to_langwell(g);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001825 unsigned long flags;
1826 int retval;
1827
JiebingLi5f81f4b2010-08-05 14:17:54 +01001828 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001829
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001830 spin_lock_irqsave(&dev->lock, flags);
1831
1832 /* hook up the driver ... */
1833 driver->driver.bus = NULL;
1834 dev->driver = driver;
1835 dev->gadget.dev.driver = &driver->driver;
1836
1837 spin_unlock_irqrestore(&dev->lock, flags);
1838
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001839 retval = device_create_file(&dev->pdev->dev, &dev_attr_function);
1840 if (retval)
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001841 goto err;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001842
1843 dev->usb_state = USB_STATE_ATTACHED;
1844 dev->ep0_state = WAIT_FOR_SETUP;
1845 dev->ep0_dir = USB_DIR_OUT;
1846
1847 /* enable interrupt and set controller to run state */
1848 if (dev->got_irq)
1849 langwell_udc_start(dev);
1850
JiebingLi5f81f4b2010-08-05 14:17:54 +01001851 dev_vdbg(&dev->pdev->dev,
1852 "After langwell_udc_start(), print all registers:\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001853 print_all_registers(dev);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001854
JiebingLi5f81f4b2010-08-05 14:17:54 +01001855 dev_info(&dev->pdev->dev, "register driver: %s\n",
1856 driver->driver.name);
1857 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001858
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001859 return 0;
1860
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001861err:
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001862 dev->gadget.dev.driver = NULL;
1863 dev->driver = NULL;
1864
JiebingLi5f81f4b2010-08-05 14:17:54 +01001865 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001866
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001867 return retval;
1868}
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001869
1870/* unregister gadget driver */
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001871static int langwell_stop(struct usb_gadget *g,
1872 struct usb_gadget_driver *driver)
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001873{
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001874 struct langwell_udc *dev = gadget_to_langwell(g);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001875 unsigned long flags;
1876
JiebingLi5f81f4b2010-08-05 14:17:54 +01001877 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001878
JiebingLi513b91b2010-08-05 14:18:13 +01001879 /* exit PHY low power suspend */
1880 if (dev->pdev->device != 0x0829)
1881 langwell_phy_low_power(dev, 0);
1882
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001883 /* unbind OTG transceiver */
1884 if (dev->transceiver)
1885 (void)otg_set_peripheral(dev->transceiver, 0);
1886
1887 /* disable interrupt and set controller to stop state */
1888 langwell_udc_stop(dev);
1889
1890 dev->usb_state = USB_STATE_ATTACHED;
1891 dev->ep0_state = WAIT_FOR_SETUP;
1892 dev->ep0_dir = USB_DIR_OUT;
1893
1894 spin_lock_irqsave(&dev->lock, flags);
1895
1896 /* stop all usb activities */
1897 dev->gadget.speed = USB_SPEED_UNKNOWN;
1898 stop_activity(dev, driver);
1899 spin_unlock_irqrestore(&dev->lock, flags);
1900
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001901 dev->gadget.dev.driver = NULL;
1902 dev->driver = NULL;
1903
1904 device_remove_file(&dev->pdev->dev, &dev_attr_function);
1905
JiebingLi5f81f4b2010-08-05 14:17:54 +01001906 dev_info(&dev->pdev->dev, "unregistered driver '%s'\n",
1907 driver->driver.name);
1908 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Felipe Balbi2c7f0982011-10-08 13:17:34 +03001909
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001910 return 0;
1911}
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001912
1913/*-------------------------------------------------------------------------*/
1914
1915/*
1916 * setup tripwire is used as a semaphore to ensure that the setup data
1917 * payload is extracted from a dQH without being corrupted
1918 */
1919static void setup_tripwire(struct langwell_udc *dev)
1920{
1921 u32 usbcmd,
1922 endptsetupstat;
1923 unsigned long timeout;
1924 struct langwell_dqh *dqh;
1925
JiebingLi5f81f4b2010-08-05 14:17:54 +01001926 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001927
1928 /* ep0 OUT dQH */
1929 dqh = &dev->ep_dqh[EP_DIR_OUT];
1930
1931 /* Write-Clear endptsetupstat */
1932 endptsetupstat = readl(&dev->op_regs->endptsetupstat);
1933 writel(endptsetupstat, &dev->op_regs->endptsetupstat);
1934
1935 /* wait until endptsetupstat is cleared */
1936 timeout = jiffies + SETUPSTAT_TIMEOUT;
1937 while (readl(&dev->op_regs->endptsetupstat)) {
1938 if (time_after(jiffies, timeout)) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01001939 dev_err(&dev->pdev->dev, "setup_tripwire timeout\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001940 break;
1941 }
1942 cpu_relax();
1943 }
1944
1945 /* while a hazard exists when setup packet arrives */
1946 do {
1947 /* set setup tripwire bit */
1948 usbcmd = readl(&dev->op_regs->usbcmd);
1949 writel(usbcmd | CMD_SUTW, &dev->op_regs->usbcmd);
1950
1951 /* copy the setup packet to local buffer */
1952 memcpy(&dev->local_setup_buff, &dqh->dqh_setup, 8);
1953 } while (!(readl(&dev->op_regs->usbcmd) & CMD_SUTW));
1954
1955 /* Write-Clear setup tripwire bit */
1956 usbcmd = readl(&dev->op_regs->usbcmd);
1957 writel(usbcmd & ~CMD_SUTW, &dev->op_regs->usbcmd);
1958
JiebingLi5f81f4b2010-08-05 14:17:54 +01001959 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001960}
1961
1962
1963/* protocol ep0 stall, will automatically be cleared on new transaction */
1964static void ep0_stall(struct langwell_udc *dev)
1965{
1966 u32 endptctrl;
1967
JiebingLi5f81f4b2010-08-05 14:17:54 +01001968 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001969
1970 /* set TX and RX to stall */
1971 endptctrl = readl(&dev->op_regs->endptctrl[0]);
1972 endptctrl |= EPCTRL_TXS | EPCTRL_RXS;
1973 writel(endptctrl, &dev->op_regs->endptctrl[0]);
1974
1975 /* update ep0 state */
1976 dev->ep0_state = WAIT_FOR_SETUP;
1977 dev->ep0_dir = USB_DIR_OUT;
1978
JiebingLi5f81f4b2010-08-05 14:17:54 +01001979 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001980}
1981
1982
1983/* PRIME a status phase for ep0 */
1984static int prime_status_phase(struct langwell_udc *dev, int dir)
1985{
1986 struct langwell_request *req;
1987 struct langwell_ep *ep;
1988 int status = 0;
1989
JiebingLi5f81f4b2010-08-05 14:17:54 +01001990 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08001991
1992 if (dir == EP_DIR_IN)
1993 dev->ep0_dir = USB_DIR_IN;
1994 else
1995 dev->ep0_dir = USB_DIR_OUT;
1996
1997 ep = &dev->ep[0];
1998 dev->ep0_state = WAIT_FOR_OUT_STATUS;
1999
2000 req = dev->status_req;
2001
2002 req->ep = ep;
2003 req->req.length = 0;
2004 req->req.status = -EINPROGRESS;
2005 req->req.actual = 0;
2006 req->req.complete = NULL;
2007 req->dtd_count = 0;
2008
2009 if (!req_to_dtd(req))
2010 status = queue_dtd(ep, req);
2011 else
2012 return -ENOMEM;
2013
2014 if (status)
JiebingLi5f81f4b2010-08-05 14:17:54 +01002015 dev_err(&dev->pdev->dev, "can't queue ep0 status request\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002016
2017 list_add_tail(&req->queue, &ep->queue);
2018
JiebingLi5f81f4b2010-08-05 14:17:54 +01002019 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002020 return status;
2021}
2022
2023
2024/* SET_ADDRESS request routine */
2025static void set_address(struct langwell_udc *dev, u16 value,
2026 u16 index, u16 length)
2027{
JiebingLi5f81f4b2010-08-05 14:17:54 +01002028 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002029
2030 /* save the new address to device struct */
2031 dev->dev_addr = (u8) value;
JiebingLi5f81f4b2010-08-05 14:17:54 +01002032 dev_vdbg(&dev->pdev->dev, "dev->dev_addr = %d\n", dev->dev_addr);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002033
2034 /* update usb state */
2035 dev->usb_state = USB_STATE_ADDRESS;
2036
2037 /* STATUS phase */
2038 if (prime_status_phase(dev, EP_DIR_IN))
2039 ep0_stall(dev);
2040
JiebingLi5f81f4b2010-08-05 14:17:54 +01002041 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002042}
2043
2044
2045/* return endpoint by windex */
2046static struct langwell_ep *get_ep_by_windex(struct langwell_udc *dev,
2047 u16 wIndex)
2048{
2049 struct langwell_ep *ep;
JiebingLi5f81f4b2010-08-05 14:17:54 +01002050 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002051
2052 if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
2053 return &dev->ep[0];
2054
2055 list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
2056 u8 bEndpointAddress;
2057 if (!ep->desc)
2058 continue;
2059
2060 bEndpointAddress = ep->desc->bEndpointAddress;
2061 if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
2062 continue;
2063
2064 if ((wIndex & USB_ENDPOINT_NUMBER_MASK)
2065 == (bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))
2066 return ep;
2067 }
2068
JiebingLi5f81f4b2010-08-05 14:17:54 +01002069 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002070 return NULL;
2071}
2072
2073
2074/* return whether endpoint is stalled, 0: not stalled; 1: stalled */
2075static int ep_is_stall(struct langwell_ep *ep)
2076{
2077 struct langwell_udc *dev = ep->dev;
2078 u32 endptctrl;
2079 int retval;
2080
JiebingLi5f81f4b2010-08-05 14:17:54 +01002081 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002082
2083 endptctrl = readl(&dev->op_regs->endptctrl[ep->ep_num]);
2084 if (is_in(ep))
2085 retval = endptctrl & EPCTRL_TXS ? 1 : 0;
2086 else
2087 retval = endptctrl & EPCTRL_RXS ? 1 : 0;
2088
JiebingLi5f81f4b2010-08-05 14:17:54 +01002089 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002090 return retval;
2091}
2092
2093
2094/* GET_STATUS request routine */
2095static void get_status(struct langwell_udc *dev, u8 request_type, u16 value,
2096 u16 index, u16 length)
2097{
2098 struct langwell_request *req;
2099 struct langwell_ep *ep;
2100 u16 status_data = 0; /* 16 bits cpu view status data */
2101 int status = 0;
2102
JiebingLi5f81f4b2010-08-05 14:17:54 +01002103 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002104
2105 ep = &dev->ep[0];
2106
2107 if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
2108 /* get device status */
JiebingLi3211cbc2010-08-05 14:18:21 +01002109 status_data = dev->dev_status;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002110 } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
2111 /* get interface status */
2112 status_data = 0;
2113 } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
2114 /* get endpoint status */
2115 struct langwell_ep *epn;
2116 epn = get_ep_by_windex(dev, index);
2117 /* stall if endpoint doesn't exist */
2118 if (!epn)
2119 goto stall;
2120
2121 status_data = ep_is_stall(epn) << USB_ENDPOINT_HALT;
2122 }
2123
JiebingLi5f81f4b2010-08-05 14:17:54 +01002124 dev_dbg(&dev->pdev->dev, "get status data: 0x%04x\n", status_data);
2125
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002126 dev->ep0_dir = USB_DIR_IN;
2127
2128 /* borrow the per device status_req */
2129 req = dev->status_req;
2130
2131 /* fill in the reqest structure */
2132 *((u16 *) req->req.buf) = cpu_to_le16(status_data);
2133 req->ep = ep;
2134 req->req.length = 2;
2135 req->req.status = -EINPROGRESS;
2136 req->req.actual = 0;
2137 req->req.complete = NULL;
2138 req->dtd_count = 0;
2139
2140 /* prime the data phase */
2141 if (!req_to_dtd(req))
2142 status = queue_dtd(ep, req);
2143 else /* no mem */
2144 goto stall;
2145
2146 if (status) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002147 dev_err(&dev->pdev->dev,
2148 "response error on GET_STATUS request\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002149 goto stall;
2150 }
2151
2152 list_add_tail(&req->queue, &ep->queue);
2153 dev->ep0_state = DATA_STATE_XMIT;
2154
JiebingLi5f81f4b2010-08-05 14:17:54 +01002155 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002156 return;
2157stall:
2158 ep0_stall(dev);
JiebingLi5f81f4b2010-08-05 14:17:54 +01002159 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002160}
2161
2162
2163/* setup packet interrupt handler */
2164static void handle_setup_packet(struct langwell_udc *dev,
2165 struct usb_ctrlrequest *setup)
2166{
2167 u16 wValue = le16_to_cpu(setup->wValue);
2168 u16 wIndex = le16_to_cpu(setup->wIndex);
2169 u16 wLength = le16_to_cpu(setup->wLength);
Luo Andy7fc56f02010-11-23 10:41:21 +08002170 u32 portsc1;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002171
JiebingLi5f81f4b2010-08-05 14:17:54 +01002172 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002173
2174 /* ep0 fifo flush */
2175 nuke(&dev->ep[0], -ESHUTDOWN);
2176
JiebingLi5f81f4b2010-08-05 14:17:54 +01002177 dev_dbg(&dev->pdev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002178 setup->bRequestType, setup->bRequest,
2179 wValue, wIndex, wLength);
2180
2181 /* RNDIS gadget delegate */
2182 if ((setup->bRequestType == 0x21) && (setup->bRequest == 0x00)) {
2183 /* USB_CDC_SEND_ENCAPSULATED_COMMAND */
2184 goto delegate;
2185 }
2186
2187 /* USB_CDC_GET_ENCAPSULATED_RESPONSE */
2188 if ((setup->bRequestType == 0xa1) && (setup->bRequest == 0x01)) {
2189 /* USB_CDC_GET_ENCAPSULATED_RESPONSE */
2190 goto delegate;
2191 }
2192
2193 /* We process some stardard setup requests here */
2194 switch (setup->bRequest) {
2195 case USB_REQ_GET_STATUS:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002196 dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_GET_STATUS\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002197 /* get status, DATA and STATUS phase */
2198 if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
2199 != (USB_DIR_IN | USB_TYPE_STANDARD))
2200 break;
2201 get_status(dev, setup->bRequestType, wValue, wIndex, wLength);
2202 goto end;
2203
2204 case USB_REQ_SET_ADDRESS:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002205 dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_SET_ADDRESS\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002206 /* STATUS phase */
2207 if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
2208 | USB_RECIP_DEVICE))
2209 break;
2210 set_address(dev, wValue, wIndex, wLength);
2211 goto end;
2212
2213 case USB_REQ_CLEAR_FEATURE:
2214 case USB_REQ_SET_FEATURE:
2215 /* STATUS phase */
2216 {
2217 int rc = -EOPNOTSUPP;
2218 if (setup->bRequest == USB_REQ_SET_FEATURE)
JiebingLi5f81f4b2010-08-05 14:17:54 +01002219 dev_dbg(&dev->pdev->dev,
2220 "SETUP: USB_REQ_SET_FEATURE\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002221 else if (setup->bRequest == USB_REQ_CLEAR_FEATURE)
JiebingLi5f81f4b2010-08-05 14:17:54 +01002222 dev_dbg(&dev->pdev->dev,
2223 "SETUP: USB_REQ_CLEAR_FEATURE\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002224
2225 if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
2226 == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
2227 struct langwell_ep *epn;
2228 epn = get_ep_by_windex(dev, wIndex);
2229 /* stall if endpoint doesn't exist */
2230 if (!epn) {
2231 ep0_stall(dev);
2232 goto end;
2233 }
2234
2235 if (wValue != 0 || wLength != 0
2236 || epn->ep_num > dev->ep_max)
2237 break;
2238
2239 spin_unlock(&dev->lock);
2240 rc = langwell_ep_set_halt(&epn->ep,
JiebingLi5f81f4b2010-08-05 14:17:54 +01002241 (setup->bRequest == USB_REQ_SET_FEATURE)
2242 ? 1 : 0);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002243 spin_lock(&dev->lock);
2244
2245 } else if ((setup->bRequestType & (USB_RECIP_MASK
2246 | USB_TYPE_MASK)) == (USB_RECIP_DEVICE
2247 | USB_TYPE_STANDARD)) {
JiebingLi3211cbc2010-08-05 14:18:21 +01002248 rc = 0;
2249 switch (wValue) {
2250 case USB_DEVICE_REMOTE_WAKEUP:
2251 if (setup->bRequest == USB_REQ_SET_FEATURE) {
2252 dev->remote_wakeup = 1;
2253 dev->dev_status |= (1 << wValue);
2254 } else {
2255 dev->remote_wakeup = 0;
2256 dev->dev_status &= ~(1 << wValue);
2257 }
2258 break;
Luo Andy7fc56f02010-11-23 10:41:21 +08002259 case USB_DEVICE_TEST_MODE:
2260 dev_dbg(&dev->pdev->dev, "SETUP: TEST MODE\n");
2261 if ((wIndex & 0xff) ||
2262 (dev->gadget.speed != USB_SPEED_HIGH))
2263 ep0_stall(dev);
2264
2265 switch (wIndex >> 8) {
2266 case TEST_J:
2267 case TEST_K:
2268 case TEST_SE0_NAK:
2269 case TEST_PACKET:
2270 case TEST_FORCE_EN:
2271 if (prime_status_phase(dev, EP_DIR_IN))
2272 ep0_stall(dev);
2273 portsc1 = readl(&dev->op_regs->portsc1);
2274 portsc1 |= (wIndex & 0xf00) << 8;
2275 writel(portsc1, &dev->op_regs->portsc1);
2276 goto end;
2277 default:
2278 rc = -EOPNOTSUPP;
2279 }
2280 break;
JiebingLi3211cbc2010-08-05 14:18:21 +01002281 default:
2282 rc = -EOPNOTSUPP;
2283 break;
2284 }
2285
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002286 if (!gadget_is_otg(&dev->gadget))
2287 break;
2288 else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) {
2289 dev->gadget.b_hnp_enable = 1;
2290#ifdef OTG_TRANSCEIVER
2291 if (!dev->lotg->otg.default_a)
2292 dev->lotg->hsm.b_hnp_enable = 1;
2293#endif
2294 } else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
2295 dev->gadget.a_hnp_support = 1;
2296 else if (setup->bRequest ==
2297 USB_DEVICE_A_ALT_HNP_SUPPORT)
2298 dev->gadget.a_alt_hnp_support = 1;
2299 else
2300 break;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002301 } else
2302 break;
2303
2304 if (rc == 0) {
2305 if (prime_status_phase(dev, EP_DIR_IN))
2306 ep0_stall(dev);
2307 }
2308 goto end;
2309 }
2310
2311 case USB_REQ_GET_DESCRIPTOR:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002312 dev_dbg(&dev->pdev->dev,
2313 "SETUP: USB_REQ_GET_DESCRIPTOR\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002314 goto delegate;
2315
2316 case USB_REQ_SET_DESCRIPTOR:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002317 dev_dbg(&dev->pdev->dev,
2318 "SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002319 goto delegate;
2320
2321 case USB_REQ_GET_CONFIGURATION:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002322 dev_dbg(&dev->pdev->dev,
2323 "SETUP: USB_REQ_GET_CONFIGURATION\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002324 goto delegate;
2325
2326 case USB_REQ_SET_CONFIGURATION:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002327 dev_dbg(&dev->pdev->dev,
2328 "SETUP: USB_REQ_SET_CONFIGURATION\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002329 goto delegate;
2330
2331 case USB_REQ_GET_INTERFACE:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002332 dev_dbg(&dev->pdev->dev,
2333 "SETUP: USB_REQ_GET_INTERFACE\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002334 goto delegate;
2335
2336 case USB_REQ_SET_INTERFACE:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002337 dev_dbg(&dev->pdev->dev,
2338 "SETUP: USB_REQ_SET_INTERFACE\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002339 goto delegate;
2340
2341 case USB_REQ_SYNCH_FRAME:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002342 dev_dbg(&dev->pdev->dev,
2343 "SETUP: USB_REQ_SYNCH_FRAME unsupported\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002344 goto delegate;
2345
2346 default:
2347 /* delegate USB standard requests to the gadget driver */
2348 goto delegate;
2349delegate:
2350 /* USB requests handled by gadget */
2351 if (wLength) {
2352 /* DATA phase from gadget, STATUS phase from udc */
2353 dev->ep0_dir = (setup->bRequestType & USB_DIR_IN)
2354 ? USB_DIR_IN : USB_DIR_OUT;
JiebingLi5f81f4b2010-08-05 14:17:54 +01002355 dev_vdbg(&dev->pdev->dev,
2356 "dev->ep0_dir = 0x%x, wLength = %d\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002357 dev->ep0_dir, wLength);
2358 spin_unlock(&dev->lock);
2359 if (dev->driver->setup(&dev->gadget,
2360 &dev->local_setup_buff) < 0)
2361 ep0_stall(dev);
2362 spin_lock(&dev->lock);
2363 dev->ep0_state = (setup->bRequestType & USB_DIR_IN)
2364 ? DATA_STATE_XMIT : DATA_STATE_RECV;
2365 } else {
2366 /* no DATA phase, IN STATUS phase from gadget */
2367 dev->ep0_dir = USB_DIR_IN;
JiebingLi5f81f4b2010-08-05 14:17:54 +01002368 dev_vdbg(&dev->pdev->dev,
2369 "dev->ep0_dir = 0x%x, wLength = %d\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002370 dev->ep0_dir, wLength);
2371 spin_unlock(&dev->lock);
2372 if (dev->driver->setup(&dev->gadget,
2373 &dev->local_setup_buff) < 0)
2374 ep0_stall(dev);
2375 spin_lock(&dev->lock);
2376 dev->ep0_state = WAIT_FOR_OUT_STATUS;
2377 }
2378 break;
2379 }
2380end:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002381 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002382}
2383
2384
2385/* transfer completion, process endpoint request and free the completed dTDs
2386 * for this request
2387 */
2388static int process_ep_req(struct langwell_udc *dev, int index,
2389 struct langwell_request *curr_req)
2390{
2391 struct langwell_dtd *curr_dtd;
2392 struct langwell_dqh *curr_dqh;
2393 int td_complete, actual, remaining_length;
2394 int i, dir;
2395 u8 dtd_status = 0;
2396 int retval = 0;
2397
2398 curr_dqh = &dev->ep_dqh[index];
2399 dir = index % 2;
2400
2401 curr_dtd = curr_req->head;
2402 td_complete = 0;
2403 actual = curr_req->req.length;
2404
JiebingLi5f81f4b2010-08-05 14:17:54 +01002405 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002406
2407 for (i = 0; i < curr_req->dtd_count; i++) {
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002408
2409 /* command execution states by dTD */
2410 dtd_status = curr_dtd->dtd_status;
2411
Christophe Leboucc8458d52010-09-30 15:34:36 +01002412 barrier();
2413 remaining_length = le16_to_cpu(curr_dtd->dtd_total);
2414 actual -= remaining_length;
2415
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002416 if (!dtd_status) {
2417 /* transfers completed successfully */
2418 if (!remaining_length) {
2419 td_complete++;
JiebingLi5f81f4b2010-08-05 14:17:54 +01002420 dev_vdbg(&dev->pdev->dev,
2421 "dTD transmitted successfully\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002422 } else {
2423 if (dir) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002424 dev_vdbg(&dev->pdev->dev,
2425 "TX dTD remains data\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002426 retval = -EPROTO;
2427 break;
2428
2429 } else {
2430 td_complete++;
2431 break;
2432 }
2433 }
2434 } else {
2435 /* transfers completed with errors */
2436 if (dtd_status & DTD_STS_ACTIVE) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002437 dev_dbg(&dev->pdev->dev,
2438 "dTD status ACTIVE dQH[%d]\n", index);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002439 retval = 1;
2440 return retval;
2441 } else if (dtd_status & DTD_STS_HALTED) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002442 dev_err(&dev->pdev->dev,
2443 "dTD error %08x dQH[%d]\n",
2444 dtd_status, index);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002445 /* clear the errors and halt condition */
2446 curr_dqh->dtd_status = 0;
2447 retval = -EPIPE;
2448 break;
2449 } else if (dtd_status & DTD_STS_DBE) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002450 dev_dbg(&dev->pdev->dev,
2451 "data buffer (overflow) error\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002452 retval = -EPROTO;
2453 break;
2454 } else if (dtd_status & DTD_STS_TRE) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002455 dev_dbg(&dev->pdev->dev,
2456 "transaction(ISO) error\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002457 retval = -EILSEQ;
2458 break;
2459 } else
JiebingLi5f81f4b2010-08-05 14:17:54 +01002460 dev_err(&dev->pdev->dev,
2461 "unknown error (0x%x)!\n",
2462 dtd_status);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002463 }
2464
2465 if (i != curr_req->dtd_count - 1)
2466 curr_dtd = (struct langwell_dtd *)
2467 curr_dtd->next_dtd_virt;
2468 }
2469
2470 if (retval)
2471 return retval;
2472
2473 curr_req->req.actual = actual;
2474
JiebingLi5f81f4b2010-08-05 14:17:54 +01002475 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002476 return 0;
2477}
2478
2479
2480/* complete DATA or STATUS phase of ep0 prime status phase if needed */
2481static void ep0_req_complete(struct langwell_udc *dev,
2482 struct langwell_ep *ep0, struct langwell_request *req)
2483{
2484 u32 new_addr;
JiebingLi5f81f4b2010-08-05 14:17:54 +01002485 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002486
2487 if (dev->usb_state == USB_STATE_ADDRESS) {
2488 /* set the new address */
2489 new_addr = (u32)dev->dev_addr;
2490 writel(new_addr << USBADR_SHIFT, &dev->op_regs->deviceaddr);
2491
2492 new_addr = USBADR(readl(&dev->op_regs->deviceaddr));
JiebingLi5f81f4b2010-08-05 14:17:54 +01002493 dev_vdbg(&dev->pdev->dev, "new_addr = %d\n", new_addr);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002494 }
2495
2496 done(ep0, req, 0);
2497
2498 switch (dev->ep0_state) {
2499 case DATA_STATE_XMIT:
2500 /* receive status phase */
2501 if (prime_status_phase(dev, EP_DIR_OUT))
2502 ep0_stall(dev);
2503 break;
2504 case DATA_STATE_RECV:
2505 /* send status phase */
2506 if (prime_status_phase(dev, EP_DIR_IN))
2507 ep0_stall(dev);
2508 break;
2509 case WAIT_FOR_OUT_STATUS:
2510 dev->ep0_state = WAIT_FOR_SETUP;
2511 break;
2512 case WAIT_FOR_SETUP:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002513 dev_err(&dev->pdev->dev, "unexpect ep0 packets\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002514 break;
2515 default:
2516 ep0_stall(dev);
2517 break;
2518 }
2519
JiebingLi5f81f4b2010-08-05 14:17:54 +01002520 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002521}
2522
2523
2524/* USB transfer completion interrupt */
2525static void handle_trans_complete(struct langwell_udc *dev)
2526{
2527 u32 complete_bits;
2528 int i, ep_num, dir, bit_mask, status;
2529 struct langwell_ep *epn;
2530 struct langwell_request *curr_req, *temp_req;
2531
JiebingLi5f81f4b2010-08-05 14:17:54 +01002532 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002533
2534 complete_bits = readl(&dev->op_regs->endptcomplete);
JiebingLi5f81f4b2010-08-05 14:17:54 +01002535 dev_vdbg(&dev->pdev->dev, "endptcomplete register: 0x%08x\n",
2536 complete_bits);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002537
2538 /* Write-Clear the bits in endptcomplete register */
2539 writel(complete_bits, &dev->op_regs->endptcomplete);
2540
2541 if (!complete_bits) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002542 dev_dbg(&dev->pdev->dev, "complete_bits = 0\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002543 goto done;
2544 }
2545
2546 for (i = 0; i < dev->ep_max; i++) {
2547 ep_num = i / 2;
2548 dir = i % 2;
2549
2550 bit_mask = 1 << (ep_num + 16 * dir);
2551
2552 if (!(complete_bits & bit_mask))
2553 continue;
2554
2555 /* ep0 */
2556 if (i == 1)
2557 epn = &dev->ep[0];
2558 else
2559 epn = &dev->ep[i];
2560
2561 if (epn->name == NULL) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002562 dev_warn(&dev->pdev->dev, "invalid endpoint\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002563 continue;
2564 }
2565
2566 if (i < 2)
2567 /* ep0 in and out */
JiebingLi5f81f4b2010-08-05 14:17:54 +01002568 dev_dbg(&dev->pdev->dev, "%s-%s transfer completed\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002569 epn->name,
2570 is_in(epn) ? "in" : "out");
2571 else
JiebingLi5f81f4b2010-08-05 14:17:54 +01002572 dev_dbg(&dev->pdev->dev, "%s transfer completed\n",
2573 epn->name);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002574
2575 /* process the req queue until an uncomplete request */
2576 list_for_each_entry_safe(curr_req, temp_req,
2577 &epn->queue, queue) {
2578 status = process_ep_req(dev, i, curr_req);
JiebingLi5f81f4b2010-08-05 14:17:54 +01002579 dev_vdbg(&dev->pdev->dev, "%s req status: %d\n",
2580 epn->name, status);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002581
2582 if (status)
2583 break;
2584
2585 /* write back status to req */
2586 curr_req->req.status = status;
2587
2588 /* ep0 request completion */
2589 if (ep_num == 0) {
2590 ep0_req_complete(dev, epn, curr_req);
2591 break;
2592 } else {
2593 done(epn, curr_req, status);
2594 }
2595 }
2596 }
2597done:
JiebingLi5f81f4b2010-08-05 14:17:54 +01002598 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002599}
2600
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002601/* port change detect interrupt handler */
2602static void handle_port_change(struct langwell_udc *dev)
2603{
2604 u32 portsc1, devlc;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002605
JiebingLi5f81f4b2010-08-05 14:17:54 +01002606 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002607
2608 if (dev->bus_reset)
2609 dev->bus_reset = 0;
2610
2611 portsc1 = readl(&dev->op_regs->portsc1);
2612 devlc = readl(&dev->op_regs->devlc);
JiebingLi5f81f4b2010-08-05 14:17:54 +01002613 dev_vdbg(&dev->pdev->dev, "portsc1 = 0x%08x, devlc = 0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002614 portsc1, devlc);
2615
2616 /* bus reset is finished */
2617 if (!(portsc1 & PORTS_PR)) {
2618 /* get the speed */
Michal Nazarewicze538dfd2011-08-30 17:11:19 +02002619 dev->gadget.speed = lpm_device_speed(devlc);
2620 dev_vdbg(&dev->pdev->dev, "dev->gadget.speed = %d\n",
2621 dev->gadget.speed);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002622 }
2623
2624 /* LPM L0 to L1 */
2625 if (dev->lpm && dev->lpm_state == LPM_L0)
2626 if (portsc1 & PORTS_SUSP && portsc1 & PORTS_SLP) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002627 dev_info(&dev->pdev->dev, "LPM L0 to L1\n");
2628 dev->lpm_state = LPM_L1;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002629 }
2630
2631 /* LPM L1 to L0, force resume or remote wakeup finished */
2632 if (dev->lpm && dev->lpm_state == LPM_L1)
2633 if (!(portsc1 & PORTS_SUSP)) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002634 dev_info(&dev->pdev->dev, "LPM L1 to L0\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002635 dev->lpm_state = LPM_L0;
2636 }
2637
2638 /* update USB state */
2639 if (!dev->resume_state)
2640 dev->usb_state = USB_STATE_DEFAULT;
2641
JiebingLi5f81f4b2010-08-05 14:17:54 +01002642 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002643}
2644
2645
2646/* USB reset interrupt handler */
2647static void handle_usb_reset(struct langwell_udc *dev)
2648{
2649 u32 deviceaddr,
2650 endptsetupstat,
2651 endptcomplete;
2652 unsigned long timeout;
2653
JiebingLi5f81f4b2010-08-05 14:17:54 +01002654 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002655
2656 /* Write-Clear the device address */
2657 deviceaddr = readl(&dev->op_regs->deviceaddr);
2658 writel(deviceaddr & ~USBADR_MASK, &dev->op_regs->deviceaddr);
2659
2660 dev->dev_addr = 0;
2661
2662 /* clear usb state */
2663 dev->resume_state = 0;
2664
2665 /* LPM L1 to L0, reset */
2666 if (dev->lpm)
2667 dev->lpm_state = LPM_L0;
2668
2669 dev->ep0_dir = USB_DIR_OUT;
2670 dev->ep0_state = WAIT_FOR_SETUP;
JiebingLi3211cbc2010-08-05 14:18:21 +01002671
2672 /* remote wakeup reset to 0 when the device is reset */
2673 dev->remote_wakeup = 0;
2674 dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002675 dev->gadget.b_hnp_enable = 0;
2676 dev->gadget.a_hnp_support = 0;
2677 dev->gadget.a_alt_hnp_support = 0;
2678
2679 /* Write-Clear all the setup token semaphores */
2680 endptsetupstat = readl(&dev->op_regs->endptsetupstat);
2681 writel(endptsetupstat, &dev->op_regs->endptsetupstat);
2682
2683 /* Write-Clear all the endpoint complete status bits */
2684 endptcomplete = readl(&dev->op_regs->endptcomplete);
2685 writel(endptcomplete, &dev->op_regs->endptcomplete);
2686
2687 /* wait until all endptprime bits cleared */
2688 timeout = jiffies + PRIME_TIMEOUT;
2689 while (readl(&dev->op_regs->endptprime)) {
2690 if (time_after(jiffies, timeout)) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002691 dev_err(&dev->pdev->dev, "USB reset timeout\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002692 break;
2693 }
2694 cpu_relax();
2695 }
2696
2697 /* write 1s to endptflush register to clear any primed buffers */
2698 writel((u32) ~0, &dev->op_regs->endptflush);
2699
2700 if (readl(&dev->op_regs->portsc1) & PORTS_PR) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002701 dev_vdbg(&dev->pdev->dev, "USB bus reset\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002702 /* bus is reseting */
2703 dev->bus_reset = 1;
2704
2705 /* reset all the queues, stop all USB activities */
2706 stop_activity(dev, dev->driver);
2707 dev->usb_state = USB_STATE_DEFAULT;
2708 } else {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002709 dev_vdbg(&dev->pdev->dev, "device controller reset\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002710 /* controller reset */
2711 langwell_udc_reset(dev);
2712
2713 /* reset all the queues, stop all USB activities */
2714 stop_activity(dev, dev->driver);
2715
2716 /* reset ep0 dQH and endptctrl */
2717 ep0_reset(dev);
2718
2719 /* enable interrupt and set controller to run state */
2720 langwell_udc_start(dev);
2721
2722 dev->usb_state = USB_STATE_ATTACHED;
2723 }
2724
2725#ifdef OTG_TRANSCEIVER
2726 /* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */
2727 if (!dev->lotg->otg.default_a)
2728 dev->lotg->hsm.b_hnp_enable = 0;
2729#endif
2730
JiebingLi5f81f4b2010-08-05 14:17:54 +01002731 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002732}
2733
2734
2735/* USB bus suspend/resume interrupt */
2736static void handle_bus_suspend(struct langwell_udc *dev)
2737{
JiebingLi5f81f4b2010-08-05 14:17:54 +01002738 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002739
2740 dev->resume_state = dev->usb_state;
2741 dev->usb_state = USB_STATE_SUSPENDED;
2742
2743#ifdef OTG_TRANSCEIVER
2744 if (dev->lotg->otg.default_a) {
2745 if (dev->lotg->hsm.b_bus_suspend_vld == 1) {
2746 dev->lotg->hsm.b_bus_suspend = 1;
2747 /* notify transceiver the state changes */
2748 if (spin_trylock(&dev->lotg->wq_lock)) {
2749 langwell_update_transceiver();
2750 spin_unlock(&dev->lotg->wq_lock);
2751 }
2752 }
2753 dev->lotg->hsm.b_bus_suspend_vld++;
2754 } else {
2755 if (!dev->lotg->hsm.a_bus_suspend) {
2756 dev->lotg->hsm.a_bus_suspend = 1;
2757 /* notify transceiver the state changes */
2758 if (spin_trylock(&dev->lotg->wq_lock)) {
2759 langwell_update_transceiver();
2760 spin_unlock(&dev->lotg->wq_lock);
2761 }
2762 }
2763 }
2764#endif
2765
2766 /* report suspend to the driver */
2767 if (dev->driver) {
2768 if (dev->driver->suspend) {
2769 spin_unlock(&dev->lock);
2770 dev->driver->suspend(&dev->gadget);
2771 spin_lock(&dev->lock);
JiebingLi5f81f4b2010-08-05 14:17:54 +01002772 dev_dbg(&dev->pdev->dev, "suspend %s\n",
2773 dev->driver->driver.name);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002774 }
2775 }
2776
2777 /* enter PHY low power suspend */
JiebingLi513b91b2010-08-05 14:18:13 +01002778 if (dev->pdev->device != 0x0829)
2779 langwell_phy_low_power(dev, 0);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002780
JiebingLi5f81f4b2010-08-05 14:17:54 +01002781 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002782}
2783
2784
2785static void handle_bus_resume(struct langwell_udc *dev)
2786{
JiebingLi5f81f4b2010-08-05 14:17:54 +01002787 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002788
2789 dev->usb_state = dev->resume_state;
2790 dev->resume_state = 0;
2791
2792 /* exit PHY low power suspend */
JiebingLi513b91b2010-08-05 14:18:13 +01002793 if (dev->pdev->device != 0x0829)
2794 langwell_phy_low_power(dev, 0);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002795
2796#ifdef OTG_TRANSCEIVER
2797 if (dev->lotg->otg.default_a == 0)
2798 dev->lotg->hsm.a_bus_suspend = 0;
2799#endif
2800
2801 /* report resume to the driver */
2802 if (dev->driver) {
2803 if (dev->driver->resume) {
2804 spin_unlock(&dev->lock);
2805 dev->driver->resume(&dev->gadget);
2806 spin_lock(&dev->lock);
JiebingLi5f81f4b2010-08-05 14:17:54 +01002807 dev_dbg(&dev->pdev->dev, "resume %s\n",
2808 dev->driver->driver.name);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002809 }
2810 }
2811
JiebingLi5f81f4b2010-08-05 14:17:54 +01002812 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002813}
2814
2815
2816/* USB device controller interrupt handler */
2817static irqreturn_t langwell_irq(int irq, void *_dev)
2818{
2819 struct langwell_udc *dev = _dev;
2820 u32 usbsts,
2821 usbintr,
2822 irq_sts,
2823 portsc1;
2824
JiebingLi5f81f4b2010-08-05 14:17:54 +01002825 dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002826
2827 if (dev->stopped) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002828 dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n");
2829 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002830 return IRQ_NONE;
2831 }
2832
2833 spin_lock(&dev->lock);
2834
2835 /* USB status */
2836 usbsts = readl(&dev->op_regs->usbsts);
2837
2838 /* USB interrupt enable */
2839 usbintr = readl(&dev->op_regs->usbintr);
2840
2841 irq_sts = usbsts & usbintr;
JiebingLi5f81f4b2010-08-05 14:17:54 +01002842 dev_vdbg(&dev->pdev->dev,
2843 "usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002844 usbsts, usbintr, irq_sts);
2845
2846 if (!irq_sts) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002847 dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n");
2848 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002849 spin_unlock(&dev->lock);
2850 return IRQ_NONE;
2851 }
2852
2853 /* Write-Clear interrupt status bits */
2854 writel(irq_sts, &dev->op_regs->usbsts);
2855
2856 /* resume from suspend */
2857 portsc1 = readl(&dev->op_regs->portsc1);
2858 if (dev->usb_state == USB_STATE_SUSPENDED)
2859 if (!(portsc1 & PORTS_SUSP))
2860 handle_bus_resume(dev);
2861
2862 /* USB interrupt */
2863 if (irq_sts & STS_UI) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002864 dev_vdbg(&dev->pdev->dev, "USB interrupt\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002865
2866 /* setup packet received from ep0 */
2867 if (readl(&dev->op_regs->endptsetupstat)
2868 & EP0SETUPSTAT_MASK) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002869 dev_vdbg(&dev->pdev->dev,
2870 "USB SETUP packet received interrupt\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002871 /* setup tripwire semaphone */
2872 setup_tripwire(dev);
2873 handle_setup_packet(dev, &dev->local_setup_buff);
2874 }
2875
2876 /* USB transfer completion */
2877 if (readl(&dev->op_regs->endptcomplete)) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002878 dev_vdbg(&dev->pdev->dev,
2879 "USB transfer completion interrupt\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002880 handle_trans_complete(dev);
2881 }
2882 }
2883
2884 /* SOF received interrupt (for ISO transfer) */
2885 if (irq_sts & STS_SRI) {
2886 /* FIXME */
JiebingLi5f81f4b2010-08-05 14:17:54 +01002887 /* dev_vdbg(&dev->pdev->dev, "SOF received interrupt\n"); */
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002888 }
2889
2890 /* port change detect interrupt */
2891 if (irq_sts & STS_PCI) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002892 dev_vdbg(&dev->pdev->dev, "port change detect interrupt\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002893 handle_port_change(dev);
2894 }
2895
Vitaliy Ivanovfb914eb2011-06-23 20:01:55 +03002896 /* suspend interrupt */
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002897 if (irq_sts & STS_SLI) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002898 dev_vdbg(&dev->pdev->dev, "suspend interrupt\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002899 handle_bus_suspend(dev);
2900 }
2901
2902 /* USB reset interrupt */
2903 if (irq_sts & STS_URI) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01002904 dev_vdbg(&dev->pdev->dev, "USB reset interrupt\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002905 handle_usb_reset(dev);
2906 }
2907
2908 /* USB error or system error interrupt */
2909 if (irq_sts & (STS_UEI | STS_SEI)) {
2910 /* FIXME */
JiebingLi5f81f4b2010-08-05 14:17:54 +01002911 dev_warn(&dev->pdev->dev, "error IRQ, irq_sts: %x\n", irq_sts);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002912 }
2913
2914 spin_unlock(&dev->lock);
2915
JiebingLi5f81f4b2010-08-05 14:17:54 +01002916 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002917 return IRQ_HANDLED;
2918}
2919
2920
2921/*-------------------------------------------------------------------------*/
2922
2923/* release device structure */
2924static void gadget_release(struct device *_dev)
2925{
Felipe Balbi5bc639f2011-10-08 13:08:01 +03002926 struct langwell_udc *dev = dev_get_drvdata(_dev);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002927
JiebingLi5f81f4b2010-08-05 14:17:54 +01002928 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002929
2930 complete(dev->done);
2931
JiebingLi5f81f4b2010-08-05 14:17:54 +01002932 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002933 kfree(dev);
2934}
2935
2936
JiebingLi912c93d2010-08-05 14:18:29 +01002937/* enable SRAM caching if SRAM detected */
2938static void sram_init(struct langwell_udc *dev)
2939{
2940 struct pci_dev *pdev = dev->pdev;
2941
2942 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
2943
2944 dev->sram_addr = pci_resource_start(pdev, 1);
2945 dev->sram_size = pci_resource_len(pdev, 1);
2946 dev_info(&dev->pdev->dev, "Found private SRAM at %x size:%x\n",
2947 dev->sram_addr, dev->sram_size);
2948 dev->got_sram = 1;
2949
2950 if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) {
2951 dev_warn(&dev->pdev->dev, "SRAM request failed\n");
2952 dev->got_sram = 0;
2953 } else if (!dma_declare_coherent_memory(&pdev->dev, dev->sram_addr,
2954 dev->sram_addr, dev->sram_size, DMA_MEMORY_MAP)) {
2955 dev_warn(&dev->pdev->dev, "SRAM DMA declare failed\n");
2956 pci_release_region(pdev, 1);
2957 dev->got_sram = 0;
2958 }
2959
2960 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
2961}
2962
2963
2964/* release SRAM caching */
2965static void sram_deinit(struct langwell_udc *dev)
2966{
2967 struct pci_dev *pdev = dev->pdev;
2968
2969 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
2970
2971 dma_release_declared_memory(&pdev->dev);
2972 pci_release_region(pdev, 1);
2973
2974 dev->got_sram = 0;
2975
2976 dev_info(&dev->pdev->dev, "release SRAM caching\n");
2977 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
2978}
2979
2980
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002981/* tear down the binding between this driver and the pci device */
2982static void langwell_udc_remove(struct pci_dev *pdev)
2983{
Felipe Balbi5bc639f2011-10-08 13:08:01 +03002984 struct langwell_udc *dev = pci_get_drvdata(pdev);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002985
2986 DECLARE_COMPLETION(done);
2987
2988 BUG_ON(dev->driver);
JiebingLi5f81f4b2010-08-05 14:17:54 +01002989 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002990
2991 dev->done = &done;
2992
JiebingLi912c93d2010-08-05 14:18:29 +01002993#ifndef OTG_TRANSCEIVER
2994 /* free dTD dma_pool and dQH */
Xiaochen Shen5be19a92009-06-04 15:34:49 +08002995 if (dev->dtd_pool)
2996 dma_pool_destroy(dev->dtd_pool);
2997
JiebingLi912c93d2010-08-05 14:18:29 +01002998 if (dev->ep_dqh)
2999 dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
3000 dev->ep_dqh, dev->ep_dqh_dma);
3001
3002 /* release SRAM caching */
3003 if (dev->has_sram && dev->got_sram)
3004 sram_deinit(dev);
3005#endif
3006
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003007 if (dev->status_req) {
3008 kfree(dev->status_req->req.buf);
3009 kfree(dev->status_req);
3010 }
3011
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003012 kfree(dev->ep);
3013
Justin P. Mattock48e34d02010-12-30 15:07:58 -08003014 /* disable IRQ handler */
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003015 if (dev->got_irq)
3016 free_irq(pdev->irq, dev);
3017
3018#ifndef OTG_TRANSCEIVER
3019 if (dev->cap_regs)
3020 iounmap(dev->cap_regs);
3021
3022 if (dev->region)
3023 release_mem_region(pci_resource_start(pdev, 0),
3024 pci_resource_len(pdev, 0));
3025
3026 if (dev->enabled)
3027 pci_disable_device(pdev);
3028#else
3029 if (dev->transceiver) {
3030 otg_put_transceiver(dev->transceiver);
3031 dev->transceiver = NULL;
3032 dev->lotg = NULL;
3033 }
3034#endif
3035
3036 dev->cap_regs = NULL;
3037
JiebingLi5f81f4b2010-08-05 14:17:54 +01003038 dev_info(&dev->pdev->dev, "unbind\n");
3039 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003040
3041 device_unregister(&dev->gadget.dev);
3042 device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
JiebingLi3211cbc2010-08-05 14:18:21 +01003043 device_remove_file(&pdev->dev, &dev_attr_remote_wakeup);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003044
3045#ifndef OTG_TRANSCEIVER
3046 pci_set_drvdata(pdev, NULL);
3047#endif
3048
3049 /* free dev, wait for the release() finished */
3050 wait_for_completion(&done);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003051}
3052
3053
3054/*
3055 * wrap this driver around the specified device, but
3056 * don't respond over USB until a gadget driver binds to us.
3057 */
3058static int langwell_udc_probe(struct pci_dev *pdev,
3059 const struct pci_device_id *id)
3060{
3061 struct langwell_udc *dev;
3062#ifndef OTG_TRANSCEIVER
3063 unsigned long resource, len;
3064#endif
3065 void __iomem *base = NULL;
3066 size_t size;
3067 int retval;
3068
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003069 /* alloc, and start init */
3070 dev = kzalloc(sizeof *dev, GFP_KERNEL);
3071 if (dev == NULL) {
3072 retval = -ENOMEM;
3073 goto error;
3074 }
3075
3076 /* initialize device spinlock */
3077 spin_lock_init(&dev->lock);
3078
3079 dev->pdev = pdev;
JiebingLi5f81f4b2010-08-05 14:17:54 +01003080 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003081
3082#ifdef OTG_TRANSCEIVER
3083 /* PCI device is already enabled by otg_transceiver driver */
3084 dev->enabled = 1;
3085
3086 /* mem region and register base */
3087 dev->region = 1;
3088 dev->transceiver = otg_get_transceiver();
3089 dev->lotg = otg_to_langwell(dev->transceiver);
3090 base = dev->lotg->regs;
3091#else
3092 pci_set_drvdata(pdev, dev);
3093
3094 /* now all the pci goodies ... */
3095 if (pci_enable_device(pdev) < 0) {
3096 retval = -ENODEV;
3097 goto error;
3098 }
3099 dev->enabled = 1;
3100
3101 /* control register: BAR 0 */
3102 resource = pci_resource_start(pdev, 0);
3103 len = pci_resource_len(pdev, 0);
3104 if (!request_mem_region(resource, len, driver_name)) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01003105 dev_err(&dev->pdev->dev, "controller already in use\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003106 retval = -EBUSY;
3107 goto error;
3108 }
3109 dev->region = 1;
3110
3111 base = ioremap_nocache(resource, len);
3112#endif
3113 if (base == NULL) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01003114 dev_err(&dev->pdev->dev, "can't map memory\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003115 retval = -EFAULT;
3116 goto error;
3117 }
3118
3119 dev->cap_regs = (struct langwell_cap_regs __iomem *) base;
JiebingLi5f81f4b2010-08-05 14:17:54 +01003120 dev_vdbg(&dev->pdev->dev, "dev->cap_regs: %p\n", dev->cap_regs);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003121 dev->op_regs = (struct langwell_op_regs __iomem *)
3122 (base + OP_REG_OFFSET);
JiebingLi5f81f4b2010-08-05 14:17:54 +01003123 dev_vdbg(&dev->pdev->dev, "dev->op_regs: %p\n", dev->op_regs);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003124
3125 /* irq setup after old hardware is cleaned up */
3126 if (!pdev->irq) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01003127 dev_err(&dev->pdev->dev, "No IRQ. Check PCI setup!\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003128 retval = -ENODEV;
3129 goto error;
3130 }
3131
JiebingLi912c93d2010-08-05 14:18:29 +01003132 dev->has_sram = 1;
3133 dev->got_sram = 0;
3134 dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram);
3135
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003136#ifndef OTG_TRANSCEIVER
JiebingLi912c93d2010-08-05 14:18:29 +01003137 /* enable SRAM caching if detected */
3138 if (dev->has_sram && !dev->got_sram)
3139 sram_init(dev);
3140
JiebingLi5f81f4b2010-08-05 14:17:54 +01003141 dev_info(&dev->pdev->dev,
3142 "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n",
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003143 pdev->irq, resource, len, base);
3144 /* enables bus-mastering for device dev */
3145 pci_set_master(pdev);
3146
3147 if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED,
3148 driver_name, dev) != 0) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01003149 dev_err(&dev->pdev->dev,
3150 "request interrupt %d failed\n", pdev->irq);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003151 retval = -EBUSY;
3152 goto error;
3153 }
3154 dev->got_irq = 1;
3155#endif
3156
3157 /* set stopped bit */
3158 dev->stopped = 1;
3159
3160 /* capabilities and endpoint number */
3161 dev->lpm = (readl(&dev->cap_regs->hccparams) & HCC_LEN) ? 1 : 0;
3162 dev->dciversion = readw(&dev->cap_regs->dciversion);
3163 dev->devcap = (readl(&dev->cap_regs->dccparams) & DEVCAP) ? 1 : 0;
JiebingLi5f81f4b2010-08-05 14:17:54 +01003164 dev_vdbg(&dev->pdev->dev, "dev->lpm: %d\n", dev->lpm);
3165 dev_vdbg(&dev->pdev->dev, "dev->dciversion: 0x%04x\n",
3166 dev->dciversion);
3167 dev_vdbg(&dev->pdev->dev, "dccparams: 0x%08x\n",
3168 readl(&dev->cap_regs->dccparams));
3169 dev_vdbg(&dev->pdev->dev, "dev->devcap: %d\n", dev->devcap);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003170 if (!dev->devcap) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01003171 dev_err(&dev->pdev->dev, "can't support device mode\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003172 retval = -ENODEV;
3173 goto error;
3174 }
3175
3176 /* a pair of endpoints (out/in) for each address */
3177 dev->ep_max = DEN(readl(&dev->cap_regs->dccparams)) * 2;
JiebingLi5f81f4b2010-08-05 14:17:54 +01003178 dev_vdbg(&dev->pdev->dev, "dev->ep_max: %d\n", dev->ep_max);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003179
3180 /* allocate endpoints memory */
3181 dev->ep = kzalloc(sizeof(struct langwell_ep) * dev->ep_max,
3182 GFP_KERNEL);
3183 if (!dev->ep) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01003184 dev_err(&dev->pdev->dev, "allocate endpoints memory failed\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003185 retval = -ENOMEM;
3186 goto error;
3187 }
3188
3189 /* allocate device dQH memory */
3190 size = dev->ep_max * sizeof(struct langwell_dqh);
Felipe Balbib9af9ea2011-07-04 11:12:32 +03003191 dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003192 if (size < DQH_ALIGNMENT)
3193 size = DQH_ALIGNMENT;
3194 else if ((size % DQH_ALIGNMENT) != 0) {
3195 size += DQH_ALIGNMENT + 1;
3196 size &= ~(DQH_ALIGNMENT - 1);
3197 }
3198 dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
3199 &dev->ep_dqh_dma, GFP_KERNEL);
3200 if (!dev->ep_dqh) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01003201 dev_err(&dev->pdev->dev, "allocate dQH memory failed\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003202 retval = -ENOMEM;
3203 goto error;
3204 }
3205 dev->ep_dqh_size = size;
Felipe Balbib9af9ea2011-07-04 11:12:32 +03003206 dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003207
3208 /* initialize ep0 status request structure */
3209 dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL);
3210 if (!dev->status_req) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01003211 dev_err(&dev->pdev->dev,
3212 "allocate status_req memory failed\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003213 retval = -ENOMEM;
3214 goto error;
3215 }
3216 INIT_LIST_HEAD(&dev->status_req->queue);
3217
3218 /* allocate a small amount of memory to get valid address */
3219 dev->status_req->req.buf = kmalloc(8, GFP_KERNEL);
3220 dev->status_req->req.dma = virt_to_phys(dev->status_req->req.buf);
3221
3222 dev->resume_state = USB_STATE_NOTATTACHED;
3223 dev->usb_state = USB_STATE_POWERED;
3224 dev->ep0_dir = USB_DIR_OUT;
JiebingLi3211cbc2010-08-05 14:18:21 +01003225
3226 /* remote wakeup reset to 0 when the device is reset */
3227 dev->remote_wakeup = 0;
3228 dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003229
3230#ifndef OTG_TRANSCEIVER
3231 /* reset device controller */
3232 langwell_udc_reset(dev);
3233#endif
3234
3235 /* initialize gadget structure */
3236 dev->gadget.ops = &langwell_ops; /* usb_gadget_ops */
3237 dev->gadget.ep0 = &dev->ep[0].ep; /* gadget ep0 */
3238 INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */
3239 dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01003240 dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003241#ifdef OTG_TRANSCEIVER
3242 dev->gadget.is_otg = 1; /* support otg mode */
3243#endif
3244
3245 /* the "gadget" abstracts/virtualizes the controller */
3246 dev_set_name(&dev->gadget.dev, "gadget");
3247 dev->gadget.dev.parent = &pdev->dev;
3248 dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
3249 dev->gadget.dev.release = gadget_release;
3250 dev->gadget.name = driver_name; /* gadget name */
3251
3252 /* controller endpoints reinit */
3253 eps_reinit(dev);
3254
3255#ifndef OTG_TRANSCEIVER
3256 /* reset ep0 dQH and endptctrl */
3257 ep0_reset(dev);
3258#endif
3259
3260 /* create dTD dma_pool resource */
3261 dev->dtd_pool = dma_pool_create("langwell_dtd",
3262 &dev->pdev->dev,
3263 sizeof(struct langwell_dtd),
3264 DTD_ALIGNMENT,
3265 DMA_BOUNDARY);
3266
3267 if (!dev->dtd_pool) {
3268 retval = -ENOMEM;
3269 goto error;
3270 }
3271
3272 /* done */
JiebingLi5f81f4b2010-08-05 14:17:54 +01003273 dev_info(&dev->pdev->dev, "%s\n", driver_desc);
3274 dev_info(&dev->pdev->dev, "irq %d, pci mem %p\n", pdev->irq, base);
3275 dev_info(&dev->pdev->dev, "Driver version: " DRIVER_VERSION "\n");
3276 dev_info(&dev->pdev->dev, "Support (max) %d endpoints\n", dev->ep_max);
3277 dev_info(&dev->pdev->dev, "Device interface version: 0x%04x\n",
3278 dev->dciversion);
3279 dev_info(&dev->pdev->dev, "Controller mode: %s\n",
3280 dev->devcap ? "Device" : "Host");
3281 dev_info(&dev->pdev->dev, "Support USB LPM: %s\n",
3282 dev->lpm ? "Yes" : "No");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003283
JiebingLi5f81f4b2010-08-05 14:17:54 +01003284 dev_vdbg(&dev->pdev->dev,
3285 "After langwell_udc_probe(), print all registers:\n");
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003286 print_all_registers(dev);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003287
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003288 retval = device_register(&dev->gadget.dev);
3289 if (retval)
3290 goto error;
3291
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003292 retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
3293 if (retval)
3294 goto error;
3295
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003296 retval = device_create_file(&pdev->dev, &dev_attr_langwell_udc);
3297 if (retval)
3298 goto error;
3299
JiebingLi3211cbc2010-08-05 14:18:21 +01003300 retval = device_create_file(&pdev->dev, &dev_attr_remote_wakeup);
3301 if (retval)
3302 goto error_attr1;
3303
JiebingLi5f81f4b2010-08-05 14:17:54 +01003304 dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003305 return 0;
3306
JiebingLi3211cbc2010-08-05 14:18:21 +01003307error_attr1:
3308 device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003309error:
3310 if (dev) {
JiebingLi5f81f4b2010-08-05 14:17:54 +01003311 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003312 langwell_udc_remove(pdev);
3313 }
3314
3315 return retval;
3316}
3317
3318
3319/* device controller suspend */
3320static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
3321{
Felipe Balbi5bc639f2011-10-08 13:08:01 +03003322 struct langwell_udc *dev = pci_get_drvdata(pdev);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003323
JiebingLi5f81f4b2010-08-05 14:17:54 +01003324 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003325
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003326 usb_del_gadget_udc(&dev->gadget);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003327 /* disable interrupt and set controller to stop state */
3328 langwell_udc_stop(dev);
3329
Justin P. Mattock48e34d02010-12-30 15:07:58 -08003330 /* disable IRQ handler */
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003331 if (dev->got_irq)
3332 free_irq(pdev->irq, dev);
3333 dev->got_irq = 0;
3334
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003335 /* save PCI state */
3336 pci_save_state(pdev);
3337
Philippe Skowronskicf7d3c82010-10-01 14:59:16 +01003338 spin_lock_irq(&dev->lock);
3339 /* stop all usb activities */
3340 stop_activity(dev, dev->driver);
3341 spin_unlock_irq(&dev->lock);
3342
JiebingLi912c93d2010-08-05 14:18:29 +01003343 /* free dTD dma_pool and dQH */
3344 if (dev->dtd_pool)
3345 dma_pool_destroy(dev->dtd_pool);
3346
3347 if (dev->ep_dqh)
3348 dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
3349 dev->ep_dqh, dev->ep_dqh_dma);
3350
3351 /* release SRAM caching */
3352 if (dev->has_sram && dev->got_sram)
3353 sram_deinit(dev);
3354
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003355 /* set device power state */
3356 pci_set_power_state(pdev, PCI_D3hot);
3357
3358 /* enter PHY low power suspend */
JiebingLi513b91b2010-08-05 14:18:13 +01003359 if (dev->pdev->device != 0x0829)
3360 langwell_phy_low_power(dev, 1);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003361
JiebingLi5f81f4b2010-08-05 14:17:54 +01003362 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003363 return 0;
3364}
3365
3366
3367/* device controller resume */
3368static int langwell_udc_resume(struct pci_dev *pdev)
3369{
Felipe Balbi5bc639f2011-10-08 13:08:01 +03003370 struct langwell_udc *dev = pci_get_drvdata(pdev);
JiebingLi912c93d2010-08-05 14:18:29 +01003371 size_t size;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003372
JiebingLi5f81f4b2010-08-05 14:17:54 +01003373 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003374
3375 /* exit PHY low power suspend */
JiebingLi513b91b2010-08-05 14:18:13 +01003376 if (dev->pdev->device != 0x0829)
3377 langwell_phy_low_power(dev, 0);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003378
3379 /* set device D0 power state */
3380 pci_set_power_state(pdev, PCI_D0);
3381
JiebingLi912c93d2010-08-05 14:18:29 +01003382 /* enable SRAM caching if detected */
3383 if (dev->has_sram && !dev->got_sram)
3384 sram_init(dev);
3385
3386 /* allocate device dQH memory */
3387 size = dev->ep_max * sizeof(struct langwell_dqh);
Felipe Balbib9af9ea2011-07-04 11:12:32 +03003388 dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size);
JiebingLi912c93d2010-08-05 14:18:29 +01003389 if (size < DQH_ALIGNMENT)
3390 size = DQH_ALIGNMENT;
3391 else if ((size % DQH_ALIGNMENT) != 0) {
3392 size += DQH_ALIGNMENT + 1;
3393 size &= ~(DQH_ALIGNMENT - 1);
3394 }
3395 dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
3396 &dev->ep_dqh_dma, GFP_KERNEL);
3397 if (!dev->ep_dqh) {
3398 dev_err(&dev->pdev->dev, "allocate dQH memory failed\n");
3399 return -ENOMEM;
3400 }
3401 dev->ep_dqh_size = size;
Felipe Balbib9af9ea2011-07-04 11:12:32 +03003402 dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size);
JiebingLi912c93d2010-08-05 14:18:29 +01003403
3404 /* create dTD dma_pool resource */
3405 dev->dtd_pool = dma_pool_create("langwell_dtd",
3406 &dev->pdev->dev,
3407 sizeof(struct langwell_dtd),
3408 DTD_ALIGNMENT,
3409 DMA_BOUNDARY);
3410
3411 if (!dev->dtd_pool)
3412 return -ENOMEM;
3413
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003414 /* restore PCI state */
3415 pci_restore_state(pdev);
3416
3417 /* enable IRQ handler */
JiebingLi5f81f4b2010-08-05 14:17:54 +01003418 if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED,
3419 driver_name, dev) != 0) {
3420 dev_err(&dev->pdev->dev, "request interrupt %d failed\n",
3421 pdev->irq);
3422 return -EBUSY;
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003423 }
3424 dev->got_irq = 1;
3425
3426 /* reset and start controller to run state */
3427 if (dev->stopped) {
3428 /* reset device controller */
3429 langwell_udc_reset(dev);
3430
3431 /* reset ep0 dQH and endptctrl */
3432 ep0_reset(dev);
3433
3434 /* start device if gadget is loaded */
3435 if (dev->driver)
3436 langwell_udc_start(dev);
3437 }
3438
3439 /* reset USB status */
3440 dev->usb_state = USB_STATE_ATTACHED;
3441 dev->ep0_state = WAIT_FOR_SETUP;
3442 dev->ep0_dir = USB_DIR_OUT;
3443
JiebingLi5f81f4b2010-08-05 14:17:54 +01003444 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003445 return 0;
3446}
3447
3448
3449/* pci driver shutdown */
3450static void langwell_udc_shutdown(struct pci_dev *pdev)
3451{
Felipe Balbi5bc639f2011-10-08 13:08:01 +03003452 struct langwell_udc *dev = pci_get_drvdata(pdev);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003453 u32 usbmode;
3454
JiebingLi5f81f4b2010-08-05 14:17:54 +01003455 dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003456
3457 /* reset controller mode to IDLE */
3458 usbmode = readl(&dev->op_regs->usbmode);
JiebingLi5f81f4b2010-08-05 14:17:54 +01003459 dev_dbg(&dev->pdev->dev, "usbmode = 0x%08x\n", usbmode);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003460 usbmode &= (~3 | MODE_IDLE);
3461 writel(usbmode, &dev->op_regs->usbmode);
3462
JiebingLi5f81f4b2010-08-05 14:17:54 +01003463 dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003464}
3465
3466/*-------------------------------------------------------------------------*/
3467
3468static const struct pci_device_id pci_ids[] = { {
3469 .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
3470 .class_mask = ~0,
3471 .vendor = 0x8086,
3472 .device = 0x0811,
3473 .subvendor = PCI_ANY_ID,
3474 .subdevice = PCI_ANY_ID,
3475}, { /* end: all zeroes */ }
3476};
3477
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003478MODULE_DEVICE_TABLE(pci, pci_ids);
3479
3480
3481static struct pci_driver langwell_pci_driver = {
3482 .name = (char *) driver_name,
3483 .id_table = pci_ids,
3484
3485 .probe = langwell_udc_probe,
3486 .remove = langwell_udc_remove,
3487
3488 /* device controller suspend/resume */
3489 .suspend = langwell_udc_suspend,
3490 .resume = langwell_udc_resume,
3491
3492 .shutdown = langwell_udc_shutdown,
3493};
3494
3495
Xiaochen Shen5be19a92009-06-04 15:34:49 +08003496static int __init init(void)
3497{
3498#ifdef OTG_TRANSCEIVER
3499 return langwell_register_peripheral(&langwell_pci_driver);
3500#else
3501 return pci_register_driver(&langwell_pci_driver);
3502#endif
3503}
3504module_init(init);
3505
3506
3507static void __exit cleanup(void)
3508{
3509#ifdef OTG_TRANSCEIVER
3510 return langwell_unregister_peripheral(&langwell_pci_driver);
3511#else
3512 pci_unregister_driver(&langwell_pci_driver);
3513#endif
3514}
3515module_exit(cleanup);
3516
JiebingLi5f81f4b2010-08-05 14:17:54 +01003517
3518MODULE_DESCRIPTION(DRIVER_DESC);
3519MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>");
3520MODULE_VERSION(DRIVER_VERSION);
3521MODULE_LICENSE("GPL");
3522