Restructure POST directory to support of other CPUs, boards, etc.

This commit is contained in:
Wolfgang Denk 2007-03-06 18:08:43 +01:00 committed by Wolfgang Denk
parent a5284efd12
commit ad5bb451ad
45 changed files with 7719 additions and 45 deletions

View File

@ -203,7 +203,13 @@ ifeq ($(CPU),mpc83xx)
LIBS += drivers/qe/qe.a
endif
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += post/libpost.a post/cpu/libcpu.a
LIBS += post/libpost.a post/drivers/libpostdrivers.a
LIBS += $(shell if [ -d post/lib_$(ARCH) ]; then echo \
"post/lib_$(ARCH)/libpost$(ARCH).a"; fi)
LIBS += $(shell if [ -d post/cpu/$(CPU) ]; then echo \
"post/cpu/$(CPU)/libpost$(CPU).a"; fi)
LIBS += $(shell if [ -d post/board/$(BOARDDIR) ]; then echo \
"post/board/$(BOARDDIR)/libpost$(BOARD).a"; fi)
LIBS += common/libcommon.a
LIBS += $(BOARDLIBS)
@ -216,9 +222,8 @@ PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -
# The "tools" are needed early, so put this first
# Don't include stuff already done in $(LIBS)
SUBDIRS = tools \
examples \
post \
post/cpu
examples
.PHONY : $(SUBDIRS)
ifeq ($(CONFIG_NAND_U_BOOT),y)

View File

