| /* | 
 |  * (C) Copyright 2002 | 
 |  * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | 
 |  * | 
 |  * See file CREDITS for list of people who contributed to this | 
 |  * project. | 
 |  * | 
 |  * This program is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU General Public License as | 
 |  * published by the Free Software Foundation; either version 2 of | 
 |  * the License, or (at your option) any later version. | 
 |  * | 
 |  * This program is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |  * GNU General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU General Public License | 
 |  * along with this program; if not, write to the Free Software | 
 |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 
 |  * MA 02111-1307 USA | 
 |  */ | 
 |  | 
 | #include <common.h> | 
 |  | 
 | /* | 
 |  * USB test | 
 |  * | 
 |  * The USB controller is tested in the local loopback mode. | 
 |  * It is configured so that endpoint 0 operates as host and endpoint 1 | 
 |  * operates as function endpoint. After that an IN token transaction | 
 |  * is performed. | 
 |  * Refer to MPC850 User Manual, Section 32.11.1 USB Host Controller | 
 |  * Initialization Example. | 
 |  */ | 
 |  | 
 | #ifdef CONFIG_POST | 
 |  | 
 | #include <post.h> | 
 |  | 
 | #if CONFIG_POST & CFG_POST_USB | 
 |  | 
 | #include <commproc.h> | 
 | #include <command.h> | 
 |  | 
 | #define TOUT_LOOP 100 | 
 |  | 
 | #define	PROFF_USB		((uint)0x0000) | 
 |  | 
 | #define CPM_USB_EP0_BASE	0x0a00 | 
 | #define CPM_USB_EP1_BASE	0x0a20 | 
 |  | 
 | #define CPM_USB_DT0_BASE	0x0a80 | 
 | #define CPM_USB_DT1_BASE	0x0a90 | 
 | #define CPM_USB_DR0_BASE	0x0aa0 | 
 | #define CPM_USB_DR1_BASE	0x0ab0 | 
 |  | 
 | #define CPM_USB_RX0_BASE	0x0b00 | 
 | #define CPM_USB_RX1_BASE	0x0b08 | 
 | #define CPM_USB_TX0_BASE	0x0b20 | 
 | #define CPM_USB_TX1_BASE	0x0b28 | 
 |  | 
 | #define USB_EXPECT(x)		if (!(x)) goto Done; | 
 |  | 
 | typedef struct usb_param { | 
 | 	ushort ep0ptr; | 
 | 	ushort ep1ptr; | 
 | 	ushort ep2ptr; | 
 | 	ushort ep3ptr; | 
 | 	uint rstate; | 
 | 	uint rptr; | 
 | 	ushort frame_n; | 
 | 	ushort rbcnt; | 
 | 	ushort rtemp; | 
 | } usb_param_t; | 
 |  | 
 | typedef struct usb_param_block { | 
 | 	ushort rbase; | 
 | 	ushort tbase; | 
 | 	uchar rfcr; | 
 | 	uchar tfcr; | 
 | 	ushort mrblr; | 
 | 	ushort rbptr; | 
 | 	ushort tbptr; | 
 | 	uint tstate; | 
 | 	uint tptr; | 
 | 	ushort tcrc; | 
 | 	ushort tbcnt; | 
 | 	uint res[2]; | 
 | } usb_param_block_t; | 
 |  | 
 | typedef struct usb { | 
 | 	uchar usmod; | 
 | 	uchar usadr; | 
 | 	uchar uscom; | 
 | 	uchar res1; | 
 | 	ushort usep[4]; | 
 | 	uchar res2[4]; | 
 | 	ushort usber; | 
 | 	uchar res3[2]; | 
 | 	ushort usbmr; | 
 | 	uchar res4; | 
 | 	uchar usbs; | 
 | 	uchar res5[8]; | 
 | } usb_t; | 
 |  | 
 | int usb_post_test (int flags) | 
 | { | 
 | 	int res = -1; | 
 | 	volatile immap_t *im = (immap_t *) CFG_IMMR; | 
 | 	volatile cpm8xx_t *cp = &(im->im_cpm); | 
 | 	volatile usb_param_t *pram_ptr; | 
 | 	uint dpram; | 
 | 	ushort DPRAM; | 
 | 	volatile cbd_t *tx; | 
 | 	volatile cbd_t *rx; | 
 | 	volatile usb_t *usbr; | 
 | 	volatile usb_param_block_t *ep0; | 
 | 	volatile usb_param_block_t *ep1; | 
 | 	int j; | 
 |  | 
 | 	pram_ptr = (usb_param_t *) & (im->im_cpm.cp_dparam[PROFF_USB]); | 
 | 	dpram = (uint) im->im_cpm.cp_dpmem; | 
 | 	DPRAM = dpram; | 
 | 	tx = (cbd_t *) (dpram + CPM_USB_TX0_BASE); | 
 | 	rx = (cbd_t *) (dpram + CPM_USB_RX0_BASE); | 
 | 	ep0 = (usb_param_block_t *) (dpram + CPM_USB_EP0_BASE); | 
 | 	ep1 = (usb_param_block_t *) (dpram + CPM_USB_EP1_BASE); | 
 | 	usbr = (usb_t *) & (im->im_cpm.cp_scc[0]); | 
 |  | 
 | 	/* 01 */ | 
 | 	im->im_ioport.iop_padir &= ~(ushort) 0x0200; | 
 | 	im->im_ioport.iop_papar |= (ushort) 0x0200; | 
 |  | 
 | 	cp->cp_sicr &= ~0x000000FF; | 
 | 	cp->cp_sicr |= 0x00000018; | 
 |  | 
 | 	cp->cp_brgc4 = 0x00010001; | 
 |  | 
 | 	/* 02 */ | 
 | 	im->im_ioport.iop_padir &= ~(ushort) 0x0002; | 
 | 	im->im_ioport.iop_padir &= ~(ushort) 0x0001; | 
 |  | 
 | 	im->im_ioport.iop_papar |= (ushort) 0x0002; | 
 | 	im->im_ioport.iop_papar |= (ushort) 0x0001; | 
 |  | 
 | 	/* 03 */ | 
 | 	im->im_ioport.iop_pcdir &= ~(ushort) 0x0020; | 
 | 	im->im_ioport.iop_pcdir &= ~(ushort) 0x0010; | 
 |  | 
 | 	im->im_ioport.iop_pcpar &= ~(ushort) 0x0020; | 
 | 	im->im_ioport.iop_pcpar &= ~(ushort) 0x0010; | 
 |  | 
 | 	im->im_ioport.iop_pcso |= (ushort) 0x0020; | 
 | 	im->im_ioport.iop_pcso |= (ushort) 0x0010; | 
 |  | 
 | 	/* 04 */ | 
 | 	im->im_ioport.iop_pcdir |= (ushort) 0x0200; | 
 | 	im->im_ioport.iop_pcdir |= (ushort) 0x0100; | 
 |  | 
 | 	im->im_ioport.iop_pcpar |= (ushort) 0x0200; | 
 | 	im->im_ioport.iop_pcpar |= (ushort) 0x0100; | 
 |  | 
 | 	/* 05 */ | 
 | 	pram_ptr->frame_n = 0; | 
 |  | 
 | 	/* 06 */ | 
 | 	pram_ptr->ep0ptr = DPRAM + CPM_USB_EP0_BASE; | 
 | 	pram_ptr->ep1ptr = DPRAM + CPM_USB_EP1_BASE; | 
 |  | 
 | 	/* 07-10 */ | 
 | 	tx[0].cbd_sc = 0xB800; | 
 | 	tx[0].cbd_datlen = 3; | 
 | 	tx[0].cbd_bufaddr = dpram + CPM_USB_DT0_BASE; | 
 |  | 
 | 	tx[1].cbd_sc = 0xBC80; | 
 | 	tx[1].cbd_datlen = 3; | 
 | 	tx[1].cbd_bufaddr = dpram + CPM_USB_DT1_BASE; | 
 |  | 
 | 	rx[0].cbd_sc = 0xA000; | 
 | 	rx[0].cbd_datlen = 0; | 
 | 	rx[0].cbd_bufaddr = dpram + CPM_USB_DR0_BASE; | 
 |  | 
 | 	rx[1].cbd_sc = 0xA000; | 
 | 	rx[1].cbd_datlen = 0; | 
 | 	rx[1].cbd_bufaddr = dpram + CPM_USB_DR1_BASE; | 
 |  | 
 | 	/* 11-12 */ | 
 | 	*(volatile int *) (dpram + CPM_USB_DT0_BASE) = 0x69856000; | 
 | 	*(volatile int *) (dpram + CPM_USB_DT1_BASE) = 0xABCD1234; | 
 |  | 
 | 	*(volatile int *) (dpram + CPM_USB_DR0_BASE) = 0; | 
 | 	*(volatile int *) (dpram + CPM_USB_DR1_BASE) = 0; | 
 |  | 
 | 	/* 13-16 */ | 
 | 	ep0->rbase = DPRAM + CPM_USB_RX0_BASE; | 
 | 	ep0->tbase = DPRAM + CPM_USB_TX0_BASE; | 
 | 	ep0->rfcr = 0x18; | 
 | 	ep0->tfcr = 0x18; | 
 | 	ep0->mrblr = 0x100; | 
 | 	ep0->rbptr = DPRAM + CPM_USB_RX0_BASE; | 
 | 	ep0->tbptr = DPRAM + CPM_USB_TX0_BASE; | 
 | 	ep0->tstate = 0; | 
 |  | 
 | 	/* 17-20 */ | 
 | 	ep1->rbase = DPRAM + CPM_USB_RX1_BASE; | 
 | 	ep1->tbase = DPRAM + CPM_USB_TX1_BASE; | 
 | 	ep1->rfcr = 0x18; | 
 | 	ep1->tfcr = 0x18; | 
 | 	ep1->mrblr = 0x100; | 
 | 	ep1->rbptr = DPRAM + CPM_USB_RX1_BASE; | 
 | 	ep1->tbptr = DPRAM + CPM_USB_TX1_BASE; | 
 | 	ep1->tstate = 0; | 
 |  | 
 | 	/* 21-24 */ | 
 | 	usbr->usep[0] = 0x0000; | 
 | 	usbr->usep[1] = 0x1100; | 
 | 	usbr->usep[2] = 0x2200; | 
 | 	usbr->usep[3] = 0x3300; | 
 |  | 
 | 	/* 25 */ | 
 | 	usbr->usmod = 0x06; | 
 |  | 
 | 	/* 26 */ | 
 | 	usbr->usadr = 0x05; | 
 |  | 
 | 	/* 27 */ | 
 | 	usbr->uscom = 0; | 
 |  | 
 | 	/* 28 */ | 
 | 	usbr->usmod |= 0x01; | 
 | 	udelay (1); | 
 |  | 
 | 	/* 29-30 */ | 
 | 	usbr->uscom = 0x80; | 
 | 	usbr->uscom = 0x81; | 
 |  | 
 | 	/* Wait for the data packet to be transmitted */ | 
 | 	for (j = 0; j < TOUT_LOOP; j++) { | 
 | 		if (tx[1].cbd_sc & (ushort) 0x8000) | 
 | 			udelay (1); | 
 | 		else | 
 | 			break; | 
 | 	} | 
 |  | 
 | 	USB_EXPECT (j < TOUT_LOOP); | 
 |  | 
 | 	USB_EXPECT (tx[0].cbd_sc == 0x3800); | 
 | 	USB_EXPECT (tx[0].cbd_datlen == 3); | 
 |  | 
 | 	USB_EXPECT (tx[1].cbd_sc == 0x3C80); | 
 | 	USB_EXPECT (tx[1].cbd_datlen == 3); | 
 |  | 
 | 	USB_EXPECT (rx[0].cbd_sc == 0x2C00); | 
 | 	USB_EXPECT (rx[0].cbd_datlen == 5); | 
 |  | 
 | 	USB_EXPECT (*(volatile int *) (dpram + CPM_USB_DR0_BASE) == | 
 | 				0xABCD122B); | 
 | 	USB_EXPECT (*(volatile char *) (dpram + CPM_USB_DR0_BASE + 4) == 0x42); | 
 |  | 
 | 	res = 0; | 
 |   Done: | 
 |  | 
 | 	return res; | 
 | } | 
 |  | 
 | #endif /* CONFIG_POST & CFG_POST_USB */ | 
 |  | 
 | #endif /* CONFIG_POST */ |