[U-Boot-Users] [PATCH 2/4][RFC] Add ehci core functionality

michael trimarchi at gandalf.sssup.it
Mon Jun 23 14:59:37 CEST 2008


Hi,
Tor Krill wrote:
> +static uint16_t portreset;
> +static struct QH qh_list __attribute__ ((aligned (32)));
> +
> +static struct {
> +	uint8_t hub[8];
> +	uint8_t device[18];
> +	uint8_t config[9];
> +	uint8_t interface[9];
> +	uint8_t endpoint[7];
> +} descr = {
> +	{			/* HUB */
> +		sizeof (descr.hub),	/* bDescLength */
> +		    0x29,	/* bDescriptorType: hub descriptor */
> +		    2,		/* bNrPorts -- runtime modified */
> +		    0, 0,	/* wHubCharacteristics -- runtime modified */
> +		    0xff,	/* bPwrOn2PwrGood */
> +		    0,		/* bHubCntrCurrent */
> +		    0		/* DeviceRemovable XXX at most 7 ports! XXX */
> +	}
> +	, {			/* DEVICE */
> +		sizeof (descr.device),	/* bLength */
> +		    1,		/* bDescriptorType: UDESC_DEVICE */
> +		    0x00, 0x02,	/* bcdUSB: v2.0 */
> +		    9,		/* bDeviceClass: UDCLASS_HUB */
> +		    0,		/* bDeviceSubClass: UDSUBCLASS_HUB */
> +		    1,		/* bDeviceProtocol: UDPROTO_HSHUBSTT */
> +		    64,		/* bMaxPacketSize: 64 bytes */
> +		    0x00, 0x00,	/* idVendor */
> +		    0x00, 0x00,	/* idProduct */
> +		    0x00, 0x01,	/* bcdDevice */
> +		    1,		/* iManufacturer */
> +		    2,		/* iProduct */
> +		    0,		/* iSerialNumber */
> +		    1		/* bNumConfigurations: 1 */
> +	}
> +	, {			/* CONFIG */
> +		sizeof (descr.config),	/* bLength */
> +		    2,		/* bDescriptorType: UDESC_CONFIG */
> +		    sizeof (descr.config) + sizeof (descr.interface) +
> +		    sizeof (descr.endpoint), 0,
> +		    /* wTotalLength */
> +		    1,		/* bNumInterface */
> +		    1,		/* bConfigurationValue */
> +		    0,		/* iConfiguration */
> +		    0x40,	/* bmAttributes: UC_SELF_POWERED */
> +		    0		/* bMaxPower */
> +	}
> +	, {			/* INTERFACE */
> +		sizeof (descr.interface),	/* bLength */
> +		    4,		/* bDescriptorType: UDESC_INTERFACE */
> +		    0,		/* bInterfaceNumber */
> +		    0,		/* bAlternateSetting */
> +		    1,		/* bNumEndpoints */
> +		    9,		/* bInterfaceClass: UICLASS_HUB */
> +		    0,		/* bInterfaceSubClass: UISUBCLASS_HUB */
> +		    0,		/* bInterfaceProtocol: UIPROTO_HSHUBSTT */
> +		    0		/* iInterface */
> +	}
> +	, {			/* ENDPOINT */
> +		sizeof (descr.endpoint),	/* bLength */
> +		    5,		/* bDescriptorType: UDESC_ENDPOINT */
> +		    0x81,	/* bEndpointAddress: UE_DIR_IN | EHCI_INTR_ENDPT */
> +		    3,		/* bmAttributes: UE_INTERRUPT */
> +		    8, 0,	/* wMaxPacketSize */
> +		    255		/* bInterval */
> +	}
> +};
> +
>   
I prefer using:

struct usb_device_descriptor device = {
        sizeof(struct usb_device_descriptor),   /* bLength */
        1,              /* bDescriptorType: UDESC_DEVICE */
        0x0002,         /* bcdUSB: v2.0 */
        9,              /* bDeviceClass: UDCLASS_HUB */
        0,              /* bDeviceSubClass: UDSUBCLASS_HUB */
        1,              /* bDeviceProtocol: UDPROTO_HSHUBSTT */
        64,             /* bMaxPacketSize: 64 bytes */
        0x0000,         /* idVendor */
        0x0000,         /* idProduct */
        0x0001,         /* bcdDevice */
        1,              /* iManufacturer */
        2,              /* iProduct */
        0,              /* iSerialNumber */
        1               /* bNumConfigurations: 1 */
};