@ -168,8 +168,8 @@ static void program_codt(unsigned long *dimm_populated,
static void program_mode(unsigned long *dimm_populated,
unsigned char *iic0_dimm_addr,
unsigned long num_dimm_banks,
ddr_cas_id_t *selected_cas,
int *write_recovery);
ddr_cas_id_t *selected_cas,
int *write_recovery);
static void program_tr(unsigned long *dimm_populated,
unsigned char *iic0_dimm_addr,
unsigned long num_dimm_banks);
@ -185,7 +185,7 @@ static void program_copt1(unsigned long *dimm_populated,
static void program_initplr(unsigned long *dimm_populated,
unsigned char *iic0_dimm_addr,
unsigned long num_dimm_banks,
ddr_cas_id_t selected_cas,
ddr_cas_id_t selected_cas,
int write_recovery);
static unsigned long is_ecc_enabled(void);
static void program_ecc(unsigned long *dimm_populated,
@ -1149,7 +1149,7 @@ static void program_codt(unsigned long *dimm_populated,
static void program_initplr(unsigned long *dimm_populated,
unsigned char *iic0_dimm_addr,
unsigned long num_dimm_banks,
ddr_cas_id_t selected_cas,
ddr_cas_id_t selected_cas,
int write_recovery)
{
u32 cas = 0;

View File

@ -1916,43 +1916,43 @@ pll_wait:
/*----------------------------------------------------------------------------+
| dcbz_area.
+----------------------------------------------------------------------------*/
function_prolog(dcbz_area)
rlwinm. r5,r4,0,27,31
rlwinm r5,r4,27,5,31
beq ..d_ra2
addi r5,r5,0x0001
function_prolog(dcbz_area)
rlwinm. r5,r4,0,27,31
rlwinm r5,r4,27,5,31
beq ..d_ra2
addi r5,r5,0x0001
..d_ra2:mtctr r5
..d_ag2:dcbz r0,r3
addi r3,r3,32
bdnz ..d_ag2
sync
blr
function_epilog(dcbz_area)
addi r3,r3,32
bdnz ..d_ag2
sync
blr
function_epilog(dcbz_area)
/*----------------------------------------------------------------------------+
| dflush. Assume 32K at vector address is cachable.
+----------------------------------------------------------------------------*/
function_prolog(dflush)
mfmsr r9
rlwinm r8,r9,0,15,13
rlwinm r8,r8,0,17,15
mtmsr r8
addi r3,r0,0x0000
mtspr dvlim,r3
mfspr r3,ivpr
addi r4,r0,1024
mtctr r4
function_prolog(dflush)
mfmsr r9
rlwinm r8,r9,0,15,13
rlwinm r8,r8,0,17,15
mtmsr r8
addi r3,r0,0x0000
mtspr dvlim,r3
mfspr r3,ivpr
addi r4,r0,1024
mtctr r4
..dflush_loop:
lwz r6,0x0(r3)
addi r3,r3,32
bdnz ..dflush_loop
addi r3,r3,-32
mtctr r4
lwz r6,0x0(r3)
addi r3,r3,32
bdnz ..dflush_loop
addi r3,r3,-32
mtctr r4
..ag: dcbf r0,r3
addi r3,r3,-32
bdnz ..ag
sync
mtmsr r9
blr
function_epilog(dflush)
addi r3,r3,-32
bdnz ..ag
sync
mtmsr r9
blr
function_epilog(dflush)
#endif /* CONFIG_440 */

View File

@ -22,14 +22,10 @@
#
SUBDIRS = cpu
SUBDIRS = drivers cpu lib_$(ARCH) board/$(BOARDDIR)
LIB = libpost.a
AOBJS = cache_8xx.o
COBJS = cache.o codec.o cpu.o dsp.o ether.o
COBJS += i2c.o memory.o post.o rtc.o
COBJS += spr.o sysmon.o tests.o uart.o
COBJS += usb.o watchdog.o
COBJS = post.o tests.o
include $(TOPDIR)/post/rules.mk

29
post/board/lwmon/Makefile Normal file
View File

@ -0,0 +1,29 @@
#
# (C) Copyright 2002-2006
# 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 = libpostlwmon.a
COBJS = sysmon.o
include $(TOPDIR)/post/rules.mk

331
post/board/lwmon/sysmon.c Normal file
View File

@ -0,0 +1,331 @@
/*
* (C) Copyright 2003
* 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 <post.h>
#include <common.h>
#ifdef CONFIG_POST
/*
* SYSMON test
*
* This test performs the system hardware monitoring.
* The test passes when all the following voltages and temperatures
* are within allowed ranges:
*
* Board temperature
* Front temperature
* +3.3V CPU logic
* +5V logic
* +12V PCMCIA
* +12V CCFL
* +5V standby
*
* CCFL is not enabled if temperature values are not within allowed ranges
*
* See the list off all parameters in the sysmon_table below
*/
#include <post.h>
#include <watchdog.h>
#include <i2c.h>
#if CONFIG_POST & CFG_POST_SYSMON
DECLARE_GLOBAL_DATA_PTR;
static int sysmon_temp_invalid = 0;
/* #define DEBUG */
#define RELOC(x) if (x != NULL) x = (void *) ((ulong) (x) + gd->reloc_off)
typedef struct sysmon_s sysmon_t;
typedef struct sysmon_table_s sysmon_table_t;
static void sysmon_lm87_init (sysmon_t * this);
static void sysmon_pic_init (sysmon_t * this);
static uint sysmon_i2c_read (sysmon_t * this, uint addr);
static uint sysmon_i2c_read_sgn (sysmon_t * this, uint addr);
static void sysmon_ccfl_disable (sysmon_table_t * this);
static void sysmon_ccfl_enable (sysmon_table_t * this);
struct sysmon_s
{
uchar chip;
void (*init)(sysmon_t *);
uint (*read)(sysmon_t *, uint);
};
static sysmon_t sysmon_lm87 =
{CFG_I2C_SYSMON_ADDR, sysmon_lm87_init, sysmon_i2c_read};
static sysmon_t sysmon_lm87_sgn =
{CFG_I2C_SYSMON_ADDR, sysmon_lm87_init, sysmon_i2c_read_sgn};
static sysmon_t sysmon_pic =
{CFG_I2C_PICIO_ADDR, sysmon_pic_init, sysmon_i2c_read};
static sysmon_t * sysmon_list[] =
{
&sysmon_lm87,
&sysmon_lm87_sgn,
&sysmon_pic,
NULL
};
struct sysmon_table_s
{
char * name;
char * unit_name;
sysmon_t * sysmon;
void (*exec_before)(sysmon_table_t *);
void (*exec_after)(sysmon_table_t *);
int unit_precision;
int unit_div;
int unit_min;
int unit_max;
uint val_mask;
uint val_min;
uint val_max;
int val_valid;
uint val_min_alt;
uint val_max_alt;
int val_valid_alt;
uint addr;
};
static sysmon_table_t sysmon_table[] =
{
{"Board temperature", " C", &sysmon_lm87_sgn, NULL, sysmon_ccfl_disable,
1, 1, -128, 127, 0xFF, 0x58, 0xD5, 0, 0x6C, 0xC6, 0, 0x27},
{"Front temperature", " C", &sysmon_lm87, NULL, sysmon_ccfl_disable,
1, 100, -27316, 8984, 0xFF, 0xA4, 0xFC, 0, 0xB2, 0xF1, 0, 0x29},
{"+3.3V CPU logic", "V", &sysmon_lm87, NULL, NULL,
100, 1000, 0, 4386, 0xFF, 0xB6, 0xC9, 0, 0xB6, 0xC9, 0, 0x22},
{"+ 5 V logic", "V", &sysmon_lm87, NULL, NULL,
100, 1000, 0, 6630, 0xFF, 0xB6, 0xCA, 0, 0xB6, 0xCA, 0, 0x23},
{"+12 V PCMCIA", "V", &sysmon_lm87, NULL, NULL,
100, 1000, 0, 15460, 0xFF, 0xBC, 0xD0, 0, 0xBC, 0xD0, 0, 0x21},
{"+12 V CCFL", "V", &sysmon_lm87, NULL, sysmon_ccfl_enable,
100, 1000, 0, 15900, 0xFF, 0xB6, 0xCA, 0, 0xB6, 0xCA, 0, 0x24},
{"+ 5 V standby", "V", &sysmon_pic, NULL, NULL,
100, 1000, 0, 6040, 0xFF, 0xC8, 0xDE, 0, 0xC8, 0xDE, 0, 0x7C},
};
static int sysmon_table_size = sizeof(sysmon_table) / sizeof(sysmon_table[0]);
static int conversion_done = 0;
int sysmon_init_f (void)
{
sysmon_t ** l;
ulong reg;
/* Power on CCFL, PCMCIA */
reg = pic_read (0x60);
reg |= 0x09;
pic_write (0x60, reg);
for (l = sysmon_list; *l; l++) {
(*l)->init(*l);
}
return 0;
}
void sysmon_reloc (void)
{
sysmon_t ** l;
sysmon_table_t * t;
for (l = sysmon_list; *l; l++) {
RELOC(*l);
RELOC((*l)->init);
RELOC((*l)->read);
}
for (t = sysmon_table; t < sysmon_table + sysmon_table_size; t ++) {
RELOC(t->exec_before);
RELOC(t->exec_after);
RELOC(t->sysmon);
}
}
static char *sysmon_unit_value (sysmon_table_t *s, uint val)
{
static char buf[32];
int unit_val =
s->unit_min + (s->unit_max - s->unit_min) * val / s->val_mask;
char *p, sign;
int dec, frac;
if (val == -1) {
return "I/O ERROR";
}
if (unit_val < 0) {
sign = '-';
unit_val = -unit_val;
} else {
sign = '+';
}
p = buf + sprintf(buf, "%c%2d", sign, unit_val / s->unit_div);
frac = unit_val % s->unit_div;
frac /= (s->unit_div / s->unit_precision);
dec = s->unit_precision;
if (dec != 1) {
*p++ = '.';
}
for (dec /= 10; dec != 0; dec /= 10) {
*p++ = '0' + (frac / dec) % 10;
}
strcpy(p, s->unit_name);
return buf;
}
static void sysmon_lm87_init (sysmon_t * this)
{
uchar val;
/* Detect LM87 chip */
if (i2c_read(this->chip, 0x40, 1, &val, 1) || (val & 0x80) != 0 ||
i2c_read(this->chip, 0x3E, 1, &val, 1) || val != 0x02) {
printf("Error: LM87 not found at 0x%02X\n", this->chip);
return;
}
/* Configure pins 5,6 as AIN */
val = 0x03;
if (i2c_write(this->chip, 0x16, 1, &val, 1)) {
printf("Error: can't write LM87 config register\n");
return;
}
/* Start monitoring */
val = 0x01;
if (i2c_write(this->chip, 0x40, 1, &val, 1)) {
printf("Error: can't write LM87 config register\n");
return;
}
}
static void sysmon_pic_init (sysmon_t * this)
{
}
static uint sysmon_i2c_read (sysmon_t * this, uint addr)
{
uchar val;
uint res = i2c_read(this->chip, addr, 1, &val, 1);
return res == 0 ? val : -1;
}
static uint sysmon_i2c_read_sgn (sysmon_t * this, uint addr)
{
uchar val;
return i2c_read(this->chip, addr, 1, &val, 1) == 0 ?
128 + (signed char)val : -1;
}
static void sysmon_ccfl_disable (sysmon_table_t * this)
{
if (!this->val_valid_alt) {
sysmon_temp_invalid = 1;
}
}
static void sysmon_ccfl_enable (sysmon_table_t * this)
{
ulong reg;
if (!sysmon_temp_invalid) {
reg = pic_read (0x60);
reg |= 0x06;
pic_write (0x60, reg);
}
}
int sysmon_post_test (int flags)
{
int res = 0;
sysmon_table_t * t;
uint val;
/*
* The A/D conversion on the LM87 sensor takes 300 ms.
*/
if (! conversion_done) {
while (post_time_ms(gd->post_init_f_time) < 300) WATCHDOG_RESET ();
conversion_done = 1;
}
for (t = sysmon_table; t < sysmon_table + sysmon_table_size; t ++) {
if (t->exec_before) {
t->exec_before(t);
}
val = t->sysmon->read(t->sysmon, t->addr);
if (val != -1) {
t->val_valid = val >= t->val_min && val <= t->val_max;
t->val_valid_alt = val >= t->val_min_alt && val <= t->val_max_alt;
} else {
t->val_valid = 0;
t->val_valid_alt = 0;
}
if (t->exec_after) {
t->exec_after(t);
}
if ((!t->val_valid) || (flags & POST_MANUAL)) {
printf("%-17s = %-10s ", t->name, sysmon_unit_value(t, val));
printf("allowed range");
printf(" %-8s ..", sysmon_unit_value(t, t->val_min));
printf(" %-8s", sysmon_unit_value(t, t->val_max));
printf(" %s\n", t->val_valid ? "OK" : "FAIL");
}
if (!t->val_valid) {
res = -1;
}
}
return res;
}
#endif /* CONFIG_POST & CFG_POST_SYSMON */
#endif /* CONFIG_POST */

29
post/board/netta/Makefile Normal file
View File

@ -0,0 +1,29 @@
#
# (C) Copyright 2002-2006
# 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 = libpostnetta.a
COBJS = codec.o dsp.o
include $(TOPDIR)/post/rules.mk

48
post/board/netta/codec.c Normal file
View File

@ -0,0 +1,48 @@
/*
* (C) Copyright 2004
* Pantelis Antoniou, Intracom S.A. , panto@intracom.gr
*
* 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>
/*
* CODEC test
*
* This test verifies the connection and performs a memory test
* on any connected codec(s). The meat of the work is done
* in the board specific function.
*/
#ifdef CONFIG_POST
#include <post.h>
#if CONFIG_POST & CFG_POST_CODEC
extern int board_post_codec(int flags);
int codec_post_test (int flags)
{
return board_post_codec(flags);
}
#endif /* CONFIG_POST & CFG_POST_CODEC */
#endif /* CONFIG_POST */

48
post/board/netta/dsp.c Normal file
View File

@ -0,0 +1,48 @@
/*
* (C) Copyright 2004
* Pantelis Antoniou, Intracom S.A. , panto@intracom.gr
*
* 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>
/*
* DSP test
*
* This test verifies the connection and performs a memory test
* on any connected DSP(s). The meat of the work is done
* in the board specific function.
*/
#ifdef CONFIG_POST
#include <post.h>
#if CONFIG_POST & CFG_POST_DSP
extern int board_post_dsp(int flags);
int dsp_post_test (int flags)
{
return board_post_dsp(flags);
}
#endif /* CONFIG_POST & CFG_POST_DSP */
#endif /* CONFIG_POST */

29
post/cpu/mpc8xx/Makefile Normal file
View File

@ -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

495
post/cpu/mpc8xx/cache_8xx.S Normal file
View File

@ -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 */

631
post/cpu/mpc8xx/ether.c Normal file
View File

@ -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 */

152
post/cpu/mpc8xx/spr.c Normal file
View File

@ -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 */

560
post/cpu/mpc8xx/uart.c Normal file
View File

@ -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 */

269
post/cpu/mpc8xx/usb.c Normal file
View File

@ -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 */

View File

@ -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 */

31
post/drivers/Makefile Normal file
View File

@ -0,0 +1,31 @@
#
# (C) Copyright 2002-2006
# 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
#
SUBDIRS =
LIB = libpostdrivers.a
COBJS = cache.o i2c.o memory.o rtc.o
include $(TOPDIR)/post/rules.mk

81
post/drivers/cache.c Normal file
View File

@ -0,0 +1,81 @@
/*
* (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>
/* Cache test
*
* This test verifies the CPU data and instruction cache using
* several test scenarios.
*/
#ifdef CONFIG_POST
#include <post.h>
#include <watchdog.h>
#if CONFIG_POST & CFG_POST_CACHE
#define CACHE_POST_SIZE 1024
extern int cache_post_test1 (char *, unsigned int);
extern int cache_post_test2 (char *, unsigned int);
extern int cache_post_test3 (char *, unsigned int);
extern int cache_post_test4 (char *, unsigned int);
extern int cache_post_test5 (void);
extern int cache_post_test6 (void);
int cache_post_test (int flags)
{
int ints = disable_interrupts ();
int res = 0;
static char ta[CACHE_POST_SIZE + 0xf];
char *testarea = (char *) (((unsigned long) ta + 0xf) & ~0xf);
WATCHDOG_RESET ();
if (res == 0)
res = cache_post_test1 (testarea, CACHE_POST_SIZE);
WATCHDOG_RESET ();
if (res == 0)
res = cache_post_test2 (testarea, CACHE_POST_SIZE);
WATCHDOG_RESET ();
if (res == 0)
res = cache_post_test3 (testarea, CACHE_POST_SIZE);
WATCHDOG_RESET ();
if (res == 0)
res = cache_post_test4 (testarea, CACHE_POST_SIZE);
WATCHDOG_RESET ();
if (res == 0)
res = cache_post_test5 ();
WATCHDOG_RESET ();
if (res == 0)
res = cache_post_test6 ();
WATCHDOG_RESET ();
if (ints)
enable_interrupts ();
return res;
}
#endif /* CONFIG_POST & CFG_POST_CACHE */
#endif /* CONFIG_POST */

94
post/drivers/i2c.c Normal file
View File

@ -0,0 +1,94 @@
/*
* (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>
#ifdef CONFIG_POST
/*
* I2C test
*
* For verifying the I2C bus, a full I2C bus scanning is performed.
*
* #ifdef I2C_ADDR_LIST
* The test is considered as passed if all the devices and
* only the devices in the list are found.
* #else [ ! I2C_ADDR_LIST ]
* The test is considered as passed if any I2C device is found.
* #endif
*/
#include <post.h>
#include <i2c.h>
#if CONFIG_POST & CFG_POST_I2C
int i2c_post_test (int flags)
{
unsigned int i;
unsigned int good = 0;
#ifdef I2C_ADDR_LIST
unsigned int bad = 0;
int j;
unsigned char i2c_addr_list[] = I2C_ADDR_LIST;
unsigned char i2c_miss_list[] = I2C_ADDR_LIST;
#endif
for (i = 0; i < 128; i++) {
if (i2c_probe (i) == 0) {
#ifndef I2C_ADDR_LIST
good++;
#else /* I2C_ADDR_LIST */
for (j=0; j<sizeof(i2c_addr_list); ++j) {
if (i == i2c_addr_list[j]) {
good++;
i2c_miss_list[j] = 0xFF;
break;
}
}
if (j == sizeof(i2c_addr_list)) {
bad++;
post_log ("I2C: addr %02X not expected\n",
i);
}
#endif /* I2C_ADDR_LIST */
}
}
#ifndef I2C_ADDR_LIST
return good > 0 ? 0 : -1;
#else /* I2C_ADDR_LIST */
if (good != sizeof(i2c_addr_list)) {
for (j=0; j<sizeof(i2c_miss_list); ++j) {
if (i2c_miss_list[j] != 0xFF) {
post_log ("I2C: addr %02X did not respond\n",
i2c_miss_list[j]);
}
}
}
return ((good == sizeof(i2c_addr_list)) && (bad == 0)) ? 0 : -1;
#endif
}
#endif /* CONFIG_POST & CFG_POST_I2C */
#endif /* CONFIG_POST */

483
post/drivers/memory.c Normal file
View File

@ -0,0 +1,483 @@
/*
* (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>
/* Memory test
*
* General observations:
* o The recommended test sequence is to test the data lines: if they are
* broken, nothing else will work properly. Then test the address
* lines. Finally, test the cells in the memory now that the test
* program knows that the address and data lines work properly.
* This sequence also helps isolate and identify what is faulty.
*
* o For the address line test, it is a good idea to use the base
* address of the lowest memory location, which causes a '1' bit to
* walk through a field of zeros on the address lines and the highest
* memory location, which causes a '0' bit to walk through a field of
* '1's on the address line.
*
* o Floating buses can fool memory tests if the test routine writes
* a value and then reads it back immediately. The problem is, the
* write will charge the residual capacitance on the data bus so the
* bus retains its state briefely. When the test program reads the
* value back immediately, the capacitance of the bus can allow it
* to read back what was written, even though the memory circuitry
* is broken. To avoid this, the test program should write a test
* pattern to the target location, write a different pattern elsewhere
* to charge the residual capacitance in a differnt manner, then read
* the target location back.
*
* o Always read the target location EXACTLY ONCE and save it in a local
* variable. The problem with reading the target location more than
* once is that the second and subsequent reads may work properly,
* resulting in a failed test that tells the poor technician that
* "Memory error at 00000000, wrote aaaaaaaa, read aaaaaaaa" which
* doesn't help him one bit and causes puzzled phone calls. Been there,
* done that.
*
* Data line test:
* ---------------
* This tests data lines for shorts and opens by forcing adjacent data
* to opposite states. Because the data lines could be routed in an
* arbitrary manner the must ensure test patterns ensure that every case
* is tested. By using the following series of binary patterns every
* combination of adjacent bits is test regardless of routing.
*
* ...101010101010101010101010
* ...110011001100110011001100
* ...111100001111000011110000
* ...111111110000000011111111
*
* Carrying this out, gives us six hex patterns as follows:
*
* 0xaaaaaaaaaaaaaaaa
* 0xcccccccccccccccc
* 0xf0f0f0f0f0f0f0f0
* 0xff00ff00ff00ff00
* 0xffff0000ffff0000
* 0xffffffff00000000
*
* To test for short and opens to other signals on our boards, we
* simply test with the 1's complemnt of the paterns as well, resulting
* in twelve patterns total.
*
* After writing a test pattern. a special pattern 0x0123456789ABCDEF is
* written to a different address in case the data lines are floating.
* Thus, if a byte lane fails, you will see part of the special
* pattern in that byte lane when the test runs. For example, if the
* xx__xxxxxxxxxxxx byte line fails, you will see aa23aaaaaaaaaaaa
* (for the 'a' test pattern).
*
* Address line test:
* ------------------
* This function performs a test to verify that all the address lines
* hooked up to the RAM work properly. If there is an address line
* fault, it usually shows up as two different locations in the address
* map (related by the faulty address line) mapping to one physical
* memory storage location. The artifact that shows up is writing to
* the first location "changes" the second location.
*
* To test all address lines, we start with the given base address and
* xor the address with a '1' bit to flip one address line. For each
* test, we shift the '1' bit left to test the next address line.
*
* In the actual code, we start with address sizeof(ulong) since our
* test pattern we use is a ulong and thus, if we tried to test lower
* order address bits, it wouldn't work because our pattern would
* overwrite itself.
*
* Example for a 4 bit address space with the base at 0000:
* 0000 <- base
* 0001 <- test 1
* 0010 <- test 2
* 0100 <- test 3
* 1000 <- test 4
* Example for a 4 bit address space with the base at 0010:
* 0010 <- base
* 0011 <- test 1
* 0000 <- (below the base address, skipped)
* 0110 <- test 2
* 1010 <- test 3
*
* The test locations are successively tested to make sure that they are
* not "mirrored" onto the base address due to a faulty address line.
* Note that the base and each test location are related by one address
* line flipped. Note that the base address need not be all zeros.
*
* Memory tests 1-4:
* -----------------
* These tests verify RAM using sequential writes and reads
* to/from RAM. There are several test cases that use different patterns to
* verify RAM. Each test case fills a region of RAM with one pattern and
* then reads the region back and compares its contents with the pattern.
* The following patterns are used:
*
* 1a) zero pattern (0x00000000)
* 1b) negative pattern (0xffffffff)
* 1c) checkerboard pattern (0x55555555)
* 1d) checkerboard pattern (0xaaaaaaaa)
* 2) bit-flip pattern ((1 << (offset % 32))
* 3) address pattern (offset)
* 4) address pattern (~offset)
*
* Being run in normal mode, the test verifies only small 4Kb
* regions of RAM around each 1Mb boundary. For example, for 64Mb
* RAM the following areas are verified: 0x00000000-0x00000800,
* 0x000ff800-0x00100800, 0x001ff800-0x00200800, ..., 0x03fff800-
* 0x04000000. If the test is run in slow-test mode, it verifies
* the whole RAM.
*/
#ifdef CONFIG_POST
#include <post.h>
#include <watchdog.h>
#if CONFIG_POST & CFG_POST_MEMORY
DECLARE_GLOBAL_DATA_PTR;
/*
* Define INJECT_*_ERRORS for testing error detection in the presence of
* _good_ hardware.
*/
#undef INJECT_DATA_ERRORS
#undef INJECT_ADDRESS_ERRORS
#ifdef INJECT_DATA_ERRORS
#warning "Injecting data line errors for testing purposes"
#endif
#ifdef INJECT_ADDRESS_ERRORS
#warning "Injecting address line errors for testing purposes"
#endif
/*
* This function performs a double word move from the data at
* the source pointer to the location at the destination pointer.
* This is helpful for testing memory on processors which have a 64 bit
* wide data bus.
*
* On those PowerPC with FPU, use assembly and a floating point move:
* this does a 64 bit move.
*
* For other processors, let the compiler generate the best code it can.
*/
static void move64(unsigned long long *src, unsigned long long *dest)
{
#if defined(CONFIG_MPC8260) || defined(CONFIG_MPC824X)
asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */
"stfd 0, 0(4)" /* *dest = fpr0 */
: : : "fr0" ); /* Clobbers fr0 */
return;
#else
*dest = *src;
#endif
}
/*
* This is 64 bit wide test patterns. Note that they reside in ROM
* (which presumably works) and the tests write them to RAM which may
* not work.
*
* The "otherpattern" is written to drive the data bus to values other
* than the test pattern. This is for detecting floating bus lines.
*
*/
const static unsigned long long pattern[] = {
0xaaaaaaaaaaaaaaaaULL,
0xccccccccccccccccULL,
0xf0f0f0f0f0f0f0f0ULL,
0xff00ff00ff00ff00ULL,
0xffff0000ffff0000ULL,
0xffffffff00000000ULL,
0x00000000ffffffffULL,
0x0000ffff0000ffffULL,
0x00ff00ff00ff00ffULL,
0x0f0f0f0f0f0f0f0fULL,
0x3333333333333333ULL,
0x5555555555555555ULL
};
const unsigned long long otherpattern = 0x0123456789abcdefULL;
static int memory_post_dataline(unsigned long long * pmem)
{
unsigned long long temp64 = 0;
int num_patterns = sizeof(pattern)/ sizeof(pattern[0]);
int i;
unsigned int hi, lo, pathi, patlo;
int ret = 0;
for ( i = 0; i < num_patterns; i++) {
move64((unsigned long long *)&(pattern[i]), pmem++);
/*
* Put a different pattern on the data lines: otherwise they
* may float long enough to read back what we wrote.
*/
move64((unsigned long long *)&otherpattern, pmem--);
move64(pmem, &temp64);
#ifdef INJECT_DATA_ERRORS
temp64 ^= 0x00008000;
#endif
if (temp64 != pattern[i]){
pathi = (pattern[i]>>32) & 0xffffffff;
patlo = pattern[i] & 0xffffffff;
hi = (temp64>>32) & 0xffffffff;
lo = temp64 & 0xffffffff;
post_log ("Memory (date line) error at %08x, "
"wrote %08x%08x, read %08x%08x !\n",
pmem, pathi, patlo, hi, lo);
ret = -1;
}
}
return ret;
}
static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size)
{
ulong *target;
ulong *end;
ulong readback;
ulong xor;
int ret = 0;
end = (ulong *)((ulong)base + size); /* pointer arith! */
xor = 0;
for(xor = sizeof(ulong); xor > 0; xor <<= 1) {
target = (ulong *)((ulong)testaddr ^ xor);
if((target >= base) && (target < end)) {
*testaddr = ~*target;
readback = *target;
#ifdef INJECT_ADDRESS_ERRORS
if(xor == 0x00008000) {
readback = *testaddr;
}
#endif
if(readback == *testaddr) {
post_log ("Memory (address line) error at %08x<->%08x, "
"XOR value %08x !\n",
testaddr, target, xor);
ret = -1;
}
}
}
return ret;
}
static int memory_post_test1 (unsigned long start,
unsigned long size,
unsigned long val)
{
unsigned long i;
ulong *mem = (ulong *) start;
ulong readback;
int ret = 0;
for (i = 0; i < size / sizeof (ulong); i++) {
mem[i] = val;
if (i % 1024 == 0)
WATCHDOG_RESET ();
}
for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
readback = mem[i];
if (readback != val) {
post_log ("Memory error at %08x, "
"wrote %08x, read %08x !\n",
mem + i, val, readback);
ret = -1;
break;
}
if (i % 1024 == 0)
WATCHDOG_RESET ();
}
return ret;
}
static int memory_post_test2 (unsigned long start, unsigned long size)
{
unsigned long i;
ulong *mem = (ulong *) start;
ulong readback;
int ret = 0;
for (i = 0; i < size / sizeof (ulong); i++) {
mem[i] = 1 << (i % 32);
if (i % 1024 == 0)
WATCHDOG_RESET ();
}
for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
readback = mem[i];
if (readback != (1 << (i % 32))) {
post_log ("Memory error at %08x, "
"wrote %08x, read %08x !\n",
mem + i, 1 << (i % 32), readback);
ret = -1;
break;
}
if (i % 1024 == 0)
WATCHDOG_RESET ();
}
return ret;
}
static int memory_post_test3 (unsigned long start, unsigned long size)
{
unsigned long i;
ulong *mem = (ulong *) start;
ulong readback;
int ret = 0;
for (i = 0; i < size / sizeof (ulong); i++) {
mem[i] = i;
if (i % 1024 == 0)
WATCHDOG_RESET ();
}
for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
readback = mem[i];
if (readback != i) {
post_log ("Memory error at %08x, "
"wrote %08x, read %08x !\n",
mem + i, i, readback);
ret = -1;
break;
}
if (i % 1024 == 0)
WATCHDOG_RESET ();
}
return ret;
}
static int memory_post_test4 (unsigned long start, unsigned long size)
{
unsigned long i;
ulong *mem = (ulong *) start;
ulong readback;
int ret = 0;
for (i = 0; i < size / sizeof (ulong); i++) {
mem[i] = ~i;
if (i % 1024 == 0)
WATCHDOG_RESET ();
}
for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
readback = mem[i];
if (readback != ~i) {
post_log ("Memory error at %08x, "
"wrote %08x, read %08x !\n",
mem + i, ~i, readback);
ret = -1;
break;
}
if (i % 1024 == 0)
WATCHDOG_RESET ();
}
return ret;
}
static int memory_post_tests (unsigned long start, unsigned long size)
{
int ret = 0;
if (ret == 0)
ret = memory_post_dataline ((unsigned long long *)start);
WATCHDOG_RESET ();
if (ret == 0)
ret = memory_post_addrline ((ulong *)start, (ulong *)start, size);
WATCHDOG_RESET ();
if (ret == 0)
ret = memory_post_addrline ((ulong *)(start + size - 8),
(ulong *)start, size);
WATCHDOG_RESET ();
if (ret == 0)
ret = memory_post_test1 (start, size, 0x00000000);
WATCHDOG_RESET ();
if (ret == 0)
ret = memory_post_test1 (start, size, 0xffffffff);
WATCHDOG_RESET ();
if (ret == 0)
ret = memory_post_test1 (start, size, 0x55555555);
WATCHDOG_RESET ();
if (ret == 0)
ret = memory_post_test1 (start, size, 0xaaaaaaaa);
WATCHDOG_RESET ();
if (ret == 0)
ret = memory_post_test2 (start, size);
WATCHDOG_RESET ();
if (ret == 0)
ret = memory_post_test3 (start, size);
WATCHDOG_RESET ();
if (ret == 0)
ret = memory_post_test4 (start, size);
WATCHDOG_RESET ();
return ret;
}
int memory_post_test (int flags)
{
int ret = 0;
bd_t *bd = gd->bd;
unsigned long memsize = (bd->bi_memsize >= 256 << 20 ?
256 << 20 : bd->bi_memsize) - (1 << 20);
if (flags & POST_SLOWTEST) {
ret = memory_post_tests (CFG_SDRAM_BASE, memsize);
} else { /* POST_NORMAL */
unsigned long i;
for (i = 0; i < (memsize >> 20) && ret == 0; i++) {
if (ret == 0)
ret = memory_post_tests (i << 20, 0x800);
if (ret == 0)
ret = memory_post_tests ((i << 20) + 0xff800, 0x800);
}
}
return ret;
}
#endif /* CONFIG_POST & CFG_POST_MEMORY */
#endif /* CONFIG_POST */

