working on USB device scan
This commit is contained in:
@@ -23,43 +23,42 @@
|
|||||||
#define USB_EHCI_H
|
#define USB_EHCI_H
|
||||||
|
|
||||||
#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 5
|
#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 5
|
||||||
#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS)
|
|
||||||
#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
|
/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
|
||||||
#define DeviceRequest \
|
#define DeviceRequest \
|
||||||
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
|
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
|
||||||
|
|
||||||
#define DeviceOutRequest \
|
#define DeviceOutRequest \
|
||||||
((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
|
((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
|
||||||
|
|
||||||
#define InterfaceRequest \
|
#define InterfaceRequest \
|
||||||
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
||||||
|
|
||||||
#define EndpointRequest \
|
#define EndpointRequest \
|
||||||
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
||||||
|
|
||||||
#define EndpointOutRequest \
|
#define EndpointOutRequest \
|
||||||
((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register Space.
|
* Register Space.
|
||||||
*/
|
*/
|
||||||
struct ehci_hccr {
|
struct ehci_hccr
|
||||||
uint32_t cr_capbase;
|
{
|
||||||
|
uint32_t cr_capbase;
|
||||||
#define HC_LENGTH(p) (((p) >> 0) & 0x00ff)
|
#define HC_LENGTH(p) (((p) >> 0) & 0x00ff)
|
||||||
#define HC_VERSION(p) (((p) >> 16) & 0xffff)
|
#define HC_VERSION(p) (((p) >> 16) & 0xffff)
|
||||||
uint32_t cr_hcsparams;
|
uint32_t cr_hcsparams;
|
||||||
#define HCS_PPC(p) ((p) & (1 << 4))
|
#define HCS_PPC(p) ((p) & (1 << 4))
|
||||||
#define HCS_INDICATOR(p) ((p) & (1 << 16)) /* Port indicators */
|
#define HCS_INDICATOR(p) ((p) & (1 << 16)) /* Port indicators */
|
||||||
#define HCS_N_PORTS(p) (((p) >> 0) & 0xf)
|
#define HCS_N_PORTS(p) (((p) >> 0) & 0xf)
|
||||||
uint32_t cr_hccparams;
|
uint32_t cr_hccparams;
|
||||||
uint8_t cr_hcsp_portrt[8];
|
uint8_t cr_hcsp_portrt[8];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct ehci_hcor {
|
struct ehci_hcor
|
||||||
uint32_t or_usbcmd;
|
{
|
||||||
|
uint32_t or_usbcmd;
|
||||||
#define CMD_PARK (1 << 11) /* enable "park" */
|
#define CMD_PARK (1 << 11) /* enable "park" */
|
||||||
#define CMD_PARK_CNT(c) (((c) >> 8) & 3) /* how many transfers to park */
|
#define CMD_PARK_CNT(c) (((c) >> 8) & 3) /* how many transfers to park */
|
||||||
#define CMD_ASE (1 << 5) /* async schedule enable */
|
#define CMD_ASE (1 << 5) /* async schedule enable */
|
||||||
@@ -68,7 +67,7 @@ struct ehci_hcor {
|
|||||||
#define CMD_PSE (1 << 4) /* periodic schedule enable */
|
#define CMD_PSE (1 << 4) /* periodic schedule enable */
|
||||||
#define CMD_RESET (1 << 1) /* reset HC not bus */
|
#define CMD_RESET (1 << 1) /* reset HC not bus */
|
||||||
#define CMD_RUN (1 << 0) /* start/stop HC */
|
#define CMD_RUN (1 << 0) /* start/stop HC */
|
||||||
uint32_t or_usbsts;
|
uint32_t or_usbsts;
|
||||||
#define STD_ASS (1 << 15)
|
#define STD_ASS (1 << 15)
|
||||||
#define STS_PSSTAT (1 << 14)
|
#define STS_PSSTAT (1 << 14)
|
||||||
#define STS_RECL (1 << 13)
|
#define STS_RECL (1 << 13)
|
||||||
@@ -79,55 +78,55 @@ struct ehci_hcor {
|
|||||||
#define STS_PCD (1 << 2)
|
#define STS_PCD (1 << 2)
|
||||||
#define STS_USBERRINT (1 << 1)
|
#define STS_USBERRINT (1 << 1)
|
||||||
#define STS_USBINT (1 << 0)
|
#define STS_USBINT (1 << 0)
|
||||||
uint32_t or_usbintr;
|
uint32_t or_usbintr;
|
||||||
#define INTR_IAAE (1 << 5)
|
#define INTR_IAAE (1 << 5)
|
||||||
#define INTR_HSEE (1 << 4)
|
#define INTR_HSEE (1 << 4)
|
||||||
#define INTR_FLRE (1 << 3)
|
#define INTR_FLRE (1 << 3)
|
||||||
#define INTR_PCDE (1 << 2)
|
#define INTR_PCDE (1 << 2)
|
||||||
#define INTR_USBERRINTE (1 << 1)
|
#define INTR_USBERRINTE (1 << 1)
|
||||||
#define INTR_USBINTE (1 << 0)
|
#define INTR_USBINTE (1 << 0)
|
||||||
uint32_t or_frindex;
|
uint32_t or_frindex;
|
||||||
uint32_t or_ctrldssegment;
|
uint32_t or_ctrldssegment;
|
||||||
uint32_t or_periodiclistbase;
|
uint32_t or_periodiclistbase;
|
||||||
uint32_t or_asynclistaddr;
|
uint32_t or_asynclistaddr;
|
||||||
uint32_t _reserved_[9];
|
uint32_t _reserved_[9];
|
||||||
uint32_t or_configflag;
|
uint32_t or_configflag;
|
||||||
#define FLAG_CF (1 << 0) /* true: we'll support "high speed" */
|
#define FLAG_CF (1 << 0) /* true: we'll support "high speed" */
|
||||||
uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS];
|
uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS];
|
||||||
uint32_t or_systune;
|
uint32_t or_systune;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#define USBMODE 0x68 /* USB Device mode */
|
#define USBMODE 0x68 /* USB Device mode */
|
||||||
#define USBMODE_SDIS (1 << 3) /* Stream disable */
|
#define USBMODE_SDIS (1 << 3) /* Stream disable */
|
||||||
#define USBMODE_BE (1 << 2) /* BE/LE endiannes select */
|
#define USBMODE_BE (1 << 2) /* BE/LE endiannes select */
|
||||||
#define USBMODE_CM_HC (3 << 0) /* host controller mode */
|
#define USBMODE_CM_HC (3 << 0) /* host controller mode */
|
||||||
#define USBMODE_CM_IDLE (0 << 0) /* idle state */
|
#define USBMODE_CM_IDLE (0 << 0) /* idle state */
|
||||||
|
|
||||||
/* Interface descriptor */
|
/* Interface descriptor */
|
||||||
struct usb_linux_interface_descriptor
|
struct usb_linux_interface_descriptor
|
||||||
{
|
{
|
||||||
unsigned char bLength;
|
unsigned char bLength;
|
||||||
unsigned char bDescriptorType;
|
unsigned char bDescriptorType;
|
||||||
unsigned char bInterfaceNumber;
|
unsigned char bInterfaceNumber;
|
||||||
unsigned char bAlternateSetting;
|
unsigned char bAlternateSetting;
|
||||||
unsigned char bNumEndpoints;
|
unsigned char bNumEndpoints;
|
||||||
unsigned char bInterfaceClass;
|
unsigned char bInterfaceClass;
|
||||||
unsigned char bInterfaceSubClass;
|
unsigned char bInterfaceSubClass;
|
||||||
unsigned char bInterfaceProtocol;
|
unsigned char bInterfaceProtocol;
|
||||||
unsigned char iInterface;
|
unsigned char iInterface;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/* Configuration descriptor information.. */
|
/* Configuration descriptor information.. */
|
||||||
struct usb_linux_config_descriptor
|
struct usb_linux_config_descriptor
|
||||||
{
|
{
|
||||||
unsigned char bLength;
|
unsigned char bLength;
|
||||||
unsigned char bDescriptorType;
|
unsigned char bDescriptorType;
|
||||||
unsigned short wTotalLength;
|
unsigned short wTotalLength;
|
||||||
unsigned char bNumInterfaces;
|
unsigned char bNumInterfaces;
|
||||||
unsigned char bConfigurationValue;
|
unsigned char bConfigurationValue;
|
||||||
unsigned char iConfiguration;
|
unsigned char iConfiguration;
|
||||||
unsigned char bmAttributes;
|
unsigned char bmAttributes;
|
||||||
unsigned char MaxPower;
|
unsigned char MaxPower;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#if defined CONFIG_EHCI_DESC_BIG_ENDIAN
|
#if defined CONFIG_EHCI_DESC_BIG_ENDIAN
|
||||||
@@ -178,31 +177,31 @@ struct usb_linux_config_descriptor
|
|||||||
/* Queue Element Transfer Descriptor (qTD). */
|
/* Queue Element Transfer Descriptor (qTD). */
|
||||||
struct qTD
|
struct qTD
|
||||||
{
|
{
|
||||||
uint32_t qt_next;
|
uint32_t qt_next;
|
||||||
#define QT_NEXT_TERMINATE 1
|
#define QT_NEXT_TERMINATE 1
|
||||||
uint32_t qt_altnext;
|
uint32_t qt_altnext;
|
||||||
uint32_t qt_token;
|
uint32_t qt_token;
|
||||||
uint32_t qt_buffer[5];
|
uint32_t qt_buffer[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Queue Head (QH). */
|
/* Queue Head (QH). */
|
||||||
struct QH
|
struct QH
|
||||||
{
|
{
|
||||||
uint32_t qh_link;
|
uint32_t qh_link;
|
||||||
#define QH_LINK_TERMINATE 1
|
#define QH_LINK_TERMINATE 1
|
||||||
#define QH_LINK_TYPE_ITD 0
|
#define QH_LINK_TYPE_ITD 0
|
||||||
#define QH_LINK_TYPE_QH 2
|
#define QH_LINK_TYPE_QH 2
|
||||||
#define QH_LINK_TYPE_SITD 4
|
#define QH_LINK_TYPE_SITD 4
|
||||||
#define QH_LINK_TYPE_FSTN 6
|
#define QH_LINK_TYPE_FSTN 6
|
||||||
uint32_t qh_endpt1;
|
uint32_t qh_endpt1;
|
||||||
uint32_t qh_endpt2;
|
uint32_t qh_endpt2;
|
||||||
uint32_t qh_curtd;
|
uint32_t qh_curtd;
|
||||||
struct qTD qh_overlay;
|
struct qTD qh_overlay;
|
||||||
/*
|
/*
|
||||||
* Add dummy fill value to make the size of this struct
|
* Add dummy fill value to make the size of this struct
|
||||||
* aligned to 32 bytes
|
* aligned to 32 bytes
|
||||||
*/
|
*/
|
||||||
uint8_t fill[16];
|
uint8_t fill[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Low level init functions */
|
/* Low level init functions */
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ extern long *tab_funcs_pci;
|
|||||||
#define __u8 uint8_t
|
#define __u8 uint8_t
|
||||||
#define __u16 uint16_t
|
#define __u16 uint16_t
|
||||||
#define __u32 uint32_t
|
#define __u32 uint32_t
|
||||||
#define u8 uint8_t
|
//#define u8 uint8_t
|
||||||
#define u16 uint16_t
|
#define u16 uint16_t
|
||||||
#define u32 uint32_t
|
#define u32 uint32_t
|
||||||
#define uint8_t uint8_t
|
#define uint8_t uint8_t
|
||||||
@@ -70,126 +70,126 @@ extern int sprintD(char *s, const char *fmt, ...);
|
|||||||
/* String descriptor */
|
/* String descriptor */
|
||||||
struct usb_string_descriptor
|
struct usb_string_descriptor
|
||||||
{
|
{
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint16_t wData[1];
|
uint16_t wData[1];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/* device request (setup) */
|
/* device request (setup) */
|
||||||
struct devrequest
|
struct devrequest
|
||||||
{
|
{
|
||||||
uint8_t requesttype;
|
uint8_t requesttype;
|
||||||
uint8_t request;
|
uint8_t request;
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/* All standard descriptors have these 2 fields in common */
|
/* All standard descriptors have these 2 fields in common */
|
||||||
struct usb_descriptor_header
|
struct usb_descriptor_header
|
||||||
{
|
{
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/* Device descriptor */
|
/* Device descriptor */
|
||||||
struct usb_device_descriptor
|
struct usb_device_descriptor
|
||||||
{
|
{
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint16_t bcdUSB;
|
uint16_t bcdUSB;
|
||||||
uint8_t bDeviceClass;
|
uint8_t bDeviceClass;
|
||||||
uint8_t bDeviceSubClass;
|
uint8_t bDeviceSubClass;
|
||||||
uint8_t bDeviceProtocol;
|
uint8_t bDeviceProtocol;
|
||||||
uint8_t bMaxPacketSize0;
|
uint8_t bMaxPacketSize0;
|
||||||
uint16_t idVendor;
|
uint16_t idVendor;
|
||||||
uint16_t idProduct;
|
uint16_t idProduct;
|
||||||
uint16_t bcdDevice;
|
uint16_t bcdDevice;
|
||||||
uint8_t iManufacturer;
|
uint8_t iManufacturer;
|
||||||
uint8_t iProduct;
|
uint8_t iProduct;
|
||||||
uint8_t iSerialNumber;
|
uint8_t iSerialNumber;
|
||||||
uint8_t bNumConfigurations;
|
uint8_t bNumConfigurations;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/* Endpoint descriptor */
|
/* Endpoint descriptor */
|
||||||
struct usb_endpoint_descriptor
|
struct usb_endpoint_descriptor
|
||||||
{
|
{
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint8_t bEndpointAddress;
|
uint8_t bEndpointAddress;
|
||||||
uint8_t bmAttributes;
|
uint8_t bmAttributes;
|
||||||
uint16_t wMaxPacketSize;
|
uint16_t wMaxPacketSize;
|
||||||
uint8_t bInterval;
|
uint8_t bInterval;
|
||||||
uint8_t bRefresh;
|
uint8_t bRefresh;
|
||||||
uint8_t bSynchAddress;
|
uint8_t bSynchAddress;
|
||||||
} __attribute__ ((packed)) __attribute__ ((aligned(2)));
|
} __attribute__ ((packed)) __attribute__ ((aligned(2)));
|
||||||
|
|
||||||
/* Interface descriptor */
|
/* Interface descriptor */
|
||||||
struct usb_interface_descriptor
|
struct usb_interface_descriptor
|
||||||
{
|
{
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint8_t bInterfaceNumber;
|
uint8_t bInterfaceNumber;
|
||||||
uint8_t bAlternateSetting;
|
uint8_t bAlternateSetting;
|
||||||
uint8_t bNumEndpoints;
|
uint8_t bNumEndpoints;
|
||||||
uint8_t bInterfaceClass;
|
uint8_t bInterfaceClass;
|
||||||
uint8_t bInterfaceSubClass;
|
uint8_t bInterfaceSubClass;
|
||||||
uint8_t bInterfaceProtocol;
|
uint8_t bInterfaceProtocol;
|
||||||
uint8_t iInterface;
|
uint8_t iInterface;
|
||||||
|
|
||||||
uint8_t no_of_ep;
|
uint8_t no_of_ep;
|
||||||
uint8_t num_altsetting;
|
uint8_t num_altsetting;
|
||||||
uint8_t act_altsetting;
|
uint8_t act_altsetting;
|
||||||
|
|
||||||
struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
|
struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
/* Configuration descriptor information.. */
|
/* Configuration descriptor information.. */
|
||||||
struct usb_config_descriptor
|
struct usb_config_descriptor
|
||||||
{
|
{
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint16_t wTotalLength;
|
uint16_t wTotalLength;
|
||||||
uint8_t bNumInterfaces;
|
uint8_t bNumInterfaces;
|
||||||
uint8_t bConfigurationValue;
|
uint8_t bConfigurationValue;
|
||||||
uint8_t iConfiguration;
|
uint8_t iConfiguration;
|
||||||
uint8_t bmAttributes;
|
uint8_t bmAttributes;
|
||||||
uint8_t MaxPower;
|
uint8_t MaxPower;
|
||||||
|
|
||||||
uint8_t no_of_if; /* number of interfaces */
|
uint8_t no_of_if; /* number of interfaces */
|
||||||
struct usb_interface_descriptor if_desc[USB_MAXINTERFACES];
|
struct usb_interface_descriptor if_desc[USB_MAXINTERFACES];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
/* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
|
/* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
|
||||||
PACKET_SIZE_8 = 0,
|
PACKET_SIZE_8 = 0,
|
||||||
PACKET_SIZE_16 = 1,
|
PACKET_SIZE_16 = 1,
|
||||||
PACKET_SIZE_32 = 2,
|
PACKET_SIZE_32 = 2,
|
||||||
PACKET_SIZE_64 = 3,
|
PACKET_SIZE_64 = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usb_device
|
struct usb_device
|
||||||
{
|
{
|
||||||
int devnum; /* Device number on USB bus */
|
int devnum; /* Device number on USB bus */
|
||||||
int speed; /* full/low/high */
|
int speed; /* full/low/high */
|
||||||
char mf[32]; /* manufacturer */
|
char mf[32]; /* manufacturer */
|
||||||
char prod[32]; /* product */
|
char prod[32]; /* product */
|
||||||
char serial[32]; /* serial number */
|
char serial[32]; /* serial number */
|
||||||
|
|
||||||
/* Maximum packet size; one of: PACKET_SIZE_* */
|
/* Maximum packet size; one of: PACKET_SIZE_* */
|
||||||
int maxpacketsize;
|
int maxpacketsize;
|
||||||
|
|
||||||
/* one bit for each endpoint ([0] = IN, [1] = OUT) */
|
/* one bit for each endpoint ([0] = IN, [1] = OUT) */
|
||||||
unsigned int toggle[2];
|
unsigned int toggle[2];
|
||||||
|
|
||||||
/* endpoint halts; one bit per endpoint # & direction;
|
/* endpoint halts; one bit per endpoint # & direction;
|
||||||
* [0] = IN, [1] = OUT
|
* [0] = IN, [1] = OUT
|
||||||
*/
|
*/
|
||||||
unsigned int halted[2];
|
unsigned int halted[2];
|
||||||
int epmaxpacketin[16]; /* INput endpoint specific maximums */
|
int epmaxpacketin[16]; /* INput endpoint specific maximums */
|
||||||
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */
|
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */
|
||||||
|
|
||||||
int configno; /* selected config number */
|
int configno; /* selected config number */
|
||||||
struct usb_device_descriptor descriptor; /* Device Descriptor */
|
struct usb_device_descriptor descriptor; /* Device Descriptor */
|
||||||
@@ -197,37 +197,37 @@ struct usb_device
|
|||||||
|
|
||||||
int have_langid; /* whether string_langid is valid yet */
|
int have_langid; /* whether string_langid is valid yet */
|
||||||
int string_langid; /* language ID for strings */
|
int string_langid; /* language ID for strings */
|
||||||
int (*irq_handle)(struct usb_device *dev);
|
int (*irq_handle)(struct usb_device *dev);
|
||||||
uint32_t irq_status;
|
uint32_t irq_status;
|
||||||
int irq_act_len; /* transfered bytes */
|
int irq_act_len; /* transfered bytes */
|
||||||
void *privptr;
|
void *privptr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Child devices - if this is a hub device
|
* Child devices - if this is a hub device
|
||||||
* Each instance needs its own set of data structures.
|
* Each instance needs its own set of data structures.
|
||||||
*/
|
*/
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
int act_len; /* transfered bytes */
|
int act_len; /* transfered bytes */
|
||||||
int maxchild; /* Number of ports if hub */
|
int maxchild; /* Number of ports if hub */
|
||||||
int portnr;
|
int portnr;
|
||||||
struct usb_device *parent;
|
struct usb_device *parent;
|
||||||
struct usb_device *children[USB_MAXCHILDREN];
|
struct usb_device *children[USB_MAXCHILDREN];
|
||||||
void *priv_hcd;
|
void *priv_hcd;
|
||||||
int (*deregister)(struct usb_device *dev);
|
int (*deregister)(struct usb_device *dev);
|
||||||
|
|
||||||
struct usb_hub_device *hub;
|
struct usb_hub_device *hub;
|
||||||
int usbnum;
|
int usbnum;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
long ident;
|
long ident;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
long l;
|
long l;
|
||||||
short i[2];
|
short i[2];
|
||||||
char c[4];
|
char c[4];
|
||||||
} v;
|
} v;
|
||||||
} USB_COOKIE;
|
} USB_COOKIE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -278,7 +278,7 @@ extern int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
|
|||||||
extern int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id);
|
extern int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id);
|
||||||
extern struct usb_device *usb_get_dev_index(int index, int bus);
|
extern struct usb_device *usb_get_dev_index(int index, int bus);
|
||||||
extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, uint8_t request, uint8_t requesttype,
|
extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, uint8_t request, uint8_t requesttype,
|
||||||
uint16_t value, uint16_t index, void *data, uint16_t size, int timeout);
|
uint16_t value, uint16_t index, void *data, uint16_t size, int timeout);
|
||||||
extern int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout);
|
extern int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout);
|
||||||
extern int usb_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval);
|
extern int usb_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval);
|
||||||
extern void usb_disable_asynch(int disable);
|
extern void usb_disable_asynch(int disable);
|
||||||
@@ -328,42 +328,42 @@ extern int usb_set_interface(struct usb_device *dev, int interface, int alternat
|
|||||||
|
|
||||||
/* Create various pipes... */
|
/* Create various pipes... */
|
||||||
#define create_pipe(dev, endpoint) \
|
#define create_pipe(dev, endpoint) \
|
||||||
(((dev)->devnum << 8) | (endpoint << 15) | \
|
(((dev)->devnum << 8) | (endpoint << 15) | \
|
||||||
((dev)->speed << 26) | (dev)->maxpacketsize)
|
((dev)->speed << 26) | (dev)->maxpacketsize)
|
||||||
#define default_pipe(dev) ((dev)->speed << 26)
|
#define default_pipe(dev) ((dev)->speed << 26)
|
||||||
|
|
||||||
#define usb_sndctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
|
#define usb_sndctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
|
||||||
create_pipe(dev, endpoint))
|
create_pipe(dev, endpoint))
|
||||||
#define usb_rcvctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
|
#define usb_rcvctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
|
||||||
create_pipe(dev, endpoint) | \
|
create_pipe(dev, endpoint) | \
|
||||||
USB_DIR_IN)
|
USB_DIR_IN)
|
||||||
#define usb_sndisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
|
#define usb_sndisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
|
||||||
create_pipe(dev, endpoint))
|
create_pipe(dev, endpoint))
|
||||||
#define usb_rcvisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
|
#define usb_rcvisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
|
||||||
create_pipe(dev, endpoint) | \
|
create_pipe(dev, endpoint) | \
|
||||||
USB_DIR_IN)
|
USB_DIR_IN)
|
||||||
#define usb_sndbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
|
#define usb_sndbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
|
||||||
create_pipe(dev, endpoint))
|
create_pipe(dev, endpoint))
|
||||||
#define usb_rcvbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
|
#define usb_rcvbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
|
||||||
create_pipe(dev, endpoint) | \
|
create_pipe(dev, endpoint) | \
|
||||||
USB_DIR_IN)
|
USB_DIR_IN)
|
||||||
#define usb_sndintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
|
#define usb_sndintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
|
||||||
create_pipe(dev, endpoint))
|
create_pipe(dev, endpoint))
|
||||||
#define usb_rcvintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
|
#define usb_rcvintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
|
||||||
create_pipe(dev, endpoint) | \
|
create_pipe(dev, endpoint) | \
|
||||||
USB_DIR_IN)
|
USB_DIR_IN)
|
||||||
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | \
|
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | \
|
||||||
default_pipe(dev))
|
default_pipe(dev))
|
||||||
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | \
|
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | \
|
||||||
default_pipe(dev) | \
|
default_pipe(dev) | \
|
||||||
USB_DIR_IN)
|
USB_DIR_IN)
|
||||||
|
|
||||||
/* The D0/D1 toggle bits */
|
/* The D0/D1 toggle bits */
|
||||||
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1)
|
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1)
|
||||||
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep))
|
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep))
|
||||||
#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = \
|
#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = \
|
||||||
((dev)->toggle[out] & \
|
((dev)->toggle[out] & \
|
||||||
~(1 << ep)) | ((bit) << ep))
|
~(1 << ep)) | ((bit) << ep))
|
||||||
|
|
||||||
/* Endpoint halt control/status */
|
/* Endpoint halt control/status */
|
||||||
#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1)
|
#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1)
|
||||||
@@ -372,7 +372,7 @@ extern int usb_set_interface(struct usb_device *dev, int interface, int alternat
|
|||||||
#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
|
#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
|
||||||
|
|
||||||
#define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : \
|
#define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : \
|
||||||
USB_PID_OUT)
|
USB_PID_OUT)
|
||||||
|
|
||||||
#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1)
|
#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1)
|
||||||
#define usb_pipein(pipe) (((pipe) >> 7) & 1)
|
#define usb_pipein(pipe) (((pipe) >> 7) & 1)
|
||||||
@@ -394,37 +394,37 @@ extern int usb_set_interface(struct usb_device *dev, int interface, int alternat
|
|||||||
*/
|
*/
|
||||||
struct usb_port_status
|
struct usb_port_status
|
||||||
{
|
{
|
||||||
uint16_t wPortStatus;
|
uint16_t wPortStatus;
|
||||||
uint16_t wPortChange;
|
uint16_t wPortChange;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct usb_hub_status
|
struct usb_hub_status
|
||||||
{
|
{
|
||||||
uint16_t wHubStatus;
|
uint16_t wHubStatus;
|
||||||
uint16_t wHubChange;
|
uint16_t wHubChange;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
/* Hub descriptor */
|
/* Hub descriptor */
|
||||||
struct usb_hub_descriptor
|
struct usb_hub_descriptor
|
||||||
{
|
{
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint8_t bNbrPorts;
|
uint8_t bNbrPorts;
|
||||||
uint16_t wHubCharacteristics;
|
uint16_t wHubCharacteristics;
|
||||||
uint8_t bPwrOn2PwrGood;
|
uint8_t bPwrOn2PwrGood;
|
||||||
uint8_t bHubContrCurrent;
|
uint8_t bHubContrCurrent;
|
||||||
uint8_t DeviceRemovable[(USB_MAXCHILDREN+1+7)/8];
|
uint8_t DeviceRemovable[(USB_MAXCHILDREN+1+7)/8];
|
||||||
uint8_t PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8];
|
uint8_t PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8];
|
||||||
/* DeviceRemovable and PortPwrCtrlMask want to be variable-length
|
/* DeviceRemovable and PortPwrCtrlMask want to be variable-length
|
||||||
bitmaps that hold max 255 entries. (bit0 is ignored) */
|
bitmaps that hold max 255 entries. (bit0 is ignored) */
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
struct usb_hub_device
|
struct usb_hub_device
|
||||||
{
|
{
|
||||||
struct usb_device *pusb_dev;
|
struct usb_device *pusb_dev;
|
||||||
struct usb_hub_descriptor desc;
|
struct usb_hub_descriptor desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*_USB_H_ */
|
#endif /*_USB_H_ */
|
||||||
|
|||||||
@@ -29,13 +29,24 @@
|
|||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "ehci.h"
|
#include "ehci.h"
|
||||||
|
|
||||||
|
#define DBG_EHCI
|
||||||
|
#ifdef DBG_EHCI
|
||||||
|
#define dbg(format, arg...) xprintf("DEBUG %s(): " format, __FUNCTION__, ## arg)
|
||||||
|
#else
|
||||||
|
#define dbg(format, arg...) do {} while (0)
|
||||||
|
#endif /* DBG_EHCI */
|
||||||
|
#define err(format, arg...) xprintf("ERROR %s(): " format, __FUNCTION__, ## arg)
|
||||||
|
#define info(format, arg...) xprintf("INFO %s(): " format, __FUNCTION__, ## arg)
|
||||||
|
|
||||||
|
|
||||||
static char ehci_inited;
|
static char ehci_inited;
|
||||||
static int rootdev;
|
static int rootdev;
|
||||||
|
|
||||||
static uint16_t portreset;
|
static uint16_t portreset;
|
||||||
static uint16_t companion;
|
static uint16_t companion;
|
||||||
|
|
||||||
struct descriptor {
|
struct descriptor
|
||||||
|
{
|
||||||
struct usb_hub_descriptor hub;
|
struct usb_hub_descriptor hub;
|
||||||
struct usb_device_descriptor device;
|
struct usb_device_descriptor device;
|
||||||
struct usb_linux_config_descriptor config;
|
struct usb_linux_config_descriptor config;
|
||||||
@@ -43,7 +54,8 @@ struct descriptor {
|
|||||||
struct usb_endpoint_descriptor endpoint;
|
struct usb_endpoint_descriptor endpoint;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
static struct descriptor rom_descriptor = {
|
static struct descriptor rom_descriptor =
|
||||||
|
{
|
||||||
{
|
{
|
||||||
0x8, /* bDescLength */
|
0x8, /* bDescLength */
|
||||||
0x29, /* bDescriptorType: hub descriptor */
|
0x29, /* bDescriptorType: hub descriptor */
|
||||||
@@ -101,12 +113,6 @@ static struct descriptor rom_descriptor = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_EHCI_IS_TDI)
|
|
||||||
#define ehci_is_TDI() (1)
|
|
||||||
#else
|
|
||||||
#define ehci_is_TDI() (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct pci_device_id ehci_usb_pci_table[] =
|
struct pci_device_id ehci_usb_pci_table[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -161,28 +167,17 @@ static struct ehci
|
|||||||
const char *slot_name;
|
const char *slot_name;
|
||||||
} gehci;
|
} gehci;
|
||||||
|
|
||||||
#define DEBUG
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define dbg(format, arg...) xprintf("DEBUG: " format, __FUNCTION__, ## arg)
|
|
||||||
#else
|
|
||||||
#define dbg(format, arg...) do {} while (0)
|
|
||||||
#endif /* DEBUG */
|
|
||||||
#define err xprintf
|
|
||||||
#ifdef SHOW_INFO
|
|
||||||
#define info(format, arg...) xprintf("INFO: " format, __FUNCTION__, ## arg)
|
|
||||||
#else
|
|
||||||
#define info(format, arg...) do {} while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static void cache_qtd(struct qTD *qtd, int flush)
|
static void cache_qtd(struct qTD *qtd, int flush)
|
||||||
{
|
{
|
||||||
flush_and_invalidate_caches();
|
/*
|
||||||
|
* not needed
|
||||||
|
*/
|
||||||
|
//flush_and_invalidate_caches();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct QH *qh_addr(struct QH *qh)
|
static inline struct QH *qh_addr(struct QH *qh)
|
||||||
{
|
{
|
||||||
return (struct QH *)((uint32_t)qh & 0xffffffe0);
|
return (struct QH *)((uint32_t) qh & 0xffffffe0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cache_qh(struct QH *qh, int flush)
|
static void cache_qh(struct QH *qh, int flush)
|
||||||
@@ -195,7 +190,7 @@ static void cache_qh(struct QH *qh, int flush)
|
|||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
flush_and_invalidate_caches();
|
flush_and_invalidate_caches();
|
||||||
if ((uint32_t)qh & QH_LINK_TYPE_QH)
|
if ((uint32_t) qh & QH_LINK_TYPE_QH)
|
||||||
break;
|
break;
|
||||||
qh = qh_addr(qh);
|
qh = qh_addr(qh);
|
||||||
qh = (struct QH *)(swpl(qh->qh_link) + gehci.dma_offset);
|
qh = (struct QH *)(swpl(qh->qh_link) + gehci.dma_offset);
|
||||||
@@ -245,15 +240,19 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
result = ehci_readl(ptr);
|
result = ehci_readl(ptr);
|
||||||
if (result == ~(uint32_t)0)
|
if (result == ~ (uint32_t) 0)
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
result &= mask;
|
result &= mask;
|
||||||
if (result == done)
|
if (result == done)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
wait(1);
|
wait(1);
|
||||||
usec--;
|
usec--;
|
||||||
}
|
} while (usec > 0);
|
||||||
while (usec > 0);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,35 +263,27 @@ static void ehci_free(void *p, size_t sz)
|
|||||||
static int ehci_reset(void)
|
static int ehci_reset(void)
|
||||||
{
|
{
|
||||||
uint32_t cmd;
|
uint32_t cmd;
|
||||||
uint32_t tmp;
|
|
||||||
uint32_t *reg_ptr;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if ((gehci.ent->vendor == PCI_VENDOR_ID_NEC) && (gehci.ent->device == PCI_DEVICE_ID_NEC_USB_2))
|
if ((gehci.ent->vendor == PCI_VENDOR_ID_NEC) && (gehci.ent->device == PCI_DEVICE_ID_NEC_USB_2))
|
||||||
{
|
{
|
||||||
dbg("ehci_reset set 48MHz clock\r\n");
|
dbg("ehci_reset set 48MHz clock\r\n");
|
||||||
pci_write_config_longword(gehci.handle, 0xE4, 0x20); // oscillator
|
pci_write_config_longword(gehci.handle, 0xE4, 0x20); // oscillator
|
||||||
|
wait(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||||
dbg("%s cmd: 0x%08x\r\n", __FUNCTION__, cmd);
|
dbg("%s cmd: 0x%08x\r\n", __FUNCTION__, cmd);
|
||||||
|
|
||||||
cmd |= CMD_RESET;
|
cmd |= CMD_RESET;
|
||||||
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
||||||
ret = handshake((uint32_t *) &gehci.hcor->or_usbcmd, CMD_RESET, 0, 250);
|
ret = handshake((uint32_t *) &gehci.hcor->or_usbcmd, CMD_RESET, 0, 250);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
err("EHCI fail to reset");
|
err("*** EHCI fail to reset! ***\r\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ehci_is_TDI())
|
|
||||||
{
|
|
||||||
reg_ptr = (uint32_t *)((u8 *)gehci.hcor + USBMODE);
|
|
||||||
tmp = ehci_readl(reg_ptr);
|
|
||||||
tmp |= USBMODE_CM_HC;
|
|
||||||
tmp |= USBMODE_BE;
|
|
||||||
ehci_writel(reg_ptr, tmp);
|
|
||||||
}
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -363,18 +354,23 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
|||||||
volatile struct qTD *vtd;
|
volatile struct qTD *vtd;
|
||||||
uint32_t ts;
|
uint32_t ts;
|
||||||
uint32_t *tdp;
|
uint32_t *tdp;
|
||||||
uint32_t endpt, token, usbsts;
|
uint32_t endpt;
|
||||||
uint32_t c, toggle;
|
uint32_t token;
|
||||||
|
uint32_t usbsts;
|
||||||
|
uint32_t c;
|
||||||
|
uint32_t toggle;
|
||||||
uint32_t cmd;
|
uint32_t cmd;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
dbg("%s: dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\r\n", __FUNCTION__, dev, pipe, buffer, length, req);
|
dbg("%s: dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\r\n", __FUNCTION__, dev, pipe, buffer, length, req);
|
||||||
|
|
||||||
|
#ifdef DBG_EHCI
|
||||||
if (req != NULL)
|
if (req != NULL)
|
||||||
dbg("ehci_submit_async req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\r\n",
|
dbg("ehci_submit_async req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\r\n",
|
||||||
req->request, req->request,
|
req->request, req->request,
|
||||||
req->requesttype, req->requesttype,
|
req->requesttype, req->requesttype,
|
||||||
swpw(req->value), swpw(req->value), swpw(req->index));
|
swpw(req->value), swpw(req->value), swpw(req->index));
|
||||||
|
#endif /* DBG_EHCI */
|
||||||
|
|
||||||
qh = ehci_alloc(sizeof(struct QH), 32);
|
qh = ehci_alloc(sizeof(struct QH), 32);
|
||||||
if (qh == NULL)
|
if (qh == NULL)
|
||||||
@@ -469,21 +465,24 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
gehci.qh_list->qh_link = swpl(((uint32_t)qh - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
gehci.qh_list->qh_link = swpl(((uint32_t)qh - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
||||||
|
|
||||||
/* Flush dcache */
|
/* Flush dcache */
|
||||||
ehci_flush_dcache(gehci.qh_list);
|
ehci_flush_dcache(gehci.qh_list);
|
||||||
usbsts = ehci_readl(&gehci.hcor->or_usbsts);
|
usbsts = ehci_readl(&gehci.hcor->or_usbsts);
|
||||||
ehci_writel(&gehci.hcor->or_usbsts, (usbsts & 0x3f));
|
ehci_writel(&gehci.hcor->or_usbsts, (usbsts & 0x3f));
|
||||||
|
|
||||||
/* Enable async. schedule. */
|
/* Enable async. schedule. */
|
||||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||||
cmd |= CMD_ASE;
|
cmd |= CMD_ASE;
|
||||||
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
||||||
|
|
||||||
ret = handshake((uint32_t *)&gehci.hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000);
|
ret = handshake((uint32_t *) &gehci.hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
err("EHCI fail timeout STD_ASS set (usbsts=%#x)", ehci_readl(&gehci.hcor->or_usbsts));
|
err("EHCI fail timeout STD_ASS set (usbsts=%#x)", ehci_readl(&gehci.hcor->or_usbsts));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for TDs to be processed. */
|
/* Wait for TDs to be processed. */
|
||||||
ts = 0;
|
ts = 0;
|
||||||
vtd = td;
|
vtd = td;
|
||||||
@@ -493,16 +492,18 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
|||||||
ehci_invalidate_dcache(gehci.qh_list);
|
ehci_invalidate_dcache(gehci.qh_list);
|
||||||
token = swpl(vtd->qt_token);
|
token = swpl(vtd->qt_token);
|
||||||
if (!(token & 0x80))
|
if (!(token & 0x80))
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
wait(1 * 1000);
|
wait(1 * 1000);
|
||||||
ts++;
|
ts++;
|
||||||
}
|
} while (ts < 1000);
|
||||||
while(ts < 1000);
|
|
||||||
/* Disable async schedule. */
|
/* Disable async schedule. */
|
||||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||||
cmd &= ~CMD_ASE;
|
cmd &= ~CMD_ASE;
|
||||||
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
||||||
ret = handshake((uint32_t *)&gehci.hcor->or_usbsts, STD_ASS, 0, 100 * 1000);
|
ret = handshake((uint32_t *) &gehci.hcor->or_usbsts, STD_ASS, 0, 100 * 1000);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
err("EHCI fail timeout STD_ASS reset (usbsts=%#x)", ehci_readl(&gehci.hcor->or_usbsts));
|
err("EHCI fail timeout STD_ASS reset (usbsts=%#x)", ehci_readl(&gehci.hcor->or_usbsts));
|
||||||
@@ -594,16 +595,19 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
|||||||
int len, srclen;
|
int len, srclen;
|
||||||
uint32_t reg;
|
uint32_t reg;
|
||||||
uint32_t *status_reg;
|
uint32_t *status_reg;
|
||||||
|
|
||||||
if (swpw(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS)
|
if (swpw(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS)
|
||||||
{
|
{
|
||||||
err("the requested port(%d) is not configured\r\n", swpw(req->index) - 1);
|
err("the requested port(%d) is not configured\r\n", swpw(req->index) - 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
status_reg = (uint32_t *)&gehci.hcor->or_portsc[swpw(req->index) - 1];
|
|
||||||
|
status_reg = (uint32_t *) &gehci.hcor->or_portsc[swpw(req->index) - 1];
|
||||||
srclen = 0;
|
srclen = 0;
|
||||||
dbg("ehci_submit_root req=%u (%#x), type=%u (%#x), value=%u, index=%u\r\n",
|
dbg("ehci_submit_root req=%u (%#x), type=%u (%#x), value=%u, index=%u\r\n",
|
||||||
req->request, req->request, req->requesttype, req->requesttype, swpw(req->value), swpw(req->index));
|
req->request, req->request, req->requesttype, req->requesttype, swpw(req->value), swpw(req->index));
|
||||||
typeReq = req->request | req->requesttype << 8;
|
typeReq = req->request | req->requesttype << 8;
|
||||||
|
|
||||||
switch(typeReq)
|
switch(typeReq)
|
||||||
{
|
{
|
||||||
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
|
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||||
@@ -714,25 +718,8 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
|||||||
tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
|
tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
|
||||||
if (reg & EHCI_PS_PP)
|
if (reg & EHCI_PS_PP)
|
||||||
tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
|
tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
|
||||||
if (ehci_is_TDI())
|
|
||||||
{
|
|
||||||
switch((reg >> 26) & 3)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
|
||||||
tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
default:
|
|
||||||
tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
|
|
||||||
|
|
||||||
if (reg & EHCI_PS_CSC)
|
if (reg & EHCI_PS_CSC)
|
||||||
tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
|
tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
|
||||||
@@ -766,7 +753,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_PORT_FEAT_RESET:
|
case USB_PORT_FEAT_RESET:
|
||||||
if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && !ehci_is_TDI() && EHCI_PS_IS_LOWSPEED(reg))
|
if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && EHCI_PS_IS_LOWSPEED(reg))
|
||||||
{
|
{
|
||||||
/* Low speed device, give up ownership. */
|
/* Low speed device, give up ownership. */
|
||||||
dbg("port %d low speed --> companion\r\n", swpw(req->index));
|
dbg("port %d low speed --> companion\r\n", swpw(req->index));
|
||||||
@@ -858,10 +845,14 @@ unknown:
|
|||||||
static int hc_interrupt(struct ehci *ehci)
|
static int hc_interrupt(struct ehci *ehci)
|
||||||
{
|
{
|
||||||
uint32_t status = ehci_readl(&ehci->hcor->or_usbsts);
|
uint32_t status = ehci_readl(&ehci->hcor->or_usbsts);
|
||||||
|
|
||||||
|
dbg("\r\n");
|
||||||
|
|
||||||
if (status & STS_PCD) /* port change detect */
|
if (status & STS_PCD) /* port change detect */
|
||||||
{
|
{
|
||||||
uint32_t reg = ehci_readl(&ehci->hccr->cr_hcsparams);
|
uint32_t reg = ehci_readl(&ehci->hccr->cr_hcsparams);
|
||||||
uint32_t i = HCS_N_PORTS(reg);
|
uint32_t i = HCS_N_PORTS(reg);
|
||||||
|
|
||||||
while(i)
|
while(i)
|
||||||
{
|
{
|
||||||
uint32_t pstatus = ehci_readl(&ehci->hcor->or_portsc[i-1]);
|
uint32_t pstatus = ehci_readl(&ehci->hcor->or_portsc[i-1]);
|
||||||
@@ -875,14 +866,14 @@ static int hc_interrupt(struct ehci *ehci)
|
|||||||
{
|
{
|
||||||
/* Low speed device, give up ownership. */
|
/* Low speed device, give up ownership. */
|
||||||
pstatus |= EHCI_PS_PO;
|
pstatus |= EHCI_PS_PO;
|
||||||
ehci_writel(&ehci->hcor->or_portsc[i-1], pstatus);
|
ehci_writel(&ehci->hcor->or_portsc[i - 1], pstatus);
|
||||||
}
|
}
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ehci_writel(&ehci->hcor->or_usbsts, status);
|
ehci_writel(&ehci->hcor->or_usbsts, status);
|
||||||
|
|
||||||
return(1); /* interrupt was from this card */
|
return 1; /* interrupt was from this card */
|
||||||
}
|
}
|
||||||
|
|
||||||
void ehci_usb_enable_interrupt(int enable)
|
void ehci_usb_enable_interrupt(int enable)
|
||||||
@@ -892,7 +883,7 @@ void ehci_usb_enable_interrupt(int enable)
|
|||||||
|
|
||||||
static int handle_usb_interrupt(struct ehci *ehci)
|
static int handle_usb_interrupt(struct ehci *ehci)
|
||||||
{
|
{
|
||||||
return(hc_interrupt(ehci));
|
return hc_interrupt(ehci);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hc_free_buffers(struct ehci *ehci)
|
static void hc_free_buffers(struct ehci *ehci)
|
||||||
@@ -943,14 +934,17 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
|||||||
gehci.ent = ent;
|
gehci.ent = ent;
|
||||||
}
|
}
|
||||||
else if (!gehci.handle) /* for restart USB cmd */
|
else if (!gehci.handle) /* for restart USB cmd */
|
||||||
return(-1);
|
{
|
||||||
|
dbg("!gehci.handle\r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
gehci.qh_list_unaligned = (struct QH *)driver_mem_alloc(sizeof(struct QH) + 32);
|
gehci.qh_list_unaligned = (struct QH *) driver_mem_alloc(sizeof(struct QH) + 32);
|
||||||
if (gehci.qh_list_unaligned == NULL)
|
if (gehci.qh_list_unaligned == NULL)
|
||||||
{
|
{
|
||||||
dbg("QHs malloc failed");
|
dbg("QHs malloc failed\r\n");
|
||||||
hc_free_buffers(&gehci);
|
hc_free_buffers(&gehci);
|
||||||
return(-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gehci.qh_list = (struct QH *)(((uint32_t)gehci.qh_list_unaligned + 31) & ~31);
|
gehci.qh_list = (struct QH *)(((uint32_t)gehci.qh_list_unaligned + 31) & ~31);
|
||||||
@@ -959,32 +953,35 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
|||||||
|
|
||||||
if (gehci.qh_unaligned == NULL)
|
if (gehci.qh_unaligned == NULL)
|
||||||
{
|
{
|
||||||
dbg("QHs malloc failed");
|
dbg("QHs malloc failed\r\n");
|
||||||
hc_free_buffers(&gehci);
|
hc_free_buffers(&gehci);
|
||||||
return(-1);
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
gehci.qh = (struct QH *)(((uint32_t)gehci.qh_unaligned + 31) & ~31);
|
gehci.qh = (struct QH *)(((uint32_t) gehci.qh_unaligned + 31) & ~31);
|
||||||
memset(gehci.qh, 0, sizeof(struct QH));
|
memset(gehci.qh, 0, sizeof(struct QH));
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
gehci.td_unaligned[i] = (struct qTD *)driver_mem_alloc(sizeof(struct qTD) + 32);
|
gehci.td_unaligned[i] = (struct qTD *) driver_mem_alloc(sizeof(struct qTD) + 32);
|
||||||
if (gehci.td_unaligned[i] == NULL)
|
if (gehci.td_unaligned[i] == NULL)
|
||||||
{
|
{
|
||||||
dbg("TDs malloc failed");
|
dbg("TDs malloc failed\r\n");
|
||||||
hc_free_buffers(&gehci);
|
hc_free_buffers(&gehci);
|
||||||
return(-1);
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
gehci.td[i] = (struct qTD *)(((uint32_t)gehci.td_unaligned[i] + 31) & ~31);
|
gehci.td[i] = (struct qTD *)(((uint32_t) gehci.td_unaligned[i] + 31) & ~31);
|
||||||
memset(gehci.td[i], 0, sizeof(struct qTD));
|
memset(gehci.td[i], 0, sizeof(struct qTD));
|
||||||
}
|
}
|
||||||
|
|
||||||
gehci.descriptor = (struct descriptor *)driver_mem_alloc(sizeof(struct descriptor));
|
gehci.descriptor = (struct descriptor *) driver_mem_alloc(sizeof(struct descriptor));
|
||||||
if (gehci.descriptor == NULL)
|
if (gehci.descriptor == NULL)
|
||||||
{
|
{
|
||||||
dbg("decriptor malloc failed");
|
dbg("decriptor malloc failed\r\n");
|
||||||
hc_free_buffers(&gehci);
|
hc_free_buffers(&gehci);
|
||||||
return(-1);
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(gehci.descriptor, &rom_descriptor, sizeof(struct descriptor));
|
memcpy(gehci.descriptor, &rom_descriptor, sizeof(struct descriptor));
|
||||||
|
|
||||||
@@ -1000,7 +997,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
|||||||
if (usb_base_addr == 0xFFFFFFFF)
|
if (usb_base_addr == 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
usb_base_addr = pci_rsc_desc->start;
|
usb_base_addr = pci_rsc_desc->start;
|
||||||
gehci.hccr = (struct ehci_hccr *)(pci_rsc_desc->offset + pci_rsc_desc->start);
|
gehci.hccr = (struct ehci_hccr *) (pci_rsc_desc->offset + pci_rsc_desc->start);
|
||||||
gehci.dma_offset = pci_rsc_desc->dmaoffset;
|
gehci.dma_offset = pci_rsc_desc->dmaoffset;
|
||||||
if ((pci_rsc_desc->flags & FLG_ENDMASK) == ORD_MOTOROLA)
|
if ((pci_rsc_desc->flags & FLG_ENDMASK) == ORD_MOTOROLA)
|
||||||
gehci.big_endian = 0; /* host bridge make swapping intel -> motorola */
|
gehci.big_endian = 0; /* host bridge make swapping intel -> motorola */
|
||||||
@@ -1009,14 +1006,16 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
flags = pci_rsc_desc->flags;
|
flags = pci_rsc_desc->flags;
|
||||||
pci_rsc_desc = (struct pci_rd *)((uint32_t)pci_rsc_desc->next + (uint32_t)pci_rsc_desc);
|
pci_rsc_desc = (struct pci_rd *)((uint32_t) pci_rsc_desc->next + (uint32_t) pci_rsc_desc);
|
||||||
}
|
}
|
||||||
while (!(flags & FLG_LAST));
|
while (!(flags & FLG_LAST));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hc_free_buffers(&gehci);
|
hc_free_buffers(&gehci);
|
||||||
return(-1); /* get_resource error */
|
dbg("pci_get_resource() error\r\n");
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usb_base_addr == 0xFFFFFFFF)
|
if (usb_base_addr == 0xFFFFFFFF)
|
||||||
@@ -1034,37 +1033,48 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
|||||||
default: gehci.slot_name = "generic"; break;
|
default: gehci.slot_name = "generic"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gehci.hcor = (struct ehci_hcor *)((uint32_t)gehci.hccr + HC_LENGTH(ehci_readl(&gehci.hccr->cr_capbase)));
|
gehci.hcor = (struct ehci_hcor *)((uint32_t) gehci.hccr + HC_LENGTH(ehci_readl(&gehci.hccr->cr_capbase)));
|
||||||
xprintf("EHCI usb-%s, regs address 0x%08X, PCI handle 0x%X\r\n", gehci.slot_name, gehci.hccr, handle);
|
xprintf("EHCI usb-%s, regs address 0x%08X, PCI handle 0x%X\r\n", gehci.slot_name, gehci.hccr, handle);
|
||||||
|
|
||||||
/* EHCI spec section 4.1 */
|
/* EHCI spec section 4.1 */
|
||||||
if (ehci_reset() != 0)
|
if (ehci_reset() != 0)
|
||||||
{
|
{
|
||||||
hc_free_buffers(&gehci);
|
hc_free_buffers(&gehci);
|
||||||
return(-1);
|
|
||||||
|
dbg("ehci_reset() failed\r\n");
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set head of reclaim list */
|
/* Set head of reclaim list */
|
||||||
gehci.qh_list->qh_link = swpl(((uint32_t)gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
gehci.qh_list->qh_link = swpl(((uint32_t) gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
||||||
gehci.qh_list->qh_endpt1 = swpl((1 << 15) | (USB_SPEED_HIGH << 12));
|
gehci.qh_list->qh_endpt1 = swpl((1 << 15) | (USB_SPEED_HIGH << 12));
|
||||||
gehci.qh_list->qh_curtd = swpl(QT_NEXT_TERMINATE);
|
gehci.qh_list->qh_curtd = swpl(QT_NEXT_TERMINATE);
|
||||||
gehci.qh_list->qh_overlay.qt_next = swpl(QT_NEXT_TERMINATE);
|
gehci.qh_list->qh_overlay.qt_next = swpl(QT_NEXT_TERMINATE);
|
||||||
gehci.qh_list->qh_overlay.qt_altnext = swpl(QT_NEXT_TERMINATE);
|
gehci.qh_list->qh_overlay.qt_altnext = swpl(QT_NEXT_TERMINATE);
|
||||||
gehci.qh_list->qh_overlay.qt_token = swpl(0x40);
|
gehci.qh_list->qh_overlay.qt_token = swpl(0x40);
|
||||||
|
|
||||||
/* Set async. queue head pointer. */
|
/* Set async. queue head pointer. */
|
||||||
ehci_writel(&gehci.hcor->or_asynclistaddr, (uint32_t)gehci.qh_list - gehci.dma_offset);
|
ehci_writel(&gehci.hcor->or_asynclistaddr, (uint32_t) gehci.qh_list - gehci.dma_offset);
|
||||||
reg = ehci_readl(&gehci.hccr->cr_hcsparams);
|
reg = ehci_readl(&gehci.hccr->cr_hcsparams);
|
||||||
gehci.descriptor->hub.bNbrPorts = HCS_N_PORTS(reg);
|
gehci.descriptor->hub.bNbrPorts = HCS_N_PORTS(reg);
|
||||||
info("Register %x NbrPorts %d", reg, gehci.descriptor->hub.bNbrPorts);
|
info("Register %x NbrPorts %d\r\n", reg, gehci.descriptor->hub.bNbrPorts);
|
||||||
|
|
||||||
/* Port Indicators */
|
/* Port Indicators */
|
||||||
if (HCS_INDICATOR(reg))
|
if (HCS_INDICATOR(reg))
|
||||||
|
{
|
||||||
gehci.descriptor->hub.wHubCharacteristics |= 0x80;
|
gehci.descriptor->hub.wHubCharacteristics |= 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
/* Port Power Control */
|
/* Port Power Control */
|
||||||
if (HCS_PPC(reg))
|
if (HCS_PPC(reg))
|
||||||
|
{
|
||||||
gehci.descriptor->hub.wHubCharacteristics |= 0x01;
|
gehci.descriptor->hub.wHubCharacteristics |= 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
/* Start the host controller. */
|
/* Start the host controller. */
|
||||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Philips, Intel, and maybe others need CMD_RUN before the
|
* Philips, Intel, and maybe others need CMD_RUN before the
|
||||||
* root hub will detect new devices (why?); NEC doesn't
|
* root hub will detect new devices (why?); NEC doesn't
|
||||||
@@ -1072,21 +1082,29 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
|||||||
cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
|
cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
|
||||||
cmd |= CMD_RUN;
|
cmd |= CMD_RUN;
|
||||||
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
||||||
|
|
||||||
/* take control over the ports */
|
/* take control over the ports */
|
||||||
ehci_writel(&gehci.hcor->or_configflag, FLAG_CF);
|
ehci_writel(&gehci.hcor->or_configflag, FLAG_CF);
|
||||||
|
|
||||||
/* unblock posted write */
|
/* unblock posted write */
|
||||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||||
wait(5 * 1000);
|
wait(5 * 1000);
|
||||||
|
|
||||||
reg = HC_VERSION(ehci_readl(&gehci.hccr->cr_capbase));
|
reg = HC_VERSION(ehci_readl(&gehci.hccr->cr_capbase));
|
||||||
info("USB EHCI %x.%02x", reg >> 8, reg & 0xff);
|
info("USB EHCI host controller version %x.%02x\r\n", reg >> 8, reg & 0xff);
|
||||||
/* turn on interrupts */
|
|
||||||
|
/* turn on interrupts */
|
||||||
pci_hook_interrupt(handle, handle_usb_interrupt, &gehci);
|
pci_hook_interrupt(handle, handle_usb_interrupt, &gehci);
|
||||||
ehci_writel(&gehci.hcor->or_usbintr, INTR_PCDE);
|
ehci_writel(&gehci.hcor->or_usbintr, INTR_PCDE);
|
||||||
|
|
||||||
rootdev = 0;
|
rootdev = 0;
|
||||||
if (priv != NULL)
|
if (priv != NULL)
|
||||||
*priv = (void *)&gehci;
|
{
|
||||||
|
*priv = (void *) &gehci;
|
||||||
|
}
|
||||||
ehci_inited = 1;
|
ehci_inited = 1;
|
||||||
return(0);
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ehci_usb_lowlevel_stop(void *priv)
|
int ehci_usb_lowlevel_stop(void *priv)
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
#undef OHCI_VERBOSE_DEBUG /* not always helpful */
|
#undef OHCI_VERBOSE_DEBUG /* not always helpful */
|
||||||
#undef OHCI_FILL_TRACE
|
#undef OHCI_FILL_TRACE
|
||||||
|
|
||||||
#define DEBUG_OHCI
|
//#define DEBUG_OHCI
|
||||||
#ifdef DEBUG_OHCI
|
#ifdef DEBUG_OHCI
|
||||||
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "wait.h"
|
#include "wait.h"
|
||||||
|
|
||||||
//#define DEBUG_PCI
|
#define DEBUG_PCI
|
||||||
#ifdef DEBUG_PCI
|
#ifdef DEBUG_PCI
|
||||||
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
||||||
#else
|
#else
|
||||||
@@ -184,7 +184,7 @@ static int32_t pci_get_interrupt_cause(int32_t *handles)
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbg("%s: no interrupt cause found\r\n");
|
dbg("no interrupt cause found\r\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +224,7 @@ void irq5_handler(void)
|
|||||||
newvalue = pci_call_interrupt_chain(handle, value);
|
newvalue = pci_call_interrupt_chain(handle, value);
|
||||||
if (newvalue == value)
|
if (newvalue == value)
|
||||||
{
|
{
|
||||||
dbg("%s: interrupt not handled!\r\n");
|
dbg("interrupt not handled!\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +247,7 @@ void irq7_handler(void)
|
|||||||
newvalue = pci_call_interrupt_chain(handle, value);
|
newvalue = pci_call_interrupt_chain(handle, value);
|
||||||
if (newvalue == value)
|
if (newvalue == value)
|
||||||
{
|
{
|
||||||
dbg("%s: interrupt not handled!\r\n");
|
dbg("interrupt not handled!\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -878,7 +878,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
|
|||||||
*/
|
*/
|
||||||
struct pci_rd *rd = &descriptors[barnum];
|
struct pci_rd *rd = &descriptors[barnum];
|
||||||
|
|
||||||
dbg("%s: address = %08x\r\n", address);
|
dbg("address = %08x\r\n", address);
|
||||||
if (IS_PCI_MEM_BAR(address))
|
if (IS_PCI_MEM_BAR(address))
|
||||||
{
|
{
|
||||||
/* adjust base address to card's alignment requirements */
|
/* adjust base address to card's alignment requirements */
|
||||||
@@ -967,10 +967,10 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
|
|||||||
|
|
||||||
/* write it to PCIERBAR and enable ROM */
|
/* write it to PCIERBAR and enable ROM */
|
||||||
pci_write_config_longword(handle, PCIERBAR, swpl(address | 1));
|
pci_write_config_longword(handle, PCIERBAR, swpl(address | 1));
|
||||||
dbg("%s: set PCIERBAR on device 0x%02x to 0x%08x\r\n", handle, address | 1);
|
dbg("set PCIERBAR on device 0x%02x to 0x%08x\r\n", handle, address | 1);
|
||||||
|
|
||||||
/* read value back just to be sure */
|
/* read value back just to be sure */
|
||||||
dbg("%s: PCIERBAR = %p\r\n", swpl(pci_read_config_longword(handle, PCIERBAR)));
|
dbg("PCIERBAR = %p\r\n", swpl(pci_read_config_longword(handle, PCIERBAR)));
|
||||||
|
|
||||||
|
|
||||||
rd->next = sizeof(struct pci_rd);
|
rd->next = sizeof(struct pci_rd);
|
||||||
@@ -1224,8 +1224,10 @@ void init_pci(void)
|
|||||||
|
|
||||||
/* initialize/clear resource descriptor table */
|
/* initialize/clear resource descriptor table */
|
||||||
memset(&resource_descriptors, 0, NUM_CARDS * NUM_RESOURCES * sizeof(struct pci_rd));
|
memset(&resource_descriptors, 0, NUM_CARDS * NUM_RESOURCES * sizeof(struct pci_rd));
|
||||||
|
|
||||||
/* initialize/clear handles array */
|
/* initialize/clear handles array */
|
||||||
memset(handles, 0, NUM_CARDS * sizeof(int32_t));
|
memset(handles, 0, NUM_CARDS * sizeof(int32_t));
|
||||||
|
|
||||||
/* initialize/clear interrupts array */
|
/* initialize/clear interrupts array */
|
||||||
memset(interrupts, 0, MAX_INTERRUPTS * sizeof(struct pci_interrupt));
|
memset(interrupts, 0, MAX_INTERRUPTS * sizeof(struct pci_interrupt));
|
||||||
|
|
||||||
@@ -1233,7 +1235,7 @@ void init_pci(void)
|
|||||||
* give devices a chance to come up befor attempting to configure them,
|
* give devices a chance to come up befor attempting to configure them,
|
||||||
* necessary to properly detect the FireBee USB chip
|
* necessary to properly detect the FireBee USB chip
|
||||||
*/
|
*/
|
||||||
wait(400000);
|
wait(600000);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do normal initialization
|
* do normal initialization
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
|
|
||||||
//#define DEBUG_SYSINIT
|
#define DEBUG_SYSINIT
|
||||||
#ifdef DEBUG_SYSINIT
|
#ifdef DEBUG_SYSINIT
|
||||||
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
||||||
#else
|
#else
|
||||||
@@ -702,7 +702,7 @@ void init_usb(void)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
handle = pci_find_device(0x0000, 0xffff, index++);
|
handle = pci_find_classcode(PCI_CLASS_SERIAL_USB, index++);
|
||||||
if (handle > 0)
|
if (handle > 0)
|
||||||
{
|
{
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
|
|||||||
@@ -203,6 +203,8 @@ int usb_init(int32_t handle, const struct pci_device_id *ent)
|
|||||||
bus_index++;
|
bus_index++;
|
||||||
usb_started = 1;
|
usb_started = 1;
|
||||||
|
|
||||||
|
xprintf("done.\r\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "usb_hub.h"
|
#include "usb_hub.h"
|
||||||
|
|
||||||
//#define DEBUG_HUB
|
#define DEBUG_HUB
|
||||||
#ifdef DEBUG_HUB
|
#ifdef DEBUG_HUB
|
||||||
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
||||||
#else
|
#else
|
||||||
@@ -296,6 +296,7 @@ static void usb_hub_events(struct usb_device *dev)
|
|||||||
if (usb_get_port_status(dev, i + 1, &portsts) < 0)
|
if (usb_get_port_status(dev, i + 1, &portsts) < 0)
|
||||||
{
|
{
|
||||||
dbg("get_port_status failed\r\n");
|
dbg("get_port_status failed\r\n");
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
portstatus = swpw(portsts.wPortStatus);
|
portstatus = swpw(portsts.wPortStatus);
|
||||||
@@ -424,7 +425,8 @@ int usb_hub_configure(struct usb_device *dev)
|
|||||||
driver_mem_free(buffer);
|
driver_mem_free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dbg("bLength:%02X bDescriptorType:%02X bNbrPorts:%02X\r\n", buffer[0], buffer[1], buffer[2]);
|
|
||||||
|
dbg("bLength:0x%02X bDescriptorType:0x%02X bNbrPorts:0x%02X\r\n", buffer[0], buffer[1], buffer[2]);
|
||||||
descriptor = (struct usb_hub_descriptor *)buffer;
|
descriptor = (struct usb_hub_descriptor *)buffer;
|
||||||
|
|
||||||
/* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */
|
/* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */
|
||||||
@@ -465,7 +467,7 @@ int usb_hub_configure(struct usb_device *dev)
|
|||||||
hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i];
|
hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++)
|
for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7) / 8); i++)
|
||||||
{
|
{
|
||||||
hub->desc.DeviceRemovable[i] = descriptor->PortPowerCtrlMask[i];
|
hub->desc.DeviceRemovable[i] = descriptor->PortPowerCtrlMask[i];
|
||||||
}
|
}
|
||||||
@@ -507,7 +509,9 @@ int usb_hub_configure(struct usb_device *dev)
|
|||||||
|
|
||||||
for (i = 0; i < dev->maxchild; i++)
|
for (i = 0; i < dev->maxchild; i++)
|
||||||
{
|
{
|
||||||
dbg("USB %d port %d is%s removable\r\n", dev->usbnum, i + 1, hub->desc.DeviceRemovable[(i + 1) / 8] & (1 << ((i + 1) % 8)) ? " not" : "");
|
dbg("USB %d port %d is%s removable\r\n",
|
||||||
|
dev->usbnum, i + 1,
|
||||||
|
hub->desc.DeviceRemovable[(i + 1) / 8] & (1 << ((i + 1) % 8)) ? " not" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeof(struct usb_hub_status) > USB_BUFSIZ)
|
if (sizeof(struct usb_hub_status) > USB_BUFSIZ)
|
||||||
@@ -526,11 +530,11 @@ int usb_hub_configure(struct usb_device *dev)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USB_DEBUG
|
#ifdef DEBUG_HUB
|
||||||
{
|
{
|
||||||
struct usb_hub_status *hubsts;
|
struct usb_hub_status *hubsts;
|
||||||
|
|
||||||
hubsts = (struct usb_hub_status *)buffer;
|
hubsts = (struct usb_hub_status *) buffer;
|
||||||
dbg("get_hub_status returned status %X, change %X\r\n",
|
dbg("get_hub_status returned status %X, change %X\r\n",
|
||||||
swpw(hubsts->wHubStatus), swpw(hubsts->wHubChange));
|
swpw(hubsts->wHubStatus), swpw(hubsts->wHubChange));
|
||||||
dbg("local power source is %s\r\n",
|
dbg("local power source is %s\r\n",
|
||||||
@@ -559,6 +563,7 @@ int usb_hub_configure(struct usb_device *dev)
|
|||||||
}
|
}
|
||||||
if (queue_poll_hub == NULL)
|
if (queue_poll_hub == NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
usb_hub_events(dev);
|
usb_hub_events(dev);
|
||||||
driver_mem_free(buffer);
|
driver_mem_free(buffer);
|
||||||
|
|
||||||
@@ -586,12 +591,15 @@ int usb_hub_probe(struct usb_device *dev, int ifnum)
|
|||||||
*/
|
*/
|
||||||
if ((iface->bInterfaceSubClass != 0) && (iface->bInterfaceSubClass != 1))
|
if ((iface->bInterfaceSubClass != 0) && (iface->bInterfaceSubClass != 1))
|
||||||
{
|
{
|
||||||
|
dbg("iface->bInterfaceSubClass != {0, 1} (%d instead)\r\n", iface->bInterfaceSubClass);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Multiple endpoints? What kind of mutant ninja-hub is this? */
|
/* Multiple endpoints? What kind of mutant ninja-hub is this? */
|
||||||
if (iface->bNumEndpoints != 1)
|
if (iface->bNumEndpoints != 1)
|
||||||
{
|
{
|
||||||
|
dbg("iface->bNumEndpoints != 1 (%d instead)\r\n", iface->bNumEndpoints);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,6 +608,8 @@ int usb_hub_probe(struct usb_device *dev, int ifnum)
|
|||||||
/* Output endpoint? Curiousier and curiousier.. */
|
/* Output endpoint? Curiousier and curiousier.. */
|
||||||
if (!(ep->bEndpointAddress & USB_DIR_IN))
|
if (!(ep->bEndpointAddress & USB_DIR_IN))
|
||||||
{
|
{
|
||||||
|
dbg("!(ep->bEndpointAddress != USB_DIR_IN (0x%x instead)\r\n", ep->bEndpointAddress);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,6 +621,7 @@ int usb_hub_probe(struct usb_device *dev, int ifnum)
|
|||||||
|
|
||||||
/* We found a hub */
|
/* We found a hub */
|
||||||
dbg("USB %d hub found\r\n", dev->usbnum);
|
dbg("USB %d hub found\r\n", dev->usbnum);
|
||||||
|
|
||||||
ret = usb_hub_configure(dev);
|
ret = usb_hub_configure(dev);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user