diff options
Diffstat (limited to 'qemu/roms/u-boot/post/cpu')
20 files changed, 3956 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/post/cpu/mpc83xx/Makefile b/qemu/roms/u-boot/post/cpu/mpc83xx/Makefile new file mode 100644 index 000000000..d57b66757 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc83xx/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2002-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += ecc.o diff --git a/qemu/roms/u-boot/post/cpu/mpc83xx/ecc.c b/qemu/roms/u-boot/post/cpu/mpc83xx/ecc.c new file mode 100644 index 000000000..76a3693aa --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc83xx/ecc.c @@ -0,0 +1,150 @@ +/* + * (C) Copyright 2010 + * Eastman Kodak Company, <www.kodak.com> + * Michael Zaidman, <michael.zaidman@kodak.com> + * + * The code is based on the cpu/mpc83xx/ecc.c written by + * Dave Liu <daveliu@freescale.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <mpc83xx.h> +#include <watchdog.h> +#include <asm/io.h> +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_ECC +/* + * We use the RAW I/O accessors where possible in order to + * achieve performance goal, since the test's execution time + * affects the board start up time. + */ +static inline void ecc_clear(ddr83xx_t *ddr) +{ + /* Clear capture registers */ + __raw_writel(0, &ddr->capture_address); + __raw_writel(0, &ddr->capture_data_hi); + __raw_writel(0, &ddr->capture_data_lo); + __raw_writel(0, &ddr->capture_ecc); + __raw_writel(0, &ddr->capture_attributes); + + /* Clear SBEC and set SBET to 1 */ + out_be32(&ddr->err_sbe, 1 << ECC_ERROR_MAN_SBET_SHIFT); + + /* Clear Error Detect register */ + out_be32(&ddr->err_detect, ECC_ERROR_DETECT_MME |\ + ECC_ERROR_DETECT_MBE |\ + ECC_ERROR_DETECT_SBE |\ + ECC_ERROR_DETECT_MSE); + + isync(); +} + +int ecc_post_test(int flags) +{ + int ret = 0; + int int_state; + int errbit; + u32 pattern[2], writeback[2], retval[2]; + ddr83xx_t *ddr = &((immap_t *)CONFIG_SYS_IMMR)->ddr; + volatile u64 *addr = (u64 *)CONFIG_SYS_POST_ECC_START_ADDR; + + /* The pattern is written into memory to generate error */ + pattern[0] = 0xfedcba98UL; + pattern[1] = 0x76543210UL; + + /* After injecting error, re-initialize the memory with the value */ + writeback[0] = ~pattern[0]; + writeback[1] = ~pattern[1]; + + /* Check if ECC is enabled */ + if (__raw_readl(&ddr->err_disable) & ECC_ERROR_ENABLE) { + debug("DDR's ECC is not enabled, skipping the ECC POST.\n"); + return 0; + } + + int_state = disable_interrupts(); + icache_enable(); + +#ifdef CONFIG_DDR_32BIT + /* It seems like no one really uses the CONFIG_DDR_32BIT mode */ +#error "Add ECC POST support for CONFIG_DDR_32BIT here!" +#else + for (addr = (u64*)CONFIG_SYS_POST_ECC_START_ADDR, errbit=0; + addr < (u64*)CONFIG_SYS_POST_ECC_STOP_ADDR; addr++, errbit++ ) { + + WATCHDOG_RESET(); + + ecc_clear(ddr); + + /* Enable error injection */ + setbits_be32(&ddr->ecc_err_inject, ECC_ERR_INJECT_EIEN); + sync(); + isync(); + + /* Set bit to be injected */ + if (errbit < 32) { + __raw_writel(1 << errbit, &ddr->data_err_inject_lo); + __raw_writel(0, &ddr->data_err_inject_hi); + } else { + __raw_writel(0, &ddr->data_err_inject_lo); + __raw_writel(1<<(errbit-32), &ddr->data_err_inject_hi); + } + sync(); + isync(); + + /* Write memory location injecting SBE */ + ppcDWstore((u32*)addr, pattern); + sync(); + + /* Disable error injection */ + clrbits_be32(&ddr->ecc_err_inject, ECC_ERR_INJECT_EIEN); + sync(); + isync(); + + /* Data read should generate SBE */ + ppcDWload((u32*)addr, retval); + sync(); + + if (!(__raw_readl(&ddr->err_detect) & ECC_ERROR_DETECT_SBE) || + (__raw_readl(&ddr->data_err_inject_hi) != + (__raw_readl(&ddr->capture_data_hi) ^ pattern[0])) || + (__raw_readl(&ddr->data_err_inject_lo) != + (__raw_readl(&ddr->capture_data_lo) ^ pattern[1]))) { + + post_log("ECC failed to detect SBE error at %08x, " + "SBE injection mask %08x-%08x, wrote " + "%08x-%08x, read %08x-%08x\n", addr, + ddr->data_err_inject_hi, + ddr->data_err_inject_lo, + pattern[0], pattern[1], + retval[0], retval[1]); + + printf("ERR_DETECT Reg: %08x\n", ddr->err_detect); + printf("ECC CAPTURE_DATA Reg: %08x-%08x\n", + ddr->capture_data_hi, ddr->capture_data_lo); + ret = 1; + break; + } + + /* Re-initialize the ECC memory */ + ppcDWstore((u32*)addr, writeback); + sync(); + isync(); + + errbit %= 63; + } +#endif /* !CONFIG_DDR_32BIT */ + + ecc_clear(ddr); + + icache_disable(); + + if (int_state) + enable_interrupts(); + + return ret; +} +#endif diff --git a/qemu/roms/u-boot/post/cpu/mpc8xx/Makefile b/qemu/roms/u-boot/post/cpu/mpc8xx/Makefile new file mode 100644 index 000000000..f8bb6c934 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc8xx/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2002-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_HAS_POST) += cache_8xx.o +obj-$(CONFIG_HAS_POST) += cache.o ether.o spr.o uart.o usb.o watchdog.o diff --git a/qemu/roms/u-boot/post/cpu/mpc8xx/cache.c b/qemu/roms/u-boot/post/cpu/mpc8xx/cache.c new file mode 100644 index 000000000..af1281b75 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc8xx/cache.c @@ -0,0 +1,62 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +/* Cache test + * + * This test verifies the CPU data and instruction cache using + * several test scenarios. + */ + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CONFIG_SYS_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 & CONFIG_SYS_POST_CACHE */ diff --git a/qemu/roms/u-boot/post/cpu/mpc8xx/cache_8xx.S b/qemu/roms/u-boot/post/cpu/mpc8xx/cache_8xx.S new file mode 100644 index 000000000..43649c896 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc8xx/cache_8xx.S @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2002 Wolfgang Denk <wd@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> + +#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 & CONFIG_SYS_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 & CONFIG_SYS_POST_CACHE */ diff --git a/qemu/roms/u-boot/post/cpu/mpc8xx/ether.c b/qemu/roms/u-boot/post/cpu/mpc8xx/ether.c new file mode 100644 index 000000000..d12250018 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc8xx/ether.c @@ -0,0 +1,561 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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 + */ + +#include <post.h> +#if CONFIG_POST & CONFIG_SYS_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 + +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) +{ + uchar ea[6]; + + 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 *) CONFIG_SYS_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 CONFIG_SYS_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) */ + + eth_getenv_enetaddr("ethaddr", ea); + 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]; + + 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; + +#ifdef CONFIG_RPXLITE + *((uchar *) BCSR0) |= BCSR0_ETHEN; +#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 */ +#endif +} + +static void scc_halt (int scc_index) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_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 < ARRAY_SIZE(ctlr_list); 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 & CONFIG_SYS_POST_ETHER */ diff --git a/qemu/roms/u-boot/post/cpu/mpc8xx/spr.c b/qemu/roms/u-boot/post/cpu/mpc8xx/spr.c new file mode 100644 index 000000000..d20da8d1e --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc8xx/spr.c @@ -0,0 +1,132 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_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, CONFIG_SYS_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 = ARRAY_SIZE(spr_test_list); + +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 & CONFIG_SYS_POST_SPR */ diff --git a/qemu/roms/u-boot/post/cpu/mpc8xx/uart.c b/qemu/roms/u-boot/post/cpu/mpc8xx/uart.c new file mode 100644 index 000000000..5214c71b0 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc8xx/uart.c @@ -0,0 +1,534 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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 + */ + +#include <post.h> +#if CONFIG_POST & CONFIG_SYS_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 + +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 *) CONFIG_SYS_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 CONFIG_SYS_SDSR + im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR; +#else + im->im_sdma.sdma_sdsr = 0x83; +#endif + + /* clear SDMA interrupt mask */ +#ifdef CONFIG_SYS_SDMR + im->im_sdma.sdma_sdmr = CONFIG_SYS_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) + /* Enable Monitor Port Transceiver */ + *((uchar *) BCSR0) |= BCSR0_ENMONXCVR; +#endif + + /* Set the physical address of the host memory buffers in + * the buffer descriptors. + */ + +#ifdef CONFIG_SYS_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; + + /* 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 *) CONFIG_SYS_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 *) CONFIG_SYS_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 *) CONFIG_SYS_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 CONFIG_SYS_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 *) CONFIG_SYS_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 *) CONFIG_SYS_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 *) CONFIG_SYS_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 < ARRAY_SIZE(ctlr_list); 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 & CONFIG_SYS_POST_UART */ diff --git a/qemu/roms/u-boot/post/cpu/mpc8xx/usb.c b/qemu/roms/u-boot/post/cpu/mpc8xx/usb.c new file mode 100644 index 000000000..6334088ea --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc8xx/usb.c @@ -0,0 +1,249 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +/* + * USB test + * + * The USB controller is tested in the local loopback mode. + * It is configured so that endpoint 0 operates as host and endpoint 1 + * operates as function endpoint. After that an IN token transaction + * is performed. + * Refer to MPC850 User Manual, Section 32.11.1 USB Host Controller + * Initialization Example. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_USB + +#include <commproc.h> +#include <command.h> + +#define TOUT_LOOP 100 + +#define PROFF_USB ((uint)0x0000) + +#define CPM_USB_EP0_BASE 0x0a00 +#define CPM_USB_EP1_BASE 0x0a20 + +#define CPM_USB_DT0_BASE 0x0a80 +#define CPM_USB_DT1_BASE 0x0a90 +#define CPM_USB_DR0_BASE 0x0aa0 +#define CPM_USB_DR1_BASE 0x0ab0 + +#define CPM_USB_RX0_BASE 0x0b00 +#define CPM_USB_RX1_BASE 0x0b08 +#define CPM_USB_TX0_BASE 0x0b20 +#define CPM_USB_TX1_BASE 0x0b28 + +#define USB_EXPECT(x) if (!(x)) goto Done; + +typedef struct usb_param { + ushort ep0ptr; + ushort ep1ptr; + ushort ep2ptr; + ushort ep3ptr; + uint rstate; + uint rptr; + ushort frame_n; + ushort rbcnt; + ushort rtemp; +} usb_param_t; + +typedef struct usb_param_block { + ushort rbase; + ushort tbase; + uchar rfcr; + uchar tfcr; + ushort mrblr; + ushort rbptr; + ushort tbptr; + uint tstate; + uint tptr; + ushort tcrc; + ushort tbcnt; + uint res[2]; +} usb_param_block_t; + +typedef struct usb { + uchar usmod; + uchar usadr; + uchar uscom; + uchar res1; + ushort usep[4]; + uchar res2[4]; + ushort usber; + uchar res3[2]; + ushort usbmr; + uchar res4; + uchar usbs; + uchar res5[8]; +} usb_t; + +int usb_post_test (int flags) +{ + int res = -1; + volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; + volatile cpm8xx_t *cp = &(im->im_cpm); + volatile usb_param_t *pram_ptr; + uint dpram; + ushort DPRAM; + volatile cbd_t *tx; + volatile cbd_t *rx; + volatile usb_t *usbr; + volatile usb_param_block_t *ep0; + volatile usb_param_block_t *ep1; + int j; + + pram_ptr = (usb_param_t *) & (im->im_cpm.cp_dparam[PROFF_USB]); + dpram = (uint) im->im_cpm.cp_dpmem; + DPRAM = dpram; + tx = (cbd_t *) (dpram + CPM_USB_TX0_BASE); + rx = (cbd_t *) (dpram + CPM_USB_RX0_BASE); + ep0 = (usb_param_block_t *) (dpram + CPM_USB_EP0_BASE); + ep1 = (usb_param_block_t *) (dpram + CPM_USB_EP1_BASE); + usbr = (usb_t *) & (im->im_cpm.cp_scc[0]); + + /* 01 */ + im->im_ioport.iop_padir &= ~(ushort) 0x0200; + im->im_ioport.iop_papar |= (ushort) 0x0200; + + cp->cp_sicr &= ~0x000000FF; + cp->cp_sicr |= 0x00000018; + + cp->cp_brgc4 = 0x00010001; + + /* 02 */ + im->im_ioport.iop_padir &= ~(ushort) 0x0002; + im->im_ioport.iop_padir &= ~(ushort) 0x0001; + + im->im_ioport.iop_papar |= (ushort) 0x0002; + im->im_ioport.iop_papar |= (ushort) 0x0001; + + /* 03 */ + im->im_ioport.iop_pcdir &= ~(ushort) 0x0020; + im->im_ioport.iop_pcdir &= ~(ushort) 0x0010; + + im->im_ioport.iop_pcpar &= ~(ushort) 0x0020; + im->im_ioport.iop_pcpar &= ~(ushort) 0x0010; + + im->im_ioport.iop_pcso |= (ushort) 0x0020; + im->im_ioport.iop_pcso |= (ushort) 0x0010; + + /* 04 */ + im->im_ioport.iop_pcdir |= (ushort) 0x0200; + im->im_ioport.iop_pcdir |= (ushort) 0x0100; + + im->im_ioport.iop_pcpar |= (ushort) 0x0200; + im->im_ioport.iop_pcpar |= (ushort) 0x0100; + + /* 05 */ + pram_ptr->frame_n = 0; + + /* 06 */ + pram_ptr->ep0ptr = DPRAM + CPM_USB_EP0_BASE; + pram_ptr->ep1ptr = DPRAM + CPM_USB_EP1_BASE; + + /* 07-10 */ + tx[0].cbd_sc = 0xB800; + tx[0].cbd_datlen = 3; + tx[0].cbd_bufaddr = dpram + CPM_USB_DT0_BASE; + + tx[1].cbd_sc = 0xBC80; + tx[1].cbd_datlen = 3; + tx[1].cbd_bufaddr = dpram + CPM_USB_DT1_BASE; + + rx[0].cbd_sc = 0xA000; + rx[0].cbd_datlen = 0; + rx[0].cbd_bufaddr = dpram + CPM_USB_DR0_BASE; + + rx[1].cbd_sc = 0xA000; + rx[1].cbd_datlen = 0; + rx[1].cbd_bufaddr = dpram + CPM_USB_DR1_BASE; + + /* 11-12 */ + *(volatile int *) (dpram + CPM_USB_DT0_BASE) = 0x69856000; + *(volatile int *) (dpram + CPM_USB_DT1_BASE) = 0xABCD1234; + + *(volatile int *) (dpram + CPM_USB_DR0_BASE) = 0; + *(volatile int *) (dpram + CPM_USB_DR1_BASE) = 0; + + /* 13-16 */ + ep0->rbase = DPRAM + CPM_USB_RX0_BASE; + ep0->tbase = DPRAM + CPM_USB_TX0_BASE; + ep0->rfcr = 0x18; + ep0->tfcr = 0x18; + ep0->mrblr = 0x100; + ep0->rbptr = DPRAM + CPM_USB_RX0_BASE; + ep0->tbptr = DPRAM + CPM_USB_TX0_BASE; + ep0->tstate = 0; + + /* 17-20 */ + ep1->rbase = DPRAM + CPM_USB_RX1_BASE; + ep1->tbase = DPRAM + CPM_USB_TX1_BASE; + ep1->rfcr = 0x18; + ep1->tfcr = 0x18; + ep1->mrblr = 0x100; + ep1->rbptr = DPRAM + CPM_USB_RX1_BASE; + ep1->tbptr = DPRAM + CPM_USB_TX1_BASE; + ep1->tstate = 0; + + /* 21-24 */ + usbr->usep[0] = 0x0000; + usbr->usep[1] = 0x1100; + usbr->usep[2] = 0x2200; + usbr->usep[3] = 0x3300; + + /* 25 */ + usbr->usmod = 0x06; + + /* 26 */ + usbr->usadr = 0x05; + + /* 27 */ + usbr->uscom = 0; + + /* 28 */ + usbr->usmod |= 0x01; + udelay (1); + + /* 29-30 */ + usbr->uscom = 0x80; + usbr->uscom = 0x81; + + /* Wait for the data packet to be transmitted */ + for (j = 0; j < TOUT_LOOP; j++) { + if (tx[1].cbd_sc & (ushort) 0x8000) + udelay (1); + else + break; + } + + USB_EXPECT (j < TOUT_LOOP); + + USB_EXPECT (tx[0].cbd_sc == 0x3800); + USB_EXPECT (tx[0].cbd_datlen == 3); + + USB_EXPECT (tx[1].cbd_sc == 0x3C80); + USB_EXPECT (tx[1].cbd_datlen == 3); + + USB_EXPECT (rx[0].cbd_sc == 0x2C00); + USB_EXPECT (rx[0].cbd_datlen == 5); + + USB_EXPECT (*(volatile int *) (dpram + CPM_USB_DR0_BASE) == + 0xABCD122B); + USB_EXPECT (*(volatile char *) (dpram + CPM_USB_DR0_BASE + 4) == 0x42); + + res = 0; + Done: + + return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_USB */ diff --git a/qemu/roms/u-boot/post/cpu/mpc8xx/watchdog.c b/qemu/roms/u-boot/post/cpu/mpc8xx/watchdog.c new file mode 100644 index 000000000..a070539b1 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/mpc8xx/watchdog.c @@ -0,0 +1,59 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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. + */ + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CONFIG_SYS_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 & CONFIG_SYS_POST_WATCHDOG */ diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/Makefile b/qemu/roms/u-boot/post/cpu/ppc4xx/Makefile new file mode 100644 index 000000000..e9ec286c7 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/Makefile @@ -0,0 +1,16 @@ +# +# (C) Copyright 2002-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cache_4xx.o +obj-y += cache.o +obj-y += denali_ecc.o +obj-y += ether.o +obj-y += fpu.o +obj-y += ocm.o +obj-y += spr.o +obj-y += uart.o +obj-y += watchdog.o diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/cache.c b/qemu/roms/u-boot/post/cpu/ppc4xx/cache.c new file mode 100644 index 000000000..e5ea5335e --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/cache.c @@ -0,0 +1,106 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +/* Cache test + * + * This test verifies the CPU data and instruction cache using + * several test scenarios. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CACHE + +#include <asm/mmu.h> +#include <watchdog.h> + +#define CACHE_POST_SIZE 1024 + +int cache_post_test1 (int tlb, void *p, int size); +int cache_post_test2 (int tlb, void *p, int size); +int cache_post_test3 (int tlb, void *p, int size); +int cache_post_test4 (int tlb, void *p, int size); +int cache_post_test5 (int tlb, void *p, int size); +int cache_post_test6 (int tlb, void *p, int size); + +#ifdef CONFIG_440 +static unsigned char testarea[CACHE_POST_SIZE] +__attribute__((__aligned__(CACHE_POST_SIZE))); +#endif + +int cache_post_test (int flags) +{ + void *virt = (void *)CONFIG_SYS_POST_CACHE_ADDR; + int ints; + int res = 0; + int tlb = -1; /* index to the victim TLB entry */ + + /* + * All 44x variants deal with cache management differently + * because they have the address translation always enabled. + * The 40x ppc's don't use address translation in U-Boot at all, + * so we have to distinguish here between 40x and 44x. + */ +#ifdef CONFIG_440 + int word0, i; + + /* + * Allocate a new TLB entry, since we are going to modify + * the write-through and caching inhibited storage attributes. + */ + program_tlb((u32)testarea, (u32)virt, CACHE_POST_SIZE, + TLB_WORD2_I_ENABLE); + + /* Find the TLB entry */ + for (i = 0;; i++) { + if (i >= PPC4XX_TLB_SIZE) { + printf ("Failed to program tlb entry\n"); + return -1; + } + word0 = mftlb1(i); + if (TLB_WORD0_EPN_DECODE(word0) == (u32)virt) { + tlb = i; + break; + } + } +#endif + ints = disable_interrupts (); + + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test1 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test2 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test3 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test4 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test5 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test6 (tlb, virt, CACHE_POST_SIZE); + + if (ints) + enable_interrupts (); + +#ifdef CONFIG_440 + remove_tlb((u32)virt, CACHE_POST_SIZE); +#endif + + return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CACHE */ diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/cache_4xx.S b/qemu/roms/u-boot/post/cpu/ppc4xx/cache_4xx.S new file mode 100644 index 000000000..15a133cfa --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/cache_4xx.S @@ -0,0 +1,473 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> +#include <asm/mmu.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CACHE + + .text + + /* + * All 44x variants deal with cache management differently + * because they have the address translation always enabled. + * The 40x ppc's don't use address translation in U-Boot at all, + * so we have to distinguish here between 40x and 44x. + */ +#ifdef CONFIG_440 +/* void cache_post_disable (int tlb) + */ +cache_post_disable: + tlbre r0, r3, 0x0002 + ori r0, r0, TLB_WORD2_I_ENABLE@l + tlbwe r0, r3, 0x0002 + sync + isync + blr + +/* void cache_post_wt (int tlb) + */ +cache_post_wt: + tlbre r0, r3, 0x0002 + ori r0, r0, TLB_WORD2_W_ENABLE@l + andi. r0, r0, ~TLB_WORD2_I_ENABLE@l + tlbwe r0, r3, 0x0002 + sync + isync + blr + +/* void cache_post_wb (int tlb) + */ +cache_post_wb: + tlbre r0, r3, 0x0002 + andi. r0, r0, ~TLB_WORD2_W_ENABLE@l + andi. r0, r0, ~TLB_WORD2_I_ENABLE@l + tlbwe r0, r3, 0x0002 + sync + isync + blr +#else +/* void cache_post_disable (int tlb) + */ +cache_post_disable: + lis r0, 0x0000 + ori r0, r0, 0x0000 + mtdccr r0 + sync + isync + blr + +/* void cache_post_wt (int tlb) + */ +cache_post_wt: + lis r0, 0x8000 + ori r0, r0, 0x0000 + mtdccr r0 + lis r0, 0x8000 + ori r0, r0, 0x0000 + mtdcwr r0 + sync + isync + blr + +/* void cache_post_wb (int tlb) + */ +cache_post_wb: + lis r0, 0x8000 + ori r0, r0, 0x0000 + mtdccr r0 + lis r0, 0x0000 + ori r0, r0, 0x0000 + mtdcwr r0 + sync + isync + blr +#endif + +/* void cache_post_dinvalidate (void *p, int size) + */ +cache_post_dinvalidate: + dcbi r0, r3 + addi r3, r3, CONFIG_SYS_CACHELINE_SIZE + subic. r4, r4, CONFIG_SYS_CACHELINE_SIZE + bgt cache_post_dinvalidate + sync + blr + +/* void cache_post_dstore (void *p, int size) + */ +cache_post_dstore: + dcbst r0, r3 + addi r3, r3, CONFIG_SYS_CACHELINE_SIZE + subic. r4, r4, CONFIG_SYS_CACHELINE_SIZE + bgt cache_post_dstore + sync + blr + +/* void cache_post_dtouch (void *p, int size) + */ +cache_post_dtouch: + dcbt r0, r3 + addi r3, r3, CONFIG_SYS_CACHELINE_SIZE + subic. r4, r4, CONFIG_SYS_CACHELINE_SIZE + bgt cache_post_dtouch + sync + blr + +/* void cache_post_iinvalidate (void) + */ +cache_post_iinvalidate: + iccci r0, r0 + sync + blr + +/* void cache_post_memset (void *p, int val, int size) + */ +cache_post_memset: + mtctr r5 +1: + stb r4, 0(r3) + addi r3, r3, 1 + bdnz 1b + blr + +/* int cache_post_check (void *p, int size) + */ +cache_post_check: + mtctr r4 +1: + lbz r0, 0(r3) + addi r3, r3, 1 + cmpwi r0, 0xff + bne 2f + bdnz 1b + li r3, 0 + blr +2: + li r3, -1 + blr + +#define CACHE_POST_DISABLE() \ + mr r3, r10; \ + bl cache_post_disable + +#define CACHE_POST_WT() \ + mr r3, r10; \ + bl cache_post_wt + +#define CACHE_POST_WB() \ + mr r3, r10; \ + bl cache_post_wb + +#define CACHE_POST_DINVALIDATE() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dinvalidate + +#define CACHE_POST_DFLUSH() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dflush + +#define CACHE_POST_DSTORE() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dstore + +#define CACHE_POST_DTOUCH() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dtouch + +#define CACHE_POST_IINVALIDATE() \ + bl cache_post_iinvalidate + +#define CACHE_POST_MEMSET(val) \ + mr r3, r11; \ + li r4, val; \ + mr r5, r12; \ + bl cache_post_memset + +#define CACHE_POST_CHECK() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_check; \ + mr r13, r3 + +/* + * Write and read 0xff pattern with caching enabled. + */ + .global cache_post_test1 +cache_post_test1: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WB() + CACHE_POST_DINVALIDATE() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + /* Read the test area */ + CACHE_POST_CHECK() + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* + * Write zeroes with caching enabled. + * Write 0xff pattern with caching disabled. + * Read 0xff pattern with caching enabled. + */ + .global cache_post_test2 +cache_post_test2: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WB() + CACHE_POST_DINVALIDATE() + + /* Write the zero pattern to the test area */ + CACHE_POST_MEMSET(0) + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + CACHE_POST_WB() + + /* Read the test area */ + CACHE_POST_CHECK() + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* + * Write-through mode test. + * Write zeroes, store the cache, write 0xff pattern. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ + .global cache_post_test3 +cache_post_test3: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WT() + CACHE_POST_DINVALIDATE() + + /* Cache the test area */ + CACHE_POST_DTOUCH() + + /* Write the zero pattern to the test area */ + CACHE_POST_MEMSET(0) + + CACHE_POST_DSTORE() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + /* Read the test area */ + CACHE_POST_CHECK() + + mr r3, r13 + mtlr r9 + blr + +/* + * Write-back mode test. + * Write 0xff pattern, store the cache, write zeroes. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ + .global cache_post_test4 +cache_post_test4: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WB() + CACHE_POST_DINVALIDATE() + + /* Cache the test area */ + CACHE_POST_DTOUCH() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + CACHE_POST_DSTORE() + + /* Write the zero pattern to the test area */ + CACHE_POST_MEMSET(0) + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + /* Read the test area */ + CACHE_POST_CHECK() + + mr r3, r13 + mtlr r9 + blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions. + * Check that the original instructions are executed. + */ + .global cache_post_test5 +cache_post_test5: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WT() + CACHE_POST_IINVALIDATE() + + /* Compute r13 = cache_post_test_inst */ + bl cache_post_test5_reloc +cache_post_test5_reloc: + mflr r13 + lis r0, (cache_post_test_inst - cache_post_test5_reloc)@h + ori r0, r0, (cache_post_test_inst - cache_post_test5_reloc)@l + add r13, r13, r0 + + /* Copy the test instructions to the test area */ + lwz r0, 0(r13) + stw r0, 0(r11) + lwz r0, 8(r13) + stw r0, 4(r11) + sync + + /* Invalidate the cache line */ + icbi r0, r11 + sync + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + + /* Replace the test instruction */ + lwz r0, 4(r13) + stw r0, 0(r11) + sync + + /* Do not invalidate the cache line */ + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + mr r13, r3 + + CACHE_POST_IINVALIDATE() + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions and invalidate the cache. + * Check that the replaced instructions are executed. + */ + .global cache_post_test6 +cache_post_test6: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WT() + CACHE_POST_IINVALIDATE() + + /* Compute r13 = cache_post_test_inst */ + bl cache_post_test6_reloc +cache_post_test6_reloc: + mflr r13 + lis r0, (cache_post_test_inst - cache_post_test6_reloc)@h + ori r0, r0, (cache_post_test_inst - cache_post_test6_reloc)@l + add r13, r13, r0 + + /* Copy the test instructions to the test area */ + lwz r0, 4(r13) + stw r0, 0(r11) + lwz r0, 8(r13) + stw r0, 4(r11) + sync + + /* Invalidate the cache line */ + icbi r0, r11 + sync + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + + /* Replace the test instruction */ + lwz r0, 0(r13) + stw r0, 0(r11) + sync + + /* Invalidate the cache line */ + icbi r0, r11 + sync + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + mr r13, r3 + + CACHE_POST_IINVALIDATE() + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* Test instructions. + */ +cache_post_test_inst: + li r3, 0 + li r3, -1 + blr + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CACHE */ diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/denali_ecc.c b/qemu/roms/u-boot/post/cpu/ppc4xx/denali_ecc.c new file mode 100644 index 000000000..1190739ae --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/denali_ecc.c @@ -0,0 +1,259 @@ +/* + * (C) Copyright 2007 + * Developed for DENX Software Engineering GmbH. + * + * Author: Pavel Kolesnikov <concord@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + +#include <common.h> +#include <watchdog.h> + +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_ECC + +/* + * MEMORY ECC test + * + * This test performs the checks ECC facility of memory. + */ +#include <asm/processor.h> +#include <asm/mmu.h> +#include <asm/io.h> +#include <asm/ppc440.h> + +DECLARE_GLOBAL_DATA_PTR; + +const static uint8_t syndrome_codes[] = { + 0xF4, 0XF1, 0XEC, 0XEA, 0XE9, 0XE6, 0XE5, 0XE3, + 0XDC, 0XDA, 0XD9, 0XD6, 0XD5, 0XD3, 0XCE, 0XCB, + 0xB5, 0XB0, 0XAD, 0XAB, 0XA8, 0XA7, 0XA4, 0XA2, + 0X9D, 0X9B, 0X98, 0X97, 0X94, 0X92, 0X8F, 0X8A, + 0x75, 0x70, 0X6D, 0X6B, 0X68, 0X67, 0X64, 0X62, + 0X5E, 0X5B, 0X58, 0X57, 0X54, 0X52, 0X4F, 0X4A, + 0x34, 0x31, 0X2C, 0X2A, 0X29, 0X26, 0X25, 0X23, + 0X1C, 0X1A, 0X19, 0X16, 0X15, 0X13, 0X0E, 0X0B, + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 +}; + +#define ECC_START_ADDR 0x10 +#define ECC_STOP_ADDR 0x2000 +#define ECC_PATTERN 0x01010101 +#define ECC_PATTERN_CORR 0x11010101 +#define ECC_PATTERN_UNCORR 0x61010101 + +inline static void disable_ecc(void) +{ + uint32_t value; + + sync(); /* Wait for any pending memory accesses to complete. */ + mfsdram(DDR0_22, value); + mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK) + | DDR0_22_CTRL_RAW_ECC_DISABLE); +} + +inline static void clear_and_enable_ecc(void) +{ + uint32_t value; + + sync(); /* Wait for any pending memory accesses to complete. */ + mfsdram(DDR0_00, value); + mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL); + mfsdram(DDR0_22, value); + mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK) + | DDR0_22_CTRL_RAW_ECC_ENABLE); +} + +static uint32_t get_ecc_status(void) +{ + uint32_t int_status; +#if defined(DEBUG) + uint8_t syndrome; + uint32_t hdata, ldata, haddr, laddr; + uint32_t value; +#endif + + mfsdram(DDR0_00, int_status); + int_status &= DDR0_00_INT_STATUS_MASK; + +#if defined(DEBUG) + if (int_status & (DDR0_00_INT_STATUS_BIT0 | DDR0_00_INT_STATUS_BIT1)) { + mfsdram(DDR0_32, laddr); + mfsdram(DDR0_33, haddr); + haddr &= 0x00000001; + if (int_status & DDR0_00_INT_STATUS_BIT1) + debug("Multiple accesses"); + else + debug("A single access"); + + debug(" outside the defined physical memory space detected\n" + " addr = 0x%01x%08x\n", haddr, laddr); + } + if (int_status & (DDR0_00_INT_STATUS_BIT2 | DDR0_00_INT_STATUS_BIT3)) { + unsigned int bit; + + mfsdram(DDR0_23, value); + syndrome = (value >> 16) & 0xff; + for (bit = 0; bit < sizeof(syndrome_codes); bit++) + if (syndrome_codes[bit] == syndrome) + break; + + mfsdram(DDR0_38, laddr); + mfsdram(DDR0_39, haddr); + haddr &= 0x00000001; + mfsdram(DDR0_40, ldata); + mfsdram(DDR0_41, hdata); + if (int_status & DDR0_00_INT_STATUS_BIT3) + debug("Multiple correctable ECC events"); + else + debug("Single correctable ECC event"); + + debug(" detected\n 0x%01x%08x - 0x%08x%08x, bit - %d\n", + haddr, laddr, hdata, ldata, bit); + } + if (int_status & (DDR0_00_INT_STATUS_BIT4 | DDR0_00_INT_STATUS_BIT5)) { + mfsdram(DDR0_23, value); + syndrome = (value >> 8) & 0xff; + mfsdram(DDR0_34, laddr); + mfsdram(DDR0_35, haddr); + haddr &= 0x00000001; + mfsdram(DDR0_36, ldata); + mfsdram(DDR0_37, hdata); + if (int_status & DDR0_00_INT_STATUS_BIT5) + debug("Multiple uncorrectable ECC events"); + else + debug("Single uncorrectable ECC event"); + + debug(" detected\n 0x%01x%08x - 0x%08x%08x, " + "syndrome - 0x%02x\n", + haddr, laddr, hdata, ldata, syndrome); + } + if (int_status & DDR0_00_INT_STATUS_BIT6) + debug("DRAM initialization complete\n"); +#endif /* defined(DEBUG) */ + + return int_status; +} + +static int test_ecc(uint32_t ecc_addr) +{ + uint32_t value; + volatile uint32_t *const ecc_mem = (volatile uint32_t *)ecc_addr; + int ret = 0; + + WATCHDOG_RESET(); + + debug("Entering test_ecc(0x%08x)\n", ecc_addr); + /* Set up correct ECC in memory */ + disable_ecc(); + clear_and_enable_ecc(); + out_be32(ecc_mem, ECC_PATTERN); + out_be32(ecc_mem + 1, ECC_PATTERN); + ppcDcbf((u32)ecc_mem); + + /* Verify no ECC error reading back */ + value = in_be32(ecc_mem); + disable_ecc(); + if (ECC_PATTERN != value) { + debug("Data read error (no-error case): " + "expected 0x%08x, read 0x%08x\n", ECC_PATTERN, value); + ret = 1; + } + value = get_ecc_status(); + if (0x00000000 != value) { + /* Expected no ECC status reported */ + debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n", + 0x00000000, value); + ret = 1; + } + + /* Test for correctable error by creating a one-bit error */ + out_be32(ecc_mem, ECC_PATTERN_CORR); + ppcDcbf((u32)ecc_mem); + clear_and_enable_ecc(); + value = in_be32(ecc_mem); + disable_ecc(); + /* Test that the corrected data was read */ + if (ECC_PATTERN != value) { + debug("Data read error (correctable-error case): " + "expected 0x%08x, read 0x%08x\n", ECC_PATTERN, value); + ret = 1; + } + value = get_ecc_status(); + if ((DDR0_00_INT_STATUS_BIT2 | DDR0_00_INT_STATUS_BIT7) != value) { + /* Expected a single correctable error reported */ + debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n", + DDR0_00_INT_STATUS_BIT2, value); + ret = 1; + } + + /* Test for uncorrectable error by creating a two-bit error */ + out_be32(ecc_mem, ECC_PATTERN_UNCORR); + ppcDcbf((u32)ecc_mem); + clear_and_enable_ecc(); + value = in_be32(ecc_mem); + disable_ecc(); + /* Test that the corrected data was read */ + if (ECC_PATTERN_UNCORR != value) { + debug("Data read error (uncorrectable-error case): " + "expected 0x%08x, read 0x%08x\n", ECC_PATTERN_UNCORR, + value); + ret = 1; + } + value = get_ecc_status(); + if ((DDR0_00_INT_STATUS_BIT4 | DDR0_00_INT_STATUS_BIT7) != value) { + /* Expected a single uncorrectable error reported */ + debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n", + DDR0_00_INT_STATUS_BIT4, value); + ret = 1; + } + + /* Remove error from SDRAM and enable ECC. */ + out_be32(ecc_mem, ECC_PATTERN); + ppcDcbf((u32)ecc_mem); + clear_and_enable_ecc(); + + return ret; +} + +int ecc_post_test(int flags) +{ + int ret = 0; + uint32_t value; + uint32_t iaddr; + + mfsdram(DDR0_22, value); + if (0x3 != DDR0_22_CTRL_RAW_DECODE(value)) { + debug("SDRAM ECC not enabled, skipping ECC POST.\n"); + return 0; + } + + /* Mask all interrupts. */ + mfsdram(DDR0_01, value); + mtsdram(DDR0_01, (value & ~DDR0_01_INT_MASK_MASK) + | DDR0_01_INT_MASK_ALL_OFF); + + for (iaddr = ECC_START_ADDR; iaddr <= ECC_STOP_ADDR; iaddr += iaddr) { + ret = test_ecc(iaddr); + if (ret) + break; + } + /* + * Clear possible errors resulting from ECC testing. (If not done, we + * we could get an interrupt later on when exceptions are enabled.) + */ + set_mcsr(get_mcsr()); + debug("ecc_post_test() returning %d\n", ret); + return ret; +} +#endif /* CONFIG_POST & CONFIG_SYS_POST_ECC */ +#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */ diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/ether.c b/qemu/roms/u-boot/post/cpu/ppc4xx/ether.c new file mode 100644 index 000000000..4c9a39b52 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/ether.c @@ -0,0 +1,419 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +/* + * Ethernet test + * + * The Ethernet Media Access Controllers (EMAC) are tested in the + * internal loopback 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 + * CONFIG_SYS_POST_ETH_LOOPS - Number of test loops. Each loop + * is tested with a different frame length. Starting with + * MAX_PACKET_LENGTH and going down to MIN_PACKET_LENGTH. + * Defaults to 10 and can be overriden in the board config header. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_ETHER + +#include <asm/cache.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/ppc4xx-mal.h> +#include <asm/ppc4xx-emac.h> +#include <malloc.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Get count of EMAC devices (doesn't have to be the max. possible number + * supported by the cpu) + * + * CONFIG_BOARD_EMAC_COUNT added so now a "dynamic" way to configure the + * EMAC count is possible. As it is needed for the Kilauea/Haleakala + * 405EX/405EXr eval board, using the same binary. + */ +#if defined(CONFIG_BOARD_EMAC_COUNT) +#define LAST_EMAC_NUM board_emac_count() +#else /* CONFIG_BOARD_EMAC_COUNT */ +#if defined(CONFIG_HAS_ETH3) +#define LAST_EMAC_NUM 4 +#elif defined(CONFIG_HAS_ETH2) +#define LAST_EMAC_NUM 3 +#elif defined(CONFIG_HAS_ETH1) +#define LAST_EMAC_NUM 2 +#else +#define LAST_EMAC_NUM 1 +#endif +#endif /* CONFIG_BOARD_EMAC_COUNT */ + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1)) +#endif + +#define MIN_PACKET_LENGTH 64 +#define MAX_PACKET_LENGTH 1514 +#ifndef CONFIG_SYS_POST_ETH_LOOPS +#define CONFIG_SYS_POST_ETH_LOOPS 10 +#endif +#define PACKET_INCR ((MAX_PACKET_LENGTH - MIN_PACKET_LENGTH) / \ + CONFIG_SYS_POST_ETH_LOOPS) + +static volatile mal_desc_t tx __cacheline_aligned; +static volatile mal_desc_t rx __cacheline_aligned; +static char *tx_buf; +static char *rx_buf; + +int board_emac_count(void); + +static void ether_post_init (int devnum, int hw_addr) +{ + int i; +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + unsigned mode_reg; + sys_info_t sysinfo; +#endif +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE) + unsigned long mfr; +#endif + +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + /* Need to get the OPB frequency so we can access the PHY */ + get_sys_info (&sysinfo); +#endif + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + /* provide clocks for EMAC internal loopback */ + mfsdr (SDR0_MFR, mfr); + mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum); + mtsdr (SDR0_MFR, mfr); + sync (); +#endif + /* reset emac */ + out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_SRST); + sync (); + + for (i = 0;; i++) { + if (!(in_be32 ((void*)(EMAC0_MR0 + hw_addr)) & EMAC_MR0_SRST)) + break; + if (i >= 1000) { + printf ("Timeout resetting EMAC\n"); + break; + } + udelay (1000); + } +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + /* Whack the M1 register */ + mode_reg = 0x0; + if (sysinfo.freqOPB <= 50000000); + else if (sysinfo.freqOPB <= 66666667) + mode_reg |= EMAC_MR1_OBCI_66; + else if (sysinfo.freqOPB <= 83333333) + mode_reg |= EMAC_MR1_OBCI_83; + else if (sysinfo.freqOPB <= 100000000) + mode_reg |= EMAC_MR1_OBCI_100; + else + mode_reg |= EMAC_MR1_OBCI_GT100; + + out_be32 ((void*)(EMAC0_MR1 + hw_addr), mode_reg); + +#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */ + + /* set the Mal configuration reg */ +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + mtdcr (MAL0_CFG, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | + MAL_CR_PLBLT_DEFAULT | 0x00330000); +#else + mtdcr (MAL0_CFG, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT); + /* Errata 1.12: MAL_1 -- Disable MAL bursting */ + if (get_pvr() == PVR_440GP_RB) { + mtdcr (MAL0_CFG, mfdcr(MAL0_CFG) & ~MAL_CR_PLBB); + } +#endif + /* setup buffer descriptors */ + tx.ctrl = MAL_TX_CTRL_WRAP; + tx.data_len = 0; + tx.data_ptr = (char*)L1_CACHE_ALIGN((u32)tx_buf); + + rx.ctrl = MAL_TX_CTRL_WRAP | MAL_RX_CTRL_EMPTY; + rx.data_len = 0; + rx.data_ptr = (char*)L1_CACHE_ALIGN((u32)rx_buf); + flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t)); + flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t)); + + switch (devnum) { + case 1: + /* setup MAL tx & rx channel pointers */ +#if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR) + mtdcr (MAL0_TXCTP2R, &tx); +#else + mtdcr (MAL0_TXCTP1R, &tx); +#endif +#if defined(CONFIG_440) + mtdcr (MAL0_TXBADDR, 0x0); + mtdcr (MAL0_RXBADDR, 0x0); +#endif + mtdcr (MAL0_RXCTP1R, &rx); + /* set RX buffer size */ + mtdcr (MAL0_RCBS1, PKTSIZE_ALIGN / 16); + break; + case 0: + default: + /* setup MAL tx & rx channel pointers */ +#if defined(CONFIG_440) + mtdcr (MAL0_TXBADDR, 0x0); + mtdcr (MAL0_RXBADDR, 0x0); +#endif + mtdcr (MAL0_TXCTP0R, &tx); + mtdcr (MAL0_RXCTP0R, &rx); + /* set RX buffer size */ + mtdcr (MAL0_RCBS0, PKTSIZE_ALIGN / 16); + break; + } + + /* Enable MAL transmit and receive channels */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) + mtdcr (MAL0_TXCASR, (MAL_TXRX_CASR >> (devnum*2))); +#else + mtdcr (MAL0_TXCASR, (MAL_TXRX_CASR >> devnum)); +#endif + mtdcr (MAL0_RXCASR, (MAL_TXRX_CASR >> devnum)); + + /* set internal loopback mode */ +#ifdef CONFIG_SYS_POST_ETHER_EXT_LOOPBACK + out_be32 ((void*)(EMAC0_MR1 + hw_addr), EMAC_MR1_FDE | 0 | + EMAC_MR1_RFS_4K | EMAC_MR1_TX_FIFO_2K | + EMAC_MR1_MF_100MBPS | EMAC_MR1_IST | + in_be32 ((void*)(EMAC0_MR1 + hw_addr))); +#else + out_be32 ((void*)(EMAC0_MR1 + hw_addr), EMAC_MR1_FDE | EMAC_MR1_ILE | + EMAC_MR1_RFS_4K | EMAC_MR1_TX_FIFO_2K | + EMAC_MR1_MF_100MBPS | EMAC_MR1_IST | + in_be32 ((void*)(EMAC0_MR1 + hw_addr))); +#endif + + /* set transmit enable & receive enable */ + out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_TXE | EMAC_MR0_RXE); + + /* enable broadcast address */ + out_be32 ((void*)(EMAC0_RXM + hw_addr), EMAC_RMR_BAE); + + /* set transmit request threshold register */ + out_be32 ((void*)(EMAC0_TRTR + hw_addr), 0x18000000); /* 256 byte threshold */ + + /* set receive low/high water mark register */ +#if defined(CONFIG_440) + /* 440s has a 64 byte burst length */ + out_be32 ((void*)(EMAC0_RX_HI_LO_WMARK + hw_addr), 0x80009000); +#else + /* 405s have a 16 byte burst length */ + out_be32 ((void*)(EMAC0_RX_HI_LO_WMARK + hw_addr), 0x0f002000); +#endif /* defined(CONFIG_440) */ + out_be32 ((void*)(EMAC0_TMR1 + hw_addr), 0xf8640000); + + /* Set fifo limit entry in tx mode 0 */ + out_be32 ((void*)(EMAC0_TMR0 + hw_addr), 0x00000003); + /* Frame gap set */ + out_be32 ((void*)(EMAC0_I_FRAME_GAP_REG + hw_addr), 0x00000008); + sync (); +} + +static void ether_post_halt (int devnum, int hw_addr) +{ + int i = 0; +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + unsigned long mfr; +#endif + + /* 1st reset MAL channel */ + /* Note: writing a 0 to a channel has no effect */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) + mtdcr (MAL0_TXCARR, MAL_TXRX_CASR >> (devnum * 2)); +#else + mtdcr (MAL0_TXCARR, MAL_TXRX_CASR >> devnum); +#endif + mtdcr (MAL0_RXCARR, MAL_TXRX_CASR >> devnum); + + /* wait for reset */ + while (mfdcr (MAL0_RXCASR) & (MAL_TXRX_CASR >> devnum)) { + if (i++ >= 1000) + break; + udelay (1000); + } + /* emac reset */ + out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_SRST); + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + /* remove clocks for EMAC internal loopback */ + mfsdr (SDR0_MFR, mfr); + mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum); + mtsdr (SDR0_MFR, mfr); +#endif +} + +static void ether_post_send (int devnum, int hw_addr, void *packet, int length) +{ + int i = 0; + + while (tx.ctrl & MAL_TX_CTRL_READY) { + if (i++ > 100) { + printf ("TX timeout\n"); + return; + } + udelay (1000); + invalidate_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t)); + } + tx.ctrl = MAL_TX_CTRL_READY | MAL_TX_CTRL_WRAP | MAL_TX_CTRL_LAST | + EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP; + tx.data_len = length; + memcpy (tx.data_ptr, packet, length); + flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t)); + flush_dcache_range((u32)tx.data_ptr, (u32)tx.data_ptr + length); + sync (); + + out_be32 ((void*)(EMAC0_TMR0 + hw_addr), in_be32 ((void*)(EMAC0_TMR0 + hw_addr)) | EMAC_TMR0_GNP0); + sync (); +} + +static int ether_post_recv (int devnum, int hw_addr, void *packet, int max_length) +{ + int length; + int i = 0; + + while (rx.ctrl & MAL_RX_CTRL_EMPTY) { + if (i++ > 100) { + printf ("RX timeout\n"); + return 0; + } + udelay (1000); + invalidate_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t)); + } + length = rx.data_len - 4; + if (length <= max_length) { + invalidate_dcache_range((u32)rx.data_ptr, (u32)rx.data_ptr + length); + memcpy(packet, rx.data_ptr, length); + } + sync (); + + rx.ctrl |= MAL_RX_CTRL_EMPTY; + flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t)); + sync (); + + return length; +} + + /* + * Test routines + */ + +static void packet_fill (char *packet, int length) +{ + char c = (char) length; + int i; + + /* set up ethernet header */ + memset (packet, 0xff, 14); + + for (i = 14; i < length; i++) { + packet[i] = c++; + } +} + +static int packet_check (char *packet, int length) +{ + char c = (char) length; + int i; + + for (i = 14; i < length; i++) { + if (packet[i] != c++) + return -1; + } + + return 0; +} + + char packet_send[MAX_PACKET_LENGTH]; + char packet_recv[MAX_PACKET_LENGTH]; +static int test_ctlr (int devnum, int hw_addr) +{ + int res = -1; + int length; + int l; + + ether_post_init (devnum, hw_addr); + + for (l = MAX_PACKET_LENGTH; l >= MIN_PACKET_LENGTH; + l -= PACKET_INCR) { + packet_fill (packet_send, l); + + ether_post_send (devnum, hw_addr, packet_send, l); + + length = ether_post_recv (devnum, hw_addr, packet_recv, + sizeof (packet_recv)); + + if (length != l || packet_check (packet_recv, length) < 0) { + goto Done; + } + } + + res = 0; + +Done: + + ether_post_halt (devnum, hw_addr); + + if (res != 0) { + post_log ("EMAC%d test failed\n", devnum); + } + + return res; +} + +int ether_post_test (int flags) +{ + int res = 0; + int i; + + /* Allocate tx & rx packet buffers */ + tx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE); + rx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE); + + if (!tx_buf || !rx_buf) { + printf ("Failed to allocate packet buffers\n"); + res = -1; + goto out_free; + } + + for (i = 0; i < LAST_EMAC_NUM; i++) { + if (test_ctlr (i, i*0x100)) + res = -1; + } + +out_free: + free (tx_buf); + free (rx_buf); + + return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_ETHER */ diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/fpu.c b/qemu/roms/u-boot/post/cpu/ppc4xx/fpu.c new file mode 100644 index 000000000..51e53ff2c --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/fpu.c @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> + +#if defined(CONFIG_440EP) || \ + defined(CONFIG_440EPX) + +#include <asm/processor.h> +#include <asm/ppc4xx.h> + + +int fpu_status(void) +{ + if (mfspr(SPRN_CCR0) & CCR0_DAPUIB) + return 0; /* Disabled */ + else + return 1; /* Enabled */ +} + + +void fpu_disable(void) +{ + mtspr(SPRN_CCR0, mfspr(SPRN_CCR0) | CCR0_DAPUIB); + mtmsr(mfmsr() & ~MSR_FP); +} + + +void fpu_enable(void) +{ + mtspr(SPRN_CCR0, mfspr(SPRN_CCR0) & ~CCR0_DAPUIB); + mtmsr(mfmsr() | MSR_FP); +} + +#endif diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/ocm.c b/qemu/roms/u-boot/post/cpu/ppc4xx/ocm.c new file mode 100644 index 000000000..bbf2d9a8e --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/ocm.c @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2008 Ilya Yanok, EmCraft Systems, yanok@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> + +/* + * This test attempts to verify on-chip memory (OCM). Result is written + * to the scratch register and if test succeed it won't be run till next + * power on. + */ + +#include <post.h> + +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define OCM_TEST_PATTERN1 0x55555555 +#define OCM_TEST_PATTERN2 0xAAAAAAAA + +#if CONFIG_POST & CONFIG_SYS_POST_OCM + +static uint ocm_status_read(void) +{ + return in_be32((void *)CONFIG_SYS_OCM_STATUS_ADDR) & + CONFIG_SYS_OCM_STATUS_MASK; +} + +static void ocm_status_write(uint value) +{ + out_be32((void *)CONFIG_SYS_OCM_STATUS_ADDR, value | + (in_be32((void *)CONFIG_SYS_OCM_STATUS_ADDR) & + ~CONFIG_SYS_OCM_STATUS_MASK)); +} + +static inline int ocm_test_word(uint value, uint *address) +{ + uint read_value; + + *address = value; + sync(); + read_value = *address; + + return (read_value != value); +} + +int ocm_post_test(int flags) +{ + uint old_value; + int ret = 0; + uint *address = (uint*)CONFIG_SYS_OCM_BASE; + + if (ocm_status_read() == CONFIG_SYS_OCM_STATUS_OK) + return 0; + for (; address < (uint*)(CONFIG_SYS_OCM_BASE + CONFIG_SYS_OCM_SIZE); address++) { + old_value = *address; + if (ocm_test_word(OCM_TEST_PATTERN1, address) || + ocm_test_word(OCM_TEST_PATTERN2, address)) { + ret = 1; + *address = old_value; + printf("OCM POST failed at %p!\n", address); + break; + } + *address = old_value; + } + ocm_status_write(ret ? CONFIG_SYS_OCM_STATUS_FAIL : CONFIG_SYS_OCM_STATUS_OK); + return ret; +} +#endif /* CONFIG_POST & CONFIG_SYS_POST_OCM */ diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/spr.c b/qemu/roms/u-boot/post/cpu/ppc4xx/spr.c new file mode 100644 index 000000000..9a3cdb3cf --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/spr.c @@ -0,0 +1,184 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_SPR + +#include <asm/processor.h> + +#ifdef CONFIG_4xx_DCACHE +#include <asm/mmu.h> + +DECLARE_GLOBAL_DATA_PTR; +#endif + +static struct { + int number; + char * name; + unsigned long mask; + unsigned long value; +} spr_test_list [] = { + /* Standard Special-Purpose Registers */ + + {0x001, "XER", 0x00000000, 0x00000000}, + {0x008, "LR", 0x00000000, 0x00000000}, + {0x009, "CTR", 0x00000000, 0x00000000}, + {0x016, "DEC", 0x00000000, 0x00000000}, + {0x01a, "SRR0", 0x00000000, 0x00000000}, + {0x01b, "SRR1", 0x00000000, 0x00000000}, + {0x110, "SPRG0", 0x00000000, 0x00000000}, + {0x111, "SPRG1", 0x00000000, 0x00000000}, + {0x112, "SPRG2", 0x00000000, 0x00000000}, + {0x113, "SPRG3", 0x00000000, 0x00000000}, + {0x11f, "PVR", 0x00000000, 0x00000000}, + + /* Additional Special-Purpose Registers. + * The values must match the initialization + * values from arch/powerpc/cpu/ppc4xx/start.S + */ + {0x30, "PID", 0x00000000, 0x00000000}, + {0x3a, "CSRR0", 0x00000000, 0x00000000}, + {0x3b, "CSRR1", 0x00000000, 0x00000000}, + {0x3d, "DEAR", 0x00000000, 0x00000000}, + {0x3e, "ESR", 0x00000000, 0x00000000}, +#ifdef CONFIG_440 + {0x3f, "IVPR", 0xffff0000, 0x00000000}, +#endif + {0x100, "USPRG0", 0x00000000, 0x00000000}, + {0x104, "SPRG4", 0x00000000, 0x00000000}, + {0x105, "SPRG5", 0x00000000, 0x00000000}, + {0x106, "SPRG6", 0x00000000, 0x00000000}, + {0x107, "SPRG7", 0x00000000, 0x00000000}, + {0x10c, "TBL", 0x00000000, 0x00000000}, + {0x10d, "TBU", 0x00000000, 0x00000000}, +#ifdef CONFIG_440 + {0x11e, "PIR", 0x0000000f, 0x00000000}, +#endif + {0x130, "DBSR", 0x00000000, 0x00000000}, + {0x134, "DBCR0", 0x00000000, 0x00000000}, + {0x135, "DBCR1", 0x00000000, 0x00000000}, + {0x136, "DBCR2", 0x00000000, 0x00000000}, + {0x138, "IAC1", 0x00000000, 0x00000000}, + {0x139, "IAC2", 0x00000000, 0x00000000}, + {0x13a, "IAC3", 0x00000000, 0x00000000}, + {0x13b, "IAC4", 0x00000000, 0x00000000}, + {0x13c, "DAC1", 0x00000000, 0x00000000}, + {0x13d, "DAC2", 0x00000000, 0x00000000}, + {0x13e, "DVC1", 0x00000000, 0x00000000}, + {0x13f, "DVC2", 0x00000000, 0x00000000}, + {0x150, "TSR", 0x00000000, 0x00000000}, + {0x154, "TCR", 0x00000000, 0x00000000}, +#ifdef CONFIG_440 + {0x190, "IVOR0", 0x0000fff0, 0x00000100}, + {0x191, "IVOR1", 0x0000fff0, 0x00000200}, + {0x192, "IVOR2", 0x0000fff0, 0x00000300}, + {0x193, "IVOR3", 0x0000fff0, 0x00000400}, + {0x194, "IVOR4", 0x0000fff0, 0x00000500}, + {0x195, "IVOR5", 0x0000fff0, 0x00000600}, + {0x196, "IVOR6", 0x0000fff0, 0x00000700}, + {0x197, "IVOR7", 0x0000fff0, 0x00000800}, + {0x198, "IVOR8", 0x0000fff0, 0x00000c00}, + {0x199, "IVOR9", 0x00000000, 0x00000000}, + {0x19a, "IVOR10", 0x0000fff0, 0x00000900}, + {0x19b, "IVOR11", 0x00000000, 0x00000000}, + {0x19c, "IVOR12", 0x00000000, 0x00000000}, + {0x19d, "IVOR13", 0x0000fff0, 0x00001300}, + {0x19e, "IVOR14", 0x0000fff0, 0x00001400}, + {0x19f, "IVOR15", 0x0000fff0, 0x00002000}, +#endif + {0x23a, "MCSRR0", 0x00000000, 0x00000000}, + {0x23b, "MCSRR1", 0x00000000, 0x00000000}, + {0x23c, "MCSR", 0x00000000, 0x00000000}, + {0x370, "INV0", 0x00000000, 0x00000000}, + {0x371, "INV1", 0x00000000, 0x00000000}, + {0x372, "INV2", 0x00000000, 0x00000000}, + {0x373, "INV3", 0x00000000, 0x00000000}, + {0x374, "ITV0", 0x00000000, 0x00000000}, + {0x375, "ITV1", 0x00000000, 0x00000000}, + {0x376, "ITV2", 0x00000000, 0x00000000}, + {0x377, "ITV3", 0x00000000, 0x00000000}, + {0x378, "CCR1", 0x00000000, 0x00000000}, + {0x390, "DNV0", 0x00000000, 0x00000000}, + {0x391, "DNV1", 0x00000000, 0x00000000}, + {0x392, "DNV2", 0x00000000, 0x00000000}, + {0x393, "DNV3", 0x00000000, 0x00000000}, + {0x394, "DTV0", 0x00000000, 0x00000000}, + {0x395, "DTV1", 0x00000000, 0x00000000}, + {0x396, "DTV2", 0x00000000, 0x00000000}, + {0x397, "DTV3", 0x00000000, 0x00000000}, +#ifdef CONFIG_440 + {0x398, "DVLIM", 0x0fc1f83f, 0x0001f800}, + {0x399, "IVLIM", 0x0fc1f83f, 0x0001f800}, +#endif + {0x39b, "RSTCFG", 0x00000000, 0x00000000}, + {0x39c, "DCDBTRL", 0x00000000, 0x00000000}, + {0x39d, "DCDBTRH", 0x00000000, 0x00000000}, + {0x39e, "ICDBTRL", 0x00000000, 0x00000000}, + {0x39f, "ICDBTRH", 0x00000000, 0x00000000}, + {0x3b2, "MMUCR", 0x00000000, 0x00000000}, + {0x3b3, "CCR0", 0x00000000, 0x00000000}, + {0x3d3, "ICDBDR", 0x00000000, 0x00000000}, + {0x3f3, "DBDR", 0x00000000, 0x00000000}, +}; + +static int spr_test_list_size = ARRAY_SIZE(spr_test_list); + +int spr_post_test (int flags) +{ + int ret = 0; + int i; + + unsigned long code[] = { + 0x7c6002a6, /* mfspr r3,SPR */ + 0x4e800020 /* blr */ + }; + unsigned long (*get_spr) (void) = (void *) code; + +#ifdef CONFIG_4xx_DCACHE + /* disable cache */ + change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, TLB_WORD2_I_ENABLE); +#endif + 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); + + asm volatile ("isync"); + + 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; + } + } +#ifdef CONFIG_4xx_DCACHE + /* enable cache */ + change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0); +#endif + + return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_SPR */ diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/uart.c b/qemu/roms/u-boot/post/cpu/ppc4xx/uart.c new file mode 100644 index 000000000..545b054c2 --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/uart.c @@ -0,0 +1,92 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * Copyright 2010, Stefan Roese, DENX Software Engineering, sr@denx.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/ppc4xx.h> +#include <ns16550.h> +#include <asm/io.h> +#include <serial.h> + +/* + * UART test + * + * The controllers are configured to loopback mode and several + * characters are transmitted. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_UART + +/* + * This table defines the UART's that should be tested and can + * be overridden in the board config file + */ +#ifndef CONFIG_SYS_POST_UART_TABLE +#define CONFIG_SYS_POST_UART_TABLE { CONFIG_SYS_NS16550_COM1, \ + CONFIG_SYS_NS16550_COM2, CONFIG_SYS_NS16550_COM3, \ + CONFIG_SYS_NS16550_COM4 } +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static int test_ctlr (struct NS16550 *com_port, int index) +{ + int res = -1; + char test_str[] = "*** UART Test String ***\r\n"; + int i; + int divisor; + + divisor = (get_serial_clock() + (gd->baudrate * (16 / 2))) / + (16 * gd->baudrate); + NS16550_init(com_port, divisor); + + /* + * Set internal loopback mode in UART + */ + out_8(&com_port->mcr, in_8(&com_port->mcr) | UART_MCR_LOOP); + + /* Reset FIFOs */ + out_8(&com_port->fcr, UART_FCR_RXSR | UART_FCR_TXSR); + udelay(100); + + /* Flush RX-FIFO */ + while (NS16550_tstc(com_port)) + NS16550_getc(com_port); + + for (i = 0; i < sizeof (test_str) - 1; i++) { + NS16550_putc(com_port, test_str[i]); + if (NS16550_getc(com_port) != test_str[i]) + goto done; + } + res = 0; +done: + if (res) + post_log ("uart%d test failed\n", index); + + return res; +} + +int uart_post_test (int flags) +{ + int i, res = 0; + static unsigned long base[] = CONFIG_SYS_POST_UART_TABLE; + + for (i = 0; i < ARRAY_SIZE(base); i++) { + if (test_ctlr((struct NS16550 *)base[i], i)) + res = -1; + } + serial_reinit_all (); + + return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_UART */ diff --git a/qemu/roms/u-boot/post/cpu/ppc4xx/watchdog.c b/qemu/roms/u-boot/post/cpu/ppc4xx/watchdog.c new file mode 100644 index 000000000..24e80939a --- /dev/null +++ b/qemu/roms/u-boot/post/cpu/ppc4xx/watchdog.c @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG + +#include <watchdog.h> + +int watchdog_post_test (int flags) +{ + if (flags & POST_REBOOT) { + /* Test passed */ + return 0; + } + else { + /* 10-second delay */ + int ints = disable_interrupts (); + ulong base = post_time_ms (0); + + while (post_time_ms (base) < 10000) + ; + if (ints) + enable_interrupts (); + + /* + * If we have reached this point, the watchdog timer + * does not work + */ + return -1; + } +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_WATCHDOG */ |