[Armadeus-commitlog] SF.net SVN: armadeus:[1284] trunk/buildroot/target/device/armadeus/linux/ kern
Brought to you by:
sszy
|
From: <ar...@us...> - 2009-05-18 14:59:44
|
Revision: 1284
http://armadeus.svn.sourceforge.net/armadeus/?rev=1284&view=rev
Author: artemys
Date: 2009-05-18 14:59:43 +0000 (Mon, 18 May 2009)
Log Message:
-----------
[LINUX] Add some 2.6.20 UDC fixes on 2.6.29
Added Paths:
-----------
trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/033-darius-imx_udc-fix_imx_udc_gadget_bugs.patch
trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/034-darius-imx_udc-fix_imx_udc_gadget_code_style.patch
trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/035-darius-imx_udc-fix_imx_udc_gadget_ep0_irq_handling.patch
trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/036-darius-imx_udc-fix_imx_udc_gadget_general_irq_handling.patch
Added: trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/033-darius-imx_udc-fix_imx_udc_gadget_bugs.patch
===================================================================
--- trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/033-darius-imx_udc-fix_imx_udc_gadget_bugs.patch (rev 0)
+++ trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/033-darius-imx_udc-fix_imx_udc_gadget_bugs.patch 2009-05-18 14:59:43 UTC (rev 1284)
@@ -0,0 +1,145 @@
+From: Darius Augulis <aug...@gm...>
+Date: Wed, 21 Jan 2009 13:17:25 +0000 (+0200)
+Subject: USB: imx_udc: Fix IMX UDC gadget bugs
+X-Git-Tag: v2.6.30-rc1~670^2~81
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=8f182e5ddc84a30d7014a753ae359d85b1238e7f
+
+USB: imx_udc: Fix IMX UDC gadget bugs
+
+Fix small bugs and add some omptimization in IMX UDC Gadget.
+
+Signed-off-by: Darius Augulis <aug...@gm...>
+Signed-off-by: Greg Kroah-Hartman <gr...@su...>
+---
+
+diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
+index 77c5d0a..9e3fe30 100644
+--- a/drivers/usb/gadget/imx_udc.c
++++ b/drivers/usb/gadget/imx_udc.c
+@@ -283,7 +283,7 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep)
+ imx_flush(imx_ep);
+
+ /* Special care for ep0 */
+- if (EP_NO(imx_ep)) {
++ if (!EP_NO(imx_ep)) {
+ temp = __raw_readl(imx_usb->base + USB_CTRL);
+ __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL);
+ do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER);
+@@ -301,7 +301,7 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep)
+ break;
+ udelay(20);
+ }
+- if (i == 50)
++ if (i == 100)
+ D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n",
+ __func__, imx_ep->ep.name);
+ }
+@@ -539,10 +539,9 @@ static int handle_ep0(struct imx_ep_struct *imx_ep)
+ struct imx_request *req = NULL;
+ int ret = 0;
+
+- if (!list_empty(&imx_ep->queue))
++ if (!list_empty(&imx_ep->queue)) {
+ req = list_entry(imx_ep->queue.next, struct imx_request, queue);
+
+- if (req) {
+ switch (imx_ep->imx_usb->ep0state) {
+
+ case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR */
+@@ -561,6 +560,10 @@ static int handle_ep0(struct imx_ep_struct *imx_ep)
+ }
+ }
+
++ else
++ D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n",
++ __func__, imx_ep->ep.name);
++
+ return ret;
+ }
+
+@@ -759,7 +762,7 @@ static int imx_ep_queue
+ */
+ if (imx_usb->set_config && !EP_NO(imx_ep)) {
+ imx_usb->set_config = 0;
+- D_EPX(imx_usb->dev,
++ D_ERR(imx_usb->dev,
+ "<%s> gadget reply set config\n", __func__);
+ return 0;
+ }
+@@ -779,8 +782,6 @@ static int imx_ep_queue
+ return -ESHUTDOWN;
+ }
+
+- local_irq_save(flags);
+-
+ /* Debug */
+ D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n",
+ __func__, EP_NO(imx_ep),
+@@ -790,17 +791,18 @@ static int imx_ep_queue
+
+ if (imx_ep->stopped) {
+ usb_req->status = -ESHUTDOWN;
+- ret = -ESHUTDOWN;
+- goto out;
++ return -ESHUTDOWN;
+ }
+
+ if (req->in_use) {
+ D_ERR(imx_usb->dev,
+ "<%s> refusing to queue req %p (already queued)\n",
+ __func__, req);
+- goto out;
++ return 0;
+ }
+
++ local_irq_save(flags);
++
+ usb_req->status = -EINPROGRESS;
+ usb_req->actual = 0;
+
+@@ -810,7 +812,7 @@ static int imx_ep_queue
+ ret = handle_ep0(imx_ep);
+ else
+ ret = handle_ep(imx_ep);
+-out:
++
+ local_irq_restore(flags);
+ return ret;
+ }
+@@ -1010,10 +1012,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
+ dump_usb_stat(__func__, imx_usb);
+ }
+
+- if (!imx_usb->driver) {
+- /*imx_udc_disable(imx_usb);*/
++ if (!imx_usb->driver)
+ goto end_irq;
+- }
+
+ if (intr & INTR_WAKEUP) {
+ if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
+@@ -1095,6 +1095,11 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
+ }
+
+ if (intr & INTR_SOF) {
++ /* Copy from Freescale BSP.
++ We must enable SOF intr and set CMDOVER.
++ Datasheet don't specifiy this action, but it
++ is done in Freescale BSP, so just copy it.
++ */
+ if (imx_usb->ep0state == EP0_IDLE) {
+ temp = __raw_readl(imx_usb->base + USB_CTRL);
+ __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL);
+diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h
+index 8500769..d1dfb2d 100644
+--- a/drivers/usb/gadget/imx_udc.h
++++ b/drivers/usb/gadget/imx_udc.h
+@@ -170,7 +170,7 @@ struct imx_udc_struct {
+ /* #define DEBUG_IRQ */
+ /* #define DEBUG_EPIRQ */
+ /* #define DEBUG_DUMP */
+-#define DEBUG_ERR
++/* #define DEBUG_ERR */
+
+ #ifdef DEBUG_REQ
+ #define D_REQ(dev, args...) dev_dbg(dev, ## args)
Added: trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/034-darius-imx_udc-fix_imx_udc_gadget_code_style.patch
===================================================================
--- trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/034-darius-imx_udc-fix_imx_udc_gadget_code_style.patch (rev 0)
+++ trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/034-darius-imx_udc-fix_imx_udc_gadget_code_style.patch 2009-05-18 14:59:43 UTC (rev 1284)
@@ -0,0 +1,317 @@
+From: Darius Augulis <aug...@gm...>
+Date: Wed, 21 Jan 2009 13:17:55 +0000 (+0200)
+Subject: USB: imx_udc: Fix IMX UDC gadget code style
+X-Git-Tag: v2.6.30-rc1~670^2~80
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=593bef6c75e11d2edb5396bd9775cf49a4cda659
+
+USB: imx_udc: Fix IMX UDC gadget code style
+
+Fix code style errors in IMX UDC Gadget.
+
+Signed-off-by: Darius Augulis <aug...@gm...>
+Signed-off-by: Greg Kroah-Hartman <gr...@su...>
+---
+
+diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
+index 9e3fe30..3ee5bd8 100644
+--- a/drivers/usb/gadget/imx_udc.c
++++ b/drivers/usb/gadget/imx_udc.c
+@@ -1,7 +1,7 @@
+ /*
+ * driver/usb/gadget/imx_udc.c
+ *
+- * Copyright (C) 2005 Mike Lee(ee...@gm...)
++ * Copyright (C) 2005 Mike Lee <ee...@gm...>
+ * Copyright (C) 2008 Darius Augulis <aug...@gm...>
+ *
+ * This program is free software; you can redistribute it and/or modify
+@@ -51,7 +51,8 @@ void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb,
+ void imx_udc_enable(struct imx_udc_struct *imx_usb)
+ {
+ int temp = __raw_readl(imx_usb->base + USB_CTRL);
+- __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, imx_usb->base + USB_CTRL);
++ __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA,
++ imx_usb->base + USB_CTRL);
+ imx_usb->gadget.speed = USB_SPEED_FULL;
+ }
+
+@@ -126,7 +127,8 @@ void imx_udc_config(struct imx_udc_struct *imx_usb)
+ for (j = 0; j < 5; j++) {
+ __raw_writeb(ep_conf[j],
+ imx_usb->base + USB_DDAT);
+- do {} while (__raw_readl(imx_usb->base + USB_DADR)
++ do {} while (__raw_readl(imx_usb->base
++ + USB_DADR)
+ & DADR_BSY);
+ }
+ }
+@@ -183,7 +185,8 @@ void imx_udc_init_ep(struct imx_udc_struct *imx_usb)
+ temp = (EP_DIR(imx_ep) << 7) | (max << 5)
+ | (imx_ep->bmAttributes << 3);
+ __raw_writel(temp, imx_usb->base + USB_EP_STAT(i));
+- __raw_writel(temp | EPSTAT_FLUSH, imx_usb->base + USB_EP_STAT(i));
++ __raw_writel(temp | EPSTAT_FLUSH,
++ imx_usb->base + USB_EP_STAT(i));
+ D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i,
+ __raw_readl(imx_usb->base + USB_EP_STAT(i)));
+ }
+@@ -278,15 +281,18 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep)
+ struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
+ int temp, i;
+
+- D_ERR(imx_usb->dev, "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name);
++ D_ERR(imx_usb->dev,
++ "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name);
+
+ imx_flush(imx_ep);
+
+ /* Special care for ep0 */
+ if (!EP_NO(imx_ep)) {
+ temp = __raw_readl(imx_usb->base + USB_CTRL);
+- __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL);
+- do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER);
++ __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR,
++ imx_usb->base + USB_CTRL);
++ do { } while (__raw_readl(imx_usb->base + USB_CTRL)
++ & CTRL_CMDOVER);
+ temp = __raw_readl(imx_usb->base + USB_CTRL);
+ __raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL);
+ }
+@@ -296,7 +302,8 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep)
+ imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
+
+ for (i = 0; i < 100; i ++) {
+- temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
++ temp = __raw_readl(imx_usb->base
++ + USB_EP_STAT(EP_NO(imx_ep)));
+ if (!(temp & EPSTAT_STALL))
+ break;
+ udelay(20);
+@@ -325,7 +332,8 @@ static int imx_udc_wakeup(struct usb_gadget *_gadget)
+ *******************************************************************************
+ */
+
+-static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req)
++static void ep_add_request(struct imx_ep_struct *imx_ep,
++ struct imx_request *req)
+ {
+ if (unlikely(!req))
+ return;
+@@ -334,7 +342,8 @@ static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req
+ list_add_tail(&req->queue, &imx_ep->queue);
+ }
+
+-static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req)
++static void ep_del_request(struct imx_ep_struct *imx_ep,
++ struct imx_request *req)
+ {
+ if (unlikely(!req))
+ return;
+@@ -343,7 +352,8 @@ static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req
+ req->in_use = 0;
+ }
+
+-static void done(struct imx_ep_struct *imx_ep, struct imx_request *req, int status)
++static void done(struct imx_ep_struct *imx_ep,
++ struct imx_request *req, int status)
+ {
+ ep_del_request(imx_ep, req);
+
+@@ -494,7 +504,8 @@ static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req)
+ __func__, imx_ep->ep.name, req,
+ completed ? "completed" : "not completed");
+ if (!EP_NO(imx_ep))
+- ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE);
++ ep0_chg_stat(__func__,
++ imx_ep->imx_usb, EP0_IDLE);
+ }
+ }
+
+@@ -586,7 +597,8 @@ static void handle_ep0_devreq(struct imx_udc_struct *imx_usb)
+ "<%s> no setup packet received\n", __func__);
+ goto stall;
+ }
+- u.word[i] = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep)));
++ u.word[i] = __raw_readl(imx_usb->base
++ + USB_EP_FDAT(EP_NO(imx_ep)));
+ }
+
+ temp = imx_ep_empty(imx_ep);
+@@ -785,8 +797,10 @@ static int imx_ep_queue
+ /* Debug */
+ D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n",
+ __func__, EP_NO(imx_ep),
+- ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE)
+- || (EP_NO(imx_ep) && EP_DIR(imx_ep))) ? "IN" : "OUT", usb_req->length);
++ ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
++ == EP0_IN_DATA_PHASE)
++ || (EP_NO(imx_ep) && EP_DIR(imx_ep)))
++ ? "IN" : "OUT", usb_req->length);
+ dump_req(__func__, imx_ep, usb_req);
+
+ if (imx_ep->stopped) {
+@@ -1061,7 +1075,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
+
+ /* Config setup */
+ if (imx_usb->cfg != cfg) {
+- D_REQ(imx_usb->dev, "<%s> Change config start\n",__func__);
++ D_REQ(imx_usb->dev,
++ "<%s> Change config start\n", __func__);
+ u.bRequest = USB_REQ_SET_CONFIGURATION;
+ u.bRequestType = USB_DIR_OUT |
+ USB_TYPE_STANDARD |
+@@ -1073,11 +1088,13 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
+ imx_usb->set_config = 1;
+ imx_usb->driver->setup(&imx_usb->gadget, &u);
+ imx_usb->set_config = 0;
+- D_REQ(imx_usb->dev, "<%s> Change config done\n",__func__);
++ D_REQ(imx_usb->dev,
++ "<%s> Change config done\n", __func__);
+
+ }
+ if (imx_usb->intf != intf || imx_usb->alt != alt) {
+- D_REQ(imx_usb->dev, "<%s> Change interface start\n",__func__);
++ D_REQ(imx_usb->dev,
++ "<%s> Change interface start\n", __func__);
+ u.bRequest = USB_REQ_SET_INTERFACE;
+ u.bRequestType = USB_DIR_OUT |
+ USB_TYPE_STANDARD |
+@@ -1090,7 +1107,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
+ imx_usb->set_config = 1;
+ imx_usb->driver->setup(&imx_usb->gadget, &u);
+ imx_usb->set_config = 0;
+- D_REQ(imx_usb->dev, "<%s> Change interface done\n",__func__);
++ D_REQ(imx_usb->dev,
++ "<%s> Change interface done\n", __func__);
+ }
+ }
+
+@@ -1102,7 +1120,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
+ */
+ if (imx_usb->ep0state == EP0_IDLE) {
+ temp = __raw_readl(imx_usb->base + USB_CTRL);
+- __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL);
++ __raw_writel(temp | CTRL_CMDOVER,
++ imx_usb->base + USB_CTRL);
+ }
+ }
+
+diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h
+index d1dfb2d..6b0b1e3 100644
+--- a/drivers/usb/gadget/imx_udc.h
++++ b/drivers/usb/gadget/imx_udc.h
+@@ -23,7 +23,8 @@
+ /* Helper macros */
+ #define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */
+ #define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0)
+-#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/
++#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) \
++ ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/
+ #define ep_to_irq(ep) (EP_NO((ep)) + USBD_INT0)
+ #define IMX_USB_NB_EP 6
+
+@@ -88,8 +89,8 @@ struct imx_udc_struct {
+ #define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */
+ #define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */
+ #define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */
+-#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last read frame pointer */
+-#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last write frame pointer */
++#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last rd f. pointer */
++#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last wr f. pointer */
+ #define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */
+ #define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */
+ #define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */
+@@ -228,7 +229,8 @@ struct imx_udc_struct {
+ #endif /* DEBUG_IRQ */
+
+ #ifdef DEBUG_EPIRQ
+- static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev)
++ static void dump_ep_intr(const char *label, int nr, int irqreg,
++ struct device *dev)
+ {
+ dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr,
+ (irqreg & EPINTR_FIFO_FULL) ? " full" : "",
+@@ -246,7 +248,8 @@ struct imx_udc_struct {
+ #endif /* DEBUG_IRQ */
+
+ #ifdef DEBUG_DUMP
+- static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb)
++ static void dump_usb_stat(const char *label,
++ struct imx_udc_struct *imx_usb)
+ {
+ int temp = __raw_readl(imx_usb->base + USB_STAT);
+
+@@ -259,12 +262,15 @@ struct imx_udc_struct {
+ (temp & STAT_ALTSET));
+ }
+
+- static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep)
++ static void dump_ep_stat(const char *label,
++ struct imx_ep_struct *imx_ep)
+ {
+- int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
++ int temp = __raw_readl(imx_ep->imx_usb->base
++ + USB_EP_INTR(EP_NO(imx_ep)));
+
+ dev_dbg(imx_ep->imx_usb->dev,
+- "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep),
++ "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n",
++ label, EP_NO(imx_ep),
+ (temp & EPINTR_FIFO_FULL) ? " full" : "",
+ (temp & EPINTR_FIFO_EMPTY) ? " fempty" : "",
+ (temp & EPINTR_FIFO_ERROR) ? " ferr" : "",
+@@ -275,18 +281,22 @@ struct imx_udc_struct {
+ (temp & EPINTR_DEVREQ) ? " devreq" : "",
+ (temp & EPINTR_EOT) ? " eot" : "");
+
+- temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
++ temp = __raw_readl(imx_ep->imx_usb->base
++ + USB_EP_STAT(EP_NO(imx_ep)));
+
+ dev_dbg(imx_ep->imx_usb->dev,
+- "<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep),
++ "<%s> EP%d_STAT=[%s%s bcount=%d]\n",
++ label, EP_NO(imx_ep),
+ (temp & EPSTAT_SIP) ? " sip" : "",
+ (temp & EPSTAT_STALL) ? " stall" : "",
+ (temp & EPSTAT_BCOUNT) >> 16);
+
+- temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep)));
++ temp = __raw_readl(imx_ep->imx_usb->base
++ + USB_EP_FSTAT(EP_NO(imx_ep)));
+
+ dev_dbg(imx_ep->imx_usb->dev,
+- "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep),
++ "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n",
++ label, EP_NO(imx_ep),
+ (temp & FSTAT_ERR) ? " ferr" : "",
+ (temp & FSTAT_UF) ? " funder" : "",
+ (temp & FSTAT_OF) ? " fover" : "",
+@@ -296,19 +306,23 @@ struct imx_udc_struct {
+ (temp & FSTAT_EMPTY) ? " fempty" : "");
+ }
+
+- static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req)
++ static void dump_req(const char *label, struct imx_ep_struct *imx_ep,
++ struct usb_request *req)
+ {
+ int i;
+
+ if (!req || !req->buf) {
+- dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label);
++ dev_dbg(imx_ep->imx_usb->dev,
++ "<%s> req or req buf is free\n", label);
+ return;
+ }
+
+- if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE)
++ if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
++ == EP0_IN_DATA_PHASE)
+ || (EP_NO(imx_ep) && EP_DIR(imx_ep))) {
+
+- dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label);
++ dev_dbg(imx_ep->imx_usb->dev,
++ "<%s> request dump <", label);
+ for (i = 0; i < req->length; i++)
+ printk("%02x-", *((u8 *)req->buf + i));
+ printk(">\n");
Added: trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/035-darius-imx_udc-fix_imx_udc_gadget_ep0_irq_handling.patch
===================================================================
--- trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/035-darius-imx_udc-fix_imx_udc_gadget_ep0_irq_handling.patch (rev 0)
+++ trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/035-darius-imx_udc-fix_imx_udc_gadget_ep0_irq_handling.patch 2009-05-18 14:59:43 UTC (rev 1284)
@@ -0,0 +1,48 @@
+From: Darius Augulis <aug...@gm...>
+Date: Wed, 21 Jan 2009 13:18:33 +0000 (+0200)
+Subject: USB: imx_udc: Fix IMX UDC gadget ep0 irq handling
+X-Git-Tag: v2.6.30-rc1~670^2~79
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=d24921a36df31332c32e1bb539671284d9e36bfa
+
+USB: imx_udc: Fix IMX UDC gadget ep0 irq handling
+
+Fix ep0 interrupt handling in IMX UDC Gadget.
+
+Signed-off-by: Darius Augulis <aug...@gm...>
+Signed-off-by: Greg Kroah-Hartman <gr...@su...>
+---
+
+diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
+index 3ee5bd8..e590464 100644
+--- a/drivers/usb/gadget/imx_udc.c
++++ b/drivers/usb/gadget/imx_udc.c
+@@ -1133,6 +1133,7 @@ end_irq:
+ static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev)
+ {
+ struct imx_udc_struct *imx_usb = dev;
++ struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0];
+ int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0));
+
+ dump_ep_intr(__func__, 0, intr, imx_usb->dev);
+@@ -1142,16 +1143,15 @@ static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev)
+ return IRQ_HANDLED;
+ }
+
+- /* DEVREQ IRQ has highest priority */
++ /* DEVREQ has highest priority */
+ if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ))
+ handle_ep0_devreq(imx_usb);
+ /* Seem i.MX is missing EOF interrupt sometimes.
+- * Therefore we monitor both EOF and FIFO_EMPTY interrups
+- * when transmiting, and both EOF and FIFO_FULL when
+- * receiving data.
++ * Therefore we don't monitor EOF.
++ * We call handle_ep0() only if a request is queued for ep0.
+ */
+- else if (intr & (EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL))
+- handle_ep0(&imx_usb->imx_ep[0]);
++ else if (!list_empty(&imx_ep->queue))
++ handle_ep0(imx_ep);
+
+ __raw_writel(intr, imx_usb->base + USB_EP_INTR(0));
+
Added: trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/036-darius-imx_udc-fix_imx_udc_gadget_general_irq_handling.patch
===================================================================
--- trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/036-darius-imx_udc-fix_imx_udc_gadget_general_irq_handling.patch (rev 0)
+++ trunk/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29/036-darius-imx_udc-fix_imx_udc_gadget_general_irq_handling.patch 2009-05-18 14:59:43 UTC (rev 1284)
@@ -0,0 +1,263 @@
+From: Darius Augulis <aug...@gm...>
+Date: Wed, 21 Jan 2009 13:19:19 +0000 (+0200)
+Subject: USB: imx_udc: Fix IMX UDC gadget general irq handling
+X-Git-Tag: v2.6.30-rc1~670^2~78
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=b633d28e2c5fbe1c8d163892644f57df04aa1421
+
+USB: imx_udc: Fix IMX UDC gadget general irq handling
+
+Workaround of hw bug in IMX UDC.
+This bug causes wrong handling of CFG_CHG interrupt.
+Workaround is documented inline source code.
+
+Signed-off-by: Darius Augulis <aug...@gm...>
+Signed-off-by: Greg Kroah-Hartman <gr...@su...>
+---
+
+diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
+index e590464..8d3c6a9 100644
+--- a/drivers/usb/gadget/imx_udc.c
++++ b/drivers/usb/gadget/imx_udc.c
+@@ -28,6 +28,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/clk.h>
+ #include <linux/delay.h>
++#include <linux/timer.h>
+
+ #include <linux/usb/ch9.h>
+ #include <linux/usb/gadget.h>
+@@ -1013,70 +1014,32 @@ static void udc_stop_activity(struct imx_udc_struct *imx_usb,
+ *******************************************************************************
+ */
+
+-static irqreturn_t imx_udc_irq(int irq, void *dev)
++/*
++ * Called when timer expires.
++ * Timer is started when CFG_CHG is received.
++ */
++static void handle_config(unsigned long data)
+ {
+- struct imx_udc_struct *imx_usb = dev;
++ struct imx_udc_struct *imx_usb = (void *)data;
+ struct usb_ctrlrequest u;
+ int temp, cfg, intf, alt;
+- int intr = __raw_readl(imx_usb->base + USB_INTR);
+-
+- if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START
+- | INTR_RESET_STOP | INTR_CFG_CHG)) {
+- dump_intr(__func__, intr, imx_usb->dev);
+- dump_usb_stat(__func__, imx_usb);
+- }
+-
+- if (!imx_usb->driver)
+- goto end_irq;
+-
+- if (intr & INTR_WAKEUP) {
+- if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
+- && imx_usb->driver && imx_usb->driver->resume)
+- imx_usb->driver->resume(&imx_usb->gadget);
+- imx_usb->set_config = 0;
+- imx_usb->gadget.speed = USB_SPEED_FULL;
+- }
+-
+- if (intr & INTR_SUSPEND) {
+- if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN
+- && imx_usb->driver && imx_usb->driver->suspend)
+- imx_usb->driver->suspend(&imx_usb->gadget);
+- imx_usb->set_config = 0;
+- imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
+- }
+
+- if (intr & INTR_RESET_START) {
+- __raw_writel(intr, imx_usb->base + USB_INTR);
+- udc_stop_activity(imx_usb, imx_usb->driver);
+- imx_usb->set_config = 0;
+- imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
+- }
+-
+- if (intr & INTR_RESET_STOP)
+- imx_usb->gadget.speed = USB_SPEED_FULL;
++ local_irq_disable();
+
+- if (intr & INTR_CFG_CHG) {
+- __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR);
+- temp = __raw_readl(imx_usb->base + USB_STAT);
+- cfg = (temp & STAT_CFG) >> 5;
+- intf = (temp & STAT_INTF) >> 3;
+- alt = temp & STAT_ALTSET;
++ temp = __raw_readl(imx_usb->base + USB_STAT);
++ cfg = (temp & STAT_CFG) >> 5;
++ intf = (temp & STAT_INTF) >> 3;
++ alt = temp & STAT_ALTSET;
+
+- D_REQ(imx_usb->dev,
+- "<%s> orig config C=%d, I=%d, A=%d / "
+- "req config C=%d, I=%d, A=%d\n",
+- __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt,
+- cfg, intf, alt);
++ D_REQ(imx_usb->dev,
++ "<%s> orig config C=%d, I=%d, A=%d / "
++ "req config C=%d, I=%d, A=%d\n",
++ __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt,
++ cfg, intf, alt);
+
+- if (cfg != 1 && cfg != 2)
+- goto end_irq;
++ if (cfg == 1 || cfg == 2) {
+
+- imx_usb->set_config = 0;
+-
+- /* Config setup */
+ if (imx_usb->cfg != cfg) {
+- D_REQ(imx_usb->dev,
+- "<%s> Change config start\n", __func__);
+ u.bRequest = USB_REQ_SET_CONFIGURATION;
+ u.bRequestType = USB_DIR_OUT |
+ USB_TYPE_STANDARD |
+@@ -1085,16 +1048,10 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
+ u.wIndex = 0;
+ u.wLength = 0;
+ imx_usb->cfg = cfg;
+- imx_usb->set_config = 1;
+ imx_usb->driver->setup(&imx_usb->gadget, &u);
+- imx_usb->set_config = 0;
+- D_REQ(imx_usb->dev,
+- "<%s> Change config done\n", __func__);
+
+ }
+ if (imx_usb->intf != intf || imx_usb->alt != alt) {
+- D_REQ(imx_usb->dev,
+- "<%s> Change interface start\n", __func__);
+ u.bRequest = USB_REQ_SET_INTERFACE;
+ u.bRequestType = USB_DIR_OUT |
+ USB_TYPE_STANDARD |
+@@ -1104,14 +1061,30 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
+ u.wLength = 0;
+ imx_usb->intf = intf;
+ imx_usb->alt = alt;
+- imx_usb->set_config = 1;
+ imx_usb->driver->setup(&imx_usb->gadget, &u);
+- imx_usb->set_config = 0;
+- D_REQ(imx_usb->dev,
+- "<%s> Change interface done\n", __func__);
+ }
+ }
+
++ imx_usb->set_config = 0;
++
++ local_irq_enable();
++}
++
++static irqreturn_t imx_udc_irq(int irq, void *dev)
++{
++ struct imx_udc_struct *imx_usb = dev;
++ int intr = __raw_readl(imx_usb->base + USB_INTR);
++ int temp;
++
++ if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START
++ | INTR_RESET_STOP | INTR_CFG_CHG)) {
++ dump_intr(__func__, intr, imx_usb->dev);
++ dump_usb_stat(__func__, imx_usb);
++ }
++
++ if (!imx_usb->driver)
++ goto end_irq;
++
+ if (intr & INTR_SOF) {
+ /* Copy from Freescale BSP.
+ We must enable SOF intr and set CMDOVER.
+@@ -1125,6 +1098,55 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
+ }
+ }
+
++ if (intr & INTR_CFG_CHG) {
++ /* A workaround of serious IMX UDC bug.
++ Handling of CFG_CHG should be delayed for some time, because
++ IMX does not NACK the host when CFG_CHG interrupt is pending.
++ There is no time to handle current CFG_CHG
++ if next CFG_CHG or SETUP packed is send immediately.
++ We have to clear CFG_CHG, start the timer and
++ NACK the host by setting CTRL_CMDOVER
++ if it sends any SETUP packet.
++ When timer expires, handler is called to handle configuration
++ changes. While CFG_CHG is not handled (set_config=1),
++ we must NACK the host to every SETUP packed.
++ This delay prevents from going out of sync with host.
++ */
++ __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR);
++ imx_usb->set_config = 1;
++ mod_timer(&imx_usb->timer, jiffies + 5);
++ goto end_irq;
++ }
++
++ if (intr & INTR_WAKEUP) {
++ if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
++ && imx_usb->driver && imx_usb->driver->resume)
++ imx_usb->driver->resume(&imx_usb->gadget);
++ imx_usb->set_config = 0;
++ del_timer(&imx_usb->timer);
++ imx_usb->gadget.speed = USB_SPEED_FULL;
++ }
++
++ if (intr & INTR_SUSPEND) {
++ if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN
++ && imx_usb->driver && imx_usb->driver->suspend)
++ imx_usb->driver->suspend(&imx_usb->gadget);
++ imx_usb->set_config = 0;
++ del_timer(&imx_usb->timer);
++ imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
++ }
++
++ if (intr & INTR_RESET_START) {
++ __raw_writel(intr, imx_usb->base + USB_INTR);
++ udc_stop_activity(imx_usb, imx_usb->driver);
++ imx_usb->set_config = 0;
++ del_timer(&imx_usb->timer);
++ imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
++ }
++
++ if (intr & INTR_RESET_STOP)
++ imx_usb->gadget.speed = USB_SPEED_FULL;
++
+ end_irq:
+ __raw_writel(intr, imx_usb->base + USB_INTR);
+ return IRQ_HANDLED;
+@@ -1342,6 +1364,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+
+ udc_stop_activity(imx_usb, driver);
+ imx_udc_disable(imx_usb);
++ del_timer(&imx_usb->timer);
+
+ driver->unbind(&imx_usb->gadget);
+ imx_usb->gadget.dev.driver = NULL;
+@@ -1459,6 +1482,10 @@ static int __init imx_udc_probe(struct platform_device *pdev)
+ usb_init_data(imx_usb);
+ imx_udc_init(imx_usb);
+
++ init_timer(&imx_usb->timer);
++ imx_usb->timer.function = handle_config;
++ imx_usb->timer.data = (unsigned long)imx_usb;
++
+ return 0;
+
+ fail3:
+@@ -1481,6 +1508,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
+ int i;
+
+ imx_udc_disable(imx_usb);
++ del_timer(&imx_usb->timer);
+
+ for (i = 0; i < IMX_USB_NB_EP + 1; i++)
+ free_irq(imx_usb->usbd_int[i], imx_usb);
+diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h
+index 6b0b1e3..b48ad59 100644
+--- a/drivers/usb/gadget/imx_udc.h
++++ b/drivers/usb/gadget/imx_udc.h
+@@ -59,6 +59,7 @@ struct imx_udc_struct {
+ struct device *dev;
+ struct imx_ep_struct imx_ep[IMX_USB_NB_EP];
+ struct clk *clk;
++ struct timer_list timer;
+ enum ep0_state ep0state;
+ struct resource *res;
+ void __iomem *base;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|