diff options
| author | Wolfgang Denk <wd@pollux.denx.de> | 2007-03-06 18:08:43 +0100 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2007-03-06 18:08:43 +0100 | 
| commit | ad5bb451ade552c44bef9119d907929ebc2c126f (patch) | |
| tree | df979d3c6385a161cd6df6b6f903ed7eaad31948 /post/cpu/mpc8xx | |
| parent | a5284efd125967675b2e9c6ef7b95832268ad360 (diff) | |
| download | olio-uboot-2014.01-ad5bb451ade552c44bef9119d907929ebc2c126f.tar.xz olio-uboot-2014.01-ad5bb451ade552c44bef9119d907929ebc2c126f.zip | |
Restructure POST directory to support of other CPUs, boards, etc.
Diffstat (limited to 'post/cpu/mpc8xx')
| -rw-r--r-- | post/cpu/mpc8xx/Makefile | 29 | ||||
| -rw-r--r-- | post/cpu/mpc8xx/cache_8xx.S | 495 | ||||
| -rw-r--r-- | post/cpu/mpc8xx/ether.c | 631 | ||||
| -rw-r--r-- | post/cpu/mpc8xx/spr.c | 152 | ||||
| -rw-r--r-- | post/cpu/mpc8xx/uart.c | 560 | ||||
| -rw-r--r-- | post/cpu/mpc8xx/usb.c | 269 | ||||
| -rw-r--r-- | post/cpu/mpc8xx/watchdog.c | 78 | 
7 files changed, 2214 insertions, 0 deletions
| diff --git a/post/cpu/mpc8xx/Makefile b/post/cpu/mpc8xx/Makefile new file mode 100644 index 000000000..9dd3f0fce --- /dev/null +++ b/post/cpu/mpc8xx/Makefile @@ -0,0 +1,29 @@ +# +# (C) Copyright 2002-2007 +# 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 +# + +LIB	= libpostmpc8xx.a + +AOBJS	= cache_8xx.o +COBJS	= ether.o spr.o uart.o usb.o watchdog.o + +include $(TOPDIR)/post/rules.mk diff --git a/post/cpu/mpc8xx/cache_8xx.S b/post/cpu/mpc8xx/cache_8xx.S new file mode 100644 index 000000000..2d41b5566 --- /dev/null +++ b/post/cpu/mpc8xx/cache_8xx.S @@ -0,0 +1,495 @@ +/* + *  Copyright (C) 2002 Wolfgang Denk <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 <config.h> + +#ifdef CONFIG_POST +#if defined(CONFIG_MPC823) || \ +    defined(CONFIG_MPC850) || \ +    defined(CONFIG_MPC855) || \ +    defined(CONFIG_MPC860) || \ +    defined(CONFIG_MPC862) + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> + +#if CONFIG_POST & CFG_POST_CACHE + +	.text + +cache_post_dinvalidate: +	lis	r10, IDC_INVALL@h +	mtspr	DC_CST, r10 +	blr + +cache_post_iinvalidate: +	lis	r10, IDC_INVALL@h +	mtspr	IC_CST, r10 +	isync +	blr + +cache_post_ddisable: +	lis	r10, IDC_DISABLE@h +	mtspr	DC_CST, r10 +	blr + +cache_post_dwb: +	lis	r10, IDC_ENABLE@h +	mtspr	DC_CST, r10 +	lis	r10, DC_CFWT@h +	mtspr	DC_CST, r10 +	blr + +cache_post_dwt: +	lis	r10, IDC_ENABLE@h +	mtspr	DC_CST, r10 +	lis	r10, DC_SFWT@h +	mtspr	DC_CST, r10 +	blr + +cache_post_idisable: +	lis	r10, IDC_DISABLE@h +	mtspr	IC_CST, r10 +	isync +	blr + +cache_post_ienable: +	lis	r10, IDC_ENABLE@h +	mtspr	IC_CST, r10 +	isync +	blr + +cache_post_iunlock: +	lis	r10, IDC_UNALL@h +	mtspr	IC_CST, r10 +	isync +	blr + +cache_post_ilock: +	mtspr	IC_ADR, r3 +	lis	r10, IDC_LDLCK@h +	mtspr	IC_CST, r10 +	isync +	blr + +/* + * turn on the data cache + * switch the data cache to write-back or write-through mode + * invalidate the data cache + * write the negative pattern to a cached area + * read the area + * + * The negative pattern must be read at the last step + */ +	.global cache_post_test1 +cache_post_test1: +	mflr	r0 +	stw	r0, 4(r1) + +	stwu	r3, -4(r1) +	stwu	r4, -4(r1) + +	bl	cache_post_dwb +	bl	cache_post_dinvalidate + +	/* Write the negative pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0xff +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	/* Read the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	lwz	r4, 4(r1) +	subi	r4, r4, 1 +	li	r3, 0 +1: +	lbzu	r0, 1(r4) +	cmpli	cr0, r0, 0xff +	beq	2f +	li	r3, -1 +	b	3f +2: +	bdnz	1b +3: + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	addi	r1, r1, 8 + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +/* + * turn on the data cache + * switch the data cache to write-back or write-through mode + * invalidate the data cache + * write the zero pattern to a cached area + * turn off the data cache + * write the negative pattern to the area + * turn on the data cache + * read the area + * + * The negative pattern must be read at the last step + */ +	.global cache_post_test2 +cache_post_test2: +	mflr	r0 +	stw	r0, 4(r1) + +	stwu	r3, -4(r1) +	stwu	r4, -4(r1) + +	bl	cache_post_dwb +	bl	cache_post_dinvalidate + +	/* Write the zero pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0 +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_ddisable + +	/* Write the negative pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0xff +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_dwb + +	/* Read the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	lwz	r4, 4(r1) +	subi	r4, r4, 1 +	li	r3, 0 +1: +	lbzu	r0, 1(r4) +	cmpli	cr0, r0, 0xff +	beq	2f +	li	r3, -1 +	b	3f +2: +	bdnz	1b +3: + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	addi	r1, r1, 8 + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +/* + * turn on the data cache + * switch the data cache to write-through mode + * invalidate the data cache + * write the zero pattern to a cached area + * flush the data cache + * write the negative pattern to the area + * turn off the data cache + * read the area + * + * The negative pattern must be read at the last step + */ +	.global cache_post_test3 +cache_post_test3: +	mflr	r0 +	stw	r0, 4(r1) + +	stwu	r3, -4(r1) +	stwu	r4, -4(r1) + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	/* Write the zero pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0 +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_dwt +	bl	cache_post_dinvalidate + +	/* Write the negative pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0xff +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	/* Read the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	lwz	r4, 4(r1) +	subi	r4, r4, 1 +	li	r3, 0 +1: +	lbzu	r0, 1(r4) +	cmpli	cr0, r0, 0xff +	beq	2f +	li	r3, -1 +	b	3f +2: +	bdnz	1b +3: + +	addi	r1, r1, 8 + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +/* + * turn on the data cache + * switch the data cache to write-back mode + * invalidate the data cache + * write the negative pattern to a cached area + * flush the data cache + * write the zero pattern to the area + * invalidate the data cache + * read the area + * + * The negative pattern must be read at the last step + */ +	.global cache_post_test4 +cache_post_test4: +	mflr	r0 +	stw	r0, 4(r1) + +	stwu	r3, -4(r1) +	stwu	r4, -4(r1) + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	/* Write the negative pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0xff +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_dwb +	bl	cache_post_dinvalidate + +	/* Write the zero pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0 +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	/* Read the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	lwz	r4, 4(r1) +	subi	r4, r4, 1 +	li	r3, 0 +1: +	lbzu	r0, 1(r4) +	cmpli	cr0, r0, 0xff +	beq	2f +	li	r3, -1 +	b	3f +2: +	bdnz	1b +3: + +	addi	r1, r1, 8 + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +cache_post_test5_1: +	li	r3, 0 +cache_post_test5_2: +	li	r3, -1 + +/* + * turn on the instruction cache + * unlock the entire instruction cache + * invalidate the instruction cache + * lock a branch instruction in the instruction cache + * replace the branch instruction with "nop" + * jump to the branch instruction + * check that the branch instruction was executed +*/ +	.global cache_post_test5 +cache_post_test5: +	mflr	r0 +	stw	r0, 4(r1) + +	bl	cache_post_ienable +	bl	cache_post_iunlock +	bl	cache_post_iinvalidate + +	/* Compute r9 = cache_post_test5_reloc */ +	bl	cache_post_test5_reloc +cache_post_test5_reloc: +	mflr	r9 + +	/* Copy the test instruction to cache_post_test5_data */ +	lis	r3, (cache_post_test5_1 - cache_post_test5_reloc)@h +	ori	r3, r3, (cache_post_test5_1 - cache_post_test5_reloc)@l +	add	r3, r3, r9 +	lis	r4, (cache_post_test5_data - cache_post_test5_reloc)@h +	ori	r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l +	add	r4, r4, r9 +	lwz	r0, 0(r3) +	stw	r0, 0(r4) + +	bl	cache_post_iinvalidate + +	/* Lock the branch instruction */ +	lis	r3, (cache_post_test5_data - cache_post_test5_reloc)@h +	ori	r3, r3, (cache_post_test5_data - cache_post_test5_reloc)@l +	add	r3, r3, r9 +	bl	cache_post_ilock + +	/* Replace the test instruction */ +	lis	r3, (cache_post_test5_2 - cache_post_test5_reloc)@h +	ori	r3, r3, (cache_post_test5_2 - cache_post_test5_reloc)@l +	add	r3, r3, r9 +	lis	r4, (cache_post_test5_data - cache_post_test5_reloc)@h +	ori	r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l +	add	r4, r4, r9 +	lwz	r0, 0(r3) +	stw	r0, 0(r4) + +	bl	cache_post_iinvalidate + +	/* Execute to the test instruction */ +cache_post_test5_data: +	nop + +	bl	cache_post_iunlock + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +cache_post_test6_1: +	li	r3, -1 +cache_post_test6_2: +	li	r3, 0 + +/* + * turn on the instruction cache + * unlock the entire instruction cache + * invalidate the instruction cache + * lock a branch instruction in the instruction cache + * replace the branch instruction with "nop" + * jump to the branch instruction + * check that the branch instruction was executed + */ +	.global cache_post_test6 +cache_post_test6: +	mflr	r0 +	stw	r0, 4(r1) + +	bl	cache_post_ienable +	bl	cache_post_iunlock +	bl	cache_post_iinvalidate + +	/* Compute r9 = cache_post_test6_reloc */ +	bl	cache_post_test6_reloc +cache_post_test6_reloc: +	mflr	r9 + +	/* Copy the test instruction to cache_post_test6_data */ +	lis	r3, (cache_post_test6_1 - cache_post_test6_reloc)@h +	ori	r3, r3, (cache_post_test6_1 - cache_post_test6_reloc)@l +	add	r3, r3, r9 +	lis	r4, (cache_post_test6_data - cache_post_test6_reloc)@h +	ori	r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l +	add	r4, r4, r9 +	lwz	r0, 0(r3) +	stw	r0, 0(r4) + +	bl	cache_post_iinvalidate + +	/* Replace the test instruction */ +	lis	r3, (cache_post_test6_2 - cache_post_test6_reloc)@h +	ori	r3, r3, (cache_post_test6_2 - cache_post_test6_reloc)@l +	add	r3, r3, r9 +	lis	r4, (cache_post_test6_data - cache_post_test6_reloc)@h +	ori	r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l +	add	r4, r4, r9 +	lwz	r0, 0(r3) +	stw	r0, 0(r4) + +	bl	cache_post_iinvalidate + +	/* Execute to the test instruction */ +cache_post_test6_data: +	nop + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +#endif /* CONFIG_MPC823 || MPC850 || MPC855 || MPC860 */ +#endif /* CONFIG_POST & CFG_POST_CACHE */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/mpc8xx/ether.c b/post/cpu/mpc8xx/ether.c new file mode 100644 index 000000000..8c87b5927 --- /dev/null +++ b/post/cpu/mpc8xx/ether.c @@ -0,0 +1,631 @@ +/* + * (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> + +/* + * Ethernet test + * + * The Serial Communication Controllers (SCC) listed in ctlr_list array below + * are tested in the loopback ethernet mode. + * The controllers are configured accordingly and several packets + * are transmitted. The configurable test parameters are: + *   MIN_PACKET_LENGTH - minimum size of packet to transmit + *   MAX_PACKET_LENGTH - maximum size of packet to transmit + *   TEST_NUM - number of tests + */ + +#ifdef CONFIG_POST + +#include <post.h> +#if CONFIG_POST & CFG_POST_ETHER +#if defined(CONFIG_8xx) +#include <commproc.h> +#elif defined(CONFIG_MPC8260) +#include <asm/cpm_8260.h> +#else +#error "Apparently a bad configuration, please fix." +#endif + +#include <command.h> +#include <net.h> +#include <serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define MIN_PACKET_LENGTH	64 +#define MAX_PACKET_LENGTH	256 +#define TEST_NUM		1 + +#define CTLR_SCC 0 + +extern void spi_init_f (void); +extern void spi_init_r (void); + +/* The list of controllers to test */ +#if defined(CONFIG_MPC823) +static int ctlr_list[][2] = { {CTLR_SCC, 1} }; +#else +static int ctlr_list[][2] = { }; +#endif + +#define CTRL_LIST_SIZE (sizeof(ctlr_list) / sizeof(ctlr_list[0])) + +static struct { +	void (*init) (int index); +	void (*halt) (int index); +	int (*send) (int index, volatile void *packet, int length); +	int (*recv) (int index, void *packet, int length); +} ctlr_proc[1]; + +static char *ctlr_name[1] = { "SCC" }; + +/* Ethernet Transmit and Receive Buffers */ +#define DBUF_LENGTH  1520 + +#define TX_BUF_CNT 2 + +#define TOUT_LOOP 100 + +static char txbuf[DBUF_LENGTH]; + +static uint rxIdx;		/* index of the current RX buffer */ +static uint txIdx;		/* index of the current TX buffer */ + +/* +  * SCC Ethernet Tx and Rx buffer descriptors allocated at the +  *  immr->udata_bd address on Dual-Port RAM +  * Provide for Double Buffering +  */ + +typedef volatile struct CommonBufferDescriptor { +	cbd_t rxbd[PKTBUFSRX];		/* Rx BD */ +	cbd_t txbd[TX_BUF_CNT];		/* Tx BD */ +} RTXBD; + +static RTXBD *rtx; + +  /* +   * SCC callbacks +   */ + +static void scc_init (int scc_index) +{ +	bd_t *bd = gd->bd; + +	static int proff[] = +			{ PROFF_SCC1, PROFF_SCC2, PROFF_SCC3, PROFF_SCC4 }; +	static unsigned int cpm_cr[] = +			{ CPM_CR_CH_SCC1, CPM_CR_CH_SCC2, CPM_CR_CH_SCC3, +CPM_CR_CH_SCC4 }; + +	int i; +	scc_enet_t *pram_ptr; + +	volatile immap_t *immr = (immap_t *) CFG_IMMR; + +	immr->im_cpm.cp_scc[scc_index].scc_gsmrl &= +			~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + +#if defined(CONFIG_FADS) +#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC86xADS) +	/* The FADS860T and MPC86xADS don't use the MODEM_EN or DATA_VOICE signals. */ +	*((uint *) BCSR4) &= ~BCSR4_ETHLOOP; +	*((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL; +	*((uint *) BCSR1) &= ~BCSR1_ETHEN; +#else +	*((uint *) BCSR4) &= ~(BCSR4_ETHLOOP | BCSR4_MODEM_EN); +	*((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL | BCSR4_DATA_VOICE; +	*((uint *) BCSR1) &= ~BCSR1_ETHEN; +#endif +#endif + +	pram_ptr = (scc_enet_t *) & (immr->im_cpm.cp_dparam[proff[scc_index]]); + +	rxIdx = 0; +	txIdx = 0; + +#ifdef CFG_ALLOC_DPRAM +	rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + +					 dpram_alloc_align (sizeof (RTXBD), 8)); +#else +	rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_SCC_BASE); +#endif + +#if 0 + +#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD)) +	/* Configure port A pins for Txd and Rxd. +	 */ +	immr->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD); +	immr->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD); +	immr->im_ioport.iop_paodr &= ~PA_ENET_TXD; +#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD)) +	/* Configure port B pins for Txd and Rxd. +	 */ +	immr->im_cpm.cp_pbpar |= (PB_ENET_RXD | PB_ENET_TXD); +	immr->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD); +	immr->im_cpm.cp_pbodr &= ~PB_ENET_TXD; +#else +#error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined +#endif + +#if defined(PC_ENET_LBK) +	/* Configure port C pins to disable External Loopback +	 */ +	immr->im_ioport.iop_pcpar &= ~PC_ENET_LBK; +	immr->im_ioport.iop_pcdir |= PC_ENET_LBK; +	immr->im_ioport.iop_pcso &= ~PC_ENET_LBK; +	immr->im_ioport.iop_pcdat &= ~PC_ENET_LBK;	/* Disable Loopback */ +#endif /* PC_ENET_LBK */ + +	/* Configure port C pins to enable CLSN and RENA. +	 */ +	immr->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA); +	immr->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA); +	immr->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA); + +	/* Configure port A for TCLK and RCLK. +	 */ +	immr->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK); +	immr->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK); + +	/* +	 * Configure Serial Interface clock routing -- see section 16.7.5.3 +	 * First, clear all SCC bits to zero, then set the ones we want. +	 */ + +	immr->im_cpm.cp_sicr &= ~SICR_ENET_MASK; +	immr->im_cpm.cp_sicr |= SICR_ENET_CLKRT; +#else +	/* +	 * SCC2 receive clock is BRG2 +	 * SCC2 transmit clock is BRG3 +	 */ +	immr->im_cpm.cp_brgc2 = 0x0001000C; +	immr->im_cpm.cp_brgc3 = 0x0001000C; + +	immr->im_cpm.cp_sicr &= ~0x00003F00; +	immr->im_cpm.cp_sicr |=  0x00000a00; +#endif /* 0 */ + + +	/* +	 * Initialize SDCR -- see section 16.9.23.7 +	 * SDMA configuration register +	 */ +	immr->im_siu_conf.sc_sdcr = 0x01; + + +	/* +	 * Setup SCC Ethernet Parameter RAM +	 */ + +	pram_ptr->sen_genscc.scc_rfcr = 0x18;	/* Normal Operation and Mot byte ordering */ +	pram_ptr->sen_genscc.scc_tfcr = 0x18;	/* Mot byte ordering, Normal access */ + +	pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH;	/* max. ET package len 1520 */ + +	pram_ptr->sen_genscc.scc_rbase = (unsigned int) (&rtx->rxbd[0]);	/* Set RXBD tbl start at Dual Port */ +	pram_ptr->sen_genscc.scc_tbase = (unsigned int) (&rtx->txbd[0]);	/* Set TXBD tbl start at Dual Port */ + +	/* +	 * Setup Receiver Buffer Descriptors (13.14.24.18) +	 * Settings: +	 *     Empty, Wrap +	 */ + +	for (i = 0; i < PKTBUFSRX; i++) { +		rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; +		rtx->rxbd[i].cbd_datlen = 0;	/* Reset */ +		rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; +	} + +	rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; + +	/* +	 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) +	 * Settings: +	 *    Add PADs to Short FRAMES, Wrap, Last, Tx CRC +	 */ + +	for (i = 0; i < TX_BUF_CNT; i++) { +		rtx->txbd[i].cbd_sc = +				(BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC); +		rtx->txbd[i].cbd_datlen = 0;	/* Reset */ +		rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]); +	} + +	rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; + +	/* +	 * Enter Command:  Initialize Rx Params for SCC +	 */ + +	do {				/* Spin until ready to issue command    */ +		__asm__ ("eieio"); +	} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); +	/* Issue command */ +	immr->im_cpm.cp_cpcr = +			((CPM_CR_INIT_RX << 8) | (cpm_cr[scc_index] << 4) | +			 CPM_CR_FLG); +	do {				/* Spin until command processed     */ +		__asm__ ("eieio"); +	} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); + +	/* +	 * Ethernet Specific Parameter RAM +	 *     see table 13-16, pg. 660, +	 *     pg. 681 (example with suggested settings) +	 */ + +	pram_ptr->sen_cpres = ~(0x0);	/* Preset CRC */ +	pram_ptr->sen_cmask = 0xdebb20e3;	/* Constant Mask for CRC */ +	pram_ptr->sen_crcec = 0x0;	/* Error Counter CRC (unused) */ +	pram_ptr->sen_alec = 0x0;	/* Alignment Error Counter (unused) */ +	pram_ptr->sen_disfc = 0x0;	/* Discard Frame Counter (unused) */ +	pram_ptr->sen_pads = 0x8888;	/* Short Frame PAD Characters */ + +	pram_ptr->sen_retlim = 15;	/* Retry Limit Threshold */ +	pram_ptr->sen_maxflr = 1518;	/* MAX Frame Length Register */ +	pram_ptr->sen_minflr = 64;	/* MIN Frame Length Register */ + +	pram_ptr->sen_maxd1 = DBUF_LENGTH;	/* MAX DMA1 Length Register */ +	pram_ptr->sen_maxd2 = DBUF_LENGTH;	/* MAX DMA2 Length Register */ + +	pram_ptr->sen_gaddr1 = 0x0;	/* Group Address Filter 1 (unused) */ +	pram_ptr->sen_gaddr2 = 0x0;	/* Group Address Filter 2 (unused) */ +	pram_ptr->sen_gaddr3 = 0x0;	/* Group Address Filter 3 (unused) */ +	pram_ptr->sen_gaddr4 = 0x0;	/* Group Address Filter 4 (unused) */ + +#define ea bd->bi_enetaddr +	pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4]; +	pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2]; +	pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0]; +#undef ea + +	pram_ptr->sen_pper = 0x0;	/* Persistence (unused) */ +	pram_ptr->sen_iaddr1 = 0x0;	/* Individual Address Filter 1 (unused) */ +	pram_ptr->sen_iaddr2 = 0x0;	/* Individual Address Filter 2 (unused) */ +	pram_ptr->sen_iaddr3 = 0x0;	/* Individual Address Filter 3 (unused) */ +	pram_ptr->sen_iaddr4 = 0x0;	/* Individual Address Filter 4 (unused) */ +	pram_ptr->sen_taddrh = 0x0;	/* Tmp Address (MSB) (unused) */ +	pram_ptr->sen_taddrm = 0x0;	/* Tmp Address (unused) */ +	pram_ptr->sen_taddrl = 0x0;	/* Tmp Address (LSB) (unused) */ + +	/* +	 * Enter Command:  Initialize Tx Params for SCC +	 */ + +	do {				/* Spin until ready to issue command    */ +		__asm__ ("eieio"); +	} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); +	/* Issue command */ +	immr->im_cpm.cp_cpcr = +			((CPM_CR_INIT_TX << 8) | (cpm_cr[scc_index] << 4) | +			 CPM_CR_FLG); +	do {				/* Spin until command processed     */ +		__asm__ ("eieio"); +	} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); + +	/* +	 * Mask all Events in SCCM - we use polling mode +	 */ +	immr->im_cpm.cp_scc[scc_index].scc_sccm = 0; + +	/* +	 * Clear Events in SCCE -- Clear bits by writing 1's +	 */ + +	immr->im_cpm.cp_scc[scc_index].scc_scce = ~(0x0); + + +	/* +	 * Initialize GSMR High 32-Bits +	 * Settings:  Normal Mode +	 */ + +	immr->im_cpm.cp_scc[scc_index].scc_gsmrh = 0; + +	/* +	 * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive +	 * Settings: +	 *     TCI = Invert +	 *     TPL =  48 bits +	 *     TPP = Repeating 10's +	 *     LOOP = Loopback +	 *     MODE = Ethernet +	 */ + +	immr->im_cpm.cp_scc[scc_index].scc_gsmrl = (SCC_GSMRL_TCI | +						    SCC_GSMRL_TPL_48 | +						    SCC_GSMRL_TPP_10 | +						    SCC_GSMRL_DIAG_LOOP | +						    SCC_GSMRL_MODE_ENET); + +	/* +	 * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4 +	 */ + +	immr->im_cpm.cp_scc[scc_index].scc_dsr = 0xd555; + +	/* +	 * Initialize the PSMR +	 * Settings: +	 *  CRC = 32-Bit CCITT +	 *  NIB = Begin searching for SFD 22 bits after RENA +	 *  LPB = Loopback Enable (Needed when FDE is set) +	 */ +	immr->im_cpm.cp_scc[scc_index].scc_psmr = SCC_PSMR_ENCRC | +			SCC_PSMR_NIB22 | SCC_PSMR_LPB; + +#if 0 +	/* +	 * Configure Ethernet TENA Signal +	 */ + +#if (defined(PC_ENET_TENA) && !defined(PB_ENET_TENA)) +	immr->im_ioport.iop_pcpar |= PC_ENET_TENA; +	immr->im_ioport.iop_pcdir &= ~PC_ENET_TENA; +#elif (defined(PB_ENET_TENA) && !defined(PC_ENET_TENA)) +	immr->im_cpm.cp_pbpar |= PB_ENET_TENA; +	immr->im_cpm.cp_pbdir |= PB_ENET_TENA; +#else +#error Configuration Error: exactly ONE of PB_ENET_TENA, PC_ENET_TENA must be defined +#endif + +#if defined(CONFIG_ADS) && defined(CONFIG_MPC860) +	/* +	 * Port C is used to control the PHY,MC68160. +	 */ +	immr->im_ioport.iop_pcdir |= +			(PC_ENET_ETHLOOP | PC_ENET_TPFLDL | PC_ENET_TPSQEL); + +	immr->im_ioport.iop_pcdat |= PC_ENET_TPFLDL; +	immr->im_ioport.iop_pcdat &= ~(PC_ENET_ETHLOOP | PC_ENET_TPSQEL); +	*((uint *) BCSR1) &= ~BCSR1_ETHEN; +#endif /* MPC860ADS */ + +#if defined(CONFIG_AMX860) +	/* +	 * Port B is used to control the PHY,MC68160. +	 */ +	immr->im_cpm.cp_pbdir |= +			(PB_ENET_ETHLOOP | PB_ENET_TPFLDL | PB_ENET_TPSQEL); + +	immr->im_cpm.cp_pbdat |= PB_ENET_TPFLDL; +	immr->im_cpm.cp_pbdat &= ~(PB_ENET_ETHLOOP | PB_ENET_TPSQEL); + +	immr->im_ioport.iop_pddir |= PD_ENET_ETH_EN; +	immr->im_ioport.iop_pddat &= ~PD_ENET_ETH_EN; +#endif /* AMX860 */ + +#endif /* 0 */ + +#ifdef CONFIG_RPXCLASSIC +	*((uchar *) BCSR0) &= ~BCSR0_ETHLPBK; +	*((uchar *) BCSR0) |= (BCSR0_ETHEN | BCSR0_COLTEST | BCSR0_FULLDPLX); +#endif + +#ifdef CONFIG_RPXLITE +	*((uchar *) BCSR0) |= BCSR0_ETHEN; +#endif + +#ifdef CONFIG_MBX +	board_ether_init (); +#endif + +	/* +	 * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive +	 */ + +	immr->im_cpm.cp_scc[scc_index].scc_gsmrl |= +			(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + +	/* +	 * Work around transmit problem with first eth packet +	 */ +#if defined (CONFIG_FADS) +	udelay (10000);				/* wait 10 ms */ +#elif defined (CONFIG_AMX860) || defined(CONFIG_RPXCLASSIC) +	udelay (100000);			/* wait 100 ms */ +#endif +} + +static void scc_halt (int scc_index) +{ +	volatile immap_t *immr = (immap_t *) CFG_IMMR; + +	immr->im_cpm.cp_scc[scc_index].scc_gsmrl &= +			~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); +	immr->im_ioport.iop_pcso  &=  ~(PC_ENET_CLSN | PC_ENET_RENA); +} + +static int scc_send (int index, volatile void *packet, int length) +{ +	int i, j = 0; + +	while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) { +		udelay (1);		/* will also trigger Wd if needed */ +		j++; +	} +	if (j >= TOUT_LOOP) +		printf ("TX not ready\n"); +	rtx->txbd[txIdx].cbd_bufaddr = (uint) packet; +	rtx->txbd[txIdx].cbd_datlen = length; +	rtx->txbd[txIdx].cbd_sc |= +			(BD_ENET_TX_READY | BD_ENET_TX_LAST | BD_ENET_TX_WRAP); +	while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) { +		udelay (1);		/* will also trigger Wd if needed */ +		j++; +	} +	if (j >= TOUT_LOOP) +		printf ("TX timeout\n"); +	i = (rtx->txbd[txIdx]. +		 cbd_sc & BD_ENET_TX_STATS) /* return only status bits */ ; +	return i; +} + +static int scc_recv (int index, void *packet, int max_length) +{ +	int length = -1; + +	if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { +		goto Done;		/* nothing received */ +	} + +	if (!(rtx->rxbd[rxIdx].cbd_sc & 0x003f)) { +		length = rtx->rxbd[rxIdx].cbd_datlen - 4; +		memcpy (packet, +				(void *) (NetRxPackets[rxIdx]), +				length < max_length ? length : max_length); +	} + +	/* Give the buffer back to the SCC. */ +	rtx->rxbd[rxIdx].cbd_datlen = 0; + +	/* wrap around buffer index when necessary */ +	if ((rxIdx + 1) >= PKTBUFSRX) { +		rtx->rxbd[PKTBUFSRX - 1].cbd_sc = +				(BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); +		rxIdx = 0; +	} else { +		rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; +		rxIdx++; +	} + +Done: +	return length; +} + +  /* +   * Test routines +   */ + +static void packet_fill (char *packet, int length) +{ +	char c = (char) length; +	int i; + +	packet[0] = 0xFF; +	packet[1] = 0xFF; +	packet[2] = 0xFF; +	packet[3] = 0xFF; +	packet[4] = 0xFF; +	packet[5] = 0xFF; + +	for (i = 6; i < length; i++) { +		packet[i] = c++; +	} +} + +static int packet_check (char *packet, int length) +{ +	char c = (char) length; +	int i; + +	for (i = 6; i < length; i++) { +		if (packet[i] != c++) +			return -1; +	} + +	return 0; +} + +static int test_ctlr (int ctlr, int index) +{ +	int res = -1; +	char packet_send[MAX_PACKET_LENGTH]; +	char packet_recv[MAX_PACKET_LENGTH]; +	int length; +	int i; +	int l; + +	ctlr_proc[ctlr].init (index); + +	for (i = 0; i < TEST_NUM; i++) { +		for (l = MIN_PACKET_LENGTH; l <= MAX_PACKET_LENGTH; l++) { +			packet_fill (packet_send, l); + +			ctlr_proc[ctlr].send (index, packet_send, l); + +			length = ctlr_proc[ctlr].recv (index, packet_recv, +							MAX_PACKET_LENGTH); + +			if (length != l || packet_check (packet_recv, length) < 0) { +				goto Done; +			} +		} +	} + +	res = 0; + +Done: + +	ctlr_proc[ctlr].halt (index); + +	/* +	 * SCC2 Ethernet parameter RAM space overlaps +	 * the SPI parameter RAM space. So we need to restore +	 * the SPI configuration after SCC2 ethernet test. +	 */ +#if defined(CONFIG_SPI) +	if (ctlr == CTLR_SCC && index == 1) { +		spi_init_f (); +		spi_init_r (); +	} +#endif + +	if (res != 0) { +		post_log ("ethernet %s%d test failed\n", ctlr_name[ctlr], +				  index + 1); +	} + +	return res; +} + +int ether_post_test (int flags) +{ +	int res = 0; +	int i; + +	ctlr_proc[CTLR_SCC].init = scc_init; +	ctlr_proc[CTLR_SCC].halt = scc_halt; +	ctlr_proc[CTLR_SCC].send = scc_send; +	ctlr_proc[CTLR_SCC].recv = scc_recv; + +	for (i = 0; i < CTRL_LIST_SIZE; i++) { +		if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) { +			res = -1; +		} +	} + +#if !defined(CONFIG_8xx_CONS_NONE) +	serial_reinit_all (); +#endif +	return res; +} + +#endif /* CONFIG_POST & CFG_POST_ETHER */ + +#endif /* CONFIG_POST */ diff --git a/post/cpu/mpc8xx/spr.c b/post/cpu/mpc8xx/spr.c new file mode 100644 index 000000000..330b977f1 --- /dev/null +++ b/post/cpu/mpc8xx/spr.c @@ -0,0 +1,152 @@ +/* + * (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> + +/* + * SPR test + * + * The test checks the contents of Special Purpose Registers (SPR) listed + * in the spr_test_list array below. + * Each SPR value is read using mfspr instruction, some bits are masked + * according to the table and the resulting value is compared to the + * corresponding table value. + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_SPR + +static struct +{ +    int number; +    char * name; +    unsigned long mask; +    unsigned long value; +} spr_test_list [] = { +	/* Standard Special-Purpose Registers */ + +	{1,	"XER",		0x00000000,	0x00000000}, +	{8,	"LR",		0x00000000,	0x00000000}, +	{9,	"CTR",		0x00000000,	0x00000000}, +	{18,	"DSISR",	0x00000000,	0x00000000}, +	{19,	"DAR",		0x00000000,	0x00000000}, +	{22,	"DEC",		0x00000000,	0x00000000}, +	{26,	"SRR0",		0x00000000,	0x00000000}, +	{27,	"SRR1",		0x00000000,	0x00000000}, +	{272,	"SPRG0",	0x00000000,	0x00000000}, +	{273,	"SPRG1",	0x00000000,	0x00000000}, +	{274,	"SPRG2",	0x00000000,	0x00000000}, +	{275,	"SPRG3",	0x00000000,	0x00000000}, +	{287,	"PVR",		0xFFFF0000,	0x00500000}, + +	/* Additional Special-Purpose Registers */ + +	{144,	"CMPA",		0x00000000,	0x00000000}, +	{145,	"CMPB",		0x00000000,	0x00000000}, +	{146,	"CMPC",		0x00000000,	0x00000000}, +	{147,	"CMPD",		0x00000000,	0x00000000}, +	{148,	"ICR",		0xFFFFFFFF,	0x00000000}, +	{149,	"DER",		0x00000000,	0x00000000}, +	{150,	"COUNTA",	0xFFFFFFFF,	0x00000000}, +	{151,	"COUNTB",	0xFFFFFFFF,	0x00000000}, +	{152,	"CMPE",		0x00000000,	0x00000000}, +	{153,	"CMPF",		0x00000000,	0x00000000}, +	{154,	"CMPG",		0x00000000,	0x00000000}, +	{155,	"CMPH",		0x00000000,	0x00000000}, +	{156,	"LCTRL1",	0xFFFFFFFF,	0x00000000}, +	{157,	"LCTRL2",	0xFFFFFFFF,	0x00000000}, +	{158,	"ICTRL",	0xFFFFFFFF,	0x00000007}, +	{159,	"BAR",		0x00000000,	0x00000000}, +	{630,	"DPDR",		0x00000000,	0x00000000}, +	{631,	"DPIR",		0x00000000,	0x00000000}, +	{638,	"IMMR",		0xFFFF0000,	CFG_IMMR  }, +	{560,	"IC_CST",	0x8E380000,	0x00000000}, +	{561,	"IC_ADR",	0x00000000,	0x00000000}, +	{562,	"IC_DAT",	0x00000000,	0x00000000}, +	{568,	"DC_CST",	0xEF380000,	0x00000000}, +	{569,	"DC_ADR",	0x00000000,	0x00000000}, +	{570,	"DC_DAT",	0x00000000,	0x00000000}, +	{784,	"MI_CTR",	0xFFFFFFFF,	0x00000000}, +	{786,	"MI_AP",	0x00000000,	0x00000000}, +	{787,	"MI_EPN",	0x00000000,	0x00000000}, +	{789,	"MI_TWC",	0xFFFFFE02,	0x00000000}, +	{790,	"MI_RPN",	0x00000000,	0x00000000}, +	{816,	"MI_DBCAM",	0x00000000,	0x00000000}, +	{817,	"MI_DBRAM0",	0x00000000,	0x00000000}, +	{818,	"MI_DBRAM1",	0x00000000,	0x00000000}, +	{792,	"MD_CTR",	0xFFFFFFFF,	0x04000000}, +	{793,	"M_CASID",	0xFFFFFFF0,	0x00000000}, +	{794,	"MD_AP",	0x00000000,	0x00000000}, +	{795,	"MD_EPN",	0x00000000,	0x00000000}, +	{796,	"M_TWB",	0x00000003,	0x00000000}, +	{797,	"MD_TWC",	0x00000003,	0x00000000}, +	{798,	"MD_RPN",	0x00000000,	0x00000000}, +	{799,	"M_TW",		0x00000000,	0x00000000}, +	{824,	"MD_DBCAM",	0x00000000,	0x00000000}, +	{825,	"MD_DBRAM0",	0x00000000,	0x00000000}, +	{826,	"MD_DBRAM1",	0x00000000,	0x00000000}, +}; + +static int spr_test_list_size = +		sizeof (spr_test_list) / sizeof (spr_test_list[0]); + +int spr_post_test (int flags) +{ +	int ret = 0; +	int ic = icache_status (); +	int i; + +	unsigned long code[] = { +		0x7c6002a6,				/* mfspr r3,SPR */ +		0x4e800020				/* blr          */ +	}; +	unsigned long (*get_spr) (void) = (void *) code; + +	if (ic) +		icache_disable (); + +	for (i = 0; i < spr_test_list_size; i++) { +		int num = spr_test_list[i].number; + +		/* mfspr r3,num */ +		code[0] = 0x7c6002a6 | ((num & 0x1F) << 16) | ((num & 0x3E0) << 6); + +		if ((get_spr () & spr_test_list[i].mask) != +			(spr_test_list[i].value & spr_test_list[i].mask)) { +			post_log ("The value of %s special register " +				  "is incorrect: 0x%08X\n", +					spr_test_list[i].name, get_spr ()); +			ret = -1; +		} +	} + +	if (ic) +		icache_enable (); + +	return ret; +} +#endif /* CONFIG_POST & CFG_POST_SPR */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/mpc8xx/uart.c b/post/cpu/mpc8xx/uart.c new file mode 100644 index 000000000..fd97e3899 --- /dev/null +++ b/post/cpu/mpc8xx/uart.c @@ -0,0 +1,560 @@ +/* + * (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> + +/* + * UART test + * + * The Serial Management Controllers (SMC) and the Serial Communication + * Controllers (SCC) listed in ctlr_list array below are tested in + * the loopback UART mode. + * The controllers are configured accordingly and several characters + * are transmitted. The configurable test parameters are: + *   MIN_PACKET_LENGTH - minimum size of packet to transmit + *   MAX_PACKET_LENGTH - maximum size of packet to transmit + *   TEST_NUM - number of tests + */ + +#ifdef CONFIG_POST + +#include <post.h> +#if CONFIG_POST & CFG_POST_UART +#if defined(CONFIG_8xx) +#include <commproc.h> +#elif defined(CONFIG_MPC8260) +#include <asm/cpm_8260.h> +#else +#error "Apparently a bad configuration, please fix." +#endif +#include <command.h> +#include <serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define CTLR_SMC 0 +#define CTLR_SCC 1 + +/* The list of controllers to test */ +#if defined(CONFIG_MPC823) +static int ctlr_list[][2] = +		{ {CTLR_SMC, 0}, {CTLR_SMC, 1}, {CTLR_SCC, 1} }; +#else +static int ctlr_list[][2] = { }; +#endif + +#define CTRL_LIST_SIZE (sizeof(ctlr_list) / sizeof(ctlr_list[0])) + +static struct { +	void (*init) (int index); +	void (*halt) (int index); +	void (*putc) (int index, const char c); +	int (*getc) (int index); +} ctlr_proc[2]; + +static char *ctlr_name[2] = { "SMC", "SCC" }; + +static int proff_smc[] = { PROFF_SMC1, PROFF_SMC2 }; +static int proff_scc[] = +		{ PROFF_SCC1, PROFF_SCC2, PROFF_SCC3, PROFF_SCC4 }; + +/* + * SMC callbacks + */ + +static void smc_init (int smc_index) +{ +	static int cpm_cr_ch[] = { CPM_CR_CH_SMC1, CPM_CR_CH_SMC2 }; + +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile smc_t *sp; +	volatile smc_uart_t *up; +	volatile cbd_t *tbdf, *rbdf; +	volatile cpm8xx_t *cp = &(im->im_cpm); +	uint dpaddr; + +	/* initialize pointers to SMC */ + +	sp = (smc_t *) & (cp->cp_smc[smc_index]); +	up = (smc_uart_t *) & cp->cp_dparam[proff_smc[smc_index]]; + +	/* Disable transmitter/receiver. +	 */ +	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); + +	/* Enable SDMA. +	 */ +	im->im_siu_conf.sc_sdcr = 1; + +	/* clear error conditions */ +#ifdef	CFG_SDSR +	im->im_sdma.sdma_sdsr = CFG_SDSR; +#else +	im->im_sdma.sdma_sdsr = 0x83; +#endif + +	/* clear SDMA interrupt mask */ +#ifdef	CFG_SDMR +	im->im_sdma.sdma_sdmr = CFG_SDMR; +#else +	im->im_sdma.sdma_sdmr = 0x00; +#endif + +#if defined(CONFIG_FADS) +	/* Enable RS232 */ +	*((uint *) BCSR1) &= +			~(smc_index == 1 ? BCSR1_RS232EN_1 : BCSR1_RS232EN_2); +#endif + +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) +	/* Enable Monitor Port Transceiver */ +	*((uchar *) BCSR0) |= BCSR0_ENMONXCVR; +#endif + +	/* Set the physical address of the host memory buffers in +	 * the buffer descriptors. +	 */ + +#ifdef CFG_ALLOC_DPRAM +	dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8); +#else +	dpaddr = CPM_POST_BASE; +#endif + +	/* Allocate space for two buffer descriptors in the DP ram. +	 * For now, this address seems OK, but it may have to +	 * change with newer versions of the firmware. +	 * damm: allocating space after the two buffers for rx/tx data +	 */ + +	rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr]; +	rbdf->cbd_bufaddr = (uint) (rbdf + 2); +	rbdf->cbd_sc = 0; +	tbdf = rbdf + 1; +	tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1; +	tbdf->cbd_sc = 0; + +	/* Set up the uart parameters in the parameter ram. +	 */ +	up->smc_rbase = dpaddr; +	up->smc_tbase = dpaddr + sizeof (cbd_t); +	up->smc_rfcr = SMC_EB; +	up->smc_tfcr = SMC_EB; + +#if defined(CONFIG_MBX) +	board_serial_init (); +#endif + +	/* Set UART mode, 8 bit, no parity, one stop. +	 * Enable receive and transmit. +	 * Set local loopback mode. +	 */ +	sp->smc_smcmr = smcr_mk_clen (9) | SMCMR_SM_UART | (ushort) 0x0004; + +	/* Mask all interrupts and remove anything pending. +	 */ +	sp->smc_smcm = 0; +	sp->smc_smce = 0xff; + +	/* Set up the baud rate generator. +	 */ +	cp->cp_simode = 0x00000000; + +	cp->cp_brgc1 = +			(((gd->cpu_clk / 16 / gd->baudrate) - +			  1) << 1) | CPM_BRG_EN; + +	/* Make the first buffer the only buffer. +	 */ +	tbdf->cbd_sc |= BD_SC_WRAP; +	rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; + +	/* Single character receive. +	 */ +	up->smc_mrblr = 1; +	up->smc_maxidl = 0; + +	/* Initialize Tx/Rx parameters. +	 */ + +	while (cp->cp_cpcr & CPM_CR_FLG)	/* wait if cp is busy */ +		; + +	cp->cp_cpcr = +			mk_cr_cmd (cpm_cr_ch[smc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG; + +	while (cp->cp_cpcr & CPM_CR_FLG)	/* wait if cp is busy */ +		; + +	/* Enable transmitter/receiver. +	 */ +	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; +} + +static void smc_halt(int smc_index) +{ +} + +static void smc_putc (int smc_index, const char c) +{ +	volatile cbd_t *tbdf; +	volatile char *buf; +	volatile smc_uart_t *up; +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile cpm8xx_t *cpmp = &(im->im_cpm); + +	up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]]; + +	tbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_tbase]; + +	/* Wait for last character to go. +	 */ + +	buf = (char *) tbdf->cbd_bufaddr; +#if 0 +	__asm__ ("eieio"); +	while (tbdf->cbd_sc & BD_SC_READY) +		__asm__ ("eieio"); +#endif + +	*buf = c; +	tbdf->cbd_datlen = 1; +	tbdf->cbd_sc |= BD_SC_READY; +	__asm__ ("eieio"); +#if 1 +	while (tbdf->cbd_sc & BD_SC_READY) +		__asm__ ("eieio"); +#endif +} + +static int smc_getc (int smc_index) +{ +	volatile cbd_t *rbdf; +	volatile unsigned char *buf; +	volatile smc_uart_t *up; +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile cpm8xx_t *cpmp = &(im->im_cpm); +	unsigned char c; +	int i; + +	up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]]; + +	rbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_rbase]; + +	/* Wait for character to show up. +	 */ +	buf = (unsigned char *) rbdf->cbd_bufaddr; +#if 0 +	while (rbdf->cbd_sc & BD_SC_EMPTY); +#else +	for (i = 100; i > 0; i--) { +		if (!(rbdf->cbd_sc & BD_SC_EMPTY)) +			break; +		udelay (1000); +	} + +	if (i == 0) +		return -1; +#endif +	c = *buf; +	rbdf->cbd_sc |= BD_SC_EMPTY; + +	return (c); +} + +  /* +   * SCC callbacks +   */ + +static void scc_init (int scc_index) +{ +	static int cpm_cr_ch[] = { +		CPM_CR_CH_SCC1, +		CPM_CR_CH_SCC2, +		CPM_CR_CH_SCC3, +		CPM_CR_CH_SCC4, +	}; + +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile scc_t *sp; +	volatile scc_uart_t *up; +	volatile cbd_t *tbdf, *rbdf; +	volatile cpm8xx_t *cp = &(im->im_cpm); +	uint dpaddr; + +	/* initialize pointers to SCC */ + +	sp = (scc_t *) & (cp->cp_scc[scc_index]); +	up = (scc_uart_t *) & cp->cp_dparam[proff_scc[scc_index]]; + +	/* Disable transmitter/receiver. +	 */ +	sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + + +	/* Allocate space for two buffer descriptors in the DP ram. +	 */ + +#ifdef CFG_ALLOC_DPRAM +	dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8); +#else +	dpaddr = CPM_POST_BASE; +#endif + +	/* Enable SDMA. +	 */ +	im->im_siu_conf.sc_sdcr = 0x0001; + +	/* Set the physical address of the host memory buffers in +	 * the buffer descriptors. +	 */ + +	rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr]; +	rbdf->cbd_bufaddr = (uint) (rbdf + 2); +	rbdf->cbd_sc = 0; +	tbdf = rbdf + 1; +	tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1; +	tbdf->cbd_sc = 0; + +	/* Set up the baud rate generator. +	 */ +	cp->cp_sicr &= ~(0x000000FF << (8 * scc_index)); +	/* no |= needed, since BRG1 is 000 */ + +	cp->cp_brgc1 = +			(((gd->cpu_clk / 16 / gd->baudrate) - +			  1) << 1) | CPM_BRG_EN; + +	/* Set up the uart parameters in the parameter ram. +	 */ +	up->scc_genscc.scc_rbase = dpaddr; +	up->scc_genscc.scc_tbase = dpaddr + sizeof (cbd_t); + +	/* Initialize Tx/Rx parameters. +	 */ +	while (cp->cp_cpcr & CPM_CR_FLG)	/* wait if cp is busy */ +		; +	cp->cp_cpcr = +			mk_cr_cmd (cpm_cr_ch[scc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG; + +	while (cp->cp_cpcr & CPM_CR_FLG)	/* wait if cp is busy */ +		; + +	up->scc_genscc.scc_rfcr = SCC_EB | 0x05; +	up->scc_genscc.scc_tfcr = SCC_EB | 0x05; + +	up->scc_genscc.scc_mrblr = 1;	/* Single character receive */ +	up->scc_maxidl = 0;		/* disable max idle */ +	up->scc_brkcr = 1;		/* send one break character on stop TX */ +	up->scc_parec = 0; +	up->scc_frmec = 0; +	up->scc_nosec = 0; +	up->scc_brkec = 0; +	up->scc_uaddr1 = 0; +	up->scc_uaddr2 = 0; +	up->scc_toseq = 0; +	up->scc_char1 = 0x8000; +	up->scc_char2 = 0x8000; +	up->scc_char3 = 0x8000; +	up->scc_char4 = 0x8000; +	up->scc_char5 = 0x8000; +	up->scc_char6 = 0x8000; +	up->scc_char7 = 0x8000; +	up->scc_char8 = 0x8000; +	up->scc_rccm = 0xc0ff; + +	/* Set low latency / small fifo. +	 */ +	sp->scc_gsmrh = SCC_GSMRH_RFW; + +	/* Set UART mode +	 */ +	sp->scc_gsmrl &= ~0xF; +	sp->scc_gsmrl |= SCC_GSMRL_MODE_UART; + +	/* Set local loopback mode. +	 */ +	sp->scc_gsmrl &= ~SCC_GSMRL_DIAG_LE; +	sp->scc_gsmrl |= SCC_GSMRL_DIAG_LOOP; + +	/* Set clock divider 16 on Tx and Rx +	 */ +	sp->scc_gsmrl |= (SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); + +	sp->scc_psmr |= SCU_PSMR_CL; + +	/* Mask all interrupts and remove anything pending. +	 */ +	sp->scc_sccm = 0; +	sp->scc_scce = 0xffff; +	sp->scc_dsr = 0x7e7e; +	sp->scc_psmr = 0x3000; + +	/* Make the first buffer the only buffer. +	 */ +	tbdf->cbd_sc |= BD_SC_WRAP; +	rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; + +	/* Enable transmitter/receiver. +	 */ +	sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); +} + +static void scc_halt(int scc_index) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile cpm8xx_t *cp = &(im->im_cpm); +	volatile scc_t *sp = (scc_t *) & (cp->cp_scc[scc_index]); + +	sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT | SCC_GSMRL_DIAG_LE); +} + +static void scc_putc (int scc_index, const char c) +{ +	volatile cbd_t *tbdf; +	volatile char *buf; +	volatile scc_uart_t *up; +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile cpm8xx_t *cpmp = &(im->im_cpm); + +	up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]]; + +	tbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_tbase]; + +	/* Wait for last character to go. +	 */ + +	buf = (char *) tbdf->cbd_bufaddr; +#if 0 +	__asm__ ("eieio"); +	while (tbdf->cbd_sc & BD_SC_READY) +		__asm__ ("eieio"); +#endif + +	*buf = c; +	tbdf->cbd_datlen = 1; +	tbdf->cbd_sc |= BD_SC_READY; +	__asm__ ("eieio"); +#if 1 +	while (tbdf->cbd_sc & BD_SC_READY) +		__asm__ ("eieio"); +#endif +} + +static int scc_getc (int scc_index) +{ +	volatile cbd_t *rbdf; +	volatile unsigned char *buf; +	volatile scc_uart_t *up; +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	volatile cpm8xx_t *cpmp = &(im->im_cpm); +	unsigned char c; +	int i; + +	up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]]; + +	rbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_rbase]; + +	/* Wait for character to show up. +	 */ +	buf = (unsigned char *) rbdf->cbd_bufaddr; +#if 0 +	while (rbdf->cbd_sc & BD_SC_EMPTY); +#else +	for (i = 100; i > 0; i--) { +		if (!(rbdf->cbd_sc & BD_SC_EMPTY)) +			break; +		udelay (1000); +	} + +	if (i == 0) +		return -1; +#endif +	c = *buf; +	rbdf->cbd_sc |= BD_SC_EMPTY; + +	return (c); +} + +  /* +   * Test routines +   */ + +static int test_ctlr (int ctlr, int index) +{ +	int res = -1; +	char test_str[] = "*** UART Test String ***\r\n"; +	int i; + +	ctlr_proc[ctlr].init (index); + +	for (i = 0; i < sizeof (test_str) - 1; i++) { +		ctlr_proc[ctlr].putc (index, test_str[i]); +		if (ctlr_proc[ctlr].getc (index) != test_str[i]) +			goto Done; +	} + +	res = 0; + +Done: +	ctlr_proc[ctlr].halt (index); + +	if (res != 0) { +		post_log ("uart %s%d test failed\n", +				ctlr_name[ctlr], index + 1); +	} + +	return res; +} + +int uart_post_test (int flags) +{ +	int res = 0; +	int i; + +	ctlr_proc[CTLR_SMC].init = smc_init; +	ctlr_proc[CTLR_SMC].halt = smc_halt; +	ctlr_proc[CTLR_SMC].putc = smc_putc; +	ctlr_proc[CTLR_SMC].getc = smc_getc; + +	ctlr_proc[CTLR_SCC].init = scc_init; +	ctlr_proc[CTLR_SCC].halt = scc_halt; +	ctlr_proc[CTLR_SCC].putc = scc_putc; +	ctlr_proc[CTLR_SCC].getc = scc_getc; + +	for (i = 0; i < CTRL_LIST_SIZE; i++) { +		if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) { +			res = -1; +		} +	} + +#if !defined(CONFIG_8xx_CONS_NONE) +	serial_reinit_all (); +#endif + +	return res; +} + +#endif /* CONFIG_POST & CFG_POST_UART */ + +#endif /* CONFIG_POST */ diff --git a/post/cpu/mpc8xx/usb.c b/post/cpu/mpc8xx/usb.c new file mode 100644 index 000000000..0c74cfa5d --- /dev/null +++ b/post/cpu/mpc8xx/usb.c @@ -0,0 +1,269 @@ +/* + * (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 */ diff --git a/post/cpu/mpc8xx/watchdog.c b/post/cpu/mpc8xx/watchdog.c new file mode 100644 index 000000000..48c4282e1 --- /dev/null +++ b/post/cpu/mpc8xx/watchdog.c @@ -0,0 +1,78 @@ +/* + * (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> + +/* + * Watchdog test + * + * The test verifies the watchdog timer operation. + * On the first iteration, the test routine disables interrupts and + * makes a 10-second delay. If the system does not reboot during this delay, + * the watchdog timer is not operational and the test fails. If the system + * reboots, on the second iteration the test routine reports a success. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CFG_POST_WATCHDOG + +static ulong gettbl (void) +{ +	ulong r; + +  asm ("mftbl %0":"=r" (r)); + +	return r; +} + +int watchdog_post_test (int flags) +{ +	if (flags & POST_REBOOT) { +		/* Test passed */ + +		return 0; +	} else { +		/* 10-second delay */ +		int ints = disable_interrupts (); +		ulong base = gettbl (); +		ulong clk = get_tbclk (); + +		while ((gettbl () - base) / 10 < clk); + +		if (ints) +			enable_interrupts (); + +		/* +		 * If we have reached this point, the watchdog timer +		 * does not work +		 */ +		return -1; +	} +} + +#endif /* CONFIG_POST & CFG_POST_WATCHDOG */ +#endif /* CONFIG_POST */ |