struct usb_interface_descriptor interface = {
        sizeof(struct usb_interface_descriptor),        /* bLength */
        4,              /* bDescriptorType: UDESC_INTERFACE */
        0,              /* bInterfaceNumber */
        0,              /* bAlternateSetting */
        1,              /* bNumEndpoints */
        9,              /* bInterfaceClass: UICLASS_HUB */
        0,              /* bInterfaceSubClass: UISUBCLASS_HUB */
        0,              /* bInterfaceProtocol: UIPROTO_HSHUBSTT */
        0               /* iInterface */
};

struct usb_endpoint_descriptor endpoint = {
        sizeof(struct usb_endpoint_descriptor),         /* bLength */
        5,              /* bDescriptorType: UDESC_ENDPOINT */
        0x81,           /* bEndpointAddress: UE_DIR_IN | EHCI_INTR_ENDPT */
        3,              /* bmAttributes: UE_INTERRUPT */
        8, 0,           /* wMaxPacketSize */
        255             /* bInterval */

};

struct usb_hub_descriptor hub = {
        sizeof(struct usb_hub_descriptor),      /* bDescLength */
        0x29,                           /* bDescriptorType: hub 
descriptor */
        2,                              /* bNrPorts -- runtime modified */
        0, 0,                           /* wHubCharacteristics */
        0xff,                           /* bPwrOn2PwrGood */
        {},                             /* bHubCntrCurrent */
        {}                              /* at most 7 ports! XXX */
};

Why don't use somenthing like this? (see up)

