usbdev.c 5.77 KB
Newer Older
Alexander Yurtsev's avatar
Alexander Yurtsev committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
/*USB 1.1,2.0 device*/

#include <common.h>
#include <asm/processor.h>

#if (defined(CONFIG_440EP) || defined(CONFIG_440EPX)) && defined(CONFIG_CMD_USB)

#include <usb.h>
#include <asm/ppc4xx-uic.h>
#include "usbdev.h"

#define USB_DT_DEVICE        0x01
#define USB_DT_CONFIG        0x02
#define USB_DT_STRING        0x03
#define USB_DT_INTERFACE     0x04
#define USB_DT_ENDPOINT      0x05

int set_value = -1;

void process_endpoints(unsigned short usb2d0_intrin)
{
	/*will hold the packet received */
	struct usb_device_descriptor usb_device_packet;
	struct usb_configuration_descriptor usb_config_packet;
	struct usb_string_descriptor usb_string_packet;
	struct devrequest setup_packet;
	unsigned int *setup_packet_pt;
	unsigned char *packet_pt = NULL;
	int temp, temp1;

	int i;

	/*printf("{USB device} - endpoint 0x%X \n", usb2d0_intrin); */

	/*set usb address, seems to not work unless it is done in the next
	   interrupt, so that is why it is done this way */
	if (set_value != -1)
		*(unsigned char *)USB2D0_FADDR_8 = (unsigned char)set_value;

	/*endpoint 1 */
	if (usb2d0_intrin & 0x01) {
		setup_packet_pt = (unsigned int *)&setup_packet;

		/*copy packet */
		setup_packet_pt[0] = *(unsigned int *)USB2D0_FIFO_0;
		setup_packet_pt[1] = *(unsigned int *)USB2D0_FIFO_0;
		temp = *(unsigned int *)USB2D0_FIFO_0;
		temp1 = *(unsigned int *)USB2D0_FIFO_0;

		/*do some swapping */
		setup_packet.value = swap_16(setup_packet.value);
		setup_packet.index = swap_16(setup_packet.index);
		setup_packet.length = swap_16(setup_packet.length);

		/*clear rx packet */
		*(unsigned short *)USB2D0_INCSR0_8 = 0x48;

		/*printf("0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", setup_packet.requesttype,
		   setup_packet.request, setup_packet.value,
		   setup_packet.index, setup_packet.length, temp, temp1 ); */

		switch (setup_packet.request) {
		case USB_REQ_GET_DESCRIPTOR:

			switch (setup_packet.value >> 8) {
			case USB_DT_DEVICE:
				/*create packet */
				usb_device_packet.bLength = 18;
				usb_device_packet.bDescriptorType =
				    USB_DT_DEVICE;
#ifdef USB_2_0_DEVICE
				usb_device_packet.bcdUSB = swap_16(0x200);
#else
				usb_device_packet.bcdUSB = swap_16(0x110);
#endif
				usb_device_packet.bDeviceClass = 0xff;
				usb_device_packet.bDeviceSubClass = 0;
				usb_device_packet.bDeviceProtocol = 0;
				usb_device_packet.bMaxPacketSize0 = 32;
				usb_device_packet.idVendor = swap_16(1);
				usb_device_packet.idProduct = swap_16(2);
				usb_device_packet.bcdDevice = swap_16(0x300);
				usb_device_packet.iManufacturer = 1;
				usb_device_packet.iProduct = 1;
				usb_device_packet.iSerialNumber = 1;
				usb_device_packet.bNumConfigurations = 1;

				/*put packet in fifo */
				packet_pt = (unsigned char *)&usb_device_packet;
				break;

			case USB_DT_CONFIG:
				/*create packet */
				usb_config_packet.bLength = 9;
				usb_config_packet.bDescriptorType =
				    USB_DT_CONFIG;
				usb_config_packet.wTotalLength = swap_16(25);
				usb_config_packet.bNumInterfaces = 1;
				usb_config_packet.bConfigurationValue = 1;
				usb_config_packet.iConfiguration = 0;
				usb_config_packet.bmAttributes = 0x40;
				usb_config_packet.bMaxPower = 0;

				/*put packet in fifo */
				packet_pt = (unsigned char *)&usb_config_packet;
				break;

			case USB_DT_STRING:
				/*create packet */
				usb_string_packet.bLength = 2;
				usb_string_packet.bDescriptorType =
				    USB_DT_STRING;
				usb_string_packet.wData[0] = 0x0094;

				/*put packet in fifo */
				packet_pt = (unsigned char *)&usb_string_packet;
				break;
			}

			/*put packet in fifo */
			for (i = 0; i < (setup_packet.length); i++) {
				*(unsigned char *)USB2D0_FIFO_0 = packet_pt[i];
			}

			/*give tx command */
			*(unsigned short *)USB2D0_INCSR0_8 = 0x0a;

			break;

		case USB_REQ_SET_ADDRESS:

			/*copy usb address */
			set_value = setup_packet.value;

			break;
		}

	}
}

void process_other(unsigned char usb2d0_intrusb)
{

	/*check for sof */
	if (usb2d0_intrusb & 0x08) {
		/*printf("{USB device} - sof detected\n"); */
	}

	/*check for reset */
	if (usb2d0_intrusb & 0x04) {
		/*printf("{USB device} - reset detected\n"); */

		/*copy usb address of zero, need to do this when usb reset */
		set_value = 0;
	}

	if (usb2d0_intrusb & 0x02) {
		/*printf("{USB device} - resume detected\n"); */
	}

	if (usb2d0_intrusb & 0x01) {
		/*printf("{USB device} - suspend detected\n"); */
	}
}

int usbInt(void)
{
	/*Must read these 2 registers and use values to clear interrupts.  If you
	   do not read them then the interrupt will not be cleared.  If you do not
	   use the variable the optimizer will not do a read. */
	volatile unsigned short usb2d0_intrin =
	    *(unsigned short *)USB2D0_INTRIN_16;
	volatile unsigned char usb2d0_intrusb =
	    *(unsigned char *)USB2D0_INTRUSB_8;

	/*check if there was an endpoint interrupt */
	if (usb2d0_intrin != 0) {
		process_endpoints(usb2d0_intrin);
	}

	/*check for other interrupts */
	if (usb2d0_intrusb != 0) {
		process_other(usb2d0_intrusb);
	}

	return 0;
}

#if defined(CONFIG_440EPX)
void usb_dev_init()
{
	printf("USB 2.0 Device init\n");

	/*usb dev init */
	*(unsigned char *)USB2D0_POWER_8 = 0xa1;	/* 2.0 */

	/*enable interrupts */
	*(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f;

	irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt,
			    NULL);
}
#else
void usb_dev_init()
{
#ifdef USB_2_0_DEVICE
	printf("USB 2.0 Device init\n");
	/*select 2.0 device */
	mtsdr(SDR0_USB0, 0x0);	/* 2.0 */

	/*usb dev init */
	*(unsigned char *)USB2D0_POWER_8 = 0xa1;	/* 2.0 */
#else
	printf("USB 1.1 Device init\n");
	/*select 1.1 device */
	mtsdr(SDR0_USB0, 0x2);	/* 1.1 */

	/*usb dev init */
	*(unsigned char *)USB2D0_POWER_8 = 0xc0;	/* 1.1 */
#endif

	/*enable interrupts */
	*(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f;

	irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt,
			    NULL);
}
#endif

#endif /* CONFIG_440EP || CONFIG_440EPX */