12731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 22731b9a8SJean-Christophe PLAGNIOL-VILLARD * URB OHCI HCD (Host Controller Driver) for USB. 32731b9a8SJean-Christophe PLAGNIOL-VILLARD * 42731b9a8SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> 52731b9a8SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> 62731b9a8SJean-Christophe PLAGNIOL-VILLARD * 72731b9a8SJean-Christophe PLAGNIOL-VILLARD * usb-ohci.h 82731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 92731b9a8SJean-Christophe PLAGNIOL-VILLARD 10a5496a18SBecky Bruce /* 11a5496a18SBecky Bruce * e.g. PCI controllers need this 12a5496a18SBecky Bruce */ 13a5496a18SBecky Bruce #ifdef CONFIG_SYS_OHCI_SWAP_REG_ACCESS 14a5496a18SBecky Bruce # define ohci_readl(a) __swap_32(*((volatile u32 *)(a))) 15a5496a18SBecky Bruce # define ohci_writel(a, b) (*((volatile u32 *)(b)) = __swap_32((volatile u32)a)) 16a5496a18SBecky Bruce #else 17a5496a18SBecky Bruce # define ohci_readl(a) (*((volatile u32 *)(a))) 18a5496a18SBecky Bruce # define ohci_writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a)) 19a5496a18SBecky Bruce #endif /* CONFIG_SYS_OHCI_SWAP_REG_ACCESS */ 20a5496a18SBecky Bruce 212731b9a8SJean-Christophe PLAGNIOL-VILLARD /* functions for doing board or CPU specific setup/cleanup */ 2216297cfbSMateusz Zalega int usb_board_stop(void); 232731b9a8SJean-Christophe PLAGNIOL-VILLARD 2416297cfbSMateusz Zalega int usb_cpu_init(void); 2516297cfbSMateusz Zalega int usb_cpu_stop(void); 2616297cfbSMateusz Zalega int usb_cpu_init_fail(void); 272731b9a8SJean-Christophe PLAGNIOL-VILLARD 282731b9a8SJean-Christophe PLAGNIOL-VILLARD static int cc_to_error[16] = { 292731b9a8SJean-Christophe PLAGNIOL-VILLARD 302731b9a8SJean-Christophe PLAGNIOL-VILLARD /* mapping of the OHCI CC status to error codes */ 312731b9a8SJean-Christophe PLAGNIOL-VILLARD /* No Error */ 0, 322731b9a8SJean-Christophe PLAGNIOL-VILLARD /* CRC Error */ USB_ST_CRC_ERR, 332731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Bit Stuff */ USB_ST_BIT_ERR, 342731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Data Togg */ USB_ST_CRC_ERR, 352731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Stall */ USB_ST_STALLED, 362731b9a8SJean-Christophe PLAGNIOL-VILLARD /* DevNotResp */ -1, 372731b9a8SJean-Christophe PLAGNIOL-VILLARD /* PIDCheck */ USB_ST_BIT_ERR, 382731b9a8SJean-Christophe PLAGNIOL-VILLARD /* UnExpPID */ USB_ST_BIT_ERR, 392731b9a8SJean-Christophe PLAGNIOL-VILLARD /* DataOver */ USB_ST_BUF_ERR, 402731b9a8SJean-Christophe PLAGNIOL-VILLARD /* DataUnder */ USB_ST_BUF_ERR, 412731b9a8SJean-Christophe PLAGNIOL-VILLARD /* reservd */ -1, 422731b9a8SJean-Christophe PLAGNIOL-VILLARD /* reservd */ -1, 432731b9a8SJean-Christophe PLAGNIOL-VILLARD /* BufferOver */ USB_ST_BUF_ERR, 442731b9a8SJean-Christophe PLAGNIOL-VILLARD /* BuffUnder */ USB_ST_BUF_ERR, 452731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Not Access */ -1, 462731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Not Access */ -1 472731b9a8SJean-Christophe PLAGNIOL-VILLARD }; 482731b9a8SJean-Christophe PLAGNIOL-VILLARD 492731b9a8SJean-Christophe PLAGNIOL-VILLARD static const char *cc_to_string[16] = { 502731b9a8SJean-Christophe PLAGNIOL-VILLARD "No Error", 512731b9a8SJean-Christophe PLAGNIOL-VILLARD "CRC: Last data packet from endpoint contained a CRC error.", 522731b9a8SJean-Christophe PLAGNIOL-VILLARD "BITSTUFFING: Last data packet from endpoint contained a bit " \ 532731b9a8SJean-Christophe PLAGNIOL-VILLARD "stuffing violation", 542731b9a8SJean-Christophe PLAGNIOL-VILLARD "DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID\n" \ 552731b9a8SJean-Christophe PLAGNIOL-VILLARD "that did not match the expected value.", 562731b9a8SJean-Christophe PLAGNIOL-VILLARD "STALL: TD was moved to the Done Queue because the endpoint returned" \ 572731b9a8SJean-Christophe PLAGNIOL-VILLARD " a STALL PID", 582731b9a8SJean-Christophe PLAGNIOL-VILLARD "DEVICENOTRESPONDING: Device did not respond to token (IN) or did\n" \ 592731b9a8SJean-Christophe PLAGNIOL-VILLARD "not provide a handshake (OUT)", 602731b9a8SJean-Christophe PLAGNIOL-VILLARD "PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID\n"\ 612731b9a8SJean-Christophe PLAGNIOL-VILLARD "(IN) or handshake (OUT)", 622731b9a8SJean-Christophe PLAGNIOL-VILLARD "UNEXPECTEDPID: Receive PID was not valid when encountered or PID\n" \ 632731b9a8SJean-Christophe PLAGNIOL-VILLARD "value is not defined.", 642731b9a8SJean-Christophe PLAGNIOL-VILLARD "DATAOVERRUN: The amount of data returned by the endpoint exceeded\n" \ 652731b9a8SJean-Christophe PLAGNIOL-VILLARD "either the size of the maximum data packet allowed\n" \ 662731b9a8SJean-Christophe PLAGNIOL-VILLARD "from the endpoint (found in MaximumPacketSize field\n" \ 672731b9a8SJean-Christophe PLAGNIOL-VILLARD "of ED) or the remaining buffer size.", 682731b9a8SJean-Christophe PLAGNIOL-VILLARD "DATAUNDERRUN: The endpoint returned less than MaximumPacketSize\n" \ 692731b9a8SJean-Christophe PLAGNIOL-VILLARD "and that amount was not sufficient to fill the\n" \ 702731b9a8SJean-Christophe PLAGNIOL-VILLARD "specified buffer", 712731b9a8SJean-Christophe PLAGNIOL-VILLARD "reserved1", 722731b9a8SJean-Christophe PLAGNIOL-VILLARD "reserved2", 732731b9a8SJean-Christophe PLAGNIOL-VILLARD "BUFFEROVERRUN: During an IN, HC received data from endpoint faster\n" \ 742731b9a8SJean-Christophe PLAGNIOL-VILLARD "than it could be written to system memory", 752731b9a8SJean-Christophe PLAGNIOL-VILLARD "BUFFERUNDERRUN: During an OUT, HC could not retrieve data from\n" \ 762731b9a8SJean-Christophe PLAGNIOL-VILLARD "system memory fast enough to keep up with data USB " \ 772731b9a8SJean-Christophe PLAGNIOL-VILLARD "data rate.", 782731b9a8SJean-Christophe PLAGNIOL-VILLARD "NOT ACCESSED: This code is set by software before the TD is placed" \ 792731b9a8SJean-Christophe PLAGNIOL-VILLARD "on a list to be processed by the HC.(1)", 802731b9a8SJean-Christophe PLAGNIOL-VILLARD "NOT ACCESSED: This code is set by software before the TD is placed" \ 812731b9a8SJean-Christophe PLAGNIOL-VILLARD "on a list to be processed by the HC.(2)", 822731b9a8SJean-Christophe PLAGNIOL-VILLARD }; 832731b9a8SJean-Christophe PLAGNIOL-VILLARD 842731b9a8SJean-Christophe PLAGNIOL-VILLARD /* ED States */ 852731b9a8SJean-Christophe PLAGNIOL-VILLARD 862731b9a8SJean-Christophe PLAGNIOL-VILLARD #define ED_NEW 0x00 872731b9a8SJean-Christophe PLAGNIOL-VILLARD #define ED_UNLINK 0x01 882731b9a8SJean-Christophe PLAGNIOL-VILLARD #define ED_OPER 0x02 892731b9a8SJean-Christophe PLAGNIOL-VILLARD #define ED_DEL 0x04 902731b9a8SJean-Christophe PLAGNIOL-VILLARD #define ED_URB_DEL 0x08 912731b9a8SJean-Christophe PLAGNIOL-VILLARD 922731b9a8SJean-Christophe PLAGNIOL-VILLARD /* usb_ohci_ed */ 932731b9a8SJean-Christophe PLAGNIOL-VILLARD struct ed { 942731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hwINFO; 952731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hwTailP; 962731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hwHeadP; 972731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hwNextED; 982731b9a8SJean-Christophe PLAGNIOL-VILLARD 992731b9a8SJean-Christophe PLAGNIOL-VILLARD struct ed *ed_prev; 1002731b9a8SJean-Christophe PLAGNIOL-VILLARD __u8 int_period; 1012731b9a8SJean-Christophe PLAGNIOL-VILLARD __u8 int_branch; 1022731b9a8SJean-Christophe PLAGNIOL-VILLARD __u8 int_load; 1032731b9a8SJean-Christophe PLAGNIOL-VILLARD __u8 int_interval; 1042731b9a8SJean-Christophe PLAGNIOL-VILLARD __u8 state; 1052731b9a8SJean-Christophe PLAGNIOL-VILLARD __u8 type; 1062731b9a8SJean-Christophe PLAGNIOL-VILLARD __u16 last_iso; 1072731b9a8SJean-Christophe PLAGNIOL-VILLARD struct ed *ed_rm_list; 1082731b9a8SJean-Christophe PLAGNIOL-VILLARD 1092731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_device *usb_dev; 1102731b9a8SJean-Christophe PLAGNIOL-VILLARD void *purb; 1112731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 unused[2]; 112f9a109b3SPeter Tyser } __attribute__((aligned(16))); 1132731b9a8SJean-Christophe PLAGNIOL-VILLARD typedef struct ed ed_t; 1142731b9a8SJean-Christophe PLAGNIOL-VILLARD 1152731b9a8SJean-Christophe PLAGNIOL-VILLARD 1162731b9a8SJean-Christophe PLAGNIOL-VILLARD /* TD info field */ 1172731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_CC 0xf0000000 1182731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) 1192731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) 1202731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_EC 0x0C000000 1212731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_T 0x03000000 1222731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_T_DATA0 0x02000000 1232731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_T_DATA1 0x03000000 1242731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_T_TOGGLE 0x00000000 1252731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_R 0x00040000 1262731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DI 0x00E00000 1272731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DI_SET(X) (((X) & 0x07)<< 21) 1282731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DP 0x00180000 1292731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DP_SETUP 0x00000000 1302731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DP_IN 0x00100000 1312731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DP_OUT 0x00080000 1322731b9a8SJean-Christophe PLAGNIOL-VILLARD 1332731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_ISO 0x00010000 1342731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DEL 0x00020000 1352731b9a8SJean-Christophe PLAGNIOL-VILLARD 1362731b9a8SJean-Christophe PLAGNIOL-VILLARD /* CC Codes */ 1372731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_CC_NOERROR 0x00 1382731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_CC_CRC 0x01 1392731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_CC_BITSTUFFING 0x02 1402731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_CC_DATATOGGLEM 0x03 1412731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_CC_STALL 0x04 1422731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DEVNOTRESP 0x05 1432731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_PIDCHECKFAIL 0x06 1442731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_UNEXPECTEDPID 0x07 1452731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DATAOVERRUN 0x08 1462731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_DATAUNDERRUN 0x09 1472731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_BUFFEROVERRUN 0x0C 1482731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_BUFFERUNDERRUN 0x0D 1492731b9a8SJean-Christophe PLAGNIOL-VILLARD #define TD_NOTACCESSED 0x0F 1502731b9a8SJean-Christophe PLAGNIOL-VILLARD 1512731b9a8SJean-Christophe PLAGNIOL-VILLARD 1522731b9a8SJean-Christophe PLAGNIOL-VILLARD #define MAXPSW 1 1532731b9a8SJean-Christophe PLAGNIOL-VILLARD 1542731b9a8SJean-Christophe PLAGNIOL-VILLARD struct td { 1552731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hwINFO; 1562731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hwCBP; /* Current Buffer Pointer */ 1572731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hwNextTD; /* Next TD Pointer */ 1582731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hwBE; /* Memory Buffer End Pointer */ 1592731b9a8SJean-Christophe PLAGNIOL-VILLARD 1602731b9a8SJean-Christophe PLAGNIOL-VILLARD /* #ifndef CONFIG_MPC5200 /\* this seems wrong *\/ */ 1612731b9a8SJean-Christophe PLAGNIOL-VILLARD __u16 hwPSW[MAXPSW]; 1622731b9a8SJean-Christophe PLAGNIOL-VILLARD /* #endif */ 1632731b9a8SJean-Christophe PLAGNIOL-VILLARD __u8 unused; 1642731b9a8SJean-Christophe PLAGNIOL-VILLARD __u8 index; 1652731b9a8SJean-Christophe PLAGNIOL-VILLARD struct ed *ed; 1662731b9a8SJean-Christophe PLAGNIOL-VILLARD struct td *next_dl_td; 1672731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_device *usb_dev; 1682731b9a8SJean-Christophe PLAGNIOL-VILLARD int transfer_len; 1692731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 data; 1702731b9a8SJean-Christophe PLAGNIOL-VILLARD 1712731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 unused2[2]; 172f9a109b3SPeter Tyser } __attribute__((aligned(32))); 1732731b9a8SJean-Christophe PLAGNIOL-VILLARD typedef struct td td_t; 1742731b9a8SJean-Christophe PLAGNIOL-VILLARD 1752731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_ED_SKIP (1 << 14) 1762731b9a8SJean-Christophe PLAGNIOL-VILLARD 1772731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 1782731b9a8SJean-Christophe PLAGNIOL-VILLARD * The HCCA (Host Controller Communications Area) is a 256 byte 1792731b9a8SJean-Christophe PLAGNIOL-VILLARD * structure defined in the OHCI spec. that the host controller is 1802731b9a8SJean-Christophe PLAGNIOL-VILLARD * told the base address of. It must be 256-byte aligned. 1812731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 1822731b9a8SJean-Christophe PLAGNIOL-VILLARD 1832731b9a8SJean-Christophe PLAGNIOL-VILLARD #define NUM_INTS 32 /* part of the OHCI standard */ 1842731b9a8SJean-Christophe PLAGNIOL-VILLARD struct ohci_hcca { 1852731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 int_table[NUM_INTS]; /* Interrupt ED table */ 1862731b9a8SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MPC5200) 1872731b9a8SJean-Christophe PLAGNIOL-VILLARD __u16 pad1; /* set to 0 on each frame_no change */ 1882731b9a8SJean-Christophe PLAGNIOL-VILLARD __u16 frame_no; /* current frame number */ 1892731b9a8SJean-Christophe PLAGNIOL-VILLARD #else 1902731b9a8SJean-Christophe PLAGNIOL-VILLARD __u16 frame_no; /* current frame number */ 1912731b9a8SJean-Christophe PLAGNIOL-VILLARD __u16 pad1; /* set to 0 on each frame_no change */ 1922731b9a8SJean-Christophe PLAGNIOL-VILLARD #endif 1932731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 done_head; /* info returned for an interrupt */ 1942731b9a8SJean-Christophe PLAGNIOL-VILLARD u8 reserved_for_hc[116]; 195f9a109b3SPeter Tyser } __attribute__((aligned(256))); 1962731b9a8SJean-Christophe PLAGNIOL-VILLARD 1972731b9a8SJean-Christophe PLAGNIOL-VILLARD 1982731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 1992731b9a8SJean-Christophe PLAGNIOL-VILLARD * Maximum number of root hub ports. 2002731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 2012731b9a8SJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2022731b9a8SJean-Christophe PLAGNIOL-VILLARD # error "CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS undefined!" 2032731b9a8SJean-Christophe PLAGNIOL-VILLARD #endif 2042731b9a8SJean-Christophe PLAGNIOL-VILLARD 2052731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 2062731b9a8SJean-Christophe PLAGNIOL-VILLARD * This is the structure of the OHCI controller's memory mapped I/O 207a5496a18SBecky Bruce * region. This is Memory Mapped I/O. You must use the ohci_readl() and 208a5496a18SBecky Bruce * ohci_writel() macros defined in this file to access these!! 2092731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 2102731b9a8SJean-Christophe PLAGNIOL-VILLARD struct ohci_regs { 2112731b9a8SJean-Christophe PLAGNIOL-VILLARD /* control and status registers */ 2122731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 revision; 2132731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 control; 2142731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 cmdstatus; 2152731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 intrstatus; 2162731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 intrenable; 2172731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 intrdisable; 2182731b9a8SJean-Christophe PLAGNIOL-VILLARD /* memory pointers */ 2192731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hcca; 2202731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 ed_periodcurrent; 2212731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 ed_controlhead; 2222731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 ed_controlcurrent; 2232731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 ed_bulkhead; 2242731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 ed_bulkcurrent; 2252731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 donehead; 2262731b9a8SJean-Christophe PLAGNIOL-VILLARD /* frame counters */ 2272731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 fminterval; 2282731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 fmremaining; 2292731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 fmnumber; 2302731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 periodicstart; 2312731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 lsthresh; 2322731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Root hub ports */ 2332731b9a8SJean-Christophe PLAGNIOL-VILLARD struct ohci_roothub_regs { 2342731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 a; 2352731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 b; 2362731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 status; 2372731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 portstatus[CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS]; 2382731b9a8SJean-Christophe PLAGNIOL-VILLARD } roothub; 239f9a109b3SPeter Tyser } __attribute__((aligned(32))); 2402731b9a8SJean-Christophe PLAGNIOL-VILLARD 2412731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Some EHCI controls */ 2422731b9a8SJean-Christophe PLAGNIOL-VILLARD #define EHCI_USBCMD_OFF 0x20 2432731b9a8SJean-Christophe PLAGNIOL-VILLARD #define EHCI_USBCMD_HCRESET (1 << 1) 2442731b9a8SJean-Christophe PLAGNIOL-VILLARD 2452731b9a8SJean-Christophe PLAGNIOL-VILLARD /* OHCI CONTROL AND STATUS REGISTER MASKS */ 2462731b9a8SJean-Christophe PLAGNIOL-VILLARD 2472731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 2482731b9a8SJean-Christophe PLAGNIOL-VILLARD * HcControl (control) register masks 2492731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 2502731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ 2512731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ 2522731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ 2532731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CTRL_CLE (1 << 4) /* control list enable */ 2542731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ 2552731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ 2562731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ 2572731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ 2582731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ 2592731b9a8SJean-Christophe PLAGNIOL-VILLARD 2602731b9a8SJean-Christophe PLAGNIOL-VILLARD /* pre-shifted values for HCFS */ 2612731b9a8SJean-Christophe PLAGNIOL-VILLARD # define OHCI_USB_RESET (0 << 6) 2622731b9a8SJean-Christophe PLAGNIOL-VILLARD # define OHCI_USB_RESUME (1 << 6) 2632731b9a8SJean-Christophe PLAGNIOL-VILLARD # define OHCI_USB_OPER (2 << 6) 2642731b9a8SJean-Christophe PLAGNIOL-VILLARD # define OHCI_USB_SUSPEND (3 << 6) 2652731b9a8SJean-Christophe PLAGNIOL-VILLARD 2662731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 2672731b9a8SJean-Christophe PLAGNIOL-VILLARD * HcCommandStatus (cmdstatus) register masks 2682731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 2692731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_HCR (1 << 0) /* host controller reset */ 2702731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_CLF (1 << 1) /* control list filled */ 2712731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_BLF (1 << 2) /* bulk list filled */ 2722731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_OCR (1 << 3) /* ownership change request */ 2732731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_SOC (3 << 16) /* scheduling overrun count */ 2742731b9a8SJean-Christophe PLAGNIOL-VILLARD 2752731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 2762731b9a8SJean-Christophe PLAGNIOL-VILLARD * masks used with interrupt registers: 2772731b9a8SJean-Christophe PLAGNIOL-VILLARD * HcInterruptStatus (intrstatus) 2782731b9a8SJean-Christophe PLAGNIOL-VILLARD * HcInterruptEnable (intrenable) 2792731b9a8SJean-Christophe PLAGNIOL-VILLARD * HcInterruptDisable (intrdisable) 2802731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 2812731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ 2822731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ 2832731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_INTR_SF (1 << 2) /* start frame */ 2842731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_INTR_RD (1 << 3) /* resume detect */ 2852731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ 2862731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ 2872731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ 2882731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_INTR_OC (1 << 30) /* ownership change */ 2892731b9a8SJean-Christophe PLAGNIOL-VILLARD #define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ 2902731b9a8SJean-Christophe PLAGNIOL-VILLARD 2912731b9a8SJean-Christophe PLAGNIOL-VILLARD 2922731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Virtual Root HUB */ 2932731b9a8SJean-Christophe PLAGNIOL-VILLARD struct virt_root_hub { 2942731b9a8SJean-Christophe PLAGNIOL-VILLARD int devnum; /* Address of Root Hub endpoint */ 2952731b9a8SJean-Christophe PLAGNIOL-VILLARD void *dev; /* was urb */ 2962731b9a8SJean-Christophe PLAGNIOL-VILLARD void *int_addr; 2972731b9a8SJean-Christophe PLAGNIOL-VILLARD int send; 2982731b9a8SJean-Christophe PLAGNIOL-VILLARD int interval; 2992731b9a8SJean-Christophe PLAGNIOL-VILLARD }; 3002731b9a8SJean-Christophe PLAGNIOL-VILLARD 3012731b9a8SJean-Christophe PLAGNIOL-VILLARD /* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ 3022731b9a8SJean-Christophe PLAGNIOL-VILLARD 3032731b9a8SJean-Christophe PLAGNIOL-VILLARD /* destination of request */ 3042731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_INTERFACE 0x01 3052731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_ENDPOINT 0x02 3062731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_OTHER 0x03 3072731b9a8SJean-Christophe PLAGNIOL-VILLARD 3082731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_CLASS 0x20 3092731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_VENDOR 0x40 3102731b9a8SJean-Christophe PLAGNIOL-VILLARD 3112731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Requests: bRequest << 8 | bmRequestType */ 3122731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_GET_STATUS 0x0080 3132731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_CLEAR_FEATURE 0x0100 3142731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_SET_FEATURE 0x0300 3152731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_SET_ADDRESS 0x0500 3162731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_GET_DESCRIPTOR 0x0680 3172731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_SET_DESCRIPTOR 0x0700 3182731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_GET_CONFIGURATION 0x0880 3192731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_SET_CONFIGURATION 0x0900 3202731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_GET_STATE 0x0280 3212731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_GET_INTERFACE 0x0A80 3222731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_SET_INTERFACE 0x0B00 3232731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_SYNC_FRAME 0x0C80 3242731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Our Vendor Specific Request */ 3252731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_SET_EP 0x2000 3262731b9a8SJean-Christophe PLAGNIOL-VILLARD 3272731b9a8SJean-Christophe PLAGNIOL-VILLARD 3282731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Hub port features */ 3292731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PORT_CONNECTION 0x00 3302731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PORT_ENABLE 0x01 3312731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PORT_SUSPEND 0x02 3322731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PORT_OVER_CURRENT 0x03 3332731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PORT_RESET 0x04 3342731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PORT_POWER 0x08 3352731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PORT_LOW_SPEED 0x09 3362731b9a8SJean-Christophe PLAGNIOL-VILLARD 3372731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_C_PORT_CONNECTION 0x10 3382731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_C_PORT_ENABLE 0x11 3392731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_C_PORT_SUSPEND 0x12 3402731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_C_PORT_OVER_CURRENT 0x13 3412731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_C_PORT_RESET 0x14 3422731b9a8SJean-Christophe PLAGNIOL-VILLARD 3432731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Hub features */ 3442731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_C_HUB_LOCAL_POWER 0x00 3452731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_C_HUB_OVER_CURRENT 0x01 3462731b9a8SJean-Christophe PLAGNIOL-VILLARD 3472731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_DEVICE_REMOTE_WAKEUP 0x00 3482731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_ENDPOINT_STALL 0x01 3492731b9a8SJean-Christophe PLAGNIOL-VILLARD 3502731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_ACK 0x01 3512731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_REQ_ERR -1 3522731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_NACK 0x00 3532731b9a8SJean-Christophe PLAGNIOL-VILLARD 3542731b9a8SJean-Christophe PLAGNIOL-VILLARD 3552731b9a8SJean-Christophe PLAGNIOL-VILLARD /* OHCI ROOT HUB REGISTER MASKS */ 3562731b9a8SJean-Christophe PLAGNIOL-VILLARD 3572731b9a8SJean-Christophe PLAGNIOL-VILLARD /* roothub.portstatus [i] bits */ 3582731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_CCS 0x00000001 /* current connect status */ 3592731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_PES 0x00000002 /* port enable status*/ 3602731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_PSS 0x00000004 /* port suspend status */ 3612731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_POCI 0x00000008 /* port over current indicator */ 3622731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_PRS 0x00000010 /* port reset status */ 3632731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_PPS 0x00000100 /* port power status */ 3642731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_LSDA 0x00000200 /* low speed device attached */ 3652731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_CSC 0x00010000 /* connect status change */ 3662731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_PESC 0x00020000 /* port enable status change */ 3672731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_PSSC 0x00040000 /* port suspend status change */ 3682731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_OCIC 0x00080000 /* over current indicator change */ 3692731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_PS_PRSC 0x00100000 /* port reset status change */ 3702731b9a8SJean-Christophe PLAGNIOL-VILLARD 3712731b9a8SJean-Christophe PLAGNIOL-VILLARD /* roothub.status bits */ 3722731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_HS_LPS 0x00000001 /* local power status */ 3732731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_HS_OCI 0x00000002 /* over current indicator */ 3742731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ 3752731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_HS_LPSC 0x00010000 /* local power status change */ 3762731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_HS_OCIC 0x00020000 /* over current indicator change */ 3772731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ 3782731b9a8SJean-Christophe PLAGNIOL-VILLARD 3792731b9a8SJean-Christophe PLAGNIOL-VILLARD /* roothub.b masks */ 3802731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_B_DR 0x0000ffff /* device removable flags */ 3812731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_B_PPCM 0xffff0000 /* port power control mask */ 3822731b9a8SJean-Christophe PLAGNIOL-VILLARD 3832731b9a8SJean-Christophe PLAGNIOL-VILLARD /* roothub.a masks */ 3842731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_A_NDP (0xff << 0) /* number of downstream ports */ 3852731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_A_PSM (1 << 8) /* power switching mode */ 3862731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_A_NPS (1 << 9) /* no power switching */ 3872731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_A_DT (1 << 10) /* device type (mbz) */ 3882731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_A_OCPM (1 << 11) /* over current protection mode */ 3892731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_A_NOCP (1 << 12) /* no over current protection */ 3902731b9a8SJean-Christophe PLAGNIOL-VILLARD #define RH_A_POTPGT (0xff << 24) /* power on to power good time */ 3912731b9a8SJean-Christophe PLAGNIOL-VILLARD 3922731b9a8SJean-Christophe PLAGNIOL-VILLARD /* urb */ 3932731b9a8SJean-Christophe PLAGNIOL-VILLARD #define N_URB_TD 48 3942731b9a8SJean-Christophe PLAGNIOL-VILLARD typedef struct 3952731b9a8SJean-Christophe PLAGNIOL-VILLARD { 3962731b9a8SJean-Christophe PLAGNIOL-VILLARD ed_t *ed; 3972731b9a8SJean-Christophe PLAGNIOL-VILLARD __u16 length; /* number of tds associated with this request */ 3982731b9a8SJean-Christophe PLAGNIOL-VILLARD __u16 td_cnt; /* number of tds already serviced */ 3992731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_device *dev; 4002731b9a8SJean-Christophe PLAGNIOL-VILLARD int state; 4012731b9a8SJean-Christophe PLAGNIOL-VILLARD unsigned long pipe; 4022731b9a8SJean-Christophe PLAGNIOL-VILLARD void *transfer_buffer; 4032731b9a8SJean-Christophe PLAGNIOL-VILLARD int transfer_buffer_length; 4042731b9a8SJean-Christophe PLAGNIOL-VILLARD int interval; 4052731b9a8SJean-Christophe PLAGNIOL-VILLARD int actual_length; 4062731b9a8SJean-Christophe PLAGNIOL-VILLARD int finished; 4072731b9a8SJean-Christophe PLAGNIOL-VILLARD td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ 4082731b9a8SJean-Christophe PLAGNIOL-VILLARD } urb_priv_t; 4092731b9a8SJean-Christophe PLAGNIOL-VILLARD #define URB_DEL 1 4102731b9a8SJean-Christophe PLAGNIOL-VILLARD 41119d95d57SHans de Goede #define NUM_EDS 8 /* num of preallocated endpoint descriptors */ 41219d95d57SHans de Goede 413*3c5497d8SHans de Goede #define NUM_TD 64 /* we need more TDs than EDs */ 414*3c5497d8SHans de Goede 41519d95d57SHans de Goede typedef struct ohci_device { 41619d95d57SHans de Goede ed_t ed[NUM_EDS] __aligned(16); 417*3c5497d8SHans de Goede td_t tds[NUM_TD] __aligned(32); 41819d95d57SHans de Goede int ed_cnt; 41919d95d57SHans de Goede } ohci_dev_t; 42019d95d57SHans de Goede 4212731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 4222731b9a8SJean-Christophe PLAGNIOL-VILLARD * This is the full ohci controller description 4232731b9a8SJean-Christophe PLAGNIOL-VILLARD * 4242731b9a8SJean-Christophe PLAGNIOL-VILLARD * Note how the "proper" USB information is just 4252731b9a8SJean-Christophe PLAGNIOL-VILLARD * a subset of what the full implementation needs. (Linus) 4262731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 4272731b9a8SJean-Christophe PLAGNIOL-VILLARD 4282731b9a8SJean-Christophe PLAGNIOL-VILLARD 4292731b9a8SJean-Christophe PLAGNIOL-VILLARD typedef struct ohci { 43019d95d57SHans de Goede /* this allocates EDs for all possible endpoints */ 431*3c5497d8SHans de Goede struct ohci_device ohci_dev __aligned(32); 4322731b9a8SJean-Christophe PLAGNIOL-VILLARD struct ohci_hcca *hcca; /* hcca */ 4332731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dma_addr_t hcca_dma;*/ 4342731b9a8SJean-Christophe PLAGNIOL-VILLARD 4352731b9a8SJean-Christophe PLAGNIOL-VILLARD int irq; 4362731b9a8SJean-Christophe PLAGNIOL-VILLARD int disabled; /* e.g. got a UE, we're hung */ 4372731b9a8SJean-Christophe PLAGNIOL-VILLARD int sleeping; 4382731b9a8SJean-Christophe PLAGNIOL-VILLARD unsigned long flags; /* for HC bugs */ 4392731b9a8SJean-Christophe PLAGNIOL-VILLARD 4402731b9a8SJean-Christophe PLAGNIOL-VILLARD struct ohci_regs *regs; /* OHCI controller's memory */ 4412731b9a8SJean-Christophe PLAGNIOL-VILLARD 4422731b9a8SJean-Christophe PLAGNIOL-VILLARD int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ 4432731b9a8SJean-Christophe PLAGNIOL-VILLARD ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ 4442731b9a8SJean-Christophe PLAGNIOL-VILLARD ed_t *ed_bulktail; /* last endpoint of bulk list */ 4452731b9a8SJean-Christophe PLAGNIOL-VILLARD ed_t *ed_controltail; /* last endpoint of control list */ 4462731b9a8SJean-Christophe PLAGNIOL-VILLARD int intrstatus; 4472731b9a8SJean-Christophe PLAGNIOL-VILLARD __u32 hc_control; /* copy of the hc control reg */ 4482731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_device *dev[32]; 4492731b9a8SJean-Christophe PLAGNIOL-VILLARD struct virt_root_hub rh; 4502731b9a8SJean-Christophe PLAGNIOL-VILLARD 4512731b9a8SJean-Christophe PLAGNIOL-VILLARD const char *slot_name; 4522731b9a8SJean-Christophe PLAGNIOL-VILLARD } ohci_t; 4532731b9a8SJean-Christophe PLAGNIOL-VILLARD 4542731b9a8SJean-Christophe PLAGNIOL-VILLARD /* hcd */ 4552731b9a8SJean-Christophe PLAGNIOL-VILLARD /* endpoint */ 4562731b9a8SJean-Christophe PLAGNIOL-VILLARD static int ep_link(ohci_t * ohci, ed_t * ed); 4572731b9a8SJean-Christophe PLAGNIOL-VILLARD static int ep_unlink(ohci_t * ohci, ed_t * ed); 45819d95d57SHans de Goede static ed_t *ep_add_ed(ohci_dev_t *ohci_dev, struct usb_device *usb_dev, 45919d95d57SHans de Goede unsigned long pipe, int interval, int load); 4602731b9a8SJean-Christophe PLAGNIOL-VILLARD 4612731b9a8SJean-Christophe PLAGNIOL-VILLARD /*-------------------------------------------------------------------------*/ 4622731b9a8SJean-Christophe PLAGNIOL-VILLARD 4632731b9a8SJean-Christophe PLAGNIOL-VILLARD /* TDs ... */ 4642731b9a8SJean-Christophe PLAGNIOL-VILLARD static inline struct td * 465*3c5497d8SHans de Goede td_alloc (ohci_dev_t *ohci_dev, struct usb_device *usb_dev) 4662731b9a8SJean-Christophe PLAGNIOL-VILLARD { 4672731b9a8SJean-Christophe PLAGNIOL-VILLARD int i; 4682731b9a8SJean-Christophe PLAGNIOL-VILLARD struct td *td; 4692731b9a8SJean-Christophe PLAGNIOL-VILLARD 4702731b9a8SJean-Christophe PLAGNIOL-VILLARD td = NULL; 4712731b9a8SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < NUM_TD; i++) 4722731b9a8SJean-Christophe PLAGNIOL-VILLARD { 473*3c5497d8SHans de Goede if (ohci_dev->tds[i].usb_dev == NULL) 4742731b9a8SJean-Christophe PLAGNIOL-VILLARD { 475*3c5497d8SHans de Goede td = &ohci_dev->tds[i]; 4762731b9a8SJean-Christophe PLAGNIOL-VILLARD td->usb_dev = usb_dev; 4772731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 4782731b9a8SJean-Christophe PLAGNIOL-VILLARD } 4792731b9a8SJean-Christophe PLAGNIOL-VILLARD } 4802731b9a8SJean-Christophe PLAGNIOL-VILLARD 4812731b9a8SJean-Christophe PLAGNIOL-VILLARD return td; 4822731b9a8SJean-Christophe PLAGNIOL-VILLARD } 4832731b9a8SJean-Christophe PLAGNIOL-VILLARD 4842731b9a8SJean-Christophe PLAGNIOL-VILLARD static inline void 4852731b9a8SJean-Christophe PLAGNIOL-VILLARD ed_free (struct ed *ed) 4862731b9a8SJean-Christophe PLAGNIOL-VILLARD { 4872731b9a8SJean-Christophe PLAGNIOL-VILLARD ed->usb_dev = NULL; 4882731b9a8SJean-Christophe PLAGNIOL-VILLARD } 489