Skip to content
Snippets Groups Projects
usb.c 6.06 KiB
Newer Older
  • Learn to ignore specific revisions
  • Wolfgang Denk's avatar
    Wolfgang Denk committed
    /*
     * (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 */