> +static int
> +ehci_submit_root (struct usb_device *dev, unsigned long pipe, void *buffer,
> +		  int length, struct devrequest *req)
> +{
> +	uint8_t tmpbuf[4];
> +	void *srcptr;
> +	int len, srclen;
> +	uint32_t reg;
> +
> +	srclen = 0;
> +	srcptr = NULL;
> +
> +	debug ("req=%u (%#x), type=%u (%#x), value=%u, index=%u",
> +	       req->request, req->request,
> +	       req->requesttype, req->requesttype,
> +	       le16_to_cpu (req->value), le16_to_cpu (req->index));
> +
> +#define C(a,b)	(((b) << 8) | (a))
> +
> +	switch (C (req->request, req->requesttype)) {
> +	case C (USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RECIP_DEVICE):
> +		switch (le16_to_cpu (req->value) >> 8) {
> +		case USB_DT_DEVICE:
> +			srcptr = descr.device;
> +			srclen = sizeof (descr.device);
> +			break;
> +		case USB_DT_CONFIG:
> +			srcptr = descr.config;
> +			srclen = sizeof (descr.config) +
> +			    sizeof (descr.interface) + sizeof (descr.endpoint);
> +			break;
> +		case USB_DT_STRING:
> +			switch (le16_to_cpu (req->value) & 0xff) {
> +			case 0:	/* Language */
> +				srcptr = "\4\3\1\0";
> +				srclen = 4;
> +				break;
> +			case 1:	/* Vendor */
> +				srcptr = "\16\3u\0-\0b\0o\0o\0t\0";
> +				srclen = 14;
> +				break;
> +			case 2:	/* Product */
> +				srcptr = "\52\3E\0H\0C\0I\0 \0H\0o\0s\0t\0 \0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0";
> +				srclen = 42;
> +				break;
> +			default:
> +				goto unknown;
> +			}
> +			break;
> +		default:
> +			debug ("unknown value %x", le16_to_cpu (req->value));
> +			goto unknown;
> +		}
> +		break;
> +	case C (USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB):
> +		switch (le16_to_cpu (req->value) >> 8) {
> +		case USB_DT_HUB:
> +			srcptr = descr.hub;
> +			srclen = sizeof (descr.hub);
> +			break;
> +		default:
> +			debug ("unknown value %x", le16_to_cpu (req->value));
> +			goto unknown;
> +		}
> +		break;
> +	case C (USB_REQ_SET_ADDRESS, USB_RECIP_DEVICE):
> +		rootdev = le16_to_cpu (req->value);
> +		break;
> +	case C (USB_REQ_SET_CONFIGURATION, USB_RECIP_DEVICE):
> +		/* Nothing to do */
> +		break;
> +	case C (USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB):
> +		tmpbuf[0] = 1;	/* USB_STATUS_SELFPOWERED */
> +		tmpbuf[1] = 0;
> +		srcptr = tmpbuf;
> +		srclen = 2;
> +		break;
> +	case C (USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT):
> +		memset (tmpbuf, 0, 4);
> +		reg = le32_to_cpu (hcor->or_portsc[le16_to_cpu (req->index) - 1]);
> +		if (reg & EHCI_PS_CS)
> +			tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
> +		if (reg & EHCI_PS_PE)
> +			tmpbuf[0] |= USB_PORT_STAT_ENABLE;
> +		if (reg & EHCI_PS_SUSP)
> +			tmpbuf[0] |= USB_PORT_STAT_SUSPEND;
> +		if (reg & EHCI_PS_OCA)
> +			tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
> +		if (reg & EHCI_PS_PR)
> +			tmpbuf[0] |= USB_PORT_STAT_RESET;
> +		if (reg & EHCI_PS_PP)
> +			tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
> +		tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
> +
> +		if (reg & EHCI_PS_CSC)
> +			tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
> +		if (reg & EHCI_PS_PEC)
> +			tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
> +		if (reg & EHCI_PS_OCC)
> +			tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
> +		if (portreset & (1 << le16_to_cpu (req->index)))
> +			tmpbuf[2] |= USB_PORT_STAT_C_RESET;
> +		srcptr = tmpbuf;
> +		srclen = 4;
> +		break;
> +	case C (USB_REQ_SET_FEATURE, USB_DIR_OUT | USB_RT_PORT):
> +		reg = le32_to_cpu (hcor->or_portsc[le16_to_cpu (req->index) - 1]);
> +		reg &= ~EHCI_PS_CLEAR;
> +		switch (le16_to_cpu (req->value)) {
> +		case USB_PORT_FEAT_POWER:
> +			reg |= EHCI_PS_PP;
> +			break;
> +		case USB_PORT_FEAT_RESET:
> +			if (EHCI_PS_IS_LOWSPEED (reg)) {
> +				/* Low speed device, give up ownership. */
> +				reg |= EHCI_PS_PO;
> +				break;
> +			}
> +			/* Start reset sequence. */
> +			reg &= ~EHCI_PS_PE;
> +			reg |= EHCI_PS_PR;
> +			hcor->or_portsc[le16_to_cpu (req->index) - 1] =
> +			    cpu_to_le32 (reg);
> +			/* Wait for reset to complete. */
> +			udelay (500000);
> +			/* Terminate reset sequence. */
> +			reg &= ~EHCI_PS_PR;
> +			/* TODO: is it only fsl chip that requires this
> +			 * manual setting of port enable?
> +			 */
> +			reg |= EHCI_PS_PE;
> +			hcor->or_portsc[le16_to_cpu (req->index) - 1] =
> +			    cpu_to_le32 (reg);
> +			/* Wait for HC to complete reset. */
> +			udelay (2000);
> +			reg =
> +			    le32_to_cpu (hcor->or_portsc[le16_to_cpu (req->index) - 1]);
> +			reg &= ~EHCI_PS_CLEAR;
> +			if ((reg & EHCI_PS_PE) == 0) {
> +				/* Not a high speed device, give up ownership. */
> +				reg |= EHCI_PS_PO;
> +				break;
> +			}
> +			portreset |= 1 << le16_to_cpu (req->index);
> +			break;
> +		default:
> +			debug ("unknown feature %x", le16_to_cpu (req->value));
> +			goto unknown;
> +		}
> +		hcor->or_portsc[le16_to_cpu (req->index) - 1] = cpu_to_le32 (reg);
> +		break;
> +	case C (USB_REQ_CLEAR_FEATURE, USB_DIR_OUT | USB_RT_PORT):
> +		reg = le32_to_cpu (hcor->or_portsc[le16_to_cpu (req->index) - 1]);
> +		reg &= ~EHCI_PS_CLEAR;
> +		switch (le16_to_cpu (req->value)) {
> +		case USB_PORT_FEAT_ENABLE:
> +			reg &= ~EHCI_PS_PE;
> +			break;
> +		case USB_PORT_FEAT_C_CONNECTION:
> +			reg |= EHCI_PS_CSC;
> +			break;
> +		case USB_PORT_FEAT_C_RESET:
> +			portreset &= ~(1 << le16_to_cpu (req->index));
> +			break;
> +		default:
> +			debug ("unknown feature %x", le16_to_cpu (req->value));
> +			goto unknown;
> +		}
> +		hcor->or_portsc[le16_to_cpu (req->index) - 1] = cpu_to_le32 (reg);
> +		break;
> +	default:
> +		debug ("Unknown request %x",
> +		       C (req->request, req->requesttype));
> +		goto unknown;
> +	}
> +
> +#undef C
> +
> +	len = min3 (srclen, le16_to_cpu (req->length), length);
> +	if (srcptr != NULL && len > 0)
> +		memcpy (buffer, srcptr, len);
> +	dev->act_len = len;
> +	dev->status = 0;
> +	return (0);
> +
> +      unknown:
> +	debug ("requesttype=%x, request=%x, value=%x, index=%x, length=%x",
> +	       req->requesttype, req->request, le16_to_cpu (req->value),
> +	       le16_to_cpu (req->index), le16_to_cpu (req->length));
> +
> +	dev->act_len = 0;
> +	dev->status = USB_ST_STALLED;
> +	return (-1);
> +}
> +
>   
This code can be change according with this one.

