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 #include <post.h>
38 
39 #if CONFIG_POST & CONFIG_SYS_POST_USB
40 
41 #include <commproc.h>
42 #include <command.h>
43 
44 #define TOUT_LOOP 100
45 
46 #define	PROFF_USB		((uint)0x0000)
47 
48 #define CPM_USB_EP0_BASE	0x0a00
49 #define CPM_USB_EP1_BASE	0x0a20
50 
51 #define CPM_USB_DT0_BASE	0x0a80
52 #define CPM_USB_DT1_BASE	0x0a90
53 #define CPM_USB_DR0_BASE	0x0aa0
54 #define CPM_USB_DR1_BASE	0x0ab0
55 
56 #define CPM_USB_RX0_BASE	0x0b00
57 #define CPM_USB_RX1_BASE	0x0b08
58 #define CPM_USB_TX0_BASE	0x0b20
59 #define CPM_USB_TX1_BASE	0x0b28
60 
61 #define USB_EXPECT(x)		if (!(x)) goto Done;
62 
63 typedef struct usb_param {
64 	ushort ep0ptr;
65 	ushort ep1ptr;
66 	ushort ep2ptr;
67 	ushort ep3ptr;
68 	uint rstate;
69 	uint rptr;
70 	ushort frame_n;
71 	ushort rbcnt;
72 	ushort rtemp;
73 } usb_param_t;
74 
75 typedef struct usb_param_block {
76 	ushort rbase;
77 	ushort tbase;
78 	uchar rfcr;
79 	uchar tfcr;
80 	ushort mrblr;
81 	ushort rbptr;
82 	ushort tbptr;
83 	uint tstate;
84 	uint tptr;
85 	ushort tcrc;
86 	ushort tbcnt;
87 	uint res[2];
88 } usb_param_block_t;
89 
90 typedef struct usb {
91 	uchar usmod;
92 	uchar usadr;
93 	uchar uscom;
94 	uchar res1;
95 	ushort usep[4];
96 	uchar res2[4];
97 	ushort usber;
98 	uchar res3[2];
99 	ushort usbmr;
100 	uchar res4;
101 	uchar usbs;
102 	uchar res5[8];
103 } usb_t;
104 
usb_post_test(int flags)105 int usb_post_test (int flags)
106 {
107 	int res = -1;
108 	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
109 	volatile cpm8xx_t *cp = &(im->im_cpm);
110 	volatile usb_param_t *pram_ptr;
111 	uint dpram;
112 	ushort DPRAM;
113 	volatile cbd_t *tx;
114 	volatile cbd_t *rx;
115 	volatile usb_t *usbr;
116 	volatile usb_param_block_t *ep0;
117 	volatile usb_param_block_t *ep1;
118 	int j;
119 
120 	pram_ptr = (usb_param_t *) & (im->im_cpm.cp_dparam[PROFF_USB]);
121 	dpram = (uint) im->im_cpm.cp_dpmem;
122 	DPRAM = dpram;
123 	tx = (cbd_t *) (dpram + CPM_USB_TX0_BASE);
124 	rx = (cbd_t *) (dpram + CPM_USB_RX0_BASE);
125 	ep0 = (usb_param_block_t *) (dpram + CPM_USB_EP0_BASE);
126 	ep1 = (usb_param_block_t *) (dpram + CPM_USB_EP1_BASE);
127 	usbr = (usb_t *) & (im->im_cpm.cp_scc[0]);
128 
129 	/* 01 */
130 	im->im_ioport.iop_padir &= ~(ushort) 0x0200;
131 	im->im_ioport.iop_papar |= (ushort) 0x0200;
132 
133 	cp->cp_sicr &= ~0x000000FF;
134 	cp->cp_sicr |= 0x00000018;
135 
136 	cp->cp_brgc4 = 0x00010001;
137 
138 	/* 02 */
139 	im->im_ioport.iop_padir &= ~(ushort) 0x0002;
140 	im->im_ioport.iop_padir &= ~(ushort) 0x0001;
141 
142 	im->im_ioport.iop_papar |= (ushort) 0x0002;
143 	im->im_ioport.iop_papar |= (ushort) 0x0001;
144 
145 	/* 03 */
146 	im->im_ioport.iop_pcdir &= ~(ushort) 0x0020;
147 	im->im_ioport.iop_pcdir &= ~(ushort) 0x0010;
148 
149 	im->im_ioport.iop_pcpar &= ~(ushort) 0x0020;
150 	im->im_ioport.iop_pcpar &= ~(ushort) 0x0010;
151 
152 	im->im_ioport.iop_pcso |= (ushort) 0x0020;
153 	im->im_ioport.iop_pcso |= (ushort) 0x0010;
154 
155 	/* 04 */
156 	im->im_ioport.iop_pcdir |= (ushort) 0x0200;
157 	im->im_ioport.iop_pcdir |= (ushort) 0x0100;
158 
159 	im->im_ioport.iop_pcpar |= (ushort) 0x0200;
160 	im->im_ioport.iop_pcpar |= (ushort) 0x0100;
161 
162 	/* 05 */
163 	pram_ptr->frame_n = 0;
164 
165 	/* 06 */
166 	pram_ptr->ep0ptr = DPRAM + CPM_USB_EP0_BASE;
167 	pram_ptr->ep1ptr = DPRAM + CPM_USB_EP1_BASE;
168 
169 	/* 07-10 */
170 	tx[0].cbd_sc = 0xB800;
171 	tx[0].cbd_datlen = 3;
172 	tx[0].cbd_bufaddr = dpram + CPM_USB_DT0_BASE;
173 
174 	tx[1].cbd_sc = 0xBC80;
175 	tx[1].cbd_datlen = 3;
176 	tx[1].cbd_bufaddr = dpram + CPM_USB_DT1_BASE;
177 
178 	rx[0].cbd_sc = 0xA000;
179 	rx[0].cbd_datlen = 0;
180 	rx[0].cbd_bufaddr = dpram + CPM_USB_DR0_BASE;
181 
182 	rx[1].cbd_sc = 0xA000;
183 	rx[1].cbd_datlen = 0;
184 	rx[1].cbd_bufaddr = dpram + CPM_USB_DR1_BASE;
185 
186 	/* 11-12 */
187 	*(volatile int *) (dpram + CPM_USB_DT0_BASE) = 0x69856000;
188 	*(volatile int *) (dpram + CPM_USB_DT1_BASE) = 0xABCD1234;
189 
190 	*(volatile int *) (dpram + CPM_USB_DR0_BASE) = 0;
191 	*(volatile int *) (dpram + CPM_USB_DR1_BASE) = 0;
192 
193 	/* 13-16 */
194 	ep0->rbase = DPRAM + CPM_USB_RX0_BASE;
195 	ep0->tbase = DPRAM + CPM_USB_TX0_BASE;
196 	ep0->rfcr = 0x18;
197 	ep0->tfcr = 0x18;
198 	ep0->mrblr = 0x100;
199 	ep0->rbptr = DPRAM + CPM_USB_RX0_BASE;
200 	ep0->tbptr = DPRAM + CPM_USB_TX0_BASE;
201 	ep0->tstate = 0;
202 
203 	/* 17-20 */
204 	ep1->rbase = DPRAM + CPM_USB_RX1_BASE;
205 	ep1->tbase = DPRAM + CPM_USB_TX1_BASE;
206 	ep1->rfcr = 0x18;
207 	ep1->tfcr = 0x18;
208 	ep1->mrblr = 0x100;
209 	ep1->rbptr = DPRAM + CPM_USB_RX1_BASE;
210 	ep1->tbptr = DPRAM + CPM_USB_TX1_BASE;
211 	ep1->tstate = 0;
212 
213 	/* 21-24 */
214 	usbr->usep[0] = 0x0000;
215 	usbr->usep[1] = 0x1100;
216 	usbr->usep[2] = 0x2200;
217 	usbr->usep[3] = 0x3300;
218 
219 	/* 25 */
220 	usbr->usmod = 0x06;
221 
222 	/* 26 */
223 	usbr->usadr = 0x05;
224 
225 	/* 27 */
226 	usbr->uscom = 0;
227 
228 	/* 28 */
229 	usbr->usmod |= 0x01;
230 	udelay (1);
231 
232 	/* 29-30 */
233 	usbr->uscom = 0x80;
234 	usbr->uscom = 0x81;
235 
236 	/* Wait for the data packet to be transmitted */
237 	for (j = 0; j < TOUT_LOOP; j++) {
238 		if (tx[1].cbd_sc & (ushort) 0x8000)
239 			udelay (1);
240 		else
241 			break;
242 	}
243 
244 	USB_EXPECT (j < TOUT_LOOP);
245 
246 	USB_EXPECT (tx[0].cbd_sc == 0x3800);
247 	USB_EXPECT (tx[0].cbd_datlen == 3);
248 
249 	USB_EXPECT (tx[1].cbd_sc == 0x3C80);
250 	USB_EXPECT (tx[1].cbd_datlen == 3);
251 
252 	USB_EXPECT (rx[0].cbd_sc == 0x2C00);
253 	USB_EXPECT (rx[0].cbd_datlen == 5);
254 
255 	USB_EXPECT (*(volatile int *) (dpram + CPM_USB_DR0_BASE) ==
256 				0xABCD122B);
257 	USB_EXPECT (*(volatile char *) (dpram + CPM_USB_DR0_BASE + 4) == 0x42);
258 
259 	res = 0;
260   Done:
261 
262 	return res;
263 }
264 
265 #endif /* CONFIG_POST & CONFIG_SYS_POST_USB */
266