diff options
Diffstat (limited to 'drivers/usb/gadget/imx_udc.c')
-rw-r--r-- | drivers/usb/gadget/imx_udc.c | 248 |
1 files changed, 150 insertions, 98 deletions
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 77c5d0a8a06..168658b4b4e 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * driver/usb/gadget/imx_udc.c | 2 | * driver/usb/gadget/imx_udc.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Mike Lee(eemike@gmail.com) | 4 | * Copyright (C) 2005 Mike Lee <eemike@gmail.com> |
5 | * Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com> | 5 | * Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <linux/clk.h> | 29 | #include <linux/clk.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/timer.h> | ||
31 | 32 | ||
32 | #include <linux/usb/ch9.h> | 33 | #include <linux/usb/ch9.h> |
33 | #include <linux/usb/gadget.h> | 34 | #include <linux/usb/gadget.h> |
@@ -51,7 +52,8 @@ void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb, | |||
51 | void imx_udc_enable(struct imx_udc_struct *imx_usb) | 52 | void imx_udc_enable(struct imx_udc_struct *imx_usb) |
52 | { | 53 | { |
53 | int temp = __raw_readl(imx_usb->base + USB_CTRL); | 54 | int temp = __raw_readl(imx_usb->base + USB_CTRL); |
54 | __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, imx_usb->base + USB_CTRL); | 55 | __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, |
56 | imx_usb->base + USB_CTRL); | ||
55 | imx_usb->gadget.speed = USB_SPEED_FULL; | 57 | imx_usb->gadget.speed = USB_SPEED_FULL; |
56 | } | 58 | } |
57 | 59 | ||
@@ -126,7 +128,8 @@ void imx_udc_config(struct imx_udc_struct *imx_usb) | |||
126 | for (j = 0; j < 5; j++) { | 128 | for (j = 0; j < 5; j++) { |
127 | __raw_writeb(ep_conf[j], | 129 | __raw_writeb(ep_conf[j], |
128 | imx_usb->base + USB_DDAT); | 130 | imx_usb->base + USB_DDAT); |
129 | do {} while (__raw_readl(imx_usb->base + USB_DADR) | 131 | do {} while (__raw_readl(imx_usb->base |
132 | + USB_DADR) | ||
130 | & DADR_BSY); | 133 | & DADR_BSY); |
131 | } | 134 | } |
132 | } | 135 | } |
@@ -183,7 +186,8 @@ void imx_udc_init_ep(struct imx_udc_struct *imx_usb) | |||
183 | temp = (EP_DIR(imx_ep) << 7) | (max << 5) | 186 | temp = (EP_DIR(imx_ep) << 7) | (max << 5) |
184 | | (imx_ep->bmAttributes << 3); | 187 | | (imx_ep->bmAttributes << 3); |
185 | __raw_writel(temp, imx_usb->base + USB_EP_STAT(i)); | 188 | __raw_writel(temp, imx_usb->base + USB_EP_STAT(i)); |
186 | __raw_writel(temp | EPSTAT_FLUSH, imx_usb->base + USB_EP_STAT(i)); | 189 | __raw_writel(temp | EPSTAT_FLUSH, |
190 | imx_usb->base + USB_EP_STAT(i)); | ||
187 | D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i, | 191 | D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i, |
188 | __raw_readl(imx_usb->base + USB_EP_STAT(i))); | 192 | __raw_readl(imx_usb->base + USB_EP_STAT(i))); |
189 | } | 193 | } |
@@ -278,15 +282,18 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) | |||
278 | struct imx_udc_struct *imx_usb = imx_ep->imx_usb; | 282 | struct imx_udc_struct *imx_usb = imx_ep->imx_usb; |
279 | int temp, i; | 283 | int temp, i; |
280 | 284 | ||
281 | D_ERR(imx_usb->dev, "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name); | 285 | D_ERR(imx_usb->dev, |
286 | "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name); | ||
282 | 287 | ||
283 | imx_flush(imx_ep); | 288 | imx_flush(imx_ep); |
284 | 289 | ||
285 | /* Special care for ep0 */ | 290 | /* Special care for ep0 */ |
286 | if (EP_NO(imx_ep)) { | 291 | if (!EP_NO(imx_ep)) { |
287 | temp = __raw_readl(imx_usb->base + USB_CTRL); | 292 | temp = __raw_readl(imx_usb->base + USB_CTRL); |
288 | __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL); | 293 | __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, |
289 | do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER); | 294 | imx_usb->base + USB_CTRL); |
295 | do { } while (__raw_readl(imx_usb->base + USB_CTRL) | ||
296 | & CTRL_CMDOVER); | ||
290 | temp = __raw_readl(imx_usb->base + USB_CTRL); | 297 | temp = __raw_readl(imx_usb->base + USB_CTRL); |
291 | __raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL); | 298 | __raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL); |
292 | } | 299 | } |
@@ -296,12 +303,13 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) | |||
296 | imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | 303 | imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); |
297 | 304 | ||
298 | for (i = 0; i < 100; i ++) { | 305 | for (i = 0; i < 100; i ++) { |
299 | temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | 306 | temp = __raw_readl(imx_usb->base |
307 | + USB_EP_STAT(EP_NO(imx_ep))); | ||
300 | if (!(temp & EPSTAT_STALL)) | 308 | if (!(temp & EPSTAT_STALL)) |
301 | break; | 309 | break; |
302 | udelay(20); | 310 | udelay(20); |
303 | } | 311 | } |
304 | if (i == 50) | 312 | if (i == 100) |
305 | D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n", | 313 | D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n", |
306 | __func__, imx_ep->ep.name); | 314 | __func__, imx_ep->ep.name); |
307 | } | 315 | } |
@@ -325,7 +333,8 @@ static int imx_udc_wakeup(struct usb_gadget *_gadget) | |||
325 | ******************************************************************************* | 333 | ******************************************************************************* |
326 | */ | 334 | */ |
327 | 335 | ||
328 | static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req) | 336 | static void ep_add_request(struct imx_ep_struct *imx_ep, |
337 | struct imx_request *req) | ||
329 | { | 338 | { |
330 | if (unlikely(!req)) | 339 | if (unlikely(!req)) |
331 | return; | 340 | return; |
@@ -334,7 +343,8 @@ static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req | |||
334 | list_add_tail(&req->queue, &imx_ep->queue); | 343 | list_add_tail(&req->queue, &imx_ep->queue); |
335 | } | 344 | } |
336 | 345 | ||
337 | static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req) | 346 | static void ep_del_request(struct imx_ep_struct *imx_ep, |
347 | struct imx_request *req) | ||
338 | { | 348 | { |
339 | if (unlikely(!req)) | 349 | if (unlikely(!req)) |
340 | return; | 350 | return; |
@@ -343,7 +353,8 @@ static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req | |||
343 | req->in_use = 0; | 353 | req->in_use = 0; |
344 | } | 354 | } |
345 | 355 | ||
346 | static void done(struct imx_ep_struct *imx_ep, struct imx_request *req, int status) | 356 | static void done(struct imx_ep_struct *imx_ep, |
357 | struct imx_request *req, int status) | ||
347 | { | 358 | { |
348 | ep_del_request(imx_ep, req); | 359 | ep_del_request(imx_ep, req); |
349 | 360 | ||
@@ -494,7 +505,8 @@ static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req) | |||
494 | __func__, imx_ep->ep.name, req, | 505 | __func__, imx_ep->ep.name, req, |
495 | completed ? "completed" : "not completed"); | 506 | completed ? "completed" : "not completed"); |
496 | if (!EP_NO(imx_ep)) | 507 | if (!EP_NO(imx_ep)) |
497 | ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE); | 508 | ep0_chg_stat(__func__, |
509 | imx_ep->imx_usb, EP0_IDLE); | ||
498 | } | 510 | } |
499 | } | 511 | } |
500 | 512 | ||
@@ -539,10 +551,9 @@ static int handle_ep0(struct imx_ep_struct *imx_ep) | |||
539 | struct imx_request *req = NULL; | 551 | struct imx_request *req = NULL; |
540 | int ret = 0; | 552 | int ret = 0; |
541 | 553 | ||
542 | if (!list_empty(&imx_ep->queue)) | 554 | if (!list_empty(&imx_ep->queue)) { |
543 | req = list_entry(imx_ep->queue.next, struct imx_request, queue); | 555 | req = list_entry(imx_ep->queue.next, struct imx_request, queue); |
544 | 556 | ||
545 | if (req) { | ||
546 | switch (imx_ep->imx_usb->ep0state) { | 557 | switch (imx_ep->imx_usb->ep0state) { |
547 | 558 | ||
548 | case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR */ | 559 | case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR */ |
@@ -561,6 +572,10 @@ static int handle_ep0(struct imx_ep_struct *imx_ep) | |||
561 | } | 572 | } |
562 | } | 573 | } |
563 | 574 | ||
575 | else | ||
576 | D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n", | ||
577 | __func__, imx_ep->ep.name); | ||
578 | |||
564 | return ret; | 579 | return ret; |
565 | } | 580 | } |
566 | 581 | ||
@@ -583,7 +598,8 @@ static void handle_ep0_devreq(struct imx_udc_struct *imx_usb) | |||
583 | "<%s> no setup packet received\n", __func__); | 598 | "<%s> no setup packet received\n", __func__); |
584 | goto stall; | 599 | goto stall; |
585 | } | 600 | } |
586 | u.word[i] = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep))); | 601 | u.word[i] = __raw_readl(imx_usb->base |
602 | + USB_EP_FDAT(EP_NO(imx_ep))); | ||
587 | } | 603 | } |
588 | 604 | ||
589 | temp = imx_ep_empty(imx_ep); | 605 | temp = imx_ep_empty(imx_ep); |
@@ -759,7 +775,7 @@ static int imx_ep_queue | |||
759 | */ | 775 | */ |
760 | if (imx_usb->set_config && !EP_NO(imx_ep)) { | 776 | if (imx_usb->set_config && !EP_NO(imx_ep)) { |
761 | imx_usb->set_config = 0; | 777 | imx_usb->set_config = 0; |
762 | D_EPX(imx_usb->dev, | 778 | D_ERR(imx_usb->dev, |
763 | "<%s> gadget reply set config\n", __func__); | 779 | "<%s> gadget reply set config\n", __func__); |
764 | return 0; | 780 | return 0; |
765 | } | 781 | } |
@@ -779,28 +795,29 @@ static int imx_ep_queue | |||
779 | return -ESHUTDOWN; | 795 | return -ESHUTDOWN; |
780 | } | 796 | } |
781 | 797 | ||
782 | local_irq_save(flags); | ||
783 | |||
784 | /* Debug */ | 798 | /* Debug */ |
785 | D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n", | 799 | D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n", |
786 | __func__, EP_NO(imx_ep), | 800 | __func__, EP_NO(imx_ep), |
787 | ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) | 801 | ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state |
788 | || (EP_NO(imx_ep) && EP_DIR(imx_ep))) ? "IN" : "OUT", usb_req->length); | 802 | == EP0_IN_DATA_PHASE) |
803 | || (EP_NO(imx_ep) && EP_DIR(imx_ep))) | ||
804 | ? "IN" : "OUT", usb_req->length); | ||
789 | dump_req(__func__, imx_ep, usb_req); | 805 | dump_req(__func__, imx_ep, usb_req); |
790 | 806 | ||
791 | if (imx_ep->stopped) { | 807 | if (imx_ep->stopped) { |
792 | usb_req->status = -ESHUTDOWN; | 808 | usb_req->status = -ESHUTDOWN; |
793 | ret = -ESHUTDOWN; | 809 | return -ESHUTDOWN; |
794 | goto out; | ||
795 | } | 810 | } |
796 | 811 | ||
797 | if (req->in_use) { | 812 | if (req->in_use) { |
798 | D_ERR(imx_usb->dev, | 813 | D_ERR(imx_usb->dev, |
799 | "<%s> refusing to queue req %p (already queued)\n", | 814 | "<%s> refusing to queue req %p (already queued)\n", |
800 | __func__, req); | 815 | __func__, req); |
801 | goto out; | 816 | return 0; |
802 | } | 817 | } |
803 | 818 | ||
819 | local_irq_save(flags); | ||
820 | |||
804 | usb_req->status = -EINPROGRESS; | 821 | usb_req->status = -EINPROGRESS; |
805 | usb_req->actual = 0; | 822 | usb_req->actual = 0; |
806 | 823 | ||
@@ -810,7 +827,7 @@ static int imx_ep_queue | |||
810 | ret = handle_ep0(imx_ep); | 827 | ret = handle_ep0(imx_ep); |
811 | else | 828 | else |
812 | ret = handle_ep(imx_ep); | 829 | ret = handle_ep(imx_ep); |
813 | out: | 830 | |
814 | local_irq_restore(flags); | 831 | local_irq_restore(flags); |
815 | return ret; | 832 | return ret; |
816 | } | 833 | } |
@@ -997,71 +1014,32 @@ static void udc_stop_activity(struct imx_udc_struct *imx_usb, | |||
997 | ******************************************************************************* | 1014 | ******************************************************************************* |
998 | */ | 1015 | */ |
999 | 1016 | ||
1000 | static irqreturn_t imx_udc_irq(int irq, void *dev) | 1017 | /* |
1018 | * Called when timer expires. | ||
1019 | * Timer is started when CFG_CHG is received. | ||
1020 | */ | ||
1021 | static void handle_config(unsigned long data) | ||
1001 | { | 1022 | { |
1002 | struct imx_udc_struct *imx_usb = dev; | 1023 | struct imx_udc_struct *imx_usb = (void *)data; |
1003 | struct usb_ctrlrequest u; | 1024 | struct usb_ctrlrequest u; |
1004 | int temp, cfg, intf, alt; | 1025 | int temp, cfg, intf, alt; |
1005 | int intr = __raw_readl(imx_usb->base + USB_INTR); | ||
1006 | 1026 | ||
1007 | if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START | 1027 | local_irq_disable(); |
1008 | | INTR_RESET_STOP | INTR_CFG_CHG)) { | ||
1009 | dump_intr(__func__, intr, imx_usb->dev); | ||
1010 | dump_usb_stat(__func__, imx_usb); | ||
1011 | } | ||
1012 | 1028 | ||
1013 | if (!imx_usb->driver) { | 1029 | temp = __raw_readl(imx_usb->base + USB_STAT); |
1014 | /*imx_udc_disable(imx_usb);*/ | 1030 | cfg = (temp & STAT_CFG) >> 5; |
1015 | goto end_irq; | 1031 | intf = (temp & STAT_INTF) >> 3; |
1016 | } | 1032 | alt = temp & STAT_ALTSET; |
1017 | 1033 | ||
1018 | if (intr & INTR_WAKEUP) { | 1034 | D_REQ(imx_usb->dev, |
1019 | if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN | 1035 | "<%s> orig config C=%d, I=%d, A=%d / " |
1020 | && imx_usb->driver && imx_usb->driver->resume) | 1036 | "req config C=%d, I=%d, A=%d\n", |
1021 | imx_usb->driver->resume(&imx_usb->gadget); | 1037 | __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt, |
1022 | imx_usb->set_config = 0; | 1038 | cfg, intf, alt); |
1023 | imx_usb->gadget.speed = USB_SPEED_FULL; | ||
1024 | } | ||
1025 | |||
1026 | if (intr & INTR_SUSPEND) { | ||
1027 | if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN | ||
1028 | && imx_usb->driver && imx_usb->driver->suspend) | ||
1029 | imx_usb->driver->suspend(&imx_usb->gadget); | ||
1030 | imx_usb->set_config = 0; | ||
1031 | imx_usb->gadget.speed = USB_SPEED_UNKNOWN; | ||
1032 | } | ||
1033 | |||
1034 | if (intr & INTR_RESET_START) { | ||
1035 | __raw_writel(intr, imx_usb->base + USB_INTR); | ||
1036 | udc_stop_activity(imx_usb, imx_usb->driver); | ||
1037 | imx_usb->set_config = 0; | ||
1038 | imx_usb->gadget.speed = USB_SPEED_UNKNOWN; | ||
1039 | } | ||
1040 | 1039 | ||
1041 | if (intr & INTR_RESET_STOP) | 1040 | if (cfg == 1 || cfg == 2) { |
1042 | imx_usb->gadget.speed = USB_SPEED_FULL; | ||
1043 | 1041 | ||
1044 | if (intr & INTR_CFG_CHG) { | ||
1045 | __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR); | ||
1046 | temp = __raw_readl(imx_usb->base + USB_STAT); | ||
1047 | cfg = (temp & STAT_CFG) >> 5; | ||
1048 | intf = (temp & STAT_INTF) >> 3; | ||
1049 | alt = temp & STAT_ALTSET; | ||
1050 | |||
1051 | D_REQ(imx_usb->dev, | ||
1052 | "<%s> orig config C=%d, I=%d, A=%d / " | ||
1053 | "req config C=%d, I=%d, A=%d\n", | ||
1054 | __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt, | ||
1055 | cfg, intf, alt); | ||
1056 | |||
1057 | if (cfg != 1 && cfg != 2) | ||
1058 | goto end_irq; | ||
1059 | |||
1060 | imx_usb->set_config = 0; | ||
1061 | |||
1062 | /* Config setup */ | ||
1063 | if (imx_usb->cfg != cfg) { | 1042 | if (imx_usb->cfg != cfg) { |
1064 | D_REQ(imx_usb->dev, "<%s> Change config start\n",__func__); | ||
1065 | u.bRequest = USB_REQ_SET_CONFIGURATION; | 1043 | u.bRequest = USB_REQ_SET_CONFIGURATION; |
1066 | u.bRequestType = USB_DIR_OUT | | 1044 | u.bRequestType = USB_DIR_OUT | |
1067 | USB_TYPE_STANDARD | | 1045 | USB_TYPE_STANDARD | |
@@ -1070,14 +1048,10 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) | |||
1070 | u.wIndex = 0; | 1048 | u.wIndex = 0; |
1071 | u.wLength = 0; | 1049 | u.wLength = 0; |
1072 | imx_usb->cfg = cfg; | 1050 | imx_usb->cfg = cfg; |
1073 | imx_usb->set_config = 1; | ||
1074 | imx_usb->driver->setup(&imx_usb->gadget, &u); | 1051 | imx_usb->driver->setup(&imx_usb->gadget, &u); |
1075 | imx_usb->set_config = 0; | ||
1076 | D_REQ(imx_usb->dev, "<%s> Change config done\n",__func__); | ||
1077 | 1052 | ||
1078 | } | 1053 | } |
1079 | if (imx_usb->intf != intf || imx_usb->alt != alt) { | 1054 | if (imx_usb->intf != intf || imx_usb->alt != alt) { |
1080 | D_REQ(imx_usb->dev, "<%s> Change interface start\n",__func__); | ||
1081 | u.bRequest = USB_REQ_SET_INTERFACE; | 1055 | u.bRequest = USB_REQ_SET_INTERFACE; |
1082 | u.bRequestType = USB_DIR_OUT | | 1056 | u.bRequestType = USB_DIR_OUT | |
1083 | USB_TYPE_STANDARD | | 1057 | USB_TYPE_STANDARD | |
@@ -1087,20 +1061,92 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) | |||
1087 | u.wLength = 0; | 1061 | u.wLength = 0; |
1088 | imx_usb->intf = intf; | 1062 | imx_usb->intf = intf; |
1089 | imx_usb->alt = alt; | 1063 | imx_usb->alt = alt; |
1090 | imx_usb->set_config = 1; | ||
1091 | imx_usb->driver->setup(&imx_usb->gadget, &u); | 1064 | imx_usb->driver->setup(&imx_usb->gadget, &u); |
1092 | imx_usb->set_config = 0; | ||
1093 | D_REQ(imx_usb->dev, "<%s> Change interface done\n",__func__); | ||
1094 | } | 1065 | } |
1095 | } | 1066 | } |
1096 | 1067 | ||
1068 | imx_usb->set_config = 0; | ||
1069 | |||
1070 | local_irq_enable(); | ||
1071 | } | ||
1072 | |||
1073 | static irqreturn_t imx_udc_irq(int irq, void *dev) | ||
1074 | { | ||
1075 | struct imx_udc_struct *imx_usb = dev; | ||
1076 | int intr = __raw_readl(imx_usb->base + USB_INTR); | ||
1077 | int temp; | ||
1078 | |||
1079 | if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START | ||
1080 | | INTR_RESET_STOP | INTR_CFG_CHG)) { | ||
1081 | dump_intr(__func__, intr, imx_usb->dev); | ||
1082 | dump_usb_stat(__func__, imx_usb); | ||
1083 | } | ||
1084 | |||
1085 | if (!imx_usb->driver) | ||
1086 | goto end_irq; | ||
1087 | |||
1097 | if (intr & INTR_SOF) { | 1088 | if (intr & INTR_SOF) { |
1089 | /* Copy from Freescale BSP. | ||
1090 | We must enable SOF intr and set CMDOVER. | ||
1091 | Datasheet don't specifiy this action, but it | ||
1092 | is done in Freescale BSP, so just copy it. | ||
1093 | */ | ||
1098 | if (imx_usb->ep0state == EP0_IDLE) { | 1094 | if (imx_usb->ep0state == EP0_IDLE) { |
1099 | temp = __raw_readl(imx_usb->base + USB_CTRL); | 1095 | temp = __raw_readl(imx_usb->base + USB_CTRL); |
1100 | __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); | 1096 | __raw_writel(temp | CTRL_CMDOVER, |
1097 | imx_usb->base + USB_CTRL); | ||
1101 | } | 1098 | } |
1102 | } | 1099 | } |
1103 | 1100 | ||
1101 | if (intr & INTR_CFG_CHG) { | ||
1102 | /* A workaround of serious IMX UDC bug. | ||
1103 | Handling of CFG_CHG should be delayed for some time, because | ||
1104 | IMX does not NACK the host when CFG_CHG interrupt is pending. | ||
1105 | There is no time to handle current CFG_CHG | ||
1106 | if next CFG_CHG or SETUP packed is send immediately. | ||
1107 | We have to clear CFG_CHG, start the timer and | ||
1108 | NACK the host by setting CTRL_CMDOVER | ||
1109 | if it sends any SETUP packet. | ||
1110 | When timer expires, handler is called to handle configuration | ||
1111 | changes. While CFG_CHG is not handled (set_config=1), | ||
1112 | we must NACK the host to every SETUP packed. | ||
1113 | This delay prevents from going out of sync with host. | ||
1114 | */ | ||
1115 | __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR); | ||
1116 | imx_usb->set_config = 1; | ||
1117 | mod_timer(&imx_usb->timer, jiffies + 5); | ||
1118 | goto end_irq; | ||
1119 | } | ||
1120 | |||
1121 | if (intr & INTR_WAKEUP) { | ||
1122 | if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN | ||
1123 | && imx_usb->driver && imx_usb->driver->resume) | ||
1124 | imx_usb->driver->resume(&imx_usb->gadget); | ||
1125 | imx_usb->set_config = 0; | ||
1126 | del_timer(&imx_usb->timer); | ||
1127 | imx_usb->gadget.speed = USB_SPEED_FULL; | ||
1128 | } | ||
1129 | |||
1130 | if (intr & INTR_SUSPEND) { | ||
1131 | if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN | ||
1132 | && imx_usb->driver && imx_usb->driver->suspend) | ||
1133 | imx_usb->driver->suspend(&imx_usb->gadget); | ||
1134 | imx_usb->set_config = 0; | ||
1135 | del_timer(&imx_usb->timer); | ||
1136 | imx_usb->gadget.speed = USB_SPEED_UNKNOWN; | ||
1137 | } | ||
1138 | |||
1139 | if (intr & INTR_RESET_START) { | ||
1140 | __raw_writel(intr, imx_usb->base + USB_INTR); | ||
1141 | udc_stop_activity(imx_usb, imx_usb->driver); | ||
1142 | imx_usb->set_config = 0; | ||
1143 | del_timer(&imx_usb->timer); | ||
1144 | imx_usb->gadget.speed = USB_SPEED_UNKNOWN; | ||
1145 | } | ||
1146 | |||
1147 | if (intr & INTR_RESET_STOP) | ||
1148 | imx_usb->gadget.speed = USB_SPEED_FULL; | ||
1149 | |||
1104 | end_irq: | 1150 | end_irq: |
1105 | __raw_writel(intr, imx_usb->base + USB_INTR); | 1151 | __raw_writel(intr, imx_usb->base + USB_INTR); |
1106 | return IRQ_HANDLED; | 1152 | return IRQ_HANDLED; |
@@ -1109,6 +1155,7 @@ end_irq: | |||
1109 | static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) | 1155 | static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) |
1110 | { | 1156 | { |
1111 | struct imx_udc_struct *imx_usb = dev; | 1157 | struct imx_udc_struct *imx_usb = dev; |
1158 | struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0]; | ||
1112 | int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0)); | 1159 | int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0)); |
1113 | 1160 | ||
1114 | dump_ep_intr(__func__, 0, intr, imx_usb->dev); | 1161 | dump_ep_intr(__func__, 0, intr, imx_usb->dev); |
@@ -1118,16 +1165,15 @@ static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) | |||
1118 | return IRQ_HANDLED; | 1165 | return IRQ_HANDLED; |
1119 | } | 1166 | } |
1120 | 1167 | ||
1121 | /* DEVREQ IRQ has highest priority */ | 1168 | /* DEVREQ has highest priority */ |
1122 | if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ)) | 1169 | if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ)) |
1123 | handle_ep0_devreq(imx_usb); | 1170 | handle_ep0_devreq(imx_usb); |
1124 | /* Seem i.MX is missing EOF interrupt sometimes. | 1171 | /* Seem i.MX is missing EOF interrupt sometimes. |
1125 | * Therefore we monitor both EOF and FIFO_EMPTY interrups | 1172 | * Therefore we don't monitor EOF. |
1126 | * when transmiting, and both EOF and FIFO_FULL when | 1173 | * We call handle_ep0() only if a request is queued for ep0. |
1127 | * receiving data. | ||
1128 | */ | 1174 | */ |
1129 | else if (intr & (EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL)) | 1175 | else if (!list_empty(&imx_ep->queue)) |
1130 | handle_ep0(&imx_usb->imx_ep[0]); | 1176 | handle_ep0(imx_ep); |
1131 | 1177 | ||
1132 | __raw_writel(intr, imx_usb->base + USB_EP_INTR(0)); | 1178 | __raw_writel(intr, imx_usb->base + USB_EP_INTR(0)); |
1133 | 1179 | ||
@@ -1186,8 +1232,8 @@ static struct imx_udc_struct controller = { | |||
1186 | .ep0 = &controller.imx_ep[0].ep, | 1232 | .ep0 = &controller.imx_ep[0].ep, |
1187 | .name = driver_name, | 1233 | .name = driver_name, |
1188 | .dev = { | 1234 | .dev = { |
1189 | .bus_id = "gadget", | 1235 | .init_name = "gadget", |
1190 | }, | 1236 | }, |
1191 | }, | 1237 | }, |
1192 | 1238 | ||
1193 | .imx_ep[0] = { | 1239 | .imx_ep[0] = { |
@@ -1318,6 +1364,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1318 | 1364 | ||
1319 | udc_stop_activity(imx_usb, driver); | 1365 | udc_stop_activity(imx_usb, driver); |
1320 | imx_udc_disable(imx_usb); | 1366 | imx_udc_disable(imx_usb); |
1367 | del_timer(&imx_usb->timer); | ||
1321 | 1368 | ||
1322 | driver->unbind(&imx_usb->gadget); | 1369 | driver->unbind(&imx_usb->gadget); |
1323 | imx_usb->gadget.dev.driver = NULL; | 1370 | imx_usb->gadget.dev.driver = NULL; |
@@ -1435,6 +1482,10 @@ static int __init imx_udc_probe(struct platform_device *pdev) | |||
1435 | usb_init_data(imx_usb); | 1482 | usb_init_data(imx_usb); |
1436 | imx_udc_init(imx_usb); | 1483 | imx_udc_init(imx_usb); |
1437 | 1484 | ||
1485 | init_timer(&imx_usb->timer); | ||
1486 | imx_usb->timer.function = handle_config; | ||
1487 | imx_usb->timer.data = (unsigned long)imx_usb; | ||
1488 | |||
1438 | return 0; | 1489 | return 0; |
1439 | 1490 | ||
1440 | fail3: | 1491 | fail3: |
@@ -1457,6 +1508,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev) | |||
1457 | int i; | 1508 | int i; |
1458 | 1509 | ||
1459 | imx_udc_disable(imx_usb); | 1510 | imx_udc_disable(imx_usb); |
1511 | del_timer(&imx_usb->timer); | ||
1460 | 1512 | ||
1461 | for (i = 0; i < IMX_USB_NB_EP + 1; i++) | 1513 | for (i = 0; i < IMX_USB_NB_EP + 1; i++) |
1462 | free_irq(imx_usb->usbd_int[i], imx_usb); | 1514 | free_irq(imx_usb->usbd_int[i], imx_usb); |