183
post/drivers/rtc.c Normal file
View File

@ -0,0 +1,183 @@
/*
* (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>
/*
* RTC test
*
* The Real Time Clock (RTC) operation is verified by this test.
* The following features are verified:
* o) Time uniformity
* This is verified by reading RTC in polling within
* a short period of time.
* o) Passing month boundaries
* This is checked by setting RTC to a second before
* a month boundary and reading it after its passing the
* boundary. The test is performed for both leap- and
* nonleap-years.
*/
#ifdef CONFIG_POST
#include <post.h>
#include <rtc.h>
#if CONFIG_POST & CFG_POST_RTC
static int rtc_post_skip (ulong * diff)
{
struct rtc_time tm1;
struct rtc_time tm2;
ulong start1;
ulong start2;
rtc_get (&tm1);
start1 = get_timer (0);
while (1) {
rtc_get (&tm2);
start2 = get_timer (0);
if (tm1.tm_sec != tm2.tm_sec)
break;
if (start2 - start1 > 1500)
break;
}
if (tm1.tm_sec != tm2.tm_sec) {
*diff = start2 - start1;
return 0;
} else {
return -1;
}
}
static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
{
time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
tm->tm_min, tm->tm_sec) + sec;
struct rtc_time ntm;
to_tm (t, &ntm);
rtc_set (&ntm);
}
int rtc_post_test (int flags)
{
ulong diff;
unsigned int i;
struct rtc_time svtm;
static unsigned int daysnl[] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static unsigned int daysl[] =
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
unsigned int ynl = 1999;
unsigned int yl = 2000;
unsigned int skipped = 0;
/* Time uniformity */
if (rtc_post_skip (&diff) != 0) {
post_log ("Timeout while waiting for a new second !\n");
return -1;
}
for (i = 0; i < 5; i++) {
if (rtc_post_skip (&diff) != 0) {
post_log ("Timeout while waiting for a new second !\n");
return -1;
}
if (diff < 950 || diff > 1050) {
post_log ("Invalid second duration !\n");
return -1;
}
}
/* Passing month boundaries */
if (rtc_post_skip (&diff) != 0) {
post_log ("Timeout while waiting for a new second !\n");
return -1;
}
rtc_get (&svtm);
for (i = 0; i < 12; i++) {
time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59);
struct rtc_time tm;
to_tm (t, &tm);
rtc_set (&tm);
skipped++;
if (rtc_post_skip (&diff) != 0) {
rtc_post_restore (&svtm, skipped);
post_log ("Timeout while waiting for a new second !\n");
return -1;
}
rtc_get (&tm);
if (tm.tm_mon == i + 1) {
rtc_post_restore (&svtm, skipped);
post_log ("Month %d boundary is not passed !\n", i + 1);
return -1;
}
}
for (i = 0; i < 12; i++) {
time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59);
struct rtc_time tm;
to_tm (t, &tm);
rtc_set (&tm);
skipped++;
if (rtc_post_skip (&diff) != 0) {
rtc_post_restore (&svtm, skipped);
post_log ("Timeout while waiting for a new second !\n");
return -1;
}
rtc_get (&tm);
if (tm.tm_mon == i + 1) {
rtc_post_restore (&svtm, skipped);
post_log ("Month %d boundary is not passed !\n", i + 1);
return -1;
}
}
rtc_post_restore (&svtm, skipped);
return 0;
}
#endif /* CONFIG_POST & CFG_POST_RTC */
#endif /* CONFIG_POST */

32
post/lib_ppc/Makefile Normal file
View File

@ -0,0 +1,32 @@
#
# (C) Copyright 2002-2006
# 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 = libpostppc.a
AOBJS = asm.o
COBJS = cpu.o cmp.o cmpi.o two.o twox.o three.o threex.o
COBJS += threei.o andi.o srawi.o rlwnm.o rlwinm.o rlwimi.o
COBJS += store.o load.o cr.o b.o multi.o string.o complex.o
include $(TOPDIR)/post/rules.mk

