|  | /* | 
|  | * (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. | 
|  | */ | 
|  |  | 
|  | #include <post.h> | 
|  |  | 
|  | #if CONFIG_POST & CONFIG_SYS_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 *) CONFIG_SYS_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 & CONFIG_SYS_POST_USB */ |