blob: 5bb4f3ce632cd8cfb7a32846ec037342c47056ad [file] [log] [blame]
Stefan Roesec157d8e2005-08-01 16:41:48 +02001/*USB 1.1,2.0 device*/
2
3#include <common.h>
4#include <asm/processor.h>
5
Jon Loeliger3a1ed1e2007-07-09 18:57:22 -05006#if (defined(CONFIG_440EP) || defined(CONFIG_440EPX)) && defined(CONFIG_CMD_USB)
Stefan Roesec157d8e2005-08-01 16:41:48 +02007
8#include <usb.h>
Stefan Roese4fb25a32008-06-25 10:59:22 +02009#include <asm/ppc4xx-uic.h>
Stefan Roesec157d8e2005-08-01 16:41:48 +020010#include "usbdev.h"
Stefan Roesec157d8e2005-08-01 16:41:48 +020011
12#define USB_DT_DEVICE 0x01
13#define USB_DT_CONFIG 0x02
14#define USB_DT_STRING 0x03
15#define USB_DT_INTERFACE 0x04
16#define USB_DT_ENDPOINT 0x05
17
Wolfgang Denkc04a76e2005-08-06 00:11:50 +020018int set_value = -1;
Stefan Roesec157d8e2005-08-01 16:41:48 +020019
20void process_endpoints(unsigned short usb2d0_intrin)
21{
22 /*will hold the packet received */
23 struct usb_device_descriptor usb_device_packet;
24 struct usb_config_descriptor usb_config_packet;
25 struct usb_string_descriptor usb_string_packet;
26 struct devrequest setup_packet;
27 unsigned int *setup_packet_pt;
Wolfgang Denkc04a76e2005-08-06 00:11:50 +020028 unsigned char *packet_pt = NULL;
Stefan Roesec157d8e2005-08-01 16:41:48 +020029 int temp, temp1;
30
31 int i;
32
33 /*printf("{USB device} - endpoint 0x%X \n", usb2d0_intrin); */
34
35 /*set usb address, seems to not work unless it is done in the next
36 interrupt, so that is why it is done this way */
37 if (set_value != -1)
Wolfgang Denkc04a76e2005-08-06 00:11:50 +020038 *(unsigned char *)USB2D0_FADDR_8 = (unsigned char)set_value;
Stefan Roesec157d8e2005-08-01 16:41:48 +020039
40 /*endpoint 1 */
41 if (usb2d0_intrin & 0x01) {
42 setup_packet_pt = (unsigned int *)&setup_packet;
43
44 /*copy packet */
45 setup_packet_pt[0] = *(unsigned int *)USB2D0_FIFO_0;
46 setup_packet_pt[1] = *(unsigned int *)USB2D0_FIFO_0;
47 temp = *(unsigned int *)USB2D0_FIFO_0;
48 temp1 = *(unsigned int *)USB2D0_FIFO_0;
49
50 /*do some swapping */
51 setup_packet.value = swap_16(setup_packet.value);
52 setup_packet.index = swap_16(setup_packet.index);
53 setup_packet.length = swap_16(setup_packet.length);
54
55 /*clear rx packet */
56 *(unsigned short *)USB2D0_INCSR0_8 = 0x48;
57
58 /*printf("0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", setup_packet.requesttype,
59 setup_packet.request, setup_packet.value,
60 setup_packet.index, setup_packet.length, temp, temp1 ); */
61
62 switch (setup_packet.request) {
63 case USB_REQ_GET_DESCRIPTOR:
64
65 switch (setup_packet.value >> 8) {
66 case USB_DT_DEVICE:
67 /*create packet */
68 usb_device_packet.bLength = 18;
69 usb_device_packet.bDescriptorType =
70 USB_DT_DEVICE;
71#ifdef USB_2_0_DEVICE
72 usb_device_packet.bcdUSB = swap_16(0x200);
73#else
74 usb_device_packet.bcdUSB = swap_16(0x110);
75#endif
76 usb_device_packet.bDeviceClass = 0xff;
77 usb_device_packet.bDeviceSubClass = 0;
78 usb_device_packet.bDeviceProtocol = 0;
79 usb_device_packet.bMaxPacketSize0 = 32;
80 usb_device_packet.idVendor = swap_16(1);
81 usb_device_packet.idProduct = swap_16(2);
82 usb_device_packet.bcdDevice = swap_16(0x300);
83 usb_device_packet.iManufacturer = 1;
84 usb_device_packet.iProduct = 1;
85 usb_device_packet.iSerialNumber = 1;
86 usb_device_packet.bNumConfigurations = 1;
87
88 /*put packet in fifo */
89 packet_pt = (unsigned char *)&usb_device_packet;
90 break;
91
92 case USB_DT_CONFIG:
93 /*create packet */
94 usb_config_packet.bLength = 9;
95 usb_config_packet.bDescriptorType =
96 USB_DT_CONFIG;
97 usb_config_packet.wTotalLength = swap_16(25);
98 usb_config_packet.bNumInterfaces = 1;
99 usb_config_packet.bConfigurationValue = 1;
100 usb_config_packet.iConfiguration = 0;
101 usb_config_packet.bmAttributes = 0x40;
102 usb_config_packet.MaxPower = 0;
103
104 /*put packet in fifo */
105 packet_pt = (unsigned char *)&usb_config_packet;
106 break;
107
108 case USB_DT_STRING:
109 /*create packet */
110 usb_string_packet.bLength = 2;
111 usb_string_packet.bDescriptorType =
112 USB_DT_STRING;
113 usb_string_packet.wData[0] = 0x0094;
114
115 /*put packet in fifo */
116 packet_pt = (unsigned char *)&usb_string_packet;
117 break;
118 }
119
120 /*put packet in fifo */
121 for (i = 0; i < (setup_packet.length); i++) {
122 *(unsigned char *)USB2D0_FIFO_0 = packet_pt[i];
123 }
124
125 /*give tx command */
126 *(unsigned short *)USB2D0_INCSR0_8 = 0x0a;
127
128 break;
129
130 case USB_REQ_SET_ADDRESS:
131
132 /*copy usb address */
133 set_value = setup_packet.value;
134
135 break;
136 }
137
138 }
139}
140
141void process_other(unsigned char usb2d0_intrusb)
142{
143
144 /*check for sof */
145 if (usb2d0_intrusb & 0x08) {
146 /*printf("{USB device} - sof detected\n"); */
147 }
148
149 /*check for reset */
150 if (usb2d0_intrusb & 0x04) {
151 /*printf("{USB device} - reset detected\n"); */
152
153 /*copy usb address of zero, need to do this when usb reset */
154 set_value = 0;
155 }
156
157 if (usb2d0_intrusb & 0x02) {
158 /*printf("{USB device} - resume detected\n"); */
159 }
160
161 if (usb2d0_intrusb & 0x01) {
162 /*printf("{USB device} - suspend detected\n"); */
163 }
164}
165
166int usbInt(void)
167{
168 /*Must read these 2 registers and use values to clear interrupts. If you
169 do not read them then the interrupt will not be cleared. If you do not
170 use the variable the optimizer will not do a read. */
171 volatile unsigned short usb2d0_intrin =
172 *(unsigned short *)USB2D0_INTRIN_16;
173 volatile unsigned char usb2d0_intrusb =
174 *(unsigned char *)USB2D0_INTRUSB_8;
175
176 /*check if there was an endpoint interrupt */
177 if (usb2d0_intrin != 0) {
178 process_endpoints(usb2d0_intrin);
179 }
180
181 /*check for other interrupts */
182 if (usb2d0_intrusb != 0) {
183 process_other(usb2d0_intrusb);
184 }
185
186 return 0;
187}
188
Stefan Roese887e2ec2006-09-07 11:51:23 +0200189#if defined(CONFIG_440EPX)
190void usb_dev_init()
191{
192 printf("USB 2.0 Device init\n");
193
194 /*usb dev init */
195 *(unsigned char *)USB2D0_POWER_8 = 0xa1; /* 2.0 */
196
197 /*enable interrupts */
198 *(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f;
199
Stefan Roesed1631fe2008-06-26 13:40:57 +0200200 irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt,
Stefan Roese887e2ec2006-09-07 11:51:23 +0200201 NULL);
202}
203#else
Stefan Roesec157d8e2005-08-01 16:41:48 +0200204void usb_dev_init()
205{
206#ifdef USB_2_0_DEVICE
207 printf("USB 2.0 Device init\n");
208 /*select 2.0 device */
Stefan Roesed1c3b272009-09-09 16:25:29 +0200209 mtsdr(SDR0_USB0, 0x0); /* 2.0 */
Stefan Roesec157d8e2005-08-01 16:41:48 +0200210
211 /*usb dev init */
212 *(unsigned char *)USB2D0_POWER_8 = 0xa1; /* 2.0 */
213#else
214 printf("USB 1.1 Device init\n");
215 /*select 1.1 device */
Stefan Roesed1c3b272009-09-09 16:25:29 +0200216 mtsdr(SDR0_USB0, 0x2); /* 1.1 */
Stefan Roesec157d8e2005-08-01 16:41:48 +0200217
218 /*usb dev init */
219 *(unsigned char *)USB2D0_POWER_8 = 0xc0; /* 1.1 */
220#endif
221
222 /*enable interrupts */
223 *(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f;
224
225 irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt,
226 NULL);
227}
Stefan Roese887e2ec2006-09-07 11:51:23 +0200228#endif
Stefan Roesec157d8e2005-08-01 16:41:48 +0200229
Stefan Roese887e2ec2006-09-07 11:51:23 +0200230#endif /* CONFIG_440EP || CONFIG_440EPX */