123
post/lib_ppc/andi.c Normal file
View File

@ -0,0 +1,123 @@
/*
* (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>
/*
* CPU test
* Logic instructions: andi., andis.
*
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_andi_s
{
ulong cmd;
ulong op1;
ushort op2;
ulong res;
} cpu_post_andi_table[] =
{
{
OP_ANDI_,
0x80008000,
0xffff,
0x00008000
},
{
OP_ANDIS_,
0x80008000,
0xffff,
0x80000000
},
};
static unsigned int cpu_post_andi_size =
sizeof (cpu_post_andi_table) / sizeof (struct cpu_post_andi_s);
int cpu_post_test_andi (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_andi_size && ret == 0; i++)
{
struct cpu_post_andi_s *test = cpu_post_andi_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long codecr[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_11IX(test->cmd, reg1, reg0, test->op2),
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
cpu_post_exec_21 (codecr, & cr, & res, test->op1);
ret = res == test->res &&
(cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
if (ret != 0)
{
post_log ("Error at andi test %d !\n", i);
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

346
post/lib_ppc/asm.S Normal file
View File

@ -0,0 +1,346 @@
/*
* 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
#include <post.h>
#include <ppc_asm.tmpl>
#include <ppc_defs.h>
#include <asm/cache.h>
#if CONFIG_POST & CFG_POST_CPU
/* void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); */
.global cpu_post_exec_02
cpu_post_exec_02:
mflr r0
stwu r0, -4(r1)
subi r1, r1, 104
stmw r6, 0(r1)
mtlr r3
mr r3, r4
mr r4, r5
blrl
lmw r6, 0(r1)
addi r1, r1, 104
lwz r0, 0(r1)
addi r1, r1, 4
mtlr r0
blr
/* void cpu_post_exec_04 (ulong *code, ulong op1, ulong op2, ulong op3, ulong op4); */
.global cpu_post_exec_04
cpu_post_exec_04:
mflr r0
stwu r0, -4(r1)
subi r1, r1, 96
stmw r8, 0(r1)
mtlr r3
mr r3, r4
mr r4, r5
mr r5, r6
mtxer r7
blrl
lmw r8, 0(r1)
addi r1, r1, 96
lwz r0, 0(r1)
addi r1, r1, 4
mtlr r0
blr
/* void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2); */
.global cpu_post_exec_12
cpu_post_exec_12:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
mtlr r3
mr r3, r5
mr r4, r6
blrl
lwz r4, 0(r1)
stw r3, 0(r4)
lwz r0, 4(r1)
addi r1, r1, 8
mtlr r0
blr
/* void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); */
.global cpu_post_exec_11
cpu_post_exec_11:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
mtlr r3
mr r3, r5
blrl
lwz r4, 0(r1)
stw r3, 0(r4)
lwz r0, 4(r1)
addi r1, r1, 8
mtlr r0
blr
/* void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); */
.global cpu_post_exec_21
cpu_post_exec_21:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
stwu r5, -4(r1)
li r0, 0
mtxer r0
lwz r0, 0(r4)
mtcr r0
mtlr r3
mr r3, r6
blrl
mfcr r0
lwz r4, 4(r1)
stw r0, 0(r4)
lwz r4, 0(r1)
stw r3, 0(r4)
lwz r0, 8(r1)
addi r1, r1, 12
mtlr r0
blr
/* void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
ulong op2); */
.global cpu_post_exec_22
cpu_post_exec_22:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
stwu r5, -4(r1)
li r0, 0
mtxer r0
lwz r0, 0(r4)
mtcr r0
mtlr r3
mr r3, r6
mr r4, r7
blrl
mfcr r0
lwz r4, 4(r1)
stw r0, 0(r4)
lwz r4, 0(r1)
stw r3, 0(r4)
lwz r0, 8(r1)
addi r1, r1, 12
mtlr r0
blr
/* void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3); */
.global cpu_post_exec_12w
cpu_post_exec_12w:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
mtlr r3
lwz r3, 0(r4)
mr r4, r5
mr r5, r6
blrl
lwz r4, 0(r1)
stw r3, 0(r4)
lwz r0, 4(r1)
addi r1, r1, 8
mtlr r0
blr
/* void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2); */
.global cpu_post_exec_11w
cpu_post_exec_11w:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
mtlr r3
lwz r3, 0(r4)
mr r4, r5
blrl
lwz r4, 0(r1)
stw r3, 0(r4)
lwz r0, 4(r1)
addi r1, r1, 8
mtlr r0
blr
/* void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3); */
.global cpu_post_exec_22w
cpu_post_exec_22w:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
stwu r6, -4(r1)
mtlr r3
lwz r3, 0(r4)
mr r4, r5
blrl
lwz r4, 4(r1)
stw r3, 0(r4)
lwz r4, 0(r1)
stw r5, 0(r4)
lwz r0, 8(r1)
addi r1, r1, 12
mtlr r0
blr
/* void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2); */
.global cpu_post_exec_21w
cpu_post_exec_21w:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
stwu r5, -4(r1)
mtlr r3
lwz r3, 0(r4)
blrl
lwz r5, 4(r1)
stw r3, 0(r5)
lwz r5, 0(r1)
stw r4, 0(r5)
lwz r0, 8(r1)
addi r1, r1, 12
mtlr r0
blr
/* void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3); */
.global cpu_post_exec_21x
cpu_post_exec_21x:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
stwu r5, -4(r1)
mtlr r3
mr r3, r6
blrl
lwz r5, 4(r1)
stw r3, 0(r5)
lwz r5, 0(r1)
stw r4, 0(r5)
lwz r0, 8(r1)
addi r1, r1, 12
mtlr r0
blr
/* void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump,
ulong cr); */
.global cpu_post_exec_31
cpu_post_exec_31:
mflr r0
stwu r0, -4(r1)
stwu r4, -4(r1)
stwu r5, -4(r1)
stwu r6, -4(r1)
mtlr r3
lwz r3, 0(r4)
lwz r4, 0(r5)
mr r6, r7
blrl
lwz r7, 8(r1)
stw r3, 0(r7)
lwz r7, 4(r1)
stw r4, 0(r7)
lwz r7, 0(r1)
stw r5, 0(r7)
lwz r0, 12(r1)
addi r1, r1, 16
mtlr r0
blr
/* int cpu_post_complex_1_asm (int a1, int a2, int a3, int a4, int n); */
.global cpu_post_complex_1_asm
cpu_post_complex_1_asm:
li r9,0
cmpw r9,r7
bge cpu_post_complex_1_done
mtctr r7
cpu_post_complex_1_loop:
mullw r0,r3,r4
subf r0,r5,r0
divw r0,r0,r6
add r9,r9,r0
bdnz cpu_post_complex_1_loop
cpu_post_complex_1_done:
mr r3,r9
blr
/* int cpu_post_complex_2_asm (int x, int n); */
.global cpu_post_complex_2_asm
cpu_post_complex_2_asm:
mr. r0,r4
mtctr r0
mr r0,r3
li r3,1
li r4,1
blelr
cpu_post_complex_2_loop:
mullw r3,r3,r0
add r3,r3,r4
bdnz cpu_post_complex_2_loop
blr
#endif
#endif

197
post/lib_ppc/b.c Normal file
View File

@ -0,0 +1,197 @@
/*
* (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>
/*
* CPU test
* Branch instructions: b, bl, bc
*
* The first 2 instructions (b, bl) are verified by jumping
* to a fixed address and checking whether control was transfered
* to that very point. For the bl instruction the value of the
* link register is checked as well (using mfspr).
* To verify the bc instruction various combinations of the BI/BO
* fields, the CTR and the condition register values are
* checked. The list of such combinations is pre-built and
* linked in U-Boot at build time.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump,
ulong cr);
static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi,
int pjump, int dec, int link, ulong pctr, ulong cr)
{
int ret = 0;
ulong lr = 0;
ulong ctr = pctr;
ulong jump;
unsigned long code[] =
{
ASM_MTCR(6),
ASM_MFLR(6),
ASM_MTCTR(3),
ASM_MTLR(4),
ASM_LI(5, 1),
ASM_3O(cmd, bo, bi, 8),
ASM_LI(5, 0),
ASM_MFCTR(3),
ASM_MFLR(4),
ASM_MTLR(6),
ASM_BLR,
};
cpu_post_exec_31 (code, &ctr, &lr, &jump, cr);
if (ret == 0)
ret = pjump == jump ? 0 : -1;
if (ret == 0)
{
if (dec)
ret = pctr == ctr + 1 ? 0 : -1;
else
ret = pctr == ctr ? 0 : -1;
}
if (ret == 0)
{
if (link)
ret = lr == (ulong) code + 24 ? 0 : -1;
else
ret = lr == 0 ? 0 : -1;
}
return ret;
}
int cpu_post_test_b (void)
{
int ret = 0;
unsigned int i;
if (ret == 0)
{
ulong code[] =
{
ASM_MFLR(4),
ASM_MTLR(3),
ASM_B(4),
ASM_MFLR(3),
ASM_MTLR(4),
ASM_BLR,
};
ulong res;
cpu_post_exec_11 (code, &res, 0);
ret = res == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at b1 test !\n");
}
}
if (ret == 0)
{
ulong code[] =
{
ASM_MFLR(4),
ASM_MTLR(3),
ASM_BL(4),
ASM_MFLR(3),
ASM_MTLR(4),
ASM_BLR,
};
ulong res;
cpu_post_exec_11 (code, &res, 0);
ret = res == (ulong)code + 12 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at b2 test !\n");
}
}
if (ret == 0)
{
ulong cc, cd;
int cond;
ulong ctr;
int link;
i = 0;
for (cc = 0; cc < 4 && ret == 0; cc++)
{
for (cd = 0; cd < 4 && ret == 0; cd++)
{
for (link = 0; link <= 1 && ret == 0; link++)
{
for (cond = 0; cond <= 1 && ret == 0; cond++)
{
for (ctr = 1; ctr <= 2 && ret == 0; ctr++)
{
int dec = cd < 2;
int cr = cond ? 0x80000000 : 0x00000000;
int jumpc = cc >= 2 ||
(cc == 0 && !cond) ||
(cc == 1 && cond);
int jumpd = cd >= 2 ||
(cd == 0 && ctr != 1) ||
(cd == 1 && ctr == 1);
int jump = jumpc && jumpd;
ret = cpu_post_test_bc (link ? OP_BCL : OP_BC,
(cc << 3) + (cd << 1), 0, jump, dec, link,
ctr, cr);
if (ret != 0)
{
post_log ("Error at b3 test %d !\n", i);
}
i++;
}
}
}
}
}
}
return ret;
}
#endif
#endif

133
post/lib_ppc/cmp.c Normal file
View File

@ -0,0 +1,133 @@
/*
* (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>
/*
* CPU test
* Integer compare instructions: cmpw, cmplw
*
* To verify these instructions the test runs them with
* different combinations of operands, reads the condition
* register value and compares it with the expected one.
* The test contains a pre-built table
* containing the description of each test case: the instruction,
* the values of the operands, the condition field to save
* the result in and the expected result.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2);
static struct cpu_post_cmp_s
{
ulong cmd;
ulong op1;
ulong op2;
ulong cr;
ulong res;
} cpu_post_cmp_table[] =
{
{
OP_CMPW,
123,
123,
2,
0x02
},
{
OP_CMPW,
123,
133,
3,
0x08
},
{
OP_CMPW,
123,
-133,
4,
0x04
},
{
OP_CMPLW,
123,
123,
2,
0x02
},
{
OP_CMPLW,
123,
-133,
3,
0x08
},
{
OP_CMPLW,
123,
113,
4,
0x04
},
};
static unsigned int cpu_post_cmp_size =
sizeof (cpu_post_cmp_table) / sizeof (struct cpu_post_cmp_s);
int cpu_post_test_cmp (void)
{
int ret = 0;
unsigned int i;
for (i = 0; i < cpu_post_cmp_size && ret == 0; i++)
{
struct cpu_post_cmp_s *test = cpu_post_cmp_table + i;
unsigned long code[] =
{
ASM_2C(test->cmd, test->cr, 3, 4),
ASM_MFCR(3),
ASM_BLR
};
ulong res;
cpu_post_exec_12 (code, & res, test->op1, test->op2);
ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1;
if (ret != 0)
{
post_log ("Error at cmp test %d !\n", i);
}
}
return ret;
}
#endif
#endif

133
post/lib_ppc/cmpi.c Normal file
View File

@ -0,0 +1,133 @@
/*
* (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>
/*
* CPU test
* Integer compare instructions: cmpwi, cmplwi
*
* To verify these instructions the test runs them with
* different combinations of operands, reads the condition
* register value and compares it with the expected one.
* The test contains a pre-built table
* containing the description of each test case: the instruction,
* the values of the operands, the condition field to save
* the result in and the expected result.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
static struct cpu_post_cmpi_s
{
ulong cmd;
ulong op1;
ushort op2;
ulong cr;
ulong res;
} cpu_post_cmpi_table[] =
{
{
OP_CMPWI,
123,
123,
2,
0x02
},
{
OP_CMPWI,
123,
133,
3,
0x08
},
{
OP_CMPWI,
123,
-133,
4,
0x04
},
{
OP_CMPLWI,
123,
123,
2,
0x02
},
{
OP_CMPLWI,
123,
-133,
3,
0x08
},
{
OP_CMPLWI,
123,
113,
4,
0x04
},
};
static unsigned int cpu_post_cmpi_size =
sizeof (cpu_post_cmpi_table) / sizeof (struct cpu_post_cmpi_s);
int cpu_post_test_cmpi (void)
{
int ret = 0;
unsigned int i;
for (i = 0; i < cpu_post_cmpi_size && ret == 0; i++)
{
struct cpu_post_cmpi_s *test = cpu_post_cmpi_table + i;
unsigned long code[] =
{
ASM_1IC(test->cmd, test->cr, 3, test->op2),
ASM_MFCR(3),
ASM_BLR
};
ulong res;
cpu_post_exec_11 (code, & res, test->op1);
ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1;
if (ret != 0)
{
post_log ("Error at cmpi test %d !\n", i);
}
}
return ret;
}
#endif
#endif

126
post/lib_ppc/complex.c Normal file
View File

@ -0,0 +1,126 @@
/*
* (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>
/*
* CPU test
* Complex calculations
*
* The calculations in this test are just a combination of simpler
* calculations, but probably under different timing conditions, etc.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern int cpu_post_complex_1_asm (int a1, int a2, int a3, int a4, int n);
extern int cpu_post_complex_2_asm (int x, int n);
/*
* n
* SUM (a1 * a2 - a3) / a4 = n * result
* i=1
*/
static int cpu_post_test_complex_1 (void)
{
int a1 = 666;
int a2 = 667;
int a3 = 668;
int a4 = 66;
int n = 100;
int result = 6720; /* (a1 * a2 - a3) / a4 */
if (cpu_post_complex_1_asm(a1, a2, a3, a4, n) != n * result)
{
return -1;
}
return 0;
}
/* (1 + x + x^2 + ... + x^n) * (1 - x) = 1 - x^(n+1)
*/
static int cpu_post_test_complex_2 (void)
{
int ret = -1;
int x;
int n;
int k;
int left;
int right;
for (x = -8; x <= 8; x ++)
{
n = 9;
left = cpu_post_complex_2_asm(x, n);
left *= 1 - x;
right = 1;
for (k = 0; k <= n; k ++)
{
right *= x;
}
right = 1 - right;
if (left != right)
{
goto Done;
}
}
ret = 0;
Done:
return ret;
}
int cpu_post_test_complex (void)
{
int ret = 0;
if (ret == 0)
{
ret = cpu_post_test_complex_1();
}
if (ret == 0)
{
ret = cpu_post_test_complex_2();
}
if (ret != 0)
{
post_log ("Error at complex test !\n");
}
return ret;
}
#endif
#endif

