Initial revision
[karo-tx-uboot.git] / post / usb.c
1 /*
2  * (C) Copyright 2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25
26 /*
27  * USB test
28  *
29  * The USB controller is tested in the local loopback mode.
30  * It is configured so that endpoint 0 operates as host and endpoint 1
31  * operates as function endpoint. After that an IN token transaction
32  * is performed.
33  * Refer to MPC850 User Manual, Section 32.11.1 USB Host Controller
34  * Initialization Example.
35  */
36
37 #ifdef CONFIG_POST
38
39 #include <post.h>
40
41 #if CONFIG_POST & CFG_POST_USB
42
43 #include <commproc.h>
44 #include <command.h>
45
46 #define TOUT_LOOP 100
47
48 #define PROFF_USB               ((uint)0x0000)
49
50 #define CPM_USB_EP0_BASE        0x0a00
51 #define CPM_USB_EP1_BASE        0x0a20
52
53 #define CPM_USB_DT0_BASE        0x0a80
54 #define CPM_USB_DT1_BASE        0x0a90
55 #define CPM_USB_DR0_BASE        0x0aa0
56 #define CPM_USB_DR1_BASE        0x0ab0
57
58 #define CPM_USB_RX0_BASE        0x0b00
59 #define CPM_USB_RX1_BASE        0x0b08
60 #define CPM_USB_TX0_BASE        0x0b20
61 #define CPM_USB_TX1_BASE        0x0b28
62
63 #define USB_EXPECT(x)           if (!(x)) goto Done;
64
65 typedef struct usb_param {
66         ushort ep0ptr;
67         ushort ep1ptr;
68         ushort ep2ptr;
69         ushort ep3ptr;
70         uint rstate;
71         uint rptr;
72         ushort frame_n;
73         ushort rbcnt;
74         ushort rtemp;
75 } usb_param_t;
76
77 typedef struct usb_param_block {
78         ushort rbase;
79         ushort tbase;
80         uchar rfcr;
81         uchar tfcr;
82         ushort mrblr;
83         ushort rbptr;
84         ushort tbptr;
85         uint tstate;
86         uint tptr;
87         ushort tcrc;
88         ushort tbcnt;
89         uint res[2];
90 } usb_param_block_t;
91
92 typedef struct usb {
93         uchar usmod;
94         uchar usadr;
95         uchar uscom;
96         uchar res1;
97         ushort usep[4];
98         uchar res2[4];
99         ushort usber;
100         uchar res3[2];
101         ushort usbmr;
102         uchar res4;
103         uchar usbs;
104         uchar res5[8];
105 } usb_t;
106
107 int usb_post_test (int flags)
108 {
109         int res = -1;
110         volatile immap_t *im = (immap_t *) CFG_IMMR;
111         volatile cpm8xx_t *cp = &(im->im_cpm);
112         volatile usb_param_t *pram_ptr;
113         uint dpram;
114         ushort DPRAM;
115         volatile cbd_t *tx;
116         volatile cbd_t *rx;
117         volatile usb_t *usbr;
118         volatile usb_param_block_t *ep0;
119         volatile usb_param_block_t *ep1;
120         int j;
121
122         pram_ptr = (usb_param_t *) & (im->im_cpm.cp_dparam[PROFF_USB]);
123         dpram = (uint) im->im_cpm.cp_dpmem;
124         DPRAM = dpram;
125         tx = (cbd_t *) (dpram + CPM_USB_TX0_BASE);
126         rx = (cbd_t *) (dpram + CPM_USB_RX0_BASE);
127         ep0 = (usb_param_block_t *) (dpram + CPM_USB_EP0_BASE);
128         ep1 = (usb_param_block_t *) (dpram + CPM_USB_EP1_BASE);
129         usbr = (usb_t *) & (im->im_cpm.cp_scc[0]);
130
131         /* 01 */
132         im->im_ioport.iop_padir &= ~(ushort) 0x0200;
133         im->im_ioport.iop_papar |= (ushort) 0x0200;
134
135         cp->cp_sicr &= ~0x000000FF;
136         cp->cp_sicr |= 0x00000018;
137
138         cp->cp_brgc4 = 0x00010001;
139
140         /* 02 */
141         im->im_ioport.iop_padir &= ~(ushort) 0x0002;
142         im->im_ioport.iop_padir &= ~(ushort) 0x0001;
143
144         im->im_ioport.iop_papar |= (ushort) 0x0002;
145         im->im_ioport.iop_papar |= (ushort) 0x0001;
146
147         /* 03 */
148         im->im_ioport.iop_pcdir &= ~(ushort) 0x0020;
149         im->im_ioport.iop_pcdir &= ~(ushort) 0x0010;
150
151         im->im_ioport.iop_pcpar &= ~(ushort) 0x0020;
152         im->im_ioport.iop_pcpar &= ~(ushort) 0x0010;
153
154         im->im_ioport.iop_pcso |= (ushort) 0x0020;
155         im->im_ioport.iop_pcso |= (ushort) 0x0010;
156
157         /* 04 */
158         im->im_ioport.iop_pcdir |= (ushort) 0x0200;
159         im->im_ioport.iop_pcdir |= (ushort) 0x0100;
160
161         im->im_ioport.iop_pcpar |= (ushort) 0x0200;
162         im->im_ioport.iop_pcpar |= (ushort) 0x0100;
163
164         /* 05 */
165         pram_ptr->frame_n = 0;
166
167         /* 06 */
168         pram_ptr->ep0ptr = DPRAM + CPM_USB_EP0_BASE;
169         pram_ptr->ep1ptr = DPRAM + CPM_USB_EP1_BASE;
170
171         /* 07-10 */
172         tx[0].cbd_sc = 0xB800;
173         tx[0].cbd_datlen = 3;
174         tx[0].cbd_bufaddr = dpram + CPM_USB_DT0_BASE;
175
176         tx[1].cbd_sc = 0xBC80;
177         tx[1].cbd_datlen = 3;
178         tx[1].cbd_bufaddr = dpram + CPM_USB_DT1_BASE;
179
180         rx[0].cbd_sc = 0xA000;
181         rx[0].cbd_datlen = 0;
182         rx[0].cbd_bufaddr = dpram + CPM_USB_DR0_BASE;
183
184         rx[1].cbd_sc = 0xA000;
185         rx[1].cbd_datlen = 0;
186         rx[1].cbd_bufaddr = dpram + CPM_USB_DR1_BASE;
187
188         /* 11-12 */
189         *(volatile int *) (dpram + CPM_USB_DT0_BASE) = 0x69856000;
190         *(volatile int *) (dpram + CPM_USB_DT1_BASE) = 0xABCD1234;
191
192         *(volatile int *) (dpram + CPM_USB_DR0_BASE) = 0;
193         *(volatile int *) (dpram + CPM_USB_DR1_BASE) = 0;
194
195         /* 13-16 */
196         ep0->rbase = DPRAM + CPM_USB_RX0_BASE;
197         ep0->tbase = DPRAM + CPM_USB_TX0_BASE;
198         ep0->rfcr = 0x18;
199         ep0->tfcr = 0x18;
200         ep0->mrblr = 0x100;
201         ep0->rbptr = DPRAM + CPM_USB_RX0_BASE;
202         ep0->tbptr = DPRAM + CPM_USB_TX0_BASE;
203         ep0->tstate = 0;
204
205         /* 17-20 */
206         ep1->rbase = DPRAM + CPM_USB_RX1_BASE;
207         ep1->tbase = DPRAM + CPM_USB_TX1_BASE;
208         ep1->rfcr = 0x18;
209         ep1->tfcr = 0x18;
210         ep1->mrblr = 0x100;
211         ep1->rbptr = DPRAM + CPM_USB_RX1_BASE;
212         ep1->tbptr = DPRAM + CPM_USB_TX1_BASE;
213         ep1->tstate = 0;
214
215         /* 21-24 */
216         usbr->usep[0] = 0x0000;
217         usbr->usep[1] = 0x1100;
218         usbr->usep[2] = 0x2200;
219         usbr->usep[3] = 0x3300;
220
221         /* 25 */
222         usbr->usmod = 0x06;
223
224         /* 26 */
225         usbr->usadr = 0x05;
226
227         /* 27 */
228         usbr->uscom = 0;
229
230         /* 28 */
231         usbr->usmod |= 0x01;
232         udelay (1);
233
234         /* 29-30 */
235         usbr->uscom = 0x80;
236         usbr->uscom = 0x81;
237
238         /* Wait for the data packet to be transmitted */
239         for (j = 0; j < TOUT_LOOP; j++) {
240                 if (tx[1].cbd_sc & (ushort) 0x8000)
241                         udelay (1);
242                 else
243                         break;
244         }
245
246         USB_EXPECT (j < TOUT_LOOP);
247
248         USB_EXPECT (tx[0].cbd_sc == 0x3800);
249         USB_EXPECT (tx[0].cbd_datlen == 3);
250
251         USB_EXPECT (tx[1].cbd_sc == 0x3C80);
252         USB_EXPECT (tx[1].cbd_datlen == 3);
253
254         USB_EXPECT (rx[0].cbd_sc == 0x2C00);
255         USB_EXPECT (rx[0].cbd_datlen == 5);
256
257         USB_EXPECT (*(volatile int *) (dpram + CPM_USB_DR0_BASE) ==
258                                 0xABCD122B);
259         USB_EXPECT (*(volatile char *) (dpram + CPM_USB_DR0_BASE + 4) == 0x42);
260
261         res = 0;
262   Done:
263
264         return res;
265 }
266
267 #endif /* CONFIG_POST & CFG_POST_USB */
268
269 #endif /* CONFIG_POST */