static int ehci_submit_root(struct usb_device *dev, unsigned long pipe,
                            void *buffer, int length, struct devrequest 
*req)
{
        uint8_t tmpbuf[4];
        u16 typeReq;
        void *srcptr;
        int len, srclen;
        uint32_t reg;

        srclen = 0;
        srcptr = NULL;

        DBG("req=%u (%#x), type=%u (%#x), value=%u, index=%u",
            req->request, req->request,
            req->requesttype, req->requesttype,
            swap_16(req->value), swap_16(req->index));

        typeReq = req->request << 8 | req->requesttype;

        switch (typeReq) {

        case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
                switch(swap_16(req->value) >> 8) {
                case USB_DT_DEVICE:
                        srcptr = &device;
                        srclen = sizeof(struct usb_device_descriptor);
                        break;
                case USB_DT_CONFIG:
                        srcptr = &config;
                        srclen = sizeof(config) +
                                sizeof(struct usb_interface_descriptor) +
                                sizeof(struct usb_hub_descriptor);
                        break;
                case USB_DT_STRING:
                        switch (swap_16(req->value) & 0xff) {
                        case 0:         /* Language */
                                srcptr = "\4\3\1\0";
                                srclen = 4;
                                break;
                        case 1:         /* Vendor */
                                srcptr = "\20\3P\0h\0i\0l\0i\0p\0s\0";
                                srclen = 16;
                                break;
                        case 2:         /* Product */
                                srcptr = "\12\3E\0H\0C\0I\0";
                                srclen = 10;
                                break;
                        default:
                                goto unknown;
                        }
                        break;
                default:
                        DBG("unknown value %x", swap_16(req->value));
                        goto unknown;
                }
                break;
        case USB_REQ_GET_DESCRIPTOR | (( USB_DIR_IN | USB_RT_HUB) << 8):
                switch (swap_16(req->value) >> 8) {
                case USB_DT_HUB:
                        srcptr = &hub;
                        srclen = sizeof(hub);
                        break;
                default:
                        DBG("unknown value %x", swap_16(req->value));
                        goto unknown;
                }
                break;
        case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
                rootdev = swap_16(req->value);
                break;
        case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
                /* Nothing to do */
                break;
        case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
                tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */
                tmpbuf[1] = 0;
                srcptr = tmpbuf;
                srclen = 2;
                break;
        case DeviceRequest | USB_REQ_GET_STATUS:
                memset(tmpbuf, 0, 4);
                reg = swap_32(hcor->or_portsc[swap_16(req->index) - 1]);
                if (reg & EHCI_PS_CS)
                        tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
                if (reg & EHCI_PS_PE)
                        tmpbuf[0] |= USB_PORT_STAT_ENABLE;
                if (reg & EHCI_PS_SUSP)
                        tmpbuf[0] |= USB_PORT_STAT_SUSPEND;
                if (reg & EHCI_PS_OCA)
                        tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
                if (reg & EHCI_PS_PR)
                        tmpbuf[0] |= USB_PORT_STAT_RESET;
                if (reg & EHCI_PS_PP)
...

All the struct are defined in u-boot and you can reuse that one, I think.

Regards Michael







More information about the U-Boot mailing list