139
post/lib_ppc/cpu.c Normal file
View File

@ -0,0 +1,139 @@
/*
* (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>
/*
* CPU test
*
* This test checks the arithmetic logic unit (ALU) of CPU.
* It tests independently various groups of instructions using
* run-time modification of the code to reduce the memory footprint.
* For more details refer to post/cpu/ *.c files.
*/
#ifdef CONFIG_POST
#include <watchdog.h>
#include <post.h>
#if CONFIG_POST & CFG_POST_CPU
extern int cpu_post_test_cmp (void);
extern int cpu_post_test_cmpi (void);
extern int cpu_post_test_two (void);
extern int cpu_post_test_twox (void);
extern int cpu_post_test_three (void);
extern int cpu_post_test_threex (void);
extern int cpu_post_test_threei (void);
extern int cpu_post_test_andi (void);
extern int cpu_post_test_srawi (void);
extern int cpu_post_test_rlwnm (void);
extern int cpu_post_test_rlwinm (void);
extern int cpu_post_test_rlwimi (void);
extern int cpu_post_test_store (void);
extern int cpu_post_test_load (void);
extern int cpu_post_test_cr (void);
extern int cpu_post_test_b (void);
extern int cpu_post_test_multi (void);
extern int cpu_post_test_string (void);
extern int cpu_post_test_complex (void);
ulong cpu_post_makecr (long v)
{
ulong cr = 0;
if (v < 0)
cr |= 0x80000000;
if (v > 0)
cr |= 0x40000000;
if (v == 0)
cr |= 0x20000000;
return cr;
}
int cpu_post_test (int flags)
{
int ic = icache_status ();
int ret = 0;
WATCHDOG_RESET();
if (ic)
icache_disable ();
if (ret == 0)
ret = cpu_post_test_cmp ();
if (ret == 0)
ret = cpu_post_test_cmpi ();
if (ret == 0)
ret = cpu_post_test_two ();
if (ret == 0)
ret = cpu_post_test_twox ();
WATCHDOG_RESET();
if (ret == 0)
ret = cpu_post_test_three ();
if (ret == 0)
ret = cpu_post_test_threex ();
if (ret == 0)
ret = cpu_post_test_threei ();
if (ret == 0)
ret = cpu_post_test_andi ();
WATCHDOG_RESET();
if (ret == 0)
ret = cpu_post_test_srawi ();
if (ret == 0)
ret = cpu_post_test_rlwnm ();
if (ret == 0)
ret = cpu_post_test_rlwinm ();
if (ret == 0)
ret = cpu_post_test_rlwimi ();
WATCHDOG_RESET();
if (ret == 0)
ret = cpu_post_test_store ();
if (ret == 0)
ret = cpu_post_test_load ();
if (ret == 0)
ret = cpu_post_test_cr ();
if (ret == 0)
ret = cpu_post_test_b ();
WATCHDOG_RESET();
if (ret == 0)
ret = cpu_post_test_multi ();
WATCHDOG_RESET();
if (ret == 0)
ret = cpu_post_test_string ();
if (ret == 0)
ret = cpu_post_test_complex ();
WATCHDOG_RESET();
if (ic)
icache_enable ();
WATCHDOG_RESET();
return ret;
}
#endif /* CONFIG_POST & CFG_POST_CPU */
#endif /* CONFIG_POST */

224
post/lib_ppc/cpu_asm.h Normal file
View File

@ -0,0 +1,224 @@
/*
* (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
*/
#ifndef _CPU_ASM_H
#define _CPU_ASM_H
#define BIT_C 0x00000001
#define OP_BLR 0x4e800020
#define OP_EXTSB 0x7c000774
#define OP_EXTSH 0x7c000734
#define OP_NEG 0x7c0000d0
#define OP_CNTLZW 0x7c000034
#define OP_ADD 0x7c000214
#define OP_ADDC 0x7c000014
#define OP_ADDME 0x7c0001d4
#define OP_ADDZE 0x7c000194
#define OP_ADDE 0x7c000114
#define OP_ADDI 0x38000000
#define OP_SUBF 0x7c000050
#define OP_SUBFC 0x7c000010
#define OP_SUBFE 0x7c000110
#define OP_SUBFME 0x7c0001d0
#define OP_SUBFZE 0x7c000190
#define OP_MFCR 0x7c000026
#define OP_MTCR 0x7c0ff120
#define OP_MFXER 0x7c0102a6
#define OP_MTXER 0x7c0103a6
#define OP_MCRXR 0x7c000400
#define OP_MCRF 0x4c000000
#define OP_CRAND 0x4c000202
#define OP_CRANDC 0x4c000102
#define OP_CROR 0x4c000382
#define OP_CRORC 0x4c000342
#define OP_CRXOR 0x4c000182
#define OP_CRNAND 0x4c0001c2
#define OP_CRNOR 0x4c000042
#define OP_CREQV 0x4c000242
#define OP_CMPW 0x7c000000
#define OP_CMPLW 0x7c000040
#define OP_CMPWI 0x2c000000
#define OP_CMPLWI 0x28000000
#define OP_MULLW 0x7c0001d6
#define OP_MULHW 0x7c000096
#define OP_MULHWU 0x7c000016
#define OP_DIVW 0x7c0003d6
#define OP_DIVWU 0x7c000396
#define OP_OR 0x7c000378
#define OP_ORC 0x7c000338
#define OP_XOR 0x7c000278
#define OP_NAND 0x7c0003b8
#define OP_NOR 0x7c0000f8
#define OP_EQV 0x7c000238
#define OP_SLW 0x7c000030
#define OP_SRW 0x7c000430
#define OP_SRAW 0x7c000630
#define OP_ORI 0x60000000
#define OP_ORIS 0x64000000
#define OP_XORI 0x68000000
#define OP_XORIS 0x6c000000
#define OP_ANDI_ 0x70000000
#define OP_ANDIS_ 0x74000000
#define OP_SRAWI 0x7c000670
#define OP_RLWINM 0x54000000
#define OP_RLWNM 0x5c000000
#define OP_RLWIMI 0x50000000
#define OP_LWZ 0x80000000
#define OP_LHZ 0xa0000000
#define OP_LHA 0xa8000000
#define OP_LBZ 0x88000000
#define OP_LWZU 0x84000000
#define OP_LHZU 0xa4000000
#define OP_LHAU 0xac000000
#define OP_LBZU 0x8c000000
#define OP_LWZX 0x7c00002e
#define OP_LHZX 0x7c00022e
#define OP_LHAX 0x7c0002ae
#define OP_LBZX 0x7c0000ae
#define OP_LWZUX 0x7c00006e
#define OP_LHZUX 0x7c00026e
#define OP_LHAUX 0x7c0002ee
#define OP_LBZUX 0x7c0000ee
#define OP_STW 0x90000000
#define OP_STH 0xb0000000
#define OP_STB 0x98000000
#define OP_STWU 0x94000000
#define OP_STHU 0xb4000000
#define OP_STBU 0x9c000000
#define OP_STWX 0x7c00012e
#define OP_STHX 0x7c00032e
#define OP_STBX 0x7c0001ae
#define OP_STWUX 0x7c00016e
#define OP_STHUX 0x7c00036e
#define OP_STBUX 0x7c0001ee
#define OP_B 0x48000000
#define OP_BL 0x48000001
#define OP_BC 0x40000000
#define OP_BCL 0x40000001
#define OP_MTLR 0x7c0803a6
#define OP_MFLR 0x7c0802a6
#define OP_MTCTR 0x7c0903a6
#define OP_MFCTR 0x7c0902a6
#define OP_LMW 0xb8000000
#define OP_STMW 0xbc000000
#define OP_LSWI 0x7c0004aa
#define OP_LSWX 0x7c00042a
#define OP_STSWI 0x7c0005aa
#define OP_STSWX 0x7c00052a
#define ASM_0(opcode) (opcode)
#define ASM_1(opcode, rd) ((opcode) + \
((rd) << 21))
#define ASM_1C(opcode, cr) ((opcode) + \
((cr) << 23))
#define ASM_11(opcode, rd, rs) ((opcode) + \
((rd) << 21) + \
((rs) << 16))
#define ASM_11C(opcode, cd, cs) ((opcode) + \
((cd) << 23) + \
((cs) << 18))
#define ASM_11X(opcode, rd, rs) ((opcode) + \
((rs) << 21) + \
((rd) << 16))
#define ASM_11I(opcode, rd, rs, simm) ((opcode) + \
((rd) << 21) + \
((rs) << 16) + \
((simm) & 0xffff))
#define ASM_11IF(opcode, rd, rs, simm) ((opcode) + \
((rd) << 21) + \
((rs) << 16) + \
((simm) << 11))
#define ASM_11S(opcode, rd, rs, sh) ((opcode) + \
((rs) << 21) + \
((rd) << 16) + \
((sh) << 11))
#define ASM_11IX(opcode, rd, rs, imm) ((opcode) + \
((rs) << 21) + \
((rd) << 16) + \
((imm) & 0xffff))
#define ASM_12(opcode, rd, rs1, rs2) ((opcode) + \
((rd) << 21) + \
((rs1) << 16) + \
((rs2) << 11))
#define ASM_12F(opcode, fd, fs1, fs2) ((opcode) + \
((fd) << 21) + \
((fs1) << 16) + \
((fs2) << 11))
#define ASM_12X(opcode, rd, rs1, rs2) ((opcode) + \
((rs1) << 21) + \
((rd) << 16) + \
((rs2) << 11))
#define ASM_2C(opcode, cr, rs1, rs2) ((opcode) + \
((cr) << 23) + \
((rs1) << 16) + \
((rs2) << 11))
#define ASM_1IC(opcode, cr, rs, imm) ((opcode) + \
((cr) << 23) + \
((rs) << 16) + \
((imm) & 0xffff))
#define ASM_122(opcode, rd, rs1, rs2, imm1, imm2) \
((opcode) + \
((rs1) << 21) + \
((rd) << 16) + \
((rs2) << 11) + \
((imm1) << 6) + \
((imm2) << 1))
#define ASM_113(opcode, rd, rs, imm1, imm2, imm3) \
((opcode) + \
((rs) << 21) + \
((rd) << 16) + \
((imm1) << 11) + \
((imm2) << 6) + \
((imm3) << 1))
#define ASM_1O(opcode, off) ((opcode) + (off))
#define ASM_3O(opcode, bo, bi, off) ((opcode) + \
((bo) << 21) + \
((bi) << 16) + \
(off))
#define ASM_ADDI(rd, rs, simm) ASM_11I(OP_ADDI, rd, rs, simm)
#define ASM_BLR ASM_0(OP_BLR)
#define ASM_STW(rd, rs, simm) ASM_11I(OP_STW, rd, rs, simm)
#define ASM_LWZ(rd, rs, simm) ASM_11I(OP_LWZ, rd, rs, simm)
#define ASM_MFCR(rd) ASM_1(OP_MFCR, rd)
#define ASM_MTCR(rd) ASM_1(OP_MTCR, rd)
#define ASM_MFXER(rd) ASM_1(OP_MFXER, rd)
#define ASM_MTXER(rd) ASM_1(OP_MTXER, rd)
#define ASM_MFCTR(rd) ASM_1(OP_MFCTR, rd)
#define ASM_MTCTR(rd) ASM_1(OP_MTCTR, rd)
#define ASM_MCRXR(cr) ASM_1C(OP_MCRXR, cr)
#define ASM_MCRF(cd, cs) ASM_11C(OP_MCRF, cd, cs)
#define ASM_B(off) ASM_1O(OP_B, off)
#define ASM_BL(off) ASM_1O(OP_BL, off)
#define ASM_MFLR(rd) ASM_1(OP_MFLR, rd)
#define ASM_MTLR(rd) ASM_1(OP_MTLR, rd)
#define ASM_LI(rd, imm) ASM_ADDI(rd, 0, imm)
#define ASM_LMW(rd, rs, simm) ASM_11I(OP_LMW, rd, rs, simm)
#define ASM_STMW(rd, rs, simm) ASM_11I(OP_STMW, rd, rs, simm)
#define ASM_LSWI(rd, rs, simm) ASM_11IF(OP_LSWI, rd, rs, simm)
#define ASM_LSWX(rd, rs1, rs2) ASM_12(OP_LSWX, rd, rs1, rs2)
#define ASM_STSWI(rd, rs, simm) ASM_11IF(OP_STSWI, rd, rs, simm)
#define ASM_STSWX(rd, rs1, rs2) ASM_12(OP_STSWX, rd, rs1, rs2)
#endif /* _CPU_ASM_H */

356
post/lib_ppc/cr.c Normal file
View File

@ -0,0 +1,356 @@
/*
* (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>
/*
* CPU test
* Condition register istructions: mtcr, mfcr, mcrxr,
* crand, crandc, cror, crorc, crxor,
* crnand, crnor, creqv, mcrf
*
* The mtcrf/mfcr instructions is tested by loading different
* values into the condition register (mtcrf), moving its value
* to a general-purpose register (mfcr) and comparing this value
* with the expected one.
* The mcrxr instruction is tested by loading a fixed value
* into the XER register (mtspr), moving XER value to the
* condition register (mcrxr), moving it to a general-purpose
* register (mfcr) and comparing the value of this register with
* the expected one.
* The rest of instructions is tested by loading a fixed
* value into the condition register (mtcrf), executing each
* instruction several times to modify all 4-bit condition
* fields, moving the value of the conditional register to a
* general-purpose register (mfcr) and comparing it with the
* expected one.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
extern void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3);
static ulong cpu_post_cr_table1[] =
{
0xaaaaaaaa,
0x55555555,
};
static unsigned int cpu_post_cr_size1 =
sizeof (cpu_post_cr_table1) / sizeof (ulong);
static struct cpu_post_cr_s2 {
ulong xer;
ulong cr;
} cpu_post_cr_table2[] =
{
{
0xa0000000,
1
},
{
0x40000000,
5
},
};
static unsigned int cpu_post_cr_size2 =
sizeof (cpu_post_cr_table2) / sizeof (struct cpu_post_cr_s2);
static struct cpu_post_cr_s3 {
ulong cr;
ulong cs;
ulong cd;
ulong res;
} cpu_post_cr_table3[] =
{
{
0x01234567,
0,
4,
0x01230567
},
{
0x01234567,
7,
0,
0x71234567
},
};
static unsigned int cpu_post_cr_size3 =
sizeof (cpu_post_cr_table3) / sizeof (struct cpu_post_cr_s3);
static struct cpu_post_cr_s4 {
ulong cmd;
ulong cr;
ulong op1;
ulong op2;
ulong op3;
ulong res;
} cpu_post_cr_table4[] =
{
{
OP_CRAND,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
{
OP_CRAND,
0x0000ffff,
16,
17,
0,
0x8000ffff
},
{
OP_CRANDC,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
{
OP_CRANDC,
0x0000ffff,
16,
0,
0,
0x8000ffff
},
{
OP_CROR,
0x0000ffff,
0,
16,
0,
0x8000ffff
},
{
OP_CROR,
0x0000ffff,
0,
1,
0,
0x0000ffff
},
{
OP_CRORC,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
{
OP_CRORC,
0x0000ffff,
0,
0,
0,
0x8000ffff
},
{
OP_CRXOR,
0x0000ffff,
0,
0,
0,
0x0000ffff
},
{
OP_CRXOR,
0x0000ffff,
0,
16,
0,
0x8000ffff
},
{
OP_CRNAND,
0x0000ffff,
0,
16,
0,
0x8000ffff
},
{
OP_CRNAND,
0x0000ffff,
16,
17,
0,
0x0000ffff
},
{
OP_CRNOR,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
{
OP_CRNOR,
0x0000ffff,
0,
1,
0,
0x8000ffff
},
{
OP_CREQV,
0x0000ffff,
0,
0,
0,
0x8000ffff
},
{
OP_CREQV,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
};
static unsigned int cpu_post_cr_size4 =
sizeof (cpu_post_cr_table4) / sizeof (struct cpu_post_cr_s4);
int cpu_post_test_cr (void)
{
int ret = 0;
unsigned int i;
unsigned long cr_sav;
asm ( "mfcr %0" : "=r" (cr_sav) : );
for (i = 0; i < cpu_post_cr_size1 && ret == 0; i++)
{
ulong cr = cpu_post_cr_table1[i];
ulong res;
unsigned long code[] =
{
ASM_MTCR(3),
ASM_MFCR(3),
ASM_BLR,
};
cpu_post_exec_11 (code, &res, cr);
ret = res == cr ? 0 : -1;
if (ret != 0)
{
post_log ("Error at cr1 test %d !\n", i);
}
}
for (i = 0; i < cpu_post_cr_size2 && ret == 0; i++)
{
struct cpu_post_cr_s2 *test = cpu_post_cr_table2 + i;
ulong res;
ulong xer;
unsigned long code[] =
{
ASM_MTXER(3),
ASM_MCRXR(test->cr),
ASM_MFCR(3),
ASM_MFXER(4),
ASM_BLR,
};
cpu_post_exec_21x (code, &res, &xer, test->xer);
ret = xer == 0 && ((res << (4 * test->cr)) & 0xe0000000) == test->xer ?
0 : -1;
if (ret != 0)
{
post_log ("Error at cr2 test %d !\n", i);
}
}
for (i = 0; i < cpu_post_cr_size3 && ret == 0; i++)
{
struct cpu_post_cr_s3 *test = cpu_post_cr_table3 + i;
ulong res;
unsigned long code[] =
{
ASM_MTCR(3),
ASM_MCRF(test->cd, test->cs),
ASM_MFCR(3),
ASM_BLR,
};
cpu_post_exec_11 (code, &res, test->cr);
ret = res == test->res ? 0 : -1;
if (ret != 0)
{
post_log ("Error at cr3 test %d !\n", i);
}
}
for (i = 0; i < cpu_post_cr_size4 && ret == 0; i++)
{
struct cpu_post_cr_s4 *test = cpu_post_cr_table4 + i;
ulong res;
unsigned long code[] =
{
ASM_MTCR(3),
ASM_12F(test->cmd, test->op3, test->op1, test->op2),
ASM_MFCR(3),
ASM_BLR,
};
cpu_post_exec_11 (code, &res, test->cr);
ret = res == test->res ? 0 : -1;
if (ret != 0)
{
post_log ("Error at cr4 test %d !\n", i);
}
}
asm ( "mtcr %0" : : "r" (cr_sav));
return ret;
}
#endif
#endif

255
post/lib_ppc/load.c Normal file
View File

@ -0,0 +1,255 @@
/*
* (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>
/*
* CPU test
* Load instructions: lbz(x)(u), lhz(x)(u), lha(x)(u), lwz(x)(u)
*
* All operations are performed on a 16-byte array. The array
* is 4-byte aligned. The base register points to offset 8.
* The immediate offset (index register) ranges in [-8 ... +7].
* The test cases are composed so that they do not
* cause alignment exceptions.
* The test contains a pre-built table describing all test cases.
* The table entry contains:
* the instruction opcode, the array contents, the value of the index
* register and the expected value of the destination register.
* After executing the instruction, the test verifies the
* value of the destination register and the value of the base
* register (it must change for "load with update" instructions).
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3);
extern void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2);
static struct cpu_post_load_s
{
ulong cmd;
uint width;
int update;
int index;
ulong offset;
} cpu_post_load_table[] =
{
{
OP_LWZ,
4,
0,
0,
4
},
{
OP_LHA,
3,
0,
0,
2
},
{
OP_LHZ,
2,
0,
0,
2
},
{
OP_LBZ,
1,
0,
0,
1
},
{
OP_LWZU,
4,
1,
0,
4
},
{
OP_LHAU,
3,
1,
0,
2
},
{
OP_LHZU,
2,
1,
0,
2
},
{
OP_LBZU,
1,
1,
0,
1
},
{
OP_LWZX,
4,
0,
1,
4
},
{
OP_LHAX,
3,
0,
1,
2
},
{
OP_LHZX,
2,
0,
1,
2
},
{
OP_LBZX,
1,
0,
1,
1
},
{
OP_LWZUX,
4,
1,
1,
4
},
{
OP_LHAUX,
3,
1,
1,
2
},
{
OP_LHZUX,
2,
1,
1,
2
},
{
OP_LBZUX,
1,
1,
1,
1
},
};
static unsigned int cpu_post_load_size =
sizeof (cpu_post_load_table) / sizeof (struct cpu_post_load_s);
int cpu_post_test_load (void)
{
int ret = 0;
unsigned int i;
for (i = 0; i < cpu_post_load_size && ret == 0; i++)
{
struct cpu_post_load_s *test = cpu_post_load_table + i;
uchar data[16] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
ulong base0 = (ulong) (data + 8);
ulong base = base0;
ulong value;
if (test->index)
{
ulong code[] =
{
ASM_12(test->cmd, 5, 3, 4),
ASM_BLR,
};
cpu_post_exec_22w (code, &base, test->offset, &value);
}
else
{
ulong code[] =
{
ASM_11I(test->cmd, 4, 3, test->offset),
ASM_BLR,
};
cpu_post_exec_21w (code, &base, &value);
}
if (ret == 0)
{
if (test->update)
ret = base == base0 + test->offset ? 0 : -1;
else
ret = base == base0 ? 0 : -1;
}
if (ret == 0)
{
switch (test->width)
{
case 1:
ret = *(uchar *)(base0 + test->offset) == value ?
0 : -1;
break;
case 2:
ret = *(ushort *)(base0 + test->offset) == value ?
0 : -1;
break;
case 3:
ret = *(short *)(base0 + test->offset) == value ?
0 : -1;
break;
case 4:
ret = *(ulong *)(base0 + test->offset) == value ?
0 : -1;
break;
}
}
if (ret != 0)
{
post_log ("Error at load test %d !\n", i);
}
}
return ret;
}
#endif
#endif

81
post/lib_ppc/multi.c Normal file
View File

@ -0,0 +1,81 @@
/*
* (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>
/*
* CPU test
* Load/store multiple word instructions: lmw, stmw
*
* 26 consecutive words are loaded from a source memory buffer
* into GPRs r6 through r31. After that, 26 consecutive words are stored
* from the GPRs r6 through r31 into a target memory buffer. The contents
* of the source and target buffers are then compared.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2);
int cpu_post_test_multi (void)
{
int ret = 0;
unsigned int i;
if (ret == 0)
{
ulong src [26], dst [26];
ulong code[] =
{
ASM_LMW(5, 3, 0),
ASM_STMW(5, 4, 0),
ASM_BLR,
};
for (i = 0; i < sizeof(src) / sizeof(src[0]); i ++)
{
src[i] = i;
dst[i] = 0;
}
cpu_post_exec_02(code, (ulong)src, (ulong)dst);
ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1;
}
if (ret != 0)
{
post_log ("Error at multi test !\n");
}
return ret;
}
#endif
#endif

162
post/lib_ppc/rlwimi.c Normal file
View File

@ -0,0 +1,162 @@
/*
* (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>
/*
* CPU test
* Shift instructions: rlwimi
*
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
ulong op2);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_rlwimi_s
{
ulong cmd;
ulong op0;
ulong op1;
uchar op2;
uchar mb;
uchar me;
ulong res;
} cpu_post_rlwimi_table[] =
{
{
OP_RLWIMI,
0xff00ffff,
0x0000aa00,
8,
8,
15,
0xffaaffff
},
};
static unsigned int cpu_post_rlwimi_size =
sizeof (cpu_post_rlwimi_table) / sizeof (struct cpu_post_rlwimi_s);
int cpu_post_test_rlwimi (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_rlwimi_size && ret == 0; i++)
{
struct cpu_post_rlwimi_s *test = cpu_post_rlwimi_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long code[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -20),
ASM_STW(3, stk, 8),
ASM_STW(4, stk, 12),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg1, stk, 8),
ASM_LWZ(reg0, stk, 12),
ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, test->me),
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 20),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
unsigned long codecr[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -20),
ASM_STW(3, stk, 8),
ASM_STW(4, stk, 12),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg1, stk, 8),
ASM_LWZ(reg0, stk, 12),
ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, test->me) |
BIT_C,
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 20),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
if (ret == 0)
{
cr = 0;
cpu_post_exec_22 (code, & cr, & res, test->op0, test->op1);
ret = res == test->res && cr == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at rlwimi test %d !\n", i);
}
}
if (ret == 0)
{
cpu_post_exec_22 (codecr, & cr, & res, test->op0, test->op1);
ret = res == test->res &&
(cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
if (ret != 0)
{
post_log ("Error at rlwimi test %d !\n", i);
}
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

155
post/lib_ppc/rlwinm.c Normal file
View File

@ -0,0 +1,155 @@
/*
* (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>
/*
* CPU test
* Shift instructions: rlwinm
*
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_rlwinm_s
{
ulong cmd;
ulong op1;
uchar op2;
uchar mb;
uchar me;
ulong res;
} cpu_post_rlwinm_table[] =
{
{
OP_RLWINM,
0xffff0000,
24,
16,
23,
0x0000ff00
},
};
static unsigned int cpu_post_rlwinm_size =
sizeof (cpu_post_rlwinm_table) / sizeof (struct cpu_post_rlwinm_s);
int cpu_post_test_rlwinm (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_rlwinm_size && ret == 0; i++)
{
struct cpu_post_rlwinm_s *test = cpu_post_rlwinm_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long code[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, test->me),
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
unsigned long codecr[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_113(test->cmd, reg1, reg0, test->op2, test->mb,
test->me) | BIT_C,
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
if (ret == 0)
{
cr = 0;
cpu_post_exec_21 (code, & cr, & res, test->op1);
ret = res == test->res && cr == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at rlwinm test %d !\n", i);
}
}
if (ret == 0)
{
cpu_post_exec_21 (codecr, & cr, & res, test->op1);
ret = res == test->res &&
(cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
if (ret != 0)
{
post_log ("Error at rlwinm test %d !\n", i);
}
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

165
post/lib_ppc/rlwnm.c Normal file
View File

@ -0,0 +1,165 @@
/*
* (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>
/*
* CPU test
* Shift instructions: rlwnm
*
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
ulong op2);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_rlwnm_s
{
ulong cmd;
ulong op1;
ulong op2;
uchar mb;
uchar me;
ulong res;
} cpu_post_rlwnm_table[] =
{
{
OP_RLWNM,
0xffff0000,
24,
16,
23,
0x0000ff00
},
};
static unsigned int cpu_post_rlwnm_size =
sizeof (cpu_post_rlwnm_table) / sizeof (struct cpu_post_rlwnm_s);
int cpu_post_test_rlwnm (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_rlwnm_size && ret == 0; i++)
{
struct cpu_post_rlwnm_s *test = cpu_post_rlwnm_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int reg2 = (reg + 2) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long code[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -24),
ASM_STW(3, stk, 12),
ASM_STW(4, stk, 16),
ASM_STW(reg0, stk, 8),
ASM_STW(reg1, stk, 4),
ASM_STW(reg2, stk, 0),
ASM_LWZ(reg1, stk, 12),
ASM_LWZ(reg0, stk, 16),
ASM_122(test->cmd, reg2, reg1, reg0, test->mb, test->me),
ASM_STW(reg2, stk, 12),
ASM_LWZ(reg2, stk, 0),
ASM_LWZ(reg1, stk, 4),
ASM_LWZ(reg0, stk, 8),
ASM_LWZ(3, stk, 12),
ASM_ADDI(1, stk, 24),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
unsigned long codecr[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -24),
ASM_STW(3, stk, 12),
ASM_STW(4, stk, 16),
ASM_STW(reg0, stk, 8),
ASM_STW(reg1, stk, 4),
ASM_STW(reg2, stk, 0),
ASM_LWZ(reg1, stk, 12),
ASM_LWZ(reg0, stk, 16),
ASM_122(test->cmd, reg2, reg1, reg0, test->mb, test->me) |
BIT_C,
ASM_STW(reg2, stk, 12),
ASM_LWZ(reg2, stk, 0),
ASM_LWZ(reg1, stk, 4),
ASM_LWZ(reg0, stk, 8),
ASM_LWZ(3, stk, 12),
ASM_ADDI(1, stk, 24),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
if (ret == 0)
{
cr = 0;
cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
ret = res == test->res && cr == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at rlwnm test %d !\n", i);
}
}
if (ret == 0)
{
cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
ret = res == test->res &&
(cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
if (ret != 0)
{
post_log ("Error at rlwnm test %d !\n", i);
}
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

156
post/lib_ppc/srawi.c Normal file
View File

@ -0,0 +1,156 @@
/*
* (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>
/*
* CPU test
* Shift instructions: srawi
*
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_srawi_s
{
ulong cmd;
ulong op1;
uchar op2;
ulong res;
} cpu_post_srawi_table[] =
{
{
OP_SRAWI,
0x8000,
3,
0x1000
},
{
OP_SRAWI,
0x80000000,
3,
0xf0000000
},
};
static unsigned int cpu_post_srawi_size =
sizeof (cpu_post_srawi_table) / sizeof (struct cpu_post_srawi_s);
int cpu_post_test_srawi (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_srawi_size && ret == 0; i++)
{
struct cpu_post_srawi_s *test = cpu_post_srawi_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long code[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_11S(test->cmd, reg1, reg0, test->op2),
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
unsigned long codecr[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_11S(test->cmd, reg1, reg0, test->op2) | BIT_C,
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
if (ret == 0)
{
cr = 0;
cpu_post_exec_21 (code, & cr, & res, test->op1);
ret = res == test->res && cr == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at srawi test %d !\n", i);
}
}
if (ret == 0)
{
cpu_post_exec_21 (codecr, & cr, & res, test->op1);
ret = res == test->res &&
(cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
if (ret != 0)
{
post_log ("Error at srawi test %d !\n", i);
}
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

235
post/lib_ppc/store.c Normal file
View File

@ -0,0 +1,235 @@
/*
* (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>
/*
* CPU test
* Store instructions: stb(x)(u), sth(x)(u), stw(x)(u)
*
* All operations are performed on a 16-byte array. The array
* is 4-byte aligned. The base register points to offset 8.
* The immediate offset (index register) ranges in [-8 ... +7].
* The test cases are composed so that they do not
* cause alignment exceptions.
* The test contains a pre-built table describing all test cases.
* The table entry contains:
* the instruction opcode, the value of the index register and
* the value of the source register. After executing the
* instruction, the test verifies the contents of the array
* and the value of the base register (it must change for "store
* with update" instructions).
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3);
extern void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2);
static struct cpu_post_store_s
{
ulong cmd;
uint width;
int update;
int index;
ulong offset;
ulong value;
} cpu_post_store_table[] =
{
{
OP_STW,
4,
0,
0,
-4,
0xff00ff00
},
{
OP_STH,
2,
0,
0,
-2,
0xff00
},
{
OP_STB,
1,
0,
0,
-1,
0xff
},
{
OP_STWU,
4,
1,
0,
-4,
0xff00ff00
},
{
OP_STHU,
2,
1,
0,
-2,
0xff00
},
{
OP_STBU,
1,
1,
0,
-1,
0xff
},
{
OP_STWX,
4,
0,
1,
-4,
0xff00ff00
},
{
OP_STHX,
2,
0,
1,
-2,
0xff00
},
{
OP_STBX,
1,
0,
1,
-1,
0xff
},
{
OP_STWUX,
4,
1,
1,
-4,
0xff00ff00
},
{
OP_STHUX,
2,
1,
1,
-2,
0xff00
},
{
OP_STBUX,
1,
1,
1,
-1,
0xff
},
};
static unsigned int cpu_post_store_size =
sizeof (cpu_post_store_table) / sizeof (struct cpu_post_store_s);
int cpu_post_test_store (void)
{
int ret = 0;
unsigned int i;
for (i = 0; i < cpu_post_store_size && ret == 0; i++)
{
struct cpu_post_store_s *test = cpu_post_store_table + i;
uchar data[16] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
ulong base0 = (ulong) (data + 8);
ulong base = base0;
if (test->index)
{
ulong code[] =
{
ASM_12(test->cmd, 5, 3, 4),
ASM_BLR,
};
cpu_post_exec_12w (code, &base, test->offset, test->value);
}
else
{
ulong code[] =
{
ASM_11I(test->cmd, 4, 3, test->offset),
ASM_BLR,
};
cpu_post_exec_11w (code, &base, test->value);
}
if (ret == 0)
{
if (test->update)
ret = base == base0 + test->offset ? 0 : -1;
else
ret = base == base0 ? 0 : -1;
}
if (ret == 0)
{
switch (test->width)
{
case 1:
ret = *(uchar *)(base0 + test->offset) == test->value ?
0 : -1;
break;
case 2:
ret = *(ushort *)(base0 + test->offset) == test->value ?
0 : -1;
break;
case 4:
ret = *(ulong *)(base0 + test->offset) == test->value ?
0 : -1;
break;
}
}
if (ret != 0)
{
post_log ("Error at store test %d !\n", i);
}
}
return ret;
}
#endif
#endif

106
post/lib_ppc/string.c Normal file
View File

@ -0,0 +1,106 @@
/*
* (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>
/*
* CPU test
* Load/store string instructions: lswi, stswi, lswx, stswx
*
* Several consecutive bytes from a source memory buffer are loaded
* left to right into GPRs. After that, the bytes are stored
* from the GPRs into a target memory buffer. The contents
* of the source and target buffers are then compared.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2);
extern void cpu_post_exec_04 (ulong *code, ulong op1, ulong op2, ulong op3,
ulong op4);
#include <bedbug/regs.h>
int cpu_post_test_string (void)
{
int ret = 0;
unsigned int i;
if (ret == 0)
{
char src [31], dst [31];
ulong code[] =
{
ASM_LSWI(5, 3, 31),
ASM_STSWI(5, 4, 31),
ASM_BLR,
};
for (i = 0; i < sizeof(src); i ++)
{
src[i] = (char) i;
dst[i] = 0;
}
cpu_post_exec_02(code, (ulong)src, (ulong)dst);
ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1;
}
if (ret == 0)
{
char src [95], dst [95];
ulong code[] =
{
ASM_LSWX(8, 3, 5),
ASM_STSWX(8, 4, 5),
ASM_BLR,
};
for (i = 0; i < sizeof(src); i ++)
{
src[i] = (char) i;
dst[i] = 0;
}
cpu_post_exec_04(code, (ulong)src, (ulong)dst, 0, sizeof(src));
ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1;
}
if (ret != 0)
{
post_log ("Error at string test !\n");
}
return ret;
}
#endif
#endif

259
post/lib_ppc/three.c Normal file
View File

@ -0,0 +1,259 @@
/*
* (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>
/*
* CPU test
* Ternary instructions instr rD,rA,rB
*
* Arithmetic instructions: add, addc, adde, subf, subfc, subfe,
* mullw, mulhw, mulhwu, divw, divwu
*
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
ulong op2);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_three_s
{
ulong cmd;
ulong op1;
ulong op2;
ulong res;
} cpu_post_three_table[] =
{
{
OP_ADD,
100,
200,
300
},
{
OP_ADD,
100,
-200,
-100
},
{
OP_ADDC,
100,
200,
300
},
{
OP_ADDC,
100,
-200,
-100
},
{
OP_ADDE,
100,
200,
300
},
{
OP_ADDE,
100,
-200,
-100
},
{
OP_SUBF,
100,
200,
100
},
{
OP_SUBF,
300,
200,
-100
},
{
OP_SUBFC,
100,
200,
100
},
{
OP_SUBFC,
300,
200,
-100
},
{
OP_SUBFE,
100,
200,
200 + ~100
},
{
OP_SUBFE,
300,
200,
200 + ~300
},
{
OP_MULLW,
200,
300,
200 * 300
},
{
OP_MULHW,
0x10000000,
0x10000000,
0x1000000
},
{
OP_MULHWU,
0x80000000,
0x80000000,
0x40000000
},
{
OP_DIVW,
-20,
5,
-4
},
{
OP_DIVWU,
0x8000,
0x200,
0x40
},
};
static unsigned int cpu_post_three_size =
sizeof (cpu_post_three_table) / sizeof (struct cpu_post_three_s);
int cpu_post_test_three (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_three_size && ret == 0; i++)
{
struct cpu_post_three_s *test = cpu_post_three_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int reg2 = (reg + 2) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long code[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -24),
ASM_STW(3, stk, 12),
ASM_STW(4, stk, 16),
ASM_STW(reg0, stk, 8),
ASM_STW(reg1, stk, 4),
ASM_STW(reg2, stk, 0),
ASM_LWZ(reg1, stk, 12),
ASM_LWZ(reg0, stk, 16),
ASM_12(test->cmd, reg2, reg1, reg0),
ASM_STW(reg2, stk, 12),
ASM_LWZ(reg2, stk, 0),
ASM_LWZ(reg1, stk, 4),
ASM_LWZ(reg0, stk, 8),
ASM_LWZ(3, stk, 12),
ASM_ADDI(1, stk, 24),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
unsigned long codecr[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -24),
ASM_STW(3, stk, 12),
ASM_STW(4, stk, 16),
ASM_STW(reg0, stk, 8),
ASM_STW(reg1, stk, 4),
ASM_STW(reg2, stk, 0),
ASM_LWZ(reg1, stk, 12),
ASM_LWZ(reg0, stk, 16),
ASM_12(test->cmd, reg2, reg1, reg0) | BIT_C,
ASM_STW(reg2, stk, 12),
ASM_LWZ(reg2, stk, 0),
ASM_LWZ(reg1, stk, 4),
ASM_LWZ(reg0, stk, 8),
ASM_LWZ(3, stk, 12),
ASM_ADDI(1, stk, 24),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
if (ret == 0)
{
cr = 0;
cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
ret = res == test->res && cr == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at three test %d !\n", i);
}
}
if (ret == 0)
{
cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
ret = res == test->res &&
(cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
if (ret != 0)
{
post_log ("Error at three test %d !\n", i);
}
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

137
post/lib_ppc/threei.c Normal file
View File

@ -0,0 +1,137 @@
/*
* (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>
/*
* CPU test
* Ternary instructions instr rA,rS,UIMM
*
* Logic instructions: ori, oris, xori, xoris
*
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_threei_s
{
ulong cmd;
ulong op1;
ushort op2;
ulong res;
} cpu_post_threei_table[] =
{
{
OP_ORI,
0x80000000,
0xffff,
0x8000ffff
},
{
OP_ORIS,
0x00008000,
0xffff,
0xffff8000
},
{
OP_XORI,
0x8000ffff,
0xffff,
0x80000000
},
{
OP_XORIS,
0x00008000,
0xffff,
0xffff8000
},
};
static unsigned int cpu_post_threei_size =
sizeof (cpu_post_threei_table) / sizeof (struct cpu_post_threei_s);
int cpu_post_test_threei (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_threei_size && ret == 0; i++)
{
struct cpu_post_threei_s *test = cpu_post_threei_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long code[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_11IX(test->cmd, reg1, reg0, test->op2),
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
cr = 0;
cpu_post_exec_21 (code, & cr, & res, test->op1);
ret = res == test->res && cr == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at threei test %d !\n", i);
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

229
post/lib_ppc/threex.c Normal file
View File

@ -0,0 +1,229 @@
/*
* (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>
/*
* CPU test
* Ternary instructions instr rA,rS,rB
*
* Logic instructions: or, orc, xor, nand, nor, eqv
* Shift instructions: slw, srw, sraw
*
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
ulong op2);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_threex_s
{
ulong cmd;
ulong op1;
ulong op2;
ulong res;
} cpu_post_threex_table[] =
{
{
OP_OR,
0x1234,
0x5678,
0x1234 | 0x5678
},
{
OP_ORC,
0x1234,
0x5678,
0x1234 | ~0x5678
},
{
OP_XOR,
0x1234,
0x5678,
0x1234 ^ 0x5678
},
{
OP_NAND,
0x1234,
0x5678,
~(0x1234 & 0x5678)
},
{
OP_NOR,
0x1234,
0x5678,
~(0x1234 | 0x5678)
},
{
OP_EQV,
0x1234,
0x5678,
~(0x1234 ^ 0x5678)
},
{
OP_SLW,
0x80,
16,
0x800000
},
{
OP_SLW,
0x80,
32,
0
},
{
OP_SRW,
0x800000,
16,
0x80
},
{
OP_SRW,
0x800000,
32,
0
},
{
OP_SRAW,
0x80000000,
3,
0xf0000000
},
{
OP_SRAW,
0x8000,
3,
0x1000
},
};
static unsigned int cpu_post_threex_size =
sizeof (cpu_post_threex_table) / sizeof (struct cpu_post_threex_s);
int cpu_post_test_threex (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_threex_size && ret == 0; i++)
{
struct cpu_post_threex_s *test = cpu_post_threex_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int reg2 = (reg + 2) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long code[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -24),
ASM_STW(3, stk, 12),
ASM_STW(4, stk, 16),
ASM_STW(reg0, stk, 8),
ASM_STW(reg1, stk, 4),
ASM_STW(reg2, stk, 0),
ASM_LWZ(reg1, stk, 12),
ASM_LWZ(reg0, stk, 16),
ASM_12X(test->cmd, reg2, reg1, reg0),
ASM_STW(reg2, stk, 12),
ASM_LWZ(reg2, stk, 0),
ASM_LWZ(reg1, stk, 4),
ASM_LWZ(reg0, stk, 8),
ASM_LWZ(3, stk, 12),
ASM_ADDI(1, stk, 24),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
unsigned long codecr[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -24),
ASM_STW(3, stk, 12),
ASM_STW(4, stk, 16),
ASM_STW(reg0, stk, 8),
ASM_STW(reg1, stk, 4),
ASM_STW(reg2, stk, 0),
ASM_LWZ(reg1, stk, 12),
ASM_LWZ(reg0, stk, 16),
ASM_12X(test->cmd, reg2, reg1, reg0) | BIT_C,
ASM_STW(reg2, stk, 12),
ASM_LWZ(reg2, stk, 0),
ASM_LWZ(reg1, stk, 4),
ASM_LWZ(reg0, stk, 8),
ASM_LWZ(3, stk, 12),
ASM_ADDI(1, stk, 24),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
if (ret == 0)
{
cr = 0;
cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
ret = res == test->res && cr == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at threex test %d !\n", i);
}
}
if (ret == 0)
{
cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
ret = res == test->res &&
(cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
if (ret != 0)
{
post_log ("Error at threex test %d !\n", i);
}
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

176
post/lib_ppc/two.c Normal file
View File

@ -0,0 +1,176 @@
/*
* (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>
/*
* CPU test
* Binary instructions instr rD,rA
*
* Logic instructions: neg
* Arithmetic instructions: addme, addze, subfme, subfze
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_two_s
{
ulong cmd;
ulong op;
ulong res;
} cpu_post_two_table[] =
{
{
OP_NEG,
3,
-3
},
{
OP_NEG,
5,
-5
},
{
OP_ADDME,
6,
5
},
{
OP_ADDZE,
5,
5
},
{
OP_SUBFME,
6,
~6 - 1
},
{
OP_SUBFZE,
5,
~5
},
};
static unsigned int cpu_post_two_size =
sizeof (cpu_post_two_table) / sizeof (struct cpu_post_two_s);
int cpu_post_test_two (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_two_size && ret == 0; i++)
{
struct cpu_post_two_s *test = cpu_post_two_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long code[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_11(test->cmd, reg1, reg0),
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
unsigned long codecr[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_11(test->cmd, reg1, reg0) | BIT_C,
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
if (ret == 0)
{
cr = 0;
cpu_post_exec_21 (code, & cr, & res, test->op);
ret = res == test->res && cr == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at two test %d !\n", i);
}
}
if (ret == 0)
{
cpu_post_exec_21 (codecr, & cr, & res, test->op);
ret = res == test->res &&
(cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
if (ret != 0)
{
post_log ("Error at two test %d !\n", i);
}
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

176
post/lib_ppc/twox.c Normal file
View File

@ -0,0 +1,176 @@
/*
* (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>
/*
* CPU test
* Binary instructions instr rA,rS
*
* Logic instructions: cntlzw
* Arithmetic instructions: extsb, extsh
* The test contains a pre-built table of instructions, operands and
* expected results. For each table entry, the test will cyclically use
* different sets of operand registers and result registers.
*/
#ifdef CONFIG_POST
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1);
extern ulong cpu_post_makecr (long v);
static struct cpu_post_twox_s
{
ulong cmd;
ulong op;
ulong res;
} cpu_post_twox_table[] =
{
{
OP_EXTSB,
3,
3
},
{
OP_EXTSB,
0xff,
-1
},
{
OP_EXTSH,
3,
3
},
{
OP_EXTSH,
0xff,
0xff
},
{
OP_EXTSH,
0xffff,
-1
},
{
OP_CNTLZW,
0x000fffff,
12
},
};
static unsigned int cpu_post_twox_size =
sizeof (cpu_post_twox_table) / sizeof (struct cpu_post_twox_s);
int cpu_post_test_twox (void)
{
int ret = 0;
unsigned int i, reg;
int flag = disable_interrupts();
for (i = 0; i < cpu_post_twox_size && ret == 0; i++)
{
struct cpu_post_twox_s *test = cpu_post_twox_table + i;
for (reg = 0; reg < 32 && ret == 0; reg++)
{
unsigned int reg0 = (reg + 0) % 32;
unsigned int reg1 = (reg + 1) % 32;
unsigned int stk = reg < 16 ? 31 : 15;
unsigned long code[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_11X(test->cmd, reg1, reg0),
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
unsigned long codecr[] =
{
ASM_STW(stk, 1, -4),
ASM_ADDI(stk, 1, -16),
ASM_STW(3, stk, 8),
ASM_STW(reg0, stk, 4),
ASM_STW(reg1, stk, 0),
ASM_LWZ(reg0, stk, 8),
ASM_11X(test->cmd, reg1, reg0) | BIT_C,
ASM_STW(reg1, stk, 8),
ASM_LWZ(reg1, stk, 0),
ASM_LWZ(reg0, stk, 4),
ASM_LWZ(3, stk, 8),
ASM_ADDI(1, stk, 16),
ASM_LWZ(stk, 1, -4),
ASM_BLR,
};
ulong res;
ulong cr;
if (ret == 0)
{
cr = 0;
cpu_post_exec_21 (code, & cr, & res, test->op);
ret = res == test->res && cr == 0 ? 0 : -1;
if (ret != 0)
{
post_log ("Error at twox test %d !\n", i);
}
}
if (ret == 0)
{
cpu_post_exec_21 (codecr, & cr, & res, test->op);
ret = res == test->res &&
(cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
if (ret != 0)
{
post_log ("Error at twox test %d !\n", i);
}
}
}
}
if (flag)
enable_interrupts();
return ret;
}
#endif
#endif

View File

@ -430,6 +430,7 @@ unsigned long post_time_ms (unsigned long base)
#ifdef CONFIG_PPC
return (unsigned long)get_ticks () / (get_tbclk () / CFG_HZ) - base;
#else
#warning "Not implemented yet"
return 0; /* Not implemented yet */
#endif
}