Merge branch 'master' of /home/stefan/git/u-boot/u-boot into next
[platform/kernel/u-boot.git] / cpu / ppc4xx / usbdev.c
1 /*USB 1.1,2.0 device*/
2
3 #include <common.h>
4 #include <asm/processor.h>
5
6 #if (defined(CONFIG_440EP) || defined(CONFIG_440EPX)) && defined(CONFIG_CMD_USB)
7
8 #include <usb.h>
9 #include <asm/ppc4xx-uic.h>
10 #include "usbdev.h"
11
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
18 int set_value = -1;
19
20 void 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;
28         unsigned char *packet_pt = NULL;
29         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)
38                 *(unsigned char *)USB2D0_FADDR_8 = (unsigned char)set_value;
39
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
141 void 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
166 int 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
189 #if defined(CONFIG_440EPX)
190 void 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
200         irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt,
201                             NULL);
202 }
203 #else
204 void usb_dev_init()
205 {
206 #ifdef USB_2_0_DEVICE
207         printf("USB 2.0 Device init\n");
208         /*select 2.0 device */
209         mtsdr(sdr_usb0, 0x0);   /* 2.0 */
210
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 */
216         mtsdr(sdr_usb0, 0x2);   /* 1.1 */
217
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 }
228 #endif
229
230 #endif /* CONFIG_440EP || CONFIG_440EPX */