diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/Makefile | 19 | ||||
-rw-r--r-- | drivers/usb/isp116x-hcd.c | 8 | ||||
-rw-r--r-- | drivers/usb/r8a66597-hcd.c | 6 | ||||
-rw-r--r-- | drivers/usb/sl811_usb.c | 7 | ||||
-rw-r--r-- | drivers/usb/usb_ohci.c | 1037 | ||||
-rw-r--r-- | drivers/usb/usb_ohci.h | 44 | ||||
-rw-r--r-- | drivers/usb/usbdcore_ep0.c | 4 | ||||
-rw-r--r-- | drivers/usb/usbdcore_mpc8xx.c | 26 | ||||
-rw-r--r-- | drivers/usb/usbdcore_omap1510.c | 8 |
9 files changed, 644 insertions, 515 deletions
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index c67a490..856f51a 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -25,15 +25,22 @@ include $(TOPDIR)/config.mk LIB := $(obj)libusb.a +# core +COBJS-y += usbdcore.o +COBJS-$(CONFIG_USB_OHCI_NEW) += usb_ohci.o + +# host +COBJS-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o COBJS-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o +COBJS-$(CONFIG_USB_SL811HS) += sl811_usb.o -COBJS-y += isp116x-hcd.o -COBJS-y += sl811_usb.o -COBJS-y += usb_ohci.o -COBJS-y += usbdcore.o +# device +ifdef CONFIG_USB_DEVICE COBJS-y += usbdcore_ep0.o -COBJS-y += usbdcore_mpc8xx.o -COBJS-y += usbdcore_omap1510.o +COBJS-$(CONFIG_OMAP1510) += usbdcore_omap1510.o +COBJS-$(CONFIG_OMAP1610) += usbdcore_omap1510.o +COBJS-$(CONFIG_MPC885_FAMILY) += usbdcore_mpc8xx.o +endif COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/usb/isp116x-hcd.c b/drivers/usb/isp116x-hcd.c index 6b9b23b..348e404 100644 --- a/drivers/usb/isp116x-hcd.c +++ b/drivers/usb/isp116x-hcd.c @@ -56,8 +56,6 @@ */ #include <common.h> - -#ifdef CONFIG_USB_ISP116X_HCD #include <asm/io.h> #include <usb.h> #include <malloc.h> @@ -687,7 +685,7 @@ retry_same: /* Start the data transfer */ /* Allow more time for a BULK device to react - some are slow */ - if (usb_pipetype(pipe) == PIPE_BULK) + if (usb_pipebulk(pipe)) timeout = 5000; else timeout = 100; @@ -822,7 +820,7 @@ static int isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe, u16 wIndex; u16 wLength; - if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { + if (usb_pipeint(pipe)) { INFO("Root-Hub submit IRQ: NOT implemented"); return 0; } @@ -1441,5 +1439,3 @@ int usb_lowlevel_stop(void) return 0; } - -#endif /* CONFIG_USB_ISP116X_HCD */ diff --git a/drivers/usb/r8a66597-hcd.c b/drivers/usb/r8a66597-hcd.c index 0d3931e..288f41a 100644 --- a/drivers/usb/r8a66597-hcd.c +++ b/drivers/usb/r8a66597-hcd.c @@ -530,7 +530,7 @@ static int check_usb_device_connecting(struct r8a66597 *r8a66597) /* based on usb_ohci.c */ #define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) + ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; }) /*-------------------------------------------------------------------------* * Virtual Root Hub *-------------------------------------------------------------------------*/ @@ -654,7 +654,7 @@ static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe, R8A66597_DPRINT("%s\n", __func__); - if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { + if (usb_pipeint(pipe)) { printf("Root-Hub submit IRQ: NOT implemented"); return 0; } @@ -794,7 +794,7 @@ static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe, case RH_SET_CONFIGURATION: break; default: - dbg("unsupported root hub command"); + R8A66597_DPRINT("unsupported root hub command"); stat = USB_ST_STALLED; } diff --git a/drivers/usb/sl811_usb.c b/drivers/usb/sl811_usb.c index 159cc25..a03e469 100644 --- a/drivers/usb/sl811_usb.c +++ b/drivers/usb/sl811_usb.c @@ -36,7 +36,6 @@ */ #include <common.h> -#ifdef CONFIG_USB_SL811HS #include <mpc8xx.h> #include <usb.h> #include "sl811.h" @@ -111,7 +110,7 @@ static void inline sl811_write_buf(__u8 offset, __u8 *buf, __u8 size) int usb_init_kup4x (void) { - volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; volatile memctl8xx_t *memctl = &immap->im_memctl; int i; unsigned char tmp; @@ -265,7 +264,7 @@ static int sl811_send_packet(struct usb_device *dev, unsigned long pipe, __u8 *b sl811_write(SL811_CTRL_A, ctrl); while (!(sl811_read(SL811_INTRSTS) & SL811_INTR_DONE_A)) { - if (5*CFG_HZ < get_timer(time_start)) { + if (5*CONFIG_SYS_HZ < get_timer(time_start)) { printf("USB transmit timed out\n"); return -USB_ST_CRC_ERR; } @@ -733,5 +732,3 @@ static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe, return status == 0 ? len : status; } - -#endif /* CONFIG_USB_SL811HS */ diff --git a/drivers/usb/usb_ohci.c b/drivers/usb/usb_ohci.c index 0bfa4d7..d68fdcf 100644 --- a/drivers/usb/usb_ohci.c +++ b/drivers/usb/usb_ohci.c @@ -46,9 +46,6 @@ */ #include <common.h> - -#ifdef CONFIG_USB_OHCI_NEW - #include <asm/byteorder.h> #if defined(CONFIG_PCI_OHCI) @@ -73,7 +70,7 @@ defined(CONFIG_440EP) || \ defined(CONFIG_PCI_OHCI) || \ defined(CONFIG_MPC5200) || \ - defined(CFG_OHCI_USE_NPS) + defined(CONFIG_SYS_OHCI_USE_NPS) # define OHCI_USE_NPS /* force NoPowerSwitching mode */ #endif @@ -89,15 +86,16 @@ /* * e.g. PCI controllers need this */ -#ifdef CFG_OHCI_SWAP_REG_ACCESS +#ifdef CONFIG_SYS_OHCI_SWAP_REG_ACCESS # define readl(a) __swap_32(*((volatile u32 *)(a))) # define writel(a, b) (*((volatile u32 *)(b)) = __swap_32((volatile u32)a)) #else # define readl(a) (*((volatile u32 *)(a))) # define writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a)) -#endif /* CFG_OHCI_SWAP_REG_ACCESS */ +#endif /* CONFIG_SYS_OHCI_SWAP_REG_ACCESS */ -#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) +#define min_t(type, x, y) \ + ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) #ifdef CONFIG_PCI_OHCI static struct pci_device_id ohci_pci_ids[] = { @@ -109,25 +107,33 @@ static struct pci_device_id ohci_pci_ids[] = { }; #endif +#ifdef CONFIG_PCI_EHCI_DEVNO +static struct pci_device_id ehci_pci_ids[] = { + {0x1131, 0x1562}, /* Philips 1562 PCI EHCI module ids */ + /* Please add supported PCI EHCI controller ids here */ + {0, 0} +}; +#endif + #ifdef DEBUG #define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) #else -#define dbg(format, arg...) do {} while(0) +#define dbg(format, arg...) do {} while (0) #endif /* DEBUG */ #define err(format, arg...) printf("ERROR: " format "\n", ## arg) #ifdef SHOW_INFO #define info(format, arg...) printf("INFO: " format "\n", ## arg) #else -#define info(format, arg...) do {} while(0) +#define info(format, arg...) do {} while (0) #endif -#ifdef CFG_OHCI_BE_CONTROLLER +#ifdef CONFIG_SYS_OHCI_BE_CONTROLLER # define m16_swap(x) cpu_to_be16(x) # define m32_swap(x) cpu_to_be32(x) #else # define m16_swap(x) cpu_to_le16(x) # define m32_swap(x) cpu_to_le32(x) -#endif /* CFG_OHCI_BE_CONTROLLER */ +#endif /* CONFIG_SYS_OHCI_BE_CONTROLLER */ /* global ohci_t */ static ohci_t gohci; @@ -137,25 +143,24 @@ struct ohci_hcca ghcca[1]; struct ohci_hcca *phcca; /* this allocates EDs for all possible endpoints */ struct ohci_device ohci_dev; -/* RHSC flag */ -int got_rhsc; /* device which was disconnected */ struct usb_device *devgone; -static inline u32 roothub_a (struct ohci *hc) - { return readl (&hc->regs->roothub.a); } -static inline u32 roothub_b (struct ohci *hc) - { return readl (&hc->regs->roothub.b); } -static inline u32 roothub_status (struct ohci *hc) - { return readl (&hc->regs->roothub.status); } -static inline u32 roothub_portstatus (struct ohci *hc, int i) - { return readl (&hc->regs->roothub.portstatus[i]); } +static inline u32 roothub_a(struct ohci *hc) + { return readl(&hc->regs->roothub.a); } +static inline u32 roothub_b(struct ohci *hc) + { return readl(&hc->regs->roothub.b); } +static inline u32 roothub_status(struct ohci *hc) + { return readl(&hc->regs->roothub.status); } +static inline u32 roothub_portstatus(struct ohci *hc, int i) + { return readl(&hc->regs->roothub.portstatus[i]); } /* forward declaration */ -static int hc_interrupt (void); -static void -td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer, - int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval); +static int hc_interrupt(void); +static void td_submit_job(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct devrequest *setup, urb_priv_t *urb, + int interval); /*-------------------------------------------------------------------------* * URB support functions @@ -163,11 +168,11 @@ td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer, /* free HCD-private data associated with this URB */ -static void urb_free_priv (urb_priv_t * urb) +static void urb_free_priv(urb_priv_t *urb) { int i; int last; - struct td * td; + struct td *td; last = urb->length - 1; if (last >= 0) { @@ -185,72 +190,74 @@ static void urb_free_priv (urb_priv_t * urb) /*-------------------------------------------------------------------------*/ #ifdef DEBUG -static int sohci_get_current_frame_number (struct usb_device * dev); +static int sohci_get_current_frame_number(struct usb_device *dev); /* debug| print the main components of an URB * small: 0) header + data packets 1) just header */ -static void pkt_print (urb_priv_t *purb, struct usb_device * dev, - unsigned long pipe, void * buffer, - int transfer_len, struct devrequest * setup, char * str, int small) +static void pkt_print(urb_priv_t *purb, struct usb_device *dev, + unsigned long pipe, void *buffer, int transfer_len, + struct devrequest *setup, char *str, int small) { - dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", + dbg("%s URB:[%4x] dev:%2lu,ep:%2lu-%c,type:%s,len:%d/%d stat:%#lx", str, - sohci_get_current_frame_number (dev), - usb_pipedevice (pipe), - usb_pipeendpoint (pipe), - usb_pipeout (pipe)? 'O': 'I', - usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): - (usb_pipecontrol (pipe)? "CTRL": "BULK"), + sohci_get_current_frame_number(dev), + usb_pipedevice(pipe), + usb_pipeendpoint(pipe), + usb_pipeout(pipe)? 'O': 'I', + usb_pipetype(pipe) < 2 ? \ + (usb_pipeint(pipe)? "INTR": "ISOC"): \ + (usb_pipecontrol(pipe)? "CTRL": "BULK"), (purb ? purb->actual_length : 0), transfer_len, dev->status); #ifdef OHCI_VERBOSE_DEBUG if (!small) { int i, len; - if (usb_pipecontrol (pipe)) { - printf (__FILE__ ": cmd(8):"); + if (usb_pipecontrol(pipe)) { + printf(__FILE__ ": cmd(8):"); for (i = 0; i < 8 ; i++) - printf (" %02x", ((__u8 *) setup) [i]); - printf ("\n"); + printf(" %02x", ((__u8 *) setup) [i]); + printf("\n"); } if (transfer_len > 0 && buffer) { - printf (__FILE__ ": data(%d/%d):", + printf(__FILE__ ": data(%d/%d):", (purb ? purb->actual_length : 0), transfer_len); - len = usb_pipeout (pipe)? - transfer_len: + len = usb_pipeout(pipe)? transfer_len: (purb ? purb->actual_length : 0); for (i = 0; i < 16 && i < len; i++) - printf (" %02x", ((__u8 *) buffer) [i]); - printf ("%s\n", i < len? "...": ""); + printf(" %02x", ((__u8 *) buffer) [i]); + printf("%s\n", i < len? "...": ""); } } #endif } -/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ -void ep_print_int_eds (ohci_t *ohci, char * str) { +/* just for debugging; prints non-empty branches of the int ed tree + * inclusive iso eds */ +void ep_print_int_eds(ohci_t *ohci, char *str) +{ int i, j; - __u32 * ed_p; - for (i= 0; i < 32; i++) { + __u32 *ed_p; + for (i = 0; i < 32; i++) { j = 5; ed_p = &(ohci->hcca->int_table [i]); if (*ed_p == 0) continue; - printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i); + printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i); while (*ed_p != 0 && j--) { ed_t *ed = (ed_t *)m32_swap(ed_p); - printf (" ed: %4x;", ed->hwINFO); + printf(" ed: %4x;", ed->hwINFO); ed_p = &ed->hwNextED; } - printf ("\n"); + printf("\n"); } } -static void ohci_dump_intr_mask (char *label, __u32 mask) +static void ohci_dump_intr_mask(char *label, __u32 mask) { - dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s", label, mask, (mask & OHCI_INTR_MIE) ? " MIE" : "", @@ -265,46 +272,46 @@ static void ohci_dump_intr_mask (char *label, __u32 mask) ); } -static void maybe_print_eds (char *label, __u32 value) +static void maybe_print_eds(char *label, __u32 value) { ed_t *edp = (ed_t *)value; if (value) { - dbg ("%s %08x", label, value); - dbg ("%08x", edp->hwINFO); - dbg ("%08x", edp->hwTailP); - dbg ("%08x", edp->hwHeadP); - dbg ("%08x", edp->hwNextED); + dbg("%s %08x", label, value); + dbg("%08x", edp->hwINFO); + dbg("%08x", edp->hwTailP); + dbg("%08x", edp->hwHeadP); + dbg("%08x", edp->hwNextED); } } -static char * hcfs2string (int state) +static char *hcfs2string(int state) { switch (state) { - case OHCI_USB_RESET: return "reset"; - case OHCI_USB_RESUME: return "resume"; - case OHCI_USB_OPER: return "operational"; - case OHCI_USB_SUSPEND: return "suspend"; + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; } return "?"; } /* dump control and status registers */ -static void ohci_dump_status (ohci_t *controller) +static void ohci_dump_status(ohci_t *controller) { struct ohci_regs *regs = controller->regs; __u32 temp; - temp = readl (®s->revision) & 0xff; + temp = readl(®s->revision) & 0xff; if (temp != 0x10) - dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + dbg("spec %d.%d", (temp >> 4), (temp & 0x0f)); - temp = readl (®s->control); - dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + temp = readl(®s->control); + dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, (temp & OHCI_CTRL_RWE) ? " RWE" : "", (temp & OHCI_CTRL_RWC) ? " RWC" : "", (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string (temp & OHCI_CTRL_HCFS), + hcfs2string(temp & OHCI_CTRL_HCFS), (temp & OHCI_CTRL_BLE) ? " BLE" : "", (temp & OHCI_CTRL_CLE) ? " CLE" : "", (temp & OHCI_CTRL_IE) ? " IE" : "", @@ -312,8 +319,8 @@ static void ohci_dump_status (ohci_t *controller) temp & OHCI_CTRL_CBSR ); - temp = readl (®s->cmdstatus); - dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + temp = readl(®s->cmdstatus); + dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, (temp & OHCI_SOC) >> 16, (temp & OHCI_OCR) ? " OCR" : "", (temp & OHCI_BLF) ? " BLF" : "", @@ -321,31 +328,31 @@ static void ohci_dump_status (ohci_t *controller) (temp & OHCI_HCR) ? " HCR" : "" ); - ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); - ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + ohci_dump_intr_mask("intrstatus", readl(®s->intrstatus)); + ohci_dump_intr_mask("intrenable", readl(®s->intrenable)); - maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + maybe_print_eds("ed_periodcurrent", readl(®s->ed_periodcurrent)); - maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); - maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + maybe_print_eds("ed_controlhead", readl(®s->ed_controlhead)); + maybe_print_eds("ed_controlcurrent", readl(®s->ed_controlcurrent)); - maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); - maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + maybe_print_eds("ed_bulkhead", readl(®s->ed_bulkhead)); + maybe_print_eds("ed_bulkcurrent", readl(®s->ed_bulkcurrent)); - maybe_print_eds ("donehead", readl (®s->donehead)); + maybe_print_eds("donehead", readl(®s->donehead)); } -static void ohci_dump_roothub (ohci_t *controller, int verbose) +static void ohci_dump_roothub(ohci_t *controller, int verbose) { __u32 temp, ndp, i; - temp = roothub_a (controller); + temp = roothub_a(controller); ndp = (temp & RH_A_NDP); #ifdef CONFIG_AT91C_PQFP_UHPBUG ndp = (ndp == 2) ? 1:0; #endif if (verbose) { - dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, ((temp & RH_A_POTPGT) >> 24) & 0xff, (temp & RH_A_NOCP) ? " NOCP" : "", (temp & RH_A_OCPM) ? " OCPM" : "", @@ -354,14 +361,14 @@ static void ohci_dump_roothub (ohci_t *controller, int verbose) (temp & RH_A_PSM) ? " PSM" : "", ndp ); - temp = roothub_b (controller); - dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp = roothub_b(controller); + dbg("roothub.b: %08x PPCM=%04x DR=%04x", temp, (temp & RH_B_PPCM) >> 16, (temp & RH_B_DR) ); - temp = roothub_status (controller); - dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp = roothub_status(controller); + dbg("roothub.status: %08x%s%s%s%s%s%s", temp, (temp & RH_HS_CRWE) ? " CRWE" : "", (temp & RH_HS_OCIC) ? " OCIC" : "", @@ -373,8 +380,8 @@ static void ohci_dump_roothub (ohci_t *controller, int verbose) } for (i = 0; i < ndp; i++) { - temp = roothub_portstatus (controller, i); - dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + temp = roothub_portstatus(controller, i); + dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", i, temp, (temp & RH_PS_PRSC) ? " PRSC" : "", @@ -395,16 +402,16 @@ static void ohci_dump_roothub (ohci_t *controller, int verbose) } } -static void ohci_dump (ohci_t *controller, int verbose) +static void ohci_dump(ohci_t *controller, int verbose) { - dbg ("OHCI controller usb-%s state", controller->slot_name); + dbg("OHCI controller usb-%s state", controller->slot_name); /* dumps some of the state we know about */ - ohci_dump_status (controller); + ohci_dump_status(controller); if (verbose) - ep_print_int_eds (controller, "hcca"); - dbg ("hcca frame #%04x", controller->hcca->frame_no); - ohci_dump_roothub (controller, 1); + ep_print_int_eds(controller, "hcca"); + dbg("hcca frame #%04x", controller->hcca->frame_no); + ohci_dump_roothub(controller, 1); } #endif /* DEBUG */ @@ -417,7 +424,7 @@ static void ohci_dump (ohci_t *controller, int verbose) int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup) { ohci_t *ohci; - ed_t * ed; + ed_t *ed; urb_priv_t *purb_priv = urb; int i, size = 0; struct usb_device *dev = urb->dev; @@ -435,27 +442,29 @@ int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup) return -1; } - /* we're about to begin a new transaction here so mark the URB unfinished */ + /* we're about to begin a new transaction here so mark the + * URB unfinished */ urb->finished = 0; /* every endpoint has a ed, locate and fill it */ - if (!(ed = ep_add_ed (dev, pipe, interval, 1))) { + ed = ep_add_ed(dev, pipe, interval, 1); + if (!ed) { err("sohci_submit_job: ENOMEM"); return -1; } /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype (pipe)) { - case PIPE_BULK: /* one TD for every 4096 Byte */ - size = (transfer_len - 1) / 4096 + 1; - break; - case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (transfer_len == 0)? 2: - (transfer_len - 1) / 4096 + 3; - break; - case PIPE_INTERRUPT: /* 1 TD */ - size = 1; - break; + switch (usb_pipetype(pipe)) { + case PIPE_BULK: /* one TD for every 4096 Byte */ + size = (transfer_len - 1) / 4096 + 1; + break; + case PIPE_CONTROL:/* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ + size = (transfer_len == 0)? 2: + (transfer_len - 1) / 4096 + 3; + break; + case PIPE_INTERRUPT: /* 1 TD */ + size = 1; + break; } ed->purb = urb; @@ -474,27 +483,28 @@ int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup) /* allocate the TDs */ /* note that td[0] was allocated in ep_add_ed */ for (i = 0; i < size; i++) { - purb_priv->td[i] = td_alloc (dev); + purb_priv->td[i] = td_alloc(dev); if (!purb_priv->td[i]) { purb_priv->length = i; - urb_free_priv (purb_priv); + urb_free_priv(purb_priv); err("sohci_submit_job: ENOMEM"); return -1; } } if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_free_priv (purb_priv); + urb_free_priv(purb_priv); err("sohci_submit_job: EINVAL"); return -1; } /* link the ed into a chain if is not already */ if (ed->state != ED_OPER) - ep_link (ohci, ed); + ep_link(ohci, ed); /* fill the TDs and link it to the ed */ - td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval); + td_submit_job(dev, pipe, buffer, transfer_len, + setup, purb_priv, interval); return 0; } @@ -503,19 +513,19 @@ static inline int sohci_return_job(struct ohci *hc, urb_priv_t *urb) { struct ohci_regs *regs = hc->regs; - switch (usb_pipetype (urb->pipe)) { + switch (usb_pipetype(urb->pipe)) { case PIPE_INTERRUPT: /* implicitly requeued */ if (urb->dev->irq_handle && (urb->dev->irq_act_len = urb->actual_length)) { - writel (OHCI_INTR_WDH, ®s->intrenable); - readl (®s->intrenable); /* PCI posting flush */ + writel(OHCI_INTR_WDH, ®s->intrenable); + readl(®s->intrenable); /* PCI posting flush */ urb->dev->irq_handle(urb->dev); - writel (OHCI_INTR_WDH, ®s->intrdisable); - readl (®s->intrdisable); /* PCI posting flush */ + writel(OHCI_INTR_WDH, ®s->intrdisable); + readl(®s->intrdisable); /* PCI posting flush */ } urb->actual_length = 0; - td_submit_job ( + td_submit_job( urb->dev, urb->pipe, urb->transfer_buffer, @@ -538,11 +548,11 @@ static inline int sohci_return_job(struct ohci *hc, urb_priv_t *urb) #ifdef DEBUG /* tell us the current USB frame number */ -static int sohci_get_current_frame_number (struct usb_device *usb_dev) +static int sohci_get_current_frame_number(struct usb_device *usb_dev) { ohci_t *ohci = &gohci; - return m16_swap (ohci->hcca->frame_no); + return m16_swap(ohci->hcca->frame_no); } #endif @@ -555,7 +565,7 @@ static int sohci_get_current_frame_number (struct usb_device *usb_dev) * returns the branch and * sets the interval to interval = 2^integer (ld (interval)) */ -static int ep_int_ballance (ohci_t * ohci, int interval, int load) +static int ep_int_ballance(ohci_t *ohci, int interval, int load) { int i, branch = 0; @@ -577,20 +587,19 @@ static int ep_int_ballance (ohci_t * ohci, int interval, int load) /* 2^int( ld (inter)) */ -static int ep_2_n_interval (int inter) +static int ep_2_n_interval(int inter) { int i; - for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); + for (i = 0; ((inter >> i) > 1) && (i < 5); i++); return 1 << i; } /*-------------------------------------------------------------------------*/ /* the int tree is a binary tree - * in order to process it sequentially the indexes of the branches have to be mapped - * the mapping reverses the bits of a word of num_bits length */ - -static int ep_rev (int num_bits, int word) + * in order to process it sequentially the indexes of the branches have to + * be mapped the mapping reverses the bits of a word of num_bits length */ +static int ep_rev(int num_bits, int word) { int i, wout = 0; @@ -605,7 +614,7 @@ static int ep_rev (int num_bits, int word) /* link an ed into one of the HC chains */ -static int ep_link (ohci_t *ohci, ed_t *edi) +static int ep_link(ohci_t *ohci, ed_t *edi) { volatile ed_t *ed = edi; int int_branch; @@ -613,7 +622,7 @@ static int ep_link (ohci_t *ohci, ed_t *edi) int inter; int interval; int load; - __u32 * ed_p; + __u32 *ed_p; ed->state = ED_OPER; ed->int_interval = 0; @@ -621,49 +630,54 @@ static int ep_link (ohci_t *ohci, ed_t *edi) switch (ed->type) { case PIPE_CONTROL: ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) { - writel (ed, &ohci->regs->ed_controlhead); - } else { - ohci->ed_controltail->hwNextED = m32_swap ((unsigned long)ed); - } + if (ohci->ed_controltail == NULL) + writel(ed, &ohci->regs->ed_controlhead); + else + ohci->ed_controltail->hwNextED = + m32_swap((unsigned long)ed); + ed->ed_prev = ohci->ed_controltail; if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && !ohci->ed_rm_list[1] && !ohci->sleeping) { ohci->hc_control |= OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); + writel(ohci->hc_control, &ohci->regs->control); } ohci->ed_controltail = edi; break; case PIPE_BULK: ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) { - writel (ed, &ohci->regs->ed_bulkhead); - } else { - ohci->ed_bulktail->hwNextED = m32_swap ((unsigned long)ed); - } + if (ohci->ed_bulktail == NULL) + writel(ed, &ohci->regs->ed_bulkhead); + else + ohci->ed_bulktail->hwNextED = + m32_swap((unsigned long)ed); + ed->ed_prev = ohci->ed_bulktail; if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && !ohci->ed_rm_list[1] && !ohci->sleeping) { ohci->hc_control |= OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); + writel(ohci->hc_control, &ohci->regs->control); } ohci->ed_bulktail = edi; break; case PIPE_INTERRUPT: load = ed->int_load; - interval = ep_2_n_interval (ed->int_period); + interval = ep_2_n_interval(ed->int_period); ed->int_interval = interval; - int_branch = ep_int_ballance (ohci, interval, load); + int_branch = ep_int_ballance(ohci, interval, load); ed->int_branch = int_branch; - for (i = 0; i < ep_rev (6, interval); i += inter) { + for (i = 0; i < ep_rev(6, interval); i += inter) { inter = 1; - for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]); - (*ed_p != 0) && (((ed_t *)ed_p)->int_interval >= interval); + for (ed_p = &(ohci->hcca->int_table[\ + ep_rev(5, i) + int_branch]); + (*ed_p != 0) && + (((ed_t *)ed_p)->int_interval >= interval); ed_p = &(((ed_t *)ed_p)->hwNextED)) - inter = ep_rev (6, ((ed_t *)ed_p)->int_interval); + inter = ep_rev(6, + ((ed_t *)ed_p)->int_interval); ed->hwNextED = *ed_p; *ed_p = m32_swap((unsigned long)ed); } @@ -675,19 +689,21 @@ static int ep_link (ohci_t *ohci, ed_t *edi) /*-------------------------------------------------------------------------*/ /* scan the periodic table to find and unlink this ED */ -static void periodic_unlink ( struct ohci *ohci, volatile struct ed *ed, - unsigned index, unsigned period) +static void periodic_unlink(struct ohci *ohci, volatile struct ed *ed, + unsigned index, unsigned period) { for (; index < NUM_INTS; index += period) { __u32 *ed_p = &ohci->hcca->int_table [index]; /* ED might have been unlinked through another path */ while (*ed_p != 0) { - if (((struct ed *)m32_swap ((unsigned long)ed_p)) == ed) { + if (((struct ed *) + m32_swap((unsigned long)ed_p)) == ed) { *ed_p = ed->hwNextED; break; } - ed_p = & (((struct ed *)m32_swap ((unsigned long)ed_p))->hwNextED); + ed_p = &(((struct ed *) + m32_swap((unsigned long)ed_p))->hwNextED); } } } @@ -697,28 +713,30 @@ static void periodic_unlink ( struct ohci *ohci, volatile struct ed *ed, * the link from the ed still points to another operational ed or 0 * so the HC can eventually finish the processing of the unlinked ed */ -static int ep_unlink (ohci_t *ohci, ed_t *edi) +static int ep_unlink(ohci_t *ohci, ed_t *edi) { volatile ed_t *ed = edi; int i; - ed->hwINFO |= m32_swap (OHCI_ED_SKIP); + ed->hwINFO |= m32_swap(OHCI_ED_SKIP); switch (ed->type) { case PIPE_CONTROL: if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); + writel(ohci->hc_control, &ohci->regs->control); } - writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead); + writel(m32_swap(*((__u32 *)&ed->hwNextED)), + &ohci->regs->ed_controlhead); } else { ed->ed_prev->hwNextED = ed->hwNextED; } if (ohci->ed_controltail == ed) { ohci->ed_controltail = ed->ed_prev; } else { - ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + ((ed_t *)m32_swap( + *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; } break; @@ -726,21 +744,23 @@ static int ep_unlink (ohci_t *ohci, ed_t *edi) if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); + writel(ohci->hc_control, &ohci->regs->control); } - writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead); + writel(m32_swap(*((__u32 *)&ed->hwNextED)), + &ohci->regs->ed_bulkhead); } else { ed->ed_prev->hwNextED = ed->hwNextED; } if (ohci->ed_bulktail == ed) { ohci->ed_bulktail = ed->ed_prev; } else { - ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + ((ed_t *)m32_swap( + *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; } break; case PIPE_INTERRUPT: - periodic_unlink (ohci, ed, 0, 1); + periodic_unlink(ohci, ed, 0, 1); for (i = ed->int_branch; i < 32; i += ed->int_interval) ohci->ohci_int_load[i] -= ed->int_load; break; @@ -759,15 +779,15 @@ static int ep_unlink (ohci_t *ohci, ed_t *edi) * info fields are setted anyway even though most of them should not * change */ -static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe, - int interval, int load) +static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe, + int interval, int load) { td_t *td; ed_t *ed_ret; volatile ed_t *ed; - ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) | - (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]; + ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint(pipe) << 1) | + (usb_pipecontrol(pipe)? 0: usb_pipeout(pipe))]; if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { err("ep_add_ed: pending delete"); @@ -776,22 +796,22 @@ static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe, } if (ed->state == ED_NEW) { - ed->hwINFO = m32_swap (OHCI_ED_SKIP); /* skip ed */ /* dummy td; end of td list for ed */ - td = td_alloc (usb_dev); - ed->hwTailP = m32_swap ((unsigned long)td); + td = td_alloc(usb_dev); + ed->hwTailP = m32_swap((unsigned long)td); ed->hwHeadP = ed->hwTailP; ed->state = ED_UNLINK; - ed->type = usb_pipetype (pipe); + ed->type = usb_pipetype(pipe); ohci_dev.ed_cnt++; } - ed->hwINFO = m32_swap (usb_pipedevice (pipe) - | usb_pipeendpoint (pipe) << 7 - | (usb_pipeisoc (pipe)? 0x8000: 0) - | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) - | usb_pipeslow (pipe) << 13 - | usb_maxpacket (usb_dev, pipe) << 16); + ed->hwINFO = m32_swap(usb_pipedevice(pipe) + | usb_pipeendpoint(pipe) << 7 + | (usb_pipeisoc(pipe)? 0x8000: 0) + | (usb_pipecontrol(pipe)? 0: \ + (usb_pipeout(pipe)? 0x800: 0x1000)) + | usb_pipeslow(pipe) << 13 + | usb_maxpacket(usb_dev, pipe) << 16); if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { ed->int_period = interval; @@ -807,7 +827,7 @@ static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe, /* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ -static void td_fill (ohci_t *ohci, unsigned int info, +static void td_fill(ohci_t *ohci, unsigned int info, void *data, int len, struct usb_device *dev, int index, urb_priv_t *urb_priv) { @@ -825,29 +845,31 @@ static void td_fill (ohci_t *ohci, unsigned int info, td_pt->hwNextTD = 0; /* fill the old dummy TD */ - td = urb_priv->td [index] = (td_t *)(m32_swap (urb_priv->ed->hwTailP) & ~0xf); + td = urb_priv->td [index] = + (td_t *)(m32_swap(urb_priv->ed->hwTailP) & ~0xf); td->ed = urb_priv->ed; td->next_dl_td = NULL; td->index = index; td->data = (__u32)data; #ifdef OHCI_FILL_TRACE - if ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe)) { + if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) { for (i = 0; i < len; i++) - printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]); + printf("td->data[%d] %#2x ", i, ((unsigned char *)td->data)[i]); printf("\n"); } #endif if (!len) data = 0; - td->hwINFO = m32_swap (info); - td->hwCBP = m32_swap ((unsigned long)data); + td->hwINFO = m32_swap(info); + td->hwCBP = m32_swap((unsigned long)data); if (data) - td->hwBE = m32_swap ((unsigned long)(data + len - 1)); + td->hwBE = m32_swap((unsigned long)(data + len - 1)); else td->hwBE = 0; - td->hwNextTD = m32_swap ((unsigned long)td_pt); + + td->hwNextTD = m32_swap((unsigned long)td_pt); /* append to queue */ td->ed->hwTailP = td->hwNextTD; @@ -857,8 +879,10 @@ static void td_fill (ohci_t *ohci, unsigned int info, /* prepare all TDs of a transfer */ -static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) +static void td_submit_job(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct devrequest *setup, urb_priv_t *urb, + int interval) { ohci_t *ohci = &gohci; int data_len = transfer_len; @@ -867,12 +891,14 @@ static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buf __u32 info = 0; unsigned int toggle = 0; - /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ - if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { + /* OHCI handles the DATA-toggles itself, we just use the USB-toggle + * bits for reseting */ + if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { toggle = TD_T_TOGGLE; } else { toggle = TD_T_DATA0; - usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1); + usb_settoggle(dev, usb_pipeendpoint(pipe), + usb_pipeout(pipe), 1); } urb->td_cnt = 0; if (data_len) @@ -880,44 +906,58 @@ static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buf else data = 0; - switch (usb_pipetype (pipe)) { + switch (usb_pipetype(pipe)) { case PIPE_BULK: - info = usb_pipeout (pipe)? + info = usb_pipeout(pipe)? TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; - while(data_len > 4096) { - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb); + while (data_len > 4096) { + td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle), + data, 4096, dev, cnt, urb); data += 4096; data_len -= 4096; cnt++; } - info = usb_pipeout (pipe)? + info = usb_pipeout(pipe)? TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb); + td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle), data, + data_len, dev, cnt, urb); cnt++; - if (!ohci->sleeping) - writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + if (!ohci->sleeping) { + /* start bulk list */ + writel(OHCI_BLF, &ohci->regs->cmdstatus); + } break; case PIPE_CONTROL: + /* Setup phase */ info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill (ohci, info, setup, 8, dev, cnt++, urb); + td_fill(ohci, info, setup, 8, dev, cnt++, urb); + + /* Optional Data phase */ if (data_len > 0) { - info = usb_pipeout (pipe)? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; + info = usb_pipeout(pipe)? + TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : + TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; /* NOTE: mishandles transfers >8K, some >4K */ - td_fill (ohci, info, data, data_len, dev, cnt++, urb); + td_fill(ohci, info, data, data_len, dev, cnt++, urb); + } + + /* Status phase */ + info = usb_pipeout(pipe)? + TD_CC | TD_DP_IN | TD_T_DATA1: + TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill(ohci, info, data, 0, dev, cnt++, urb); + + if (!ohci->sleeping) { + /* start Control list */ + writel(OHCI_CLF, &ohci->regs->cmdstatus); } - info = usb_pipeout (pipe)? - TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill (ohci, info, data, 0, dev, cnt++, urb); - if (!ohci->sleeping) - writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ break; case PIPE_INTERRUPT: - info = usb_pipeout (urb->pipe)? + info = usb_pipeout(urb->pipe)? TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle; - td_fill (ohci, info, data, data_len, dev, cnt++, urb); + td_fill(ohci, info, data, data_len, dev, cnt++, urb); break; } if (urb->length != cnt) @@ -930,16 +970,16 @@ static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buf /* calculate the transfer length and update the urb */ -static void dl_transfer_length(td_t * td) +static void dl_transfer_length(td_t *td) { __u32 tdINFO, tdBE, tdCBP; urb_priv_t *lurb_priv = td->ed->purb; - tdINFO = m32_swap (td->hwINFO); - tdBE = m32_swap (td->hwBE); - tdCBP = m32_swap (td->hwCBP); + tdINFO = m32_swap(td->hwINFO); + tdBE = m32_swap(td->hwBE); + tdCBP = m32_swap(td->hwCBP); - if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL && + if (!(usb_pipecontrol(lurb_priv->pipe) && ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { if (tdBE != 0) { if (td->hwCBP == 0) @@ -951,105 +991,127 @@ static void dl_transfer_length(td_t * td) } /*-------------------------------------------------------------------------*/ +static void check_status(td_t *td_list) +{ + urb_priv_t *lurb_priv = td_list->ed->purb; + int urb_len = lurb_priv->length; + __u32 *phwHeadP = &td_list->ed->hwHeadP; + int cc; + + cc = TD_CC_GET(m32_swap(td_list->hwINFO)); + if (cc) { + err(" USB-error: %s (%x)", cc_to_string[cc], cc); + + if (*phwHeadP & m32_swap(0x1)) { + if (lurb_priv && + ((td_list->index + 1) < urb_len)) { + *phwHeadP = + (lurb_priv->td[urb_len - 1]->hwNextTD &\ + m32_swap(0xfffffff0)) | + (*phwHeadP & m32_swap(0x2)); + + lurb_priv->td_cnt += urb_len - + td_list->index - 1; + } else + *phwHeadP &= m32_swap(0xfffffff2); + } +#ifdef CONFIG_MPC5200 + td_list->hwNextTD = 0; +#endif + } +} /* replies to the request have to be on a FIFO basis so * we reverse the reversed done-list */ - -static td_t * dl_reverse_done_list (ohci_t *ohci) +static td_t *dl_reverse_done_list(ohci_t *ohci) { __u32 td_list_hc; td_t *td_rev = NULL; td_t *td_list = NULL; - urb_priv_t *lurb_priv = NULL; - td_list_hc = m32_swap (ohci->hcca->done_head) & 0xfffffff0; + td_list_hc = m32_swap(ohci->hcca->done_head) & 0xfffffff0; ohci->hcca->done_head = 0; while (td_list_hc) { td_list = (td_t *)td_list_hc; - - if (TD_CC_GET (m32_swap (td_list->hwINFO))) { - lurb_priv = td_list->ed->purb; - dbg(" USB-error/status: %x : %p", - TD_CC_GET (m32_swap (td_list->hwINFO)), td_list); - if (td_list->ed->hwHeadP & m32_swap (0x1)) { - if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) { - td_list->ed->hwHeadP = - (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & m32_swap (0xfffffff0)) | - (td_list->ed->hwHeadP & m32_swap (0x2)); - lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1; - } else - td_list->ed->hwHeadP &= m32_swap (0xfffffff2); - } -#ifdef CONFIG_MPC5200 - td_list->hwNextTD = 0; -#endif - } - + check_status(td_list); td_list->next_dl_td = td_rev; td_rev = td_list; - td_list_hc = m32_swap (td_list->hwNextTD) & 0xfffffff0; + td_list_hc = m32_swap(td_list->hwNextTD) & 0xfffffff0; } return td_list; } /*-------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------*/ -/* td done list */ -static int dl_done_list (ohci_t *ohci, td_t *td_list) +static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status) +{ + if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL)) + urb->finished = sohci_return_job(ohci, urb); + else + dbg("finish_urb: strange.., ED state %x, \n", status); +} + +/* + * Used to take back a TD from the host controller. This would normally be + * called from within dl_done_list, however it may be called directly if the + * HC no longer sees the TD and it has not appeared on the donelist (after + * two frames). This bug has been observed on ZF Micro systems. + */ +static int takeback_td(ohci_t *ohci, td_t *td_list) { - td_t *td_list_next = NULL; ed_t *ed; - int cc = 0; + int cc; int stat = 0; /* urb_t *urb; */ urb_priv_t *lurb_priv; __u32 tdINFO, edHeadP, edTailP; - while (td_list) { - td_list_next = td_list->next_dl_td; + tdINFO = m32_swap(td_list->hwINFO); - tdINFO = m32_swap (td_list->hwINFO); + ed = td_list->ed; + lurb_priv = ed->purb; - ed = td_list->ed; - lurb_priv = ed->purb; + dl_transfer_length(td_list); - dl_transfer_length(td_list); + lurb_priv->td_cnt++; - /* error code of transfer */ - cc = TD_CC_GET (tdINFO); - if (cc != 0) { - dbg("ConditionCode %#x", cc); - stat = cc_to_error[cc]; - } + /* error code of transfer */ + cc = TD_CC_GET(tdINFO); + if (cc) { + err("USB-error: %s (%x)", cc_to_string[cc], cc); + stat = cc_to_error[cc]; + } - /* see if this done list makes for all TD's of current URB, - * and mark the URB finished if so */ - if (++(lurb_priv->td_cnt) == lurb_priv->length) { -#if 1 - if ((ed->state & (ED_OPER | ED_UNLINK)) && - (lurb_priv->state != URB_DEL)) -#else - if ((ed->state & (ED_OPER | ED_UNLINK))) -#endif - lurb_priv->finished = sohci_return_job(ohci, - lurb_priv); - else - dbg("dl_done_list: strange.., ED state %x, ed->state\n"); - } else - dbg("dl_done_list: processing TD %x, len %x\n", lurb_priv->td_cnt, - lurb_priv->length); - if (ed->state != ED_NEW && - (usb_pipetype (lurb_priv->pipe) != PIPE_INTERRUPT)) { - edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0; - edTailP = m32_swap (ed->hwTailP); - - /* unlink eds if they are not busy */ - if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink (ohci, ed); - } + /* see if this done list makes for all TD's of current URB, + * and mark the URB finished if so */ + if (lurb_priv->td_cnt == lurb_priv->length) + finish_urb(ohci, lurb_priv, ed->state); + + dbg("dl_done_list: processing TD %x, len %x\n", + lurb_priv->td_cnt, lurb_priv->length); - td_list = td_list_next; + if (ed->state != ED_NEW && (!usb_pipeint(lurb_priv->pipe))) { + edHeadP = m32_swap(ed->hwHeadP) & 0xfffffff0; + edTailP = m32_swap(ed->hwTailP); + + /* unlink eds if they are not busy */ + if ((edHeadP == edTailP) && (ed->state == ED_OPER)) + ep_unlink(ohci, ed); + } + return stat; +} + +static int dl_done_list(ohci_t *ohci) +{ + int stat = 0; + td_t *td_list = dl_reverse_done_list(ohci); + + while (td_list) { + td_t *td_next = td_list->next_dl_td; + stat = takeback_td(ohci, td_list); + td_list = td_next; } return stat; } @@ -1092,7 +1154,7 @@ static __u8 root_hub_config_des[] = 0x01, /* __u8 bConfigurationValue; */ 0x00, /* __u8 iConfiguration; */ 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ 0x00, /* __u8 MaxPower; */ /* interface */ @@ -1162,14 +1224,17 @@ static unsigned char root_hub_str_index1[] = #define OK(x) len = (x); break #ifdef DEBUG -#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);} -#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);} +#define WR_RH_STAT(x) {info("WR:status %#8x", (x)); writel((x), \ + &gohci.regs->roothub.status); } +#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, \ + (x)); writel((x), &gohci.regs->roothub.portstatus[wIndex-1]); } #else #define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status) -#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) +#define WR_RH_PORTSTAT(x) writel((x), \ + &gohci.regs->roothub.portstatus[wIndex-1]) #endif #define RD_RH_STAT roothub_status(&gohci) -#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1) +#define RD_RH_PORTSTAT roothub_portstatus(&gohci, wIndex-1) /* request to virtual root hub */ @@ -1179,13 +1244,13 @@ int rh_check_port_status(ohci_t *controller) int res; res = -1; - temp = roothub_a (controller); + temp = roothub_a(controller); ndp = (temp & RH_A_NDP); #ifdef CONFIG_AT91C_PQFP_UHPBUG ndp = (ndp == 2) ? 1:0; #endif for (i = 0; i < ndp; i++) { - temp = roothub_portstatus (controller, i); + temp = roothub_portstatus(controller, i); /* check for a device disconnect */ if (((temp & (RH_PS_PESC | RH_PS_CSC)) == (RH_PS_PESC | RH_PS_CSC)) && @@ -1200,7 +1265,7 @@ int rh_check_port_status(ohci_t *controller) static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *cmd) { - void * data = buffer; + void *data = buffer; int leni = transfer_len; int len = 0; int stat = 0; @@ -1212,19 +1277,20 @@ static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, __u16 wLength; #ifdef DEBUG -pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); +pkt_print(NULL, dev, pipe, buffer, transfer_len, + cmd, "SUB(rh)", usb_pipein(pipe)); #else wait_ms(1); #endif - if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { + if (usb_pipeint(pipe)) { info("Root-Hub submit IRQ: NOT implemented"); return 0; } bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = le16_to_cpu (cmd->value); - wIndex = le16_to_cpu (cmd->index); - wLength = le16_to_cpu (cmd->length); + wValue = le16_to_cpu(cmd->value); + wIndex = le16_to_cpu(cmd->index); + wLength = le16_to_cpu(cmd->length); info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); @@ -1239,118 +1305,118 @@ pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe */ case RH_GET_STATUS: - *(__u16 *) data_buf = cpu_to_le16 (1); OK (2); + *(__u16 *) data_buf = cpu_to_le16(1); + OK(2); case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); + *(__u16 *) data_buf = cpu_to_le16(0); + OK(2); case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); + *(__u16 *) data_buf = cpu_to_le16(0); + OK(2); case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32 ( + *(__u32 *) data_buf = cpu_to_le32( RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK (4); + OK(4); case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4); + *(__u32 *) data_buf = cpu_to_le32(RD_RH_PORTSTAT); + OK(4); case RH_CLEAR_FEATURE | RH_ENDPOINT: switch (wValue) { - case (RH_ENDPOINT_STALL): OK (0); + case (RH_ENDPOINT_STALL): + OK(0); } break; case RH_CLEAR_FEATURE | RH_CLASS: switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - OK(0); - case (RH_C_HUB_OVER_CURRENT): - WR_RH_STAT(RH_HS_OCIC); OK (0); + case RH_C_HUB_LOCAL_POWER: + OK(0); + case (RH_C_HUB_OVER_CURRENT): + WR_RH_STAT(RH_HS_OCIC); + OK(0); } break; case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { - case (RH_PORT_ENABLE): - WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_POCI); OK (0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); - case (RH_C_PORT_CONNECTION): - WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); - case (RH_C_PORT_ENABLE): - WR_RH_PORTSTAT (RH_PS_PESC); OK (0); - case (RH_C_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); - case (RH_C_PORT_OVER_CURRENT): - WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); - case (RH_C_PORT_RESET): - WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); + case (RH_PORT_ENABLE): WR_RH_PORTSTAT(RH_PS_CCS); OK(0); + case (RH_PORT_SUSPEND): WR_RH_PORTSTAT(RH_PS_POCI); OK(0); + case (RH_PORT_POWER): WR_RH_PORTSTAT(RH_PS_LSDA); OK(0); + case (RH_C_PORT_CONNECTION): WR_RH_PORTSTAT(RH_PS_CSC); OK(0); + case (RH_C_PORT_ENABLE): WR_RH_PORTSTAT(RH_PS_PESC); OK(0); + case (RH_C_PORT_SUSPEND): WR_RH_PORTSTAT(RH_PS_PSSC); OK(0); + case (RH_C_PORT_OVER_CURRENT):WR_RH_PORTSTAT(RH_PS_OCIC); OK(0); + case (RH_C_PORT_RESET): WR_RH_PORTSTAT(RH_PS_PRSC); OK(0); } break; case RH_SET_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); - case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT (RH_PS_PRS); - OK (0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT (RH_PS_PPS ); - wait_ms(100); - OK (0); - case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT (RH_PS_PES ); - OK (0); + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT(RH_PS_PSS); OK(0); + case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT(RH_PS_PRS); + OK(0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT(RH_PS_PPS); + wait_ms(100); + OK(0); + case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT(RH_PS_PES); + OK(0); } break; - case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0); + case RH_SET_ADDRESS: + gohci.rh.devnum = wValue; + OK(0); case RH_GET_DESCRIPTOR: switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ + case (0x01): /* device descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof(root_hub_dev_des), + wLength)); + data_buf = root_hub_dev_des; OK(len); + case (0x02): /* configuration descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof(root_hub_config_des), + wLength)); + data_buf = root_hub_config_des; OK(len); + case (0x03): /* string descriptors */ + if (wValue == 0x0300) { len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_dev_des), - wLength)); - data_buf = root_hub_dev_des; OK(len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; OK(len); - case (0x03): /* string descriptors */ - if(wValue==0x0300) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_str_index0), - wLength)); - data_buf = root_hub_str_index0; - OK(len); - } - if(wValue==0x0301) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_str_index1), - wLength)); - data_buf = root_hub_str_index1; - OK(len); + leni, + min_t(unsigned int, + sizeof(root_hub_str_index0), + wLength)); + data_buf = root_hub_str_index0; + OK(len); } - default: - stat = USB_ST_STALLED; + if (wValue == 0x0301) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof(root_hub_str_index1), + wLength)); + data_buf = root_hub_str_index1; + OK(len); + } + default: + stat = USB_ST_STALLED; } break; case RH_GET_DESCRIPTOR | RH_CLASS: { - __u32 temp = roothub_a (&gohci); + __u32 temp = roothub_a(&gohci); data_buf [0] = 9; /* min length; */ data_buf [1] = 0x29; @@ -1363,13 +1429,13 @@ pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe data_buf [3] |= 0x1; if (temp & RH_A_NOCP) /* no overcurrent reporting? */ data_buf [3] |= 0x10; - else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ + else if (temp & RH_A_OCPM)/* per-port overcurrent reporting? */ data_buf [3] |= 0x8; /* corresponds to data_buf[4-7] */ datab [1] = 0; data_buf [5] = (temp & RH_A_POTPGT) >> 24; - temp = roothub_b (&gohci); + temp = roothub_b(&gohci); data_buf [7] = temp & RH_B_DR; if (data_buf [2] < 7) { data_buf [8] = 0xff; @@ -1381,32 +1447,33 @@ pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe len = min_t(unsigned int, leni, min_t(unsigned int, data_buf [0], wLength)); - OK (len); + OK(len); } - case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); + case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK(1); - case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); + case RH_SET_CONFIGURATION: WR_RH_STAT(0x10000); OK(0); default: - dbg ("unsupported root hub command"); + dbg("unsupported root hub command"); stat = USB_ST_STALLED; } #ifdef DEBUG - ohci_dump_roothub (&gohci, 1); + ohci_dump_roothub(&gohci, 1); #else wait_ms(1); #endif len = min_t(int, len, leni); if (data != data_buf) - memcpy (data, data_buf, len); + memcpy(data, data_buf, len); dev->act_len = len; dev->status = stat; #ifdef DEBUG - pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); + pkt_print(NULL, dev, pipe, buffer, + transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); #else wait_ms(1); #endif @@ -1443,7 +1510,8 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, #ifdef DEBUG urb->actual_length = 0; - pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); + pkt_print(urb, dev, pipe, buffer, transfer_len, + setup, "SUB", usb_pipein(pipe)); #else wait_ms(1); #endif @@ -1465,7 +1533,7 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, /* allow more time for a BULK device to react - some are slow */ #define BULK_TO 5000 /* timeout in milliseconds */ - if (usb_pipetype (pipe) == PIPE_BULK) + if (usb_pipebulk(pipe)) timeout = BULK_TO; else timeout = 100; @@ -1496,7 +1564,7 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, if (--timeout) { wait_ms(1); if (!urb->finished) - dbg("\%"); + dbg("*"); } else { err("CTL:TIMEOUT "); @@ -1511,14 +1579,15 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, dev->act_len = transfer_len; #ifdef DEBUG - pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); + pkt_print(urb, dev, pipe, buffer, transfer_len, + setup, "RET(ctlr)", usb_pipein(pipe)); #else wait_ms(1); #endif /* free TDs in urb_priv */ - if (usb_pipetype (pipe) != PIPE_INTERRUPT) - urb_free_priv (urb); + if (!usb_pipeint(pipe)) + urb_free_priv(urb); return 0; } @@ -1537,7 +1606,8 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, info("submit_control_msg"); #ifdef DEBUG - pkt_print(NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); + pkt_print(NULL, dev, pipe, buffer, transfer_len, + setup, "SUB", usb_pipein(pipe)); #else wait_ms(1); #endif @@ -1570,18 +1640,46 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, /* reset the HC and BUS */ -static int hc_reset (ohci_t *ohci) +static int hc_reset(ohci_t *ohci) { +#ifdef CONFIG_PCI_EHCI_DEVNO + pci_dev_t pdev; +#endif int timeout = 30; int smm_timeout = 50; /* 0,5 sec */ dbg("%s\n", __FUNCTION__); - if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ - writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ +#ifdef CONFIG_PCI_EHCI_DEVNO + /* + * Some multi-function controllers (e.g. ISP1562) allow root hub + * resetting via EHCI registers only. + */ + pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVNO); + if (pdev != -1) { + u32 base; + int timeout = 1000; + + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base); + writel(readl(base + EHCI_USBCMD_OFF) | EHCI_USBCMD_HCRESET, + base + EHCI_USBCMD_OFF); + + while (readl(base + EHCI_USBCMD_OFF) & EHCI_USBCMD_HCRESET) { + if (timeout-- <= 0) { + printf("USB RootHub reset timed out!"); + break; + } + udelay(1); + } + } else + printf("No EHCI func at %d index!\n", CONFIG_PCI_EHCI_DEVNO); +#endif + if (readl(&ohci->regs->control) & OHCI_CTRL_IR) { + /* SMM owns the HC */ + writel(OHCI_OCR, &ohci->regs->cmdstatus);/* request ownership */ info("USB HC TakeOver from SMM"); - while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { - wait_ms (10); + while (readl(&ohci->regs->control) & OHCI_CTRL_IR) { + wait_ms(10); if (--smm_timeout == 0) { err("USB HC TakeOver failed!"); return -1; @@ -1590,7 +1688,7 @@ static int hc_reset (ohci_t *ohci) } /* Disable HC interrupts */ - writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + writel(OHCI_INTR_MIE, &ohci->regs->intrdisable); dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;\n", ohci->slot_name, @@ -1598,16 +1696,16 @@ static int hc_reset (ohci_t *ohci) /* Reset USB (needed by some controllers) */ ohci->hc_control = 0; - writel (ohci->hc_control, &ohci->regs->control); + writel(ohci->hc_control, &ohci->regs->control); /* HC Reset requires max 10 us delay */ - writel (OHCI_HCR, &ohci->regs->cmdstatus); - while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + writel(OHCI_HCR, &ohci->regs->cmdstatus); + while ((readl(&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { if (--timeout == 0) { err("USB HC reset timed out!"); return -1; } - udelay (1); + udelay(1); } return 0; } @@ -1618,7 +1716,7 @@ static int hc_reset (ohci_t *ohci) * enable interrupts * connect the virtual root hub */ -static int hc_start (ohci_t * ohci) +static int hc_start(ohci_t *ohci) { __u32 mask; unsigned int fminterval; @@ -1628,44 +1726,44 @@ static int hc_start (ohci_t * ohci) /* Tell the controller where the control and bulk lists are * The lists are empty now. */ - writel (0, &ohci->regs->ed_controlhead); - writel (0, &ohci->regs->ed_bulkhead); + writel(0, &ohci->regs->ed_controlhead); + writel(0, &ohci->regs->ed_bulkhead); - writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */ + writel((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */ fminterval = 0x2edf; - writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); + writel((fminterval * 9) / 10, &ohci->regs->periodicstart); fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - writel (fminterval, &ohci->regs->fminterval); - writel (0x628, &ohci->regs->lsthresh); + writel(fminterval, &ohci->regs->fminterval); + writel(0x628, &ohci->regs->lsthresh); /* start controller operations */ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci->disabled = 0; - writel (ohci->hc_control, &ohci->regs->control); + writel(ohci->hc_control, &ohci->regs->control); /* disable all interrupts */ mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | OHCI_INTR_OC | OHCI_INTR_MIE); - writel (mask, &ohci->regs->intrdisable); + writel(mask, &ohci->regs->intrdisable); /* clear all interrupts */ mask &= ~OHCI_INTR_MIE; - writel (mask, &ohci->regs->intrstatus); + writel(mask, &ohci->regs->intrstatus); /* Choose the interrupts we care about now - but w/o MIE */ mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - writel (mask, &ohci->regs->intrenable); + writel(mask, &ohci->regs->intrenable); #ifdef OHCI_USE_NPS /* required for AMD-756 and some Mac platforms */ - writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, + writel((roothub_a(ohci) | RH_A_NPS) & ~RH_A_PSM, &ohci->regs->roothub.a); - writel (RH_HS_LPSC, &ohci->regs->roothub.status); + writel(RH_HS_LPSC, &ohci->regs->roothub.status); #endif /* OHCI_USE_NPS */ -#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) +#define mdelay(n) ({unsigned long msec = (n); while (msec--) udelay(1000); }) /* POTPGT delay is bits 24-31, in 2 ms units. */ - mdelay ((roothub_a (ohci) >> 23) & 0x1fe); + mdelay((roothub_a(ohci) >> 23) & 0x1fe); /* connect the virtual root hub */ ohci->rh.devnum = 0; @@ -1683,7 +1781,7 @@ void usb_event_poll(void) /* an interrupt happens */ -static int hc_interrupt (void) +static int hc_interrupt(void) { ohci_t *ohci = &gohci; struct ohci_regs *regs = ohci->regs; @@ -1691,69 +1789,74 @@ static int hc_interrupt (void) int stat = -1; if ((ohci->hcca->done_head != 0) && - !(m32_swap (ohci->hcca->done_head) & 0x01)) { + !(m32_swap(ohci->hcca->done_head) & 0x01)) { ints = OHCI_INTR_WDH; - } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { - ohci->disabled++; - err ("%s device removed!", ohci->slot_name); - return -1; - } else if ((ints &= readl (®s->intrenable)) == 0) { - dbg("hc_interrupt: returning..\n"); - return 0xff; + } else { + ints = readl(®s->intrstatus); + if (ints == ~(u32)0) { + ohci->disabled++; + err("%s device removed!", ohci->slot_name); + return -1; + } else { + ints &= readl(®s->intrenable); + if (ints == 0) { + dbg("hc_interrupt: returning..\n"); + return 0xff; + } + } } - /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ + /* dbg("Interrupt: %x frame: %x", ints, + le16_to_cpu(ohci->hcca->frame_no)); */ - if (ints & OHCI_INTR_RHSC) { - got_rhsc = 1; + if (ints & OHCI_INTR_RHSC) stat = 0xff; - } if (ints & OHCI_INTR_UE) { ohci->disabled++; - err ("OHCI Unrecoverable Error, controller usb-%s disabled", + err("OHCI Unrecoverable Error, controller usb-%s disabled", ohci->slot_name); /* e.g. due to PCI Master/Target Abort */ #ifdef DEBUG - ohci_dump (ohci, 1); + ohci_dump(ohci, 1); #else - wait_ms(1); + wait_ms(1); #endif /* FIXME: be optimistic, hope that bug won't repeat often. */ /* Make some non-interrupt context restart the controller. */ /* Count and limit the retries though; either hardware or */ /* software errors can go forever... */ - hc_reset (ohci); + hc_reset(ohci); return -1; } if (ints & OHCI_INTR_WDH) { wait_ms(1); - writel (OHCI_INTR_WDH, ®s->intrdisable); - (void)readl (®s->intrdisable); /* flush */ - stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci)); - writel (OHCI_INTR_WDH, ®s->intrenable); - (void)readl (®s->intrdisable); /* flush */ + writel(OHCI_INTR_WDH, ®s->intrdisable); + (void)readl(®s->intrdisable); /* flush */ + stat = dl_done_list(&gohci); + writel(OHCI_INTR_WDH, ®s->intrenable); + (void)readl(®s->intrdisable); /* flush */ } if (ints & OHCI_INTR_SO) { dbg("USB Schedule overrun\n"); - writel (OHCI_INTR_SO, ®s->intrenable); + writel(OHCI_INTR_SO, ®s->intrenable); stat = -1; } /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ if (ints & OHCI_INTR_SF) { - unsigned int frame = m16_swap (ohci->hcca->frame_no) & 1; + unsigned int frame = m16_swap(ohci->hcca->frame_no) & 1; wait_ms(1); - writel (OHCI_INTR_SF, ®s->intrdisable); + writel(OHCI_INTR_SF, ®s->intrdisable); if (ohci->ed_rm_list[frame] != NULL) - writel (OHCI_INTR_SF, ®s->intrenable); + writel(OHCI_INTR_SF, ®s->intrenable); stat = 0xff; } - writel (ints, ®s->intrstatus); + writel(ints, ®s->intrstatus); return stat; } @@ -1763,12 +1866,12 @@ static int hc_interrupt (void) /* De-allocate all resources.. */ -static void hc_release_ohci (ohci_t *ohci) +static void hc_release_ohci(ohci_t *ohci) { - dbg ("USB HC release ohci usb-%s", ohci->slot_name); + dbg("USB HC release ohci usb-%s", ohci->slot_name); if (!ohci->disabled) - hc_reset (ohci); + hc_reset(ohci); } /*-------------------------------------------------------------------------*/ @@ -1784,18 +1887,18 @@ int usb_lowlevel_init(void) pci_dev_t pdev; #endif -#ifdef CFG_USB_OHCI_CPU_INIT +#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT /* cpu dependant init */ - if(usb_cpu_init()) + if (usb_cpu_init()) return -1; #endif -#ifdef CFG_USB_OHCI_BOARD_INIT +#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT /* board dependant init */ - if(usb_board_init()) + if (usb_board_init()) return -1; #endif - memset (&gohci, 0, sizeof (ohci_t)); + memset(&gohci, 0, sizeof(ohci_t)); /* align the storage */ if ((__u32)&ghcca[0] & 0xff) { @@ -1816,7 +1919,7 @@ int usb_lowlevel_init(void) } ptd = gtd; gohci.hcca = phcca; - memset (phcca, 0, sizeof (struct ohci_hcca)); + memset(phcca, 0, sizeof(struct ohci_hcca)); gohci.disabled = 1; gohci.sleeping = 0; @@ -1838,40 +1941,37 @@ int usb_lowlevel_init(void) } else return -1; #else - gohci.regs = (struct ohci_regs *)CFG_USB_OHCI_REGS_BASE; + gohci.regs = (struct ohci_regs *)CONFIG_SYS_USB_OHCI_REGS_BASE; #endif gohci.flags = 0; - gohci.slot_name = CFG_USB_OHCI_SLOT_NAME; + gohci.slot_name = CONFIG_SYS_USB_OHCI_SLOT_NAME; if (hc_reset (&gohci) < 0) { hc_release_ohci (&gohci); err ("can't reset usb-%s", gohci.slot_name); -#ifdef CFG_USB_OHCI_BOARD_INIT +#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT /* board dependant cleanup */ usb_board_init_fail(); #endif -#ifdef CFG_USB_OHCI_CPU_INIT +#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT /* cpu dependant cleanup */ usb_cpu_init_fail(); #endif return -1; } - /* FIXME this is a second HC reset; why?? */ - /* writel(gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control); - wait_ms(10); */ - if (hc_start (&gohci) < 0) { - err ("can't start usb-%s", gohci.slot_name); - hc_release_ohci (&gohci); + if (hc_start(&gohci) < 0) { + err("can't start usb-%s", gohci.slot_name); + hc_release_ohci(&gohci); /* Initialization failed */ -#ifdef CFG_USB_OHCI_BOARD_INIT +#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT /* board dependant cleanup */ usb_board_stop(); #endif -#ifdef CFG_USB_OHCI_CPU_INIT +#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT /* cpu dependant cleanup */ usb_cpu_stop(); #endif @@ -1879,7 +1979,7 @@ int usb_lowlevel_init(void) } #ifdef DEBUG - ohci_dump (&gohci, 1); + ohci_dump(&gohci, 1); #else wait_ms(1); #endif @@ -1895,20 +1995,21 @@ int usb_lowlevel_stop(void) return 0; /* TODO release any interrupts, etc. */ /* call hc_release_ohci() here ? */ - hc_reset (&gohci); + hc_reset(&gohci); -#ifdef CFG_USB_OHCI_BOARD_INIT +#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT /* board dependant cleanup */ - if(usb_board_stop()) + if (usb_board_stop()) return -1; #endif -#ifdef CFG_USB_OHCI_CPU_INIT +#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT /* cpu dependant cleanup */ - if(usb_cpu_stop()) + if (usb_cpu_stop()) return -1; #endif - + /* This driver is no longer initialised. It needs a new low-level + * init (board/cpu) before it can be used again. */ + ohci_inited = 0; return 0; } -#endif /* CONFIG_USB_OHCI_NEW */ diff --git a/drivers/usb/usb_ohci.h b/drivers/usb/usb_ohci.h index 380cb4c..a547337 100644 --- a/drivers/usb/usb_ohci.h +++ b/drivers/usb/usb_ohci.h @@ -38,6 +38,41 @@ static int cc_to_error[16] = { /* Not Access */ -1 }; +static const char *cc_to_string[16] = { + "No Error", + "CRC: Last data packet from endpoint contained a CRC error.", + "BITSTUFFING: Last data packet from endpoint contained a bit " \ + "stuffing violation", + "DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID\n" \ + "that did not match the expected value.", + "STALL: TD was moved to the Done Queue because the endpoint returned" \ + " a STALL PID", + "DEVICENOTRESPONDING: Device did not respond to token (IN) or did\n" \ + "not provide a handshake (OUT)", + "PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID\n"\ + "(IN) or handshake (OUT)", + "UNEXPECTEDPID: Receive PID was not valid when encountered or PID\n" \ + "value is not defined.", + "DATAOVERRUN: The amount of data returned by the endpoint exceeded\n" \ + "either the size of the maximum data packet allowed\n" \ + "from the endpoint (found in MaximumPacketSize field\n" \ + "of ED) or the remaining buffer size.", + "DATAUNDERRUN: The endpoint returned less than MaximumPacketSize\n" \ + "and that amount was not sufficient to fill the\n" \ + "specified buffer", + "reserved1", + "reserved2", + "BUFFEROVERRUN: During an IN, HC received data from endpoint faster\n" \ + "than it could be written to system memory", + "BUFFERUNDERRUN: During an OUT, HC could not retrieve data from\n" \ + "system memory fast enough to keep up with data USB " \ + "data rate.", + "NOT ACCESSED: This code is set by software before the TD is placed" \ + "on a list to be processed by the HC.(1)", + "NOT ACCESSED: This code is set by software before the TD is placed" \ + "on a list to be processed by the HC.(2)", +}; + /* ED States */ #define ED_NEW 0x00 @@ -155,8 +190,8 @@ struct ohci_hcca { /* * Maximum number of root hub ports. */ -#ifndef CFG_USB_OHCI_MAX_ROOT_PORTS -# error "CFG_USB_OHCI_MAX_ROOT_PORTS undefined!" +#ifndef CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS +# error "CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS undefined!" #endif /* @@ -191,10 +226,13 @@ struct ohci_regs { __u32 a; __u32 b; __u32 status; - __u32 portstatus[CFG_USB_OHCI_MAX_ROOT_PORTS]; + __u32 portstatus[CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS]; } roothub; } __attribute((aligned(32))); +/* Some EHCI controls */ +#define EHCI_USBCMD_OFF 0x20 +#define EHCI_USBCMD_HCRESET (1 << 1) /* OHCI CONTROL AND STATUS REGISTER MASKS */ diff --git a/drivers/usb/usbdcore_ep0.c b/drivers/usb/usbdcore_ep0.c index cf3f382..f6e017d 100644 --- a/drivers/usb/usbdcore_ep0.c +++ b/drivers/usb/usbdcore_ep0.c @@ -51,8 +51,6 @@ */ #include <common.h> - -#if defined(CONFIG_USB_DEVICE) #include "usbdcore.h" #if 0 @@ -597,5 +595,3 @@ int ep0_recv_setup (struct urb *urb) } return -1; } - -#endif diff --git a/drivers/usb/usbdcore_mpc8xx.c b/drivers/usb/usbdcore_mpc8xx.c index 122793c..0e311ad 100644 --- a/drivers/usb/usbdcore_mpc8xx.c +++ b/drivers/usb/usbdcore_mpc8xx.c @@ -58,8 +58,6 @@ */ #include <common.h> #include <config.h> - -#if defined(CONFIG_MPC885_FAMILY) && defined(CONFIG_USB_DEVICE) #include <commproc.h> #include "usbdcore.h" #include "usbdcore_mpc8xx.h" @@ -133,7 +131,7 @@ static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid); int udc_init (void) { /* Init various pointers */ - immr = (immap_t *) CFG_IMMR; + immr = (immap_t *) CONFIG_SYS_IMMR; cp = (cpm8xx_t *) & (immr->im_cpm); usb_paramp = (usb_pram_t *) & (cp->cp_dparam[PROFF_USB]); usbp = (usb_t *) & (cp->cp_scc[0]); @@ -752,7 +750,7 @@ static short mpc8xx_udc_handle_txerr () static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid) { if ((*rx_cbdp)->cbd_sc & RX_BD_W) { - *rx_cbdp = (volatile cbd_t *) (endpoints[epid]->rbase + CFG_IMMR); + *rx_cbdp = (volatile cbd_t *) (endpoints[epid]->rbase + CONFIG_SYS_IMMR); } else { (*rx_cbdp)++; @@ -780,7 +778,7 @@ static void mpc8xx_udc_flush_tx_fifo (int epid) usbp->uscom = 0x40 | 0; /* reset ring */ - tx_cbdp = (cbd_t *) (endpoints[epid]->tbptr + CFG_IMMR); + tx_cbdp = (cbd_t *) (endpoints[epid]->tbptr + CONFIG_SYS_IMMR); tx_cbdp->cbd_sc = (TX_BD_I | TX_BD_W); @@ -886,7 +884,7 @@ static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi) } ep = epi->endpoint_address & 0x03; - tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CFG_IMMR); + tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR); if (tx_cbdp->cbd_sc & TX_BD_R || usbp->usber & USB_E_TXB) { mpc8xx_udc_flush_tx_fifo (ep); @@ -903,7 +901,7 @@ static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi) return -1; } - tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CFG_IMMR); + tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR); while (tx_cbdp->cbd_sc & TX_BD_R) { }; tx_cbdp->cbd_sc = (tx_cbdp->cbd_sc & TX_BD_W); @@ -1187,10 +1185,10 @@ static void mpc8xx_udc_clock_init (volatile immap_t * immr, volatile cpm8xx_t * cp) { -#if defined(CFG_USB_EXTC_CLK) +#if defined(CONFIG_SYS_USB_EXTC_CLK) /* This has been tested with a 48MHz crystal on CLK6 */ - switch (CFG_USB_EXTC_CLK) { + switch (CONFIG_SYS_USB_EXTC_CLK) { case 1: immr->im_ioport.iop_papar |= 0x0100; immr->im_ioport.iop_padir &= ~0x0100; @@ -1216,7 +1214,7 @@ static void mpc8xx_udc_clock_init (volatile immap_t * immr, break; } -#elif defined(CFG_USB_BRGCLK) +#elif defined(CONFIG_SYS_USB_BRGCLK) /* This has been tested with brgclk == 50MHz */ int divisor = 0; @@ -1227,13 +1225,13 @@ static void mpc8xx_udc_clock_init (volatile immap_t * immr, return; } - /* Assume the brgclk is 'good enough', we want !(gd->cpu_clk%48Mhz) + /* Assume the brgclk is 'good enough', we want !(gd->cpu_clk%48MHz) * but, can /probably/ live with close-ish alternative rates. */ divisor = (gd->cpu_clk / 48000000L) - 1; cp->cp_sicr &= ~0x0000003F; - switch (CFG_USB_BRGCLK) { + switch (CONFIG_SYS_USB_BRGCLK) { case 1: cp->cp_brgc1 |= (divisor | CPM_BRG_EN); cp->cp_sicr &= ~0x2F; @@ -1256,7 +1254,7 @@ static void mpc8xx_udc_clock_init (volatile immap_t * immr, } #else -#error "CFG_USB_EXTC_CLK or CFG_USB_BRGCLK must be defined" +#error "CONFIG_SYS_USB_EXTC_CLK or CONFIG_SYS_USB_BRGCLK must be defined" #endif } @@ -1398,5 +1396,3 @@ static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment) return retaddr; } - -#endif /* CONFIG_MPC885_FAMILY && CONFIG_USB_DEVICE) */ diff --git a/drivers/usb/usbdcore_omap1510.c b/drivers/usb/usbdcore_omap1510.c index 4e3239f..6b7b61b 100644 --- a/drivers/usb/usbdcore_omap1510.c +++ b/drivers/usb/usbdcore_omap1510.c @@ -27,9 +27,6 @@ */ #include <common.h> - -#if ((defined(CONFIG_OMAP1510) || defined(CONFIG_OMAP1610)) && defined(CONFIG_USB_DEVICE)) - #include <asm/io.h> #ifdef CONFIG_OMAP_SX1 #include <i2c.h> @@ -1064,7 +1061,7 @@ void omap1510_udc_noniso_irq (void) */ /* Called to start packet transmission. */ -void udc_endpoint_write (struct usb_endpoint_instance *endpoint) +int udc_endpoint_write (struct usb_endpoint_instance *endpoint) { unsigned short epnum = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK; @@ -1081,6 +1078,8 @@ void udc_endpoint_write (struct usb_endpoint_instance *endpoint) /* deselect the endpoint FIFO */ outw (UDC_EP_Dir | epnum, UDC_EP_NUM); } + + return 0; } /* Start to initialize h/w stuff */ @@ -1566,4 +1565,3 @@ void udc_unset_nak (int epid) { /* TODO: implement this functionality in omap1510 */ } -#endif |