diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2015-08-28 09:58:54 +0800 |
---|---|---|
committer | Yang Zhang <yang.z.zhang@intel.com> | 2015-09-01 12:44:00 +0800 |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/board/gen860t | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/board/gen860t')
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/Makefile | 8 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/README | 131 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/beeper.c | 183 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/beeper.h | 13 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/flash.c | 628 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/fpga.c | 362 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/fpga.h | 26 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/gen860t.c | 278 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/ioport.c | 331 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/ioport.h | 26 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/u-boot-flashenv.lds | 92 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/u-boot.lds | 87 |
12 files changed, 2165 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/board/gen860t/Makefile b/qemu/roms/u-boot/board/gen860t/Makefile new file mode 100644 index 000000000..86ae5e80e --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = gen860t.o flash.o beeper.o fpga.o ioport.o diff --git a/qemu/roms/u-boot/board/gen860t/README b/qemu/roms/u-boot/board/gen860t/README new file mode 100644 index 000000000..3ef8ae196 --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/README @@ -0,0 +1,131 @@ +This directory contains board specific code for a generic MPC860T based +embedded computer, called 'GEN860T'. The design is generic in the sense that +common, readily available components are used and that the architecture of the +system is relatively straightforward: + + One eight bit wide boot (FLASH) memory + 32 bit main memory using SDRAM + DOC 2000+ + Ethernet PHY + Some I2C peripheral devices: Atmel AT24C256 EEPROM, Maxim DS1337 RTC. + Some other miscellaneous peripherals + +NOTE: There are references to a XIlinx FPGA and Mil-Std 1553 databus in this +port. I guess the computer is not as generic as I first said 8) However, +these extras can be safely ignored. + +Given the GEN860T files, it should be pretty easy to reverse engineer the +hardware configuration, if that's useful to you. Hopefully, this code will +be useful to someone as a basis for a port to a new system or as a head start +on a custom design. If you end up using any of this, I would appreciate +hearing from you, especially if you discover bugs or find ways to improve the +quality of this U-Boot port. + +Here are the salient features of the system: +Clock : 33.3 Mhz oscillator +Processor core frequency : 66.6 Mhz if in 1:2:1 mode; can also run 1:1 +Bus frequency : 33.3 Mhz + +Main memory: + Type : SDRAM + Width : 32 bits + Size : 64 mibibytes + Chip : Two Micron MT48LC16M16A2TG-7E + CS : MPC860T CS1*/UPMA + UPMA CONNECTIONS: + SDRAM A10 : GPLA0* + SDRAM CAS* : GPLA2* + SDRAM WE* : GPLA3* + SDRAM RAS* : GPLA4* + +Boot memory: + Type : FLASH + Width : 8 bits + Size : 16 mibibytes + Chip : One Intel 28F128J3A (StrataFlash) + CS : MPC860T CS0*/GPCM (this is the "boot" chip select) + +EEPROM memory: + Type : Serial I2C EEPROM + Width : 8 bits + Size : 32 kibibytes + Chip : One Atmel AT25C256 + CS : 0x50 (external I2C address pins on device are tied to GND) + +Filesystem memory: + Type : NAND FLASH (Toshiba) + Width : 8 bits (i.e. interface to DOC is 8 bits) + Size : 32 mibibytes + Chip : One DiskOnCHip Millenium Plus (DOC 2000+) + CS : MPC860T CS2*/GPCM + +Network support: + MAC : MPC86OT FEC (Fast Ethernet Controller) + PHY : Intel LXT971A + MII Addr: 0x0 (hardwired on the board) + MII IRQ : + +Console: + RS-232 on SMC1 (Maxim MAX3232 LVCMOS-RS232 level shifter) + +Real Time Clock: + Type : Low power, I2C interface + Chip : Maxim DS1337 + CS : Address 0x68 on I2C bus + + The MPC860T's internal RTC has a defect in Mask rev D that increases + the current drain on the KAPWR line to 10 mA. Since this is an + unreasonable amount of current draw for a RTC, and Motorola does not + plan to fix this in future mask revisions, a serial (I2C) RTC that + works has been included instead. NOTE that the DS1337 can be + configured to output a 32768 Hz clock while the main power is on. + This clock output has been routed to the MPC860T's EXTAL pin to allow + the internal RTC to be used. NOTE also that due to yet another + defect in the rev D mask, the RTC does not operate reliably when the + internal RTC divisor is set to use a 32768 Hz reference. So just use + the I2C RTC. + +Miscellaneous: + Xilinx Virtex FPGA on CS3*/GPCM. + Virtex FPGA slave SelectMap interface on cs4*/UPMB. + Mil-Std 1553 databus interface on CS5*/GPCM. + Audio sounder (beeper) with digital volume control connected to SPKROUT. + +SC variant: + A reduced-feature version of the GEN860T port is also supported: GEN860T_SC. + The 'SC' variant only provides support for the Virtex FPGA, SDRAM main + memory, EEPROM and flash memory. The system clock frequency is reduced + to 24 MHz. + +Issues: + The DOC 2000+ returns 0x40 as its device ID when probed using the method + desxribed in the DOC datasheet. Unfortunately, the U-Boot DOC driver + does not recognize this device. As of this writing, it seems that MTD + does not support the DOC 2000+ either. + +Status: + Everything appears to work except DOC support. As of this writing, + David Woodhouse has stated on the MTD mailing list that he has no + knowledge of the DOC Millineum Plus and therfore there is no support + in MTD for this device. I wish I had known this sooner :( + +The GEN860T board specific files and configuration is based on the work +of others who have contributed to U-Boot. The copyright and license notices +of these authors have been retained wherever their code has been reused. +All new code to support the GEN860T board is: + + (C) Copyright 2001-2003 + Keith Outwater (keith_outwater@mvis.com) + +and the following license applies: + +SPDX-License-Identifier: GPL-2.0+ + +Thanks to Wolfgang Denk for a great software package and to everyone +who contributed to its development. + +Keith Outwater +Sr. Staff Engineer +Microvision, Inc. +<keith_outwater@mvis.com> +<outwater@eskimo.com> diff --git a/qemu/roms/u-boot/board/gen860t/beeper.c b/qemu/roms/u-boot/board/gen860t/beeper.c new file mode 100644 index 000000000..0bebca98b --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/beeper.c @@ -0,0 +1,183 @@ +/* + * (C) Copyright 2002 + * Keith Outwater, keith_outwater@mvis.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <mpc8xx.h> +#include <asm/8xx_immap.h> +#include <linux/ctype.h> + +/* + * Basic beeper support for the GEN860T board. The GEN860T includes + * an audio sounder driven by a Phillips TDA8551 amplifier. The + * TDA8551 features a digital volume control which uses a "trinary" + * input (high/high-Z/low) to set volume. The 860's SPKROUT pin + * drives the amplifier input. + */ + +/* + * Initialize beeper-related hardware. Initialize timer 1 for use with + * the beeper. Use 66 MHz internal clock with prescale of 33 to get + * 1 uS period per count. + * FIXME: we should really compute the prescale based on the reported + * core clock frequency. + */ +void init_beeper (void) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + + immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_RST1 | TGCR_STP1; + immap->im_cpmtimer.cpmt_tmr1 = ((33 << TMR_PS_SHIFT) & TMR_PS_MSK) + | TMR_OM | TMR_FRR | TMR_ICLK_IN_GEN; + immap->im_cpmtimer.cpmt_tcn1 = 0; + immap->im_cpmtimer.cpmt_ter1 = 0xffff; + immap->im_cpmtimer.cpmt_tgcr |= TGCR_RST1; +} + +/* + * Set beeper frequency. Max allowed frequency is 2.5 KHz. This limit + * is mostly arbitrary, but the beeper isn't really much good beyond this + * frequency. + */ +void set_beeper_frequency (uint frequency) +{ +#define FREQ_LIMIT 2500 + + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + + /* + * Compute timer ticks given desired frequency. The timer is set up + * to count 0.5 uS per tick and it takes two ticks per cycle (Hz). + */ + if (frequency > FREQ_LIMIT) + frequency = FREQ_LIMIT; + frequency = 1000000 / frequency; + immap->im_cpmtimer.cpmt_trr1 = (ushort) frequency; +} + +/* + * Turn the beeper on + */ +void beeper_on (void) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + + immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_STP1; +} + +/* + * Turn the beeper off + */ +void beeper_off (void) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + + immap->im_cpmtimer.cpmt_tgcr |= TGCR_STP1; +} + +/* + * Increase or decrease the beeper volume. Volume can be set + * from off to full in 64 steps. To increase volume, the output + * pin is actively driven high, then returned to tristate. + * To decrease volume, output a low on the port pin (no need to + * change pin mode to tristate) then output a high to go back to + * tristate. + */ +void set_beeper_volume (int steps) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + int i; + + if (steps >= 0) { + for (i = 0; i < (steps >= 64 ? 64 : steps); i++) { + immap->im_cpm.cp_pbodr &= ~(0x80000000 >> 19); + udelay (1); + immap->im_cpm.cp_pbodr |= (0x80000000 >> 19); + udelay (1); + } + } else { + for (i = 0; i > (steps <= -64 ? -64 : steps); i--) { + immap->im_cpm.cp_pbdat &= ~(0x80000000 >> 19); + udelay (1); + immap->im_cpm.cp_pbdat |= (0x80000000 >> 19); + udelay (1); + } + } +} + +/* + * Check the environment to see if the beeper needs beeping. + * Controlled by a sequence of the form: + * freq/delta volume/on time/off time;... where: + * freq = frequency in Hz (0 - 2500) + * delta volume = volume steps up or down (-64 <= vol <= 64) + * on time = time in mS + * off time = time in mS + * + * Return 1 on success, 0 on failure + */ +int do_beeper (char *sequence) +{ +#define DELIMITER ';' + + int args[4]; + int i; + int val; + char *p = sequence; + char *tp; + + /* + * Parse the control sequence. This is a really simple parser + * without any real error checking. You can probably blow it + * up really easily. + */ + if (*p == '\0' || !isdigit (*p)) { + printf ("%s:%d: null or invalid string (%s)\n", + __FILE__, __LINE__, p); + return 0; + } + + i = 0; + while (*p != '\0') { + while (*p != DELIMITER) { + if (i > 3) + i = 0; + val = (int) simple_strtol (p, &tp, 0); + if (tp == p) { + printf ("%s:%d: no digits or bad format\n", + __FILE__, __LINE__); + return 0; + } else { + args[i] = val; + } + + i++; + if (*tp == DELIMITER) + p = tp; + else + p = ++tp; + } + p++; + + /* + * Well, we got something that has a chance of being correct + */ +#if 0 + for (i = 0; i < 4; i++) { + printf ("%s:%d:arg %d = %d\n", __FILE__, __LINE__, i, + args[i]); + } + printf ("\n"); +#endif + set_beeper_frequency (args[0]); + set_beeper_volume (args[1]); + beeper_on (); + udelay (1000 * args[2]); + beeper_off (); + udelay (1000 * args[3]); + } + return 1; +} diff --git a/qemu/roms/u-boot/board/gen860t/beeper.h b/qemu/roms/u-boot/board/gen860t/beeper.h new file mode 100644 index 000000000..0734fcab0 --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/beeper.h @@ -0,0 +1,13 @@ +/* + * (C) Copyright 2002 + * Keith Outwater, keith_outwater@mvis.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +void init_beeper(void); +void set_beeper_frequency(uint frequency); +void beeper_on(void); +void beeper_off(void); +void set_beeper_volume(int steps); +int do_beeper(char *sequence); diff --git a/qemu/roms/u-boot/board/gen860t/flash.c b/qemu/roms/u-boot/board/gen860t/flash.c new file mode 100644 index 000000000..ca1ed3d62 --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/flash.c @@ -0,0 +1,628 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvsi.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <mpc8xx.h> + +#if defined(CONFIG_ENV_IS_IN_FLASH) +# ifndef CONFIG_ENV_ADDR +# define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET) +# endif +# ifndef CONFIG_ENV_SIZE +# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +# endif +# ifndef CONFIG_ENV_SECT_SIZE +# define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE +# endif +#endif + +/* + * Use buffered writes to flash by default - they are about 32x faster than + * single byte writes. + */ +#ifndef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER +#define CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER +#endif + +/* + * Max time to wait (in mS) for flash device to allocate a write buffer. + */ +#ifndef CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT +#define CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT 100 +#endif + +/* + * These functions support a single Intel StrataFlash device (28F128J3A) + * in byte mode only!. The flash routines are very basic and simple + * since there isn't really any remapping necessary. + */ + +/* + * Intel SCS (Scalable Command Set) command definitions + * (taken from 28F128J3A datasheet) + */ +#define SCS_READ_CMD 0xff +#define SCS_READ_ID_CMD 0x90 +#define SCS_QUERY_CMD 0x98 +#define SCS_READ_STATUS_CMD 0x70 +#define SCS_CLEAR_STATUS_CMD 0x50 +#define SCS_WRITE_BUF_CMD 0xe8 +#define SCS_PROGRAM_CMD 0x40 +#define SCS_BLOCK_ERASE_CMD 0x20 +#define SCS_BLOCK_ERASE_RESUME_CMD 0xd0 +#define SCS_PROGRAM_RESUME_CMD 0xd0 +#define SCS_BLOCK_ERASE_SUSPEND_CMD 0xb0 +#define SCS_SET_BLOCK_LOCK_CMD 0x60 +#define SCS_CLR_BLOCK_LOCK_CMD 0x60 + +/* + * SCS status/extended status register bit definitions + */ +#define SCS_SR7 0x80 +#define SCS_XSR7 0x80 + +/*---------------------------------------------------------------------*/ +#if 0 +#define DEBUG_FLASH +#endif + +#ifdef DEBUG_FLASH +#define PRINTF(fmt,args...) printf(fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif +/*---------------------------------------------------------------------*/ + +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_char *addr, flash_info_t *info); +static int write_data8 (flash_info_t *info, ulong dest, uchar data); +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + * Initialize the flash memory. + */ +unsigned long +flash_init (void) +{ + volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + unsigned long size_b0; + int i; + + for (i= 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* + * The gen860t board only has one FLASH memory device, so the + * FLASH Bank configuration is done statically. + */ + PRINTF("\n## Get flash bank 1 size @ 0x%08x\n", FLASH_BASE0_PRELIM); + size_b0 = flash_get_size((vu_char *)FLASH_BASE0_PRELIM, &flash_info[0]); + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0: " + "ID 0x%lx, Size = 0x%08lx = %ld MB\n", + flash_info[0].flash_id,size_b0, size_b0 << 20); + } + + PRINTF("## Before remap:\n" + " BR0: 0x%08x OR0: 0x%08x\n BR1: 0x%08x OR1: 0x%08x\n", + memctl->memc_br0, memctl->memc_or0, + memctl->memc_br1, memctl->memc_or1); + + /* + * Remap FLASH according to real size + */ + memctl->memc_or0 |= (-size_b0 & 0xFFFF8000); + memctl->memc_br0 |= (CONFIG_SYS_FLASH_BASE & BR_BA_MSK); + + PRINTF("## After remap:\n" + " BR0: 0x%08x OR0: 0x%08x\n", memctl->memc_br0, memctl->memc_or0); + + /* + * Re-do sizing to get full correct info + */ + size_b0 = flash_get_size ((vu_char *)CONFIG_SYS_FLASH_BASE, &flash_info[0]); + flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]); + flash_info[0].size = size_b0; + +#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE + /* + * Monitor protection is ON by default + */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_SYS_MONITOR_BASE, + CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, + &flash_info[0]); +#endif + +#ifdef CONFIG_ENV_IS_IN_FLASH + /* + * Environment protection ON by default + */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, + &flash_info[0]); +#endif + + PRINTF("## Final Flash bank size: 0x%08lx\n",size_b0); + return (size_b0); +} + + +/*----------------------------------------------------------------------- + * Fill in the FLASH offset table + */ +static void +flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_INTEL: + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base; + base += 1024 * 128; + } + return; + + default: + printf ("Don't know sector offsets for FLASH" + " type 0x%lx\n", info->flash_id); + return; + } +} + + +/*----------------------------------------------------------------------- + * Display FLASH device info + */ +void +flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("Missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_INTEL: + printf ("Intel "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F128J3A: + printf ("28F128J3A (128Mbit = 128K x 128)\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + if (info->size >= (1024 * 1024)) { + i = 20; + } else { + i = 10; + } + printf (" Size: %ld %cB in %d Sectors\n", + info->size >> i, + (i == 20) ? 'M' : 'k', + info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + + +/*----------------------------------------------------------------------- + * Get size and other information for a FLASH device. + * NOTE: The following code cannot be run from FLASH! + */ +static +ulong flash_get_size (vu_char *addr, flash_info_t *info) +{ +#define NO_FLASH 0 + + vu_char value[2]; + + /* + * Try to read the manufacturer ID + */ + addr[0] = SCS_READ_CMD; + addr[0] = SCS_READ_ID_CMD; + value[0] = addr[0]; + value[1] = addr[2]; + addr[0] = SCS_READ_CMD; + + PRINTF("Manuf. ID @ 0x%08lx: 0x%02x\n", (ulong)addr, value[0]); + switch (value[0]) { + case (INTEL_MANUFACT & 0xff): + info->flash_id = FLASH_MAN_INTEL; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (NO_FLASH); + } + + /* + * Read the device ID + */ + PRINTF("Device ID @ 0x%08lx: 0x%02x\n", (ulong)(&addr[2]), value[1]); + switch (value[1]) { + case (INTEL_ID_28F128J3A & 0xff): + info->flash_id += FLASH_28F128J3A; + info->sector_count = 128; + info->size = 16 * 1024 * 1024; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + return (NO_FLASH); + } + + if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CONFIG_SYS_MAX_FLASH_SECT); + info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; + } + return (info->size); +} + + +/*----------------------------------------------------------------------- + * Erase the specified sectors in the specified FLASH device + */ +int +flash_erase(flash_info_t *info, int s_first, int s_last) +{ + int flag, prot, sect; + ulong start, now, last; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) { + printf ("Can erase only Intel flash types - aborted\n"); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + start = get_timer (0); + last = start; + + /* + * Start erase on unprotected sectors + */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + vu_char *addr = (uchar *)(info->start[sect]); + vu_char status; + + /* + * Disable interrupts which might cause a timeout + */ + flag = disable_interrupts(); + + *addr = SCS_CLEAR_STATUS_CMD; + *addr = SCS_BLOCK_ERASE_CMD; + *addr = SCS_BLOCK_ERASE_RESUME_CMD; + + /* + * Re-enable interrupts if necessary + */ + if (flag) + enable_interrupts(); + + /* + * Wait at least 80us - let's wait 1 ms + */ + udelay (1000); + + while (((status = *addr) & SCS_SR7) != SCS_SR7) { + if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + *addr = SCS_BLOCK_ERASE_SUSPEND_CMD; + *addr = SCS_READ_CMD; + return 1; + } + + /* + * Show that we're waiting + */ + if ((now - last) > 1000) { /* 1 second */ + putc ('.'); + last = now; + } + } + *addr = SCS_READ_CMD; + } + } + printf (" done\n"); + return 0; +} + + +#ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER +/* + * Allocate a flash buffer, fill it with data and write it to the flash. + * 0 - OK + * 1 - Timeout on buffer request + * + * NOTE: After the last call to this function, WSM status needs to be checked! + */ +static int +write_flash_buffer8(flash_info_t *info_p, vu_char *src_p, vu_char *dest_p, + uint count) +{ + vu_char *block_addr_p = NULL; + vu_char *start_addr_p = NULL; + ulong blocksize = info_p->size / (ulong)info_p->sector_count; + + int i; + uint time = get_timer(0); + + PRINTF("%s:%d: src: 0x%p dest: 0x%p count: %d\n", + __FUNCTION__, __LINE__, src_p, dest_p, count); + + /* + * What block are we in? We already know that the source address is + * in the flash address range, but we also can't cross a block boundary. + * We assume that the block does not cross a boundary (we'll check before + * calling this function). + */ + for (i = 0; i < info_p->sector_count; ++i) { + if ( ((ulong)dest_p >= info_p->start[i]) && + ((ulong)dest_p < (info_p->start[i] + blocksize)) ) { + PRINTF("%s:%d: Dest addr 0x%p is in block %d @ 0x%.8lx\n", + __FUNCTION__, __LINE__, dest_p, i, info_p->start[i]); + block_addr_p = (vu_char *)info_p->start[i]; + break; + } + } + + /* + * Request a buffer + */ + *block_addr_p = SCS_WRITE_BUF_CMD; + while ((*block_addr_p & SCS_XSR7) != SCS_XSR7) { + if (get_timer(time) > CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT) { + PRINTF("%s:%d: Buffer allocation timeout @ 0x%p (waited %d mS)\n", + __FUNCTION__, __LINE__, block_addr_p, + CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT); + return 1; + } + *block_addr_p = SCS_WRITE_BUF_CMD; + } + + /* + * Fill the buffer with data + */ + start_addr_p = dest_p; + *block_addr_p = count - 1; /* flash device wants count - 1 */ + PRINTF("%s:%d: Fill buffer at block addr 0x%p\n", + __FUNCTION__, __LINE__, block_addr_p); + for (i = 0; i < count; i++) { + *start_addr_p++ = *src_p++; + } + + /* + * Flush buffer to flash + */ + *block_addr_p = SCS_PROGRAM_RESUME_CMD; +#if 1 + time = get_timer(0); + while ((*block_addr_p & SCS_SR7) != SCS_SR7) { + if (get_timer(time) > CONFIG_SYS_FLASH_WRITE_TOUT) { + PRINTF("%s:%d: Write timeout @ 0x%p (waited %d mS)\n", + __FUNCTION__, __LINE__, block_addr_p, CONFIG_SYS_FLASH_WRITE_TOUT); + return 1; + } + } + +#endif + return 0; +} +#endif + + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - Flash not identified + */ +int +write_buff(flash_info_t *info_p, uchar *src_p, ulong addr, ulong count) +{ + int rc = 0; +#ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER +#define FLASH_WRITE_BUF_SIZE 0x00000020 /* 32 bytes */ + int i; + uint bufs; + ulong buf_count; + vu_char *sp; + vu_char *dp; +#else + ulong wp; +#endif + + PRINTF("\n%s:%d: src: 0x%.8lx dest: 0x%.8lx size: %d (0x%.8lx)\n", + __FUNCTION__, __LINE__, (ulong)src_p, addr, (uint)count, count); + + if (info_p->flash_id == FLASH_UNKNOWN) { + return 4; + } + +#ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER + sp = src_p; + dp = (uchar *)addr; + + /* + * For maximum performance, we want to align the start address to + * the beginning of a write buffer boundary (i.e. A4-A0 of the + * start address = 0). See how many bytes are required to get to a + * write-buffer-aligned address. If that number is non-zero, do + * non buffered writes of the non-aligned data. By doing non-buffered + * writes, we avoid the problem of crossing a block (sector) boundary + * with buffered writes. + */ + buf_count = FLASH_WRITE_BUF_SIZE - (addr & (FLASH_WRITE_BUF_SIZE - 1)); + if (buf_count == FLASH_WRITE_BUF_SIZE) { /* already on a boundary */ + buf_count = 0; + } + if (buf_count > count) { /* not a full buffers worth of data to write */ + buf_count = count; + } + count -= buf_count; + + PRINTF("%s:%d: Write buffer alignment count = %ld\n", + __FUNCTION__, __LINE__, buf_count); + while (buf_count-- >= 1) { + if ((rc = write_data8(info_p, (ulong)dp++, *sp++)) != 0) { + return (rc); + } + } + + PRINTF("%s:%d: count = %ld\n", __FUNCTION__, __LINE__, count); + if (count == 0) { /* all done */ + PRINTF("%s:%d: Less than 1 buffer (%d) worth of bytes\n", + __FUNCTION__, __LINE__, FLASH_WRITE_BUF_SIZE); + return (rc); + } + + /* + * Now that we are write buffer aligned, write full or partial buffers. + * The fact that we are write buffer aligned automatically avoids + * crossing a block address during a write buffer operation. + */ + bufs = count / FLASH_WRITE_BUF_SIZE; + PRINTF("%s:%d: %d (0x%x) buffers to write\n", __FUNCTION__, __LINE__, + bufs, bufs); + while (bufs >= 1) { + rc = write_flash_buffer8(info_p, sp, dp, FLASH_WRITE_BUF_SIZE); + if (rc != 0) { + PRINTF("%s:%d: ** Error writing buf %d\n", + __FUNCTION__, __LINE__, bufs); + return (rc); + } + bufs--; + sp += FLASH_WRITE_BUF_SIZE; + dp += FLASH_WRITE_BUF_SIZE; + } + + /* + * Do the leftovers + */ + i = count % FLASH_WRITE_BUF_SIZE; + PRINTF("%s:%d: %d (0x%x) leftover bytes\n", __FUNCTION__, __LINE__, i, i); + if (i > 0) { + rc = write_flash_buffer8(info_p, sp, dp, i); + } + + sp = (vu_char*)info_p->start[0]; + *sp = SCS_READ_CMD; + return (rc); + +#else + wp = addr; + while (count-- >= 1) { + if((rc = write_data8(info_p, wp++, *src_p++)) != 0) + return (rc); + } + return 0; +#endif +} + + +/*----------------------------------------------------------------------- + * Write a byte to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int +write_data8 (flash_info_t *info, ulong dest, uchar data) +{ + vu_char *addr = (vu_char *)dest; + vu_char status; + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*addr & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + *addr = SCS_PROGRAM_CMD; + *addr = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + start = get_timer (0); + + while (((status = *addr) & SCS_SR7) != SCS_SR7) { + if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) { + *addr = SCS_READ_CMD; + return (1); + } + } + *addr = SCS_READ_CMD; + return (0); +} + +/* vim: set ts=4 sw=4 tw=78: */ diff --git a/qemu/roms/u-boot/board/gen860t/fpga.c b/qemu/roms/u-boot/board/gen860t/fpga.c new file mode 100644 index 000000000..dd0ef707d --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/fpga.c @@ -0,0 +1,362 @@ +/* + * (C) Copyright 2002 + * Rich Ireland, Enterasys Networks, rireland@enterasys.com. + * Keith Outwater, keith_outwater@mvis.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Virtex2 FPGA configuration support for the GEN860T computer + */ + +#include <common.h> +#include <virtex2.h> +#include <command.h> +#include "fpga.h" + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_FPGA) + +#if 0 +#define GEN860T_FPGA_DEBUG +#endif + +#ifdef GEN860T_FPGA_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/* + * Port bit numbers for the Selectmap controls + */ +#define FPGA_INIT_BIT_NUM 22 /* PB22 */ +#define FPGA_RESET_BIT_NUM 11 /* PC11 */ +#define FPGA_DONE_BIT_NUM 16 /* PB16 */ +#define FPGA_PROGRAM_BIT_NUM 7 /* PA7 */ + +/* Note that these are pointers to code that is in Flash. They will be + * relocated at runtime. + */ +xilinx_virtex2_slave_selectmap_fns fpga_fns = { + fpga_pre_config_fn, + fpga_pgm_fn, + fpga_init_fn, + fpga_err_fn, + fpga_done_fn, + fpga_clk_fn, + fpga_cs_fn, + fpga_wr_fn, + fpga_read_data_fn, + fpga_write_data_fn, + fpga_busy_fn, + fpga_abort_fn, + fpga_post_config_fn +}; + +xilinx_desc fpga[CONFIG_FPGA_COUNT] = { + {xilinx_virtex2, + slave_selectmap, + XILINX_XC2V3000_SIZE, + (void *) &fpga_fns, + 0} +}; + +/* + * Display FPGA revision information + */ +void print_fpga_revision (void) +{ + vu_long *rev_p = (vu_long *) 0x60000008; + + printf ("FPGA Revision 0x%.8lx" + " (Date %.2lx/%.2lx/%.2lx, Status \"%.1lx\", Version %.3lu)\n", + *rev_p, + ((*rev_p >> 28) & 0xf), + ((*rev_p >> 20) & 0xff), + ((*rev_p >> 12) & 0xff), + ((*rev_p >> 8) & 0xf), (*rev_p & 0xff)); +} + + +/* + * Perform a simple test of the FPGA to processor interface using the FPGA's + * inverting bus test register. The great thing about doing a read/write + * test on a register that inverts it's contents is that you avoid any + * problems with bus charging. + * Return 0 on failure, 1 on success. + */ +int test_fpga_ibtr (void) +{ + vu_long *ibtr_p = (vu_long *) 0x60000010; + vu_long readback; + vu_long compare; + int i; + int j; + int k; + int pass = 1; + + static const ulong bitpattern[] = { + 0xdeadbeef, /* magic ID pattern for debug */ + 0x00000001, /* single bit */ + 0x00000003, /* two adjacent bits */ + 0x00000007, /* three adjacent bits */ + 0x0000000F, /* four adjacent bits */ + 0x00000005, /* two non-adjacent bits */ + 0x00000015, /* three non-adjacent bits */ + 0x00000055, /* four non-adjacent bits */ + 0xaaaaaaaa, /* alternating 1/0 */ + }; + + for (i = 0; i < 1024; i++) { + for (j = 0; j < 31; j++) { + for (k = 0; + k < sizeof (bitpattern) / sizeof (bitpattern[0]); + k++) { + *ibtr_p = compare = (bitpattern[k] << j); + readback = *ibtr_p; + if (readback != ~compare) { + printf ("%s:%d: FPGA test fail: expected 0x%.8lx" " actual 0x%.8lx\n", __FUNCTION__, __LINE__, ~compare, readback); + pass = 0; + break; + } + } + if (!pass) + break; + } + if (!pass) + break; + } + if (pass) { + printf ("FPGA inverting bus test passed\n"); + print_fpga_revision (); + } else { + printf ("** FPGA inverting bus test failed\n"); + } + return pass; +} + + +/* + * Set the active-low FPGA reset signal. + */ +void fpga_reset (int assert) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + + PRINTF ("%s:%d: RESET ", __FUNCTION__, __LINE__); + if (assert) { + immap->im_ioport.iop_pcdat &= ~(0x8000 >> FPGA_RESET_BIT_NUM); + PRINTF ("asserted\n"); + } else { + immap->im_ioport.iop_pcdat |= (0x8000 >> FPGA_RESET_BIT_NUM); + PRINTF ("deasserted\n"); + } +} + + +/* + * Initialize the SelectMap interface. We assume that the mode and the + * initial state of all of the port pins have already been set! + */ +void fpga_selectmap_init (void) +{ + PRINTF ("%s:%d: Initialize SelectMap interface\n", __FUNCTION__, + __LINE__); + fpga_pgm_fn(false, false, 0); /* make sure program pin is inactive */ +} + + +/* + * Initialize the fpga. Return 1 on success, 0 on failure. + */ +int gen860t_init_fpga (void) +{ + int i; + + PRINTF ("%s:%d: Initialize FPGA interface\n", + __FUNCTION__, __LINE__); + fpga_init (); + fpga_selectmap_init (); + + for (i = 0; i < CONFIG_FPGA_COUNT; i++) { + PRINTF ("%s:%d: Adding fpga %d\n", __FUNCTION__, __LINE__, i); + fpga_add (fpga_xilinx, &fpga[i]); + } + return 1; +} + + +/* + * Set the FPGA's active-low SelectMap program line to the specified level + */ +int fpga_pgm_fn (int assert, int flush, int cookie) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + + PRINTF ("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__); + + if (assert) { + immap->im_ioport.iop_padat &= + ~(0x8000 >> FPGA_PROGRAM_BIT_NUM); + PRINTF ("asserted\n"); + } else { + immap->im_ioport.iop_padat |= + (0x8000 >> FPGA_PROGRAM_BIT_NUM); + PRINTF ("deasserted\n"); + } + return assert; +} + + +/* + * Test the state of the active-low FPGA INIT line. Return 1 on INIT + * asserted (low). + */ +int fpga_init_fn (int cookie) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + + PRINTF ("%s:%d: INIT check... ", __FUNCTION__, __LINE__); + if (immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_INIT_BIT_NUM)) { + PRINTF ("high\n"); + return 0; + } else { + PRINTF ("low\n"); + return 1; + } +} + + +/* + * Test the state of the active-high FPGA DONE pin + */ +int fpga_done_fn (int cookie) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + + PRINTF ("%s:%d: DONE check... ", __FUNCTION__, __LINE__); + if (immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_DONE_BIT_NUM)) { + PRINTF ("high\n"); + return FPGA_SUCCESS; + } else { + PRINTF ("low\n"); + return FPGA_FAIL; + } +} + + +/* + * Read FPGA SelectMap data. + */ +int fpga_read_data_fn (unsigned char *data, int cookie) +{ + vu_char *p = (vu_char *) SELECTMAP_BASE; + + *data = *p; +#if 0 + PRINTF ("%s: Read 0x%x into 0x%p\n", __FUNCTION__, (int) data, data); +#endif + return (int) data; +} + + +/* + * Write data to the FPGA SelectMap port + */ +int fpga_write_data_fn (unsigned char data, int flush, int cookie) +{ + vu_char *p = (vu_char *) SELECTMAP_BASE; + +#if 0 + PRINTF ("%s: Write Data 0x%x\n", __FUNCTION__, (int) data); +#endif + *p = data; + return (int) data; +} + + +/* + * Abort and FPGA operation + */ +int fpga_abort_fn (int cookie) +{ + PRINTF ("%s:%d: FPGA program sequence aborted\n", + __FUNCTION__, __LINE__); + return FPGA_FAIL; +} + + +/* + * FPGA pre-configuration function. Just make sure that + * FPGA reset is asserted to keep the FPGA from starting up after + * configuration. + */ +int fpga_pre_config_fn (int cookie) +{ + PRINTF ("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__); + fpga_reset(true); + return 0; +} + + +/* + * FPGA post configuration function. Blip the FPGA reset line and then see if + * the FPGA appears to be running. + */ +int fpga_post_config_fn (int cookie) +{ + int rc; + + PRINTF ("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__); + fpga_reset(true); + udelay (1000); + fpga_reset(false); + udelay (1000); + + /* + * Use the FPGA,s inverting bus test register to do a simple test of the + * processor interface. + */ + rc = test_fpga_ibtr (); + return rc; +} + + +/* + * Clock, chip select and write signal assert functions and error check + * and busy functions. These are only stubs because the GEN860T selectmap + * interface handles sequencing of control signals automatically (it uses + * a memory-mapped interface to the FPGA SelectMap port). The design of + * the interface guarantees that the SelectMap port cannot be overrun so + * no busy check is needed. A configuration error is signalled by INIT + * going low during configuration, so there is no need for a separate error + * function. + */ +int fpga_clk_fn (int assert_clk, int flush, int cookie) +{ + return assert_clk; +} + +int fpga_cs_fn (int assert_cs, int flush, int cookie) +{ + return assert_cs; +} + +int fpga_wr_fn (int assert_write, int flush, int cookie) +{ + return assert_write; +} + +int fpga_err_fn (int cookie) +{ + return 0; +} + +int fpga_busy_fn (int cookie) +{ + return 0; +} +#endif diff --git a/qemu/roms/u-boot/board/gen860t/fpga.h b/qemu/roms/u-boot/board/gen860t/fpga.h new file mode 100644 index 000000000..95c15c4f6 --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/fpga.h @@ -0,0 +1,26 @@ +/* + * (C) Copyright 2002 + * Rich Ireland, Enterasys Networks, rireland@enterasys.com. + * Keith Outwater, keith_outwater@mvis.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Virtex2 FPGA configuration support for the GEN860T computer + */ + +extern int gen860t_init_fpga(void); +extern int fpga_pgm_fn(int assert_pgm, int flush, int cookie); +extern int fpga_init_fn(int cookie); +extern int fpga_err_fn(int cookie); +extern int fpga_done_fn(int cookie); +extern int fpga_clk_fn(int assert_clk, int flush, int cookie); +extern int fpga_cs_fn(int assert_cs, int flush, int cookie); +extern int fpga_wr_fn(int assert_write, int flush, int cookie); +extern int fpga_read_data_fn(unsigned char *data, int cookie); +extern int fpga_write_data_fn(unsigned char data, int flush, int cookie); +extern int fpga_busy_fn(int cookie); +extern int fpga_abort_fn(int cookie ); +extern int fpga_pre_config_fn(int cookie ); +extern int fpga_post_config_fn(int cookie ); diff --git a/qemu/roms/u-boot/board/gen860t/gen860t.c b/qemu/roms/u-boot/board/gen860t/gen860t.c new file mode 100644 index 000000000..fe139f492 --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/gen860t.c @@ -0,0 +1,278 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvis.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <virtex2.h> +#include <common.h> +#include <mpc8xx.h> +#include <asm/8xx_immap.h> +#include "beeper.h" +#include "fpga.h" +#include "ioport.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_STATUS_LED +#include <status_led.h> +#endif + +#if defined(CONFIG_CMD_MII) && defined(CONFIG_MII) +#include <net.h> +#endif + +#if 0 +#define GEN860T_DEBUG +#endif + +#ifdef GEN860T_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/* + * The following UPM init tables were generated automatically by + * Motorola's MCUINIT program. See the README file for UPM to + * SDRAM pin assignments if you want to type this data into + * MCUINIT in order to reverse engineer the waveforms. + */ + +/* + * UPM initialization tables for MICRON MT48LC16M16A2TG SDRAM devices + * (UPMA) and Virtex FPGA SelectMap interface (UPMB). + * NOTE that unused areas of the table are used to hold NOP, precharge + * and mode register set sequences. + * + */ +#define UPMA_NOP_ADDR 0x5 +#define UPMA_PRECHARGE_ADDR 0x6 +#define UPMA_MRS_ADDR 0x12 + +#define UPM_SINGLE_READ_ADDR 0x00 +#define UPM_BURST_READ_ADDR 0x08 +#define UPM_SINGLE_WRITE_ADDR 0x18 +#define UPM_BURST_WRITE_ADDR 0x20 +#define UPM_REFRESH_ADDR 0x30 + +const uint sdram_upm_table[] = { + /* single read (offset 0x00 in upm ram) */ + 0x0e0fdc04, 0x01adfc04, 0x0fbffc00, 0x1fff5c05, + 0xffffffff, 0x0fffffcd, 0x0fff0fce, 0xefcfffff, + /* burst read (offset 0x08 in upm ram) */ + 0x0f0fdc04, 0x00fdfc04, 0xf0fffc00, 0xf0fffc00, + 0xf1fffc00, 0xfffffc00, 0xfffffc05, 0xffffffff, + 0xffffffff, 0xffffffff, 0x0ffffff4, 0x1f3d5ff4, + 0xfffffff4, 0xfffffff5, 0xffffffff, 0xffffffff, + /* single write (offset 0x18 in upm ram) */ + 0x0f0fdc04, 0x00ad3c00, 0x1fff5c05, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* burst write (offset 0x20 in upm ram) */ + 0x0f0fdc00, 0x10fd7c00, 0xf0fffc00, 0xf0fffc00, + 0xf1fffc04, 0xfffffc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff7ff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* refresh (offset 0x30 in upm ram) */ + 0x1ffddc84, 0xfffffc04, 0xfffffc04, 0xfffffc84, + 0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* exception (offset 0x3C in upm ram) */ +}; + +const uint selectmap_upm_table[] = { + /* single read (offset 0x00 in upm ram) */ + 0x88fffc06, 0x00fff404, 0x00fffc04, 0x33fffc00, + 0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff, + /* burst read (offset 0x08 in upm ram) */ + 0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* single write (offset 0x18 in upm ram) */ + 0x88fffc04, 0x00fff400, 0x77fffc05, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* burst write (offset 0x20 in upm ram) */ + 0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* refresh (offset 0x30 in upm ram) */ + 0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* exception (offset 0x3C in upm ram) */ + 0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff +}; + +/* + * Check board identity. Always successful (gives information only) + */ +int checkboard (void) +{ + char *s; + char buf[64]; + int i; + + i = getenv_f("board_id", buf, sizeof (buf)); + s = (i > 0) ? buf : NULL; + + if (s) { + printf ("%s ", s); + } else { + printf ("<unknown> "); + } + + i = getenv_f("serial#", buf, sizeof (buf)); + s = (i > 0) ? buf : NULL; + + if (s) { + printf ("S/N %s\n", s); + } else { + printf ("S/N <unknown>\n"); + } + + printf ("CPU at %s MHz, ", strmhz (buf, gd->cpu_clk)); + printf ("local bus at %s MHz\n", strmhz (buf, gd->bus_clk)); + return (0); +} + +/* + * Initialize SDRAM + */ +phys_size_t initdram (int board_type) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + volatile memctl8xx_t *memctl = &immr->im_memctl; + + upmconfig (UPMA, + (uint *) sdram_upm_table, + sizeof (sdram_upm_table) / sizeof (uint) + ); + + /* + * Setup MAMR register + */ + memctl->memc_mptpr = CONFIG_SYS_MPTPR_1BK_8K; + memctl->memc_mamr = CONFIG_SYS_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */ + + /* + * Map CS1* to SDRAM bank + */ + memctl->memc_or1 = CONFIG_SYS_OR1; + memctl->memc_br1 = CONFIG_SYS_BR1; + + /* + * Perform SDRAM initialization sequence: + * 1. Apply at least one NOP command + * 2. 100 uS delay (JEDEC standard says 200 uS) + * 3. Issue 4 precharge commands + * 4. Perform two refresh cycles + * 5. Program mode register + * + * Program SDRAM for standard operation, sequential burst, burst length + * of 4, CAS latency of 2. + */ + memctl->memc_mar = 0x00000000; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF (0) | UPMA_NOP_ADDR; + udelay (200); + memctl->memc_mar = 0x00000000; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF (4) | UPMA_PRECHARGE_ADDR; + + memctl->memc_mar = 0x00000000; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF (2) | UPM_REFRESH_ADDR; + + memctl->memc_mar = 0x00000088; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF (1) | UPMA_MRS_ADDR; + + memctl->memc_mar = 0x00000000; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF (0) | UPMA_NOP_ADDR; + /* + * Enable refresh + */ + memctl->memc_mamr |= MAMR_PTAE; + + return (SDRAM_SIZE); +} + +/* + * Disk On Chip (DOC) Millenium initialization. + * The DOC lives in the CS2* space + */ +#if defined(CONFIG_CMD_DOC) +void doc_init (void) +{ + printf ("Probing at 0x%.8x: ", DOC_BASE); + doc_probe (DOC_BASE); +} +#endif + +/* + * Miscellaneous intialization + */ +int misc_init_r (void) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + volatile memctl8xx_t *memctl = &immr->im_memctl; + + /* + * Set up UPMB to handle the Virtex FPGA SelectMap interface + */ + upmconfig (UPMB, (uint *) selectmap_upm_table, + sizeof (selectmap_upm_table) / sizeof (uint)); + + memctl->memc_mbmr = 0x0; + + config_mpc8xx_ioports (immr); + +#if defined(CONFIG_CMD_MII) + mii_init (); +#endif + +#if defined(CONFIG_FPGA) + gen860t_init_fpga (); +#endif + return 0; +} + +/* + * Final init hook before entering command loop. + */ +int last_stage_init (void) +{ +#if !defined(CONFIG_SC) + char buf[256]; + int i; + + /* + * Turn the beeper volume all the way down in case this is a warm boot. + */ + set_beeper_volume (-64); + init_beeper (); + + /* + * Read the environment to see what to do with the beeper + */ + i = getenv_f("beeper", buf, sizeof (buf)); + if (i > 0) { + do_beeper (buf); + } +#endif + return 0; +} + +/* + * Stub to make POST code happy. Can't self-poweroff, so just hang. + */ +void board_poweroff (void) +{ + puts ("### Please power off the board ###\n"); + while (1); +} diff --git a/qemu/roms/u-boot/board/gen860t/ioport.c b/qemu/roms/u-boot/board/gen860t/ioport.c new file mode 100644 index 000000000..7cd209b7a --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/ioport.c @@ -0,0 +1,331 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <mpc8xx.h> +#include <asm/8xx_immap.h> +#include "ioport.h" + +#if 0 +#define IOPORT_DEBUG +#endif + +#ifdef IOPORT_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/* + * The ioport configuration table. + */ +const mpc8xx_iop_conf_t iop_conf_tab[NUM_PORTS][PORT_BITS] = { + /* + * Port A configuration + * Pin Signal Type Active Initial state + * PA7 fpgaProgramLowOut Out Low High + * PA1 fpgaCoreVoltageFailLow In Low N/A + */ + { /* conf ppar psor pdir podr pdat pint function */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* No pin */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* No pin */ + /* PA15 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA14 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA13 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA12 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA11 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA10 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA9 */ { 1, 0, 0, 1, 0, 0, 0 }, /* grn bicolor LED 1*/ + /* PA8 */ { 1, 0, 0, 1, 0, 0, 0 }, /* red bicolor LED 1*/ + /* PA7 */ { 1, 0, 0, 1, 0, 1, 0 }, /* fpgaProgramLow */ + /* PA6 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA5 */ { 1, 0, 0, 1, 0, 0, 0 }, /* grn bicolor LED 0*/ + /* PA4 */ { 1, 0, 0, 1, 0, 0, 0 }, /* red bicolor LED 0*/ + /* PA3 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA2 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ +#if !defined(CONFIG_SC) + /* PA1 */ { 1, 0, 0, 0, 0, 0, 0 }, /* fpgaCoreVoltageFail*/ +#else + /* PA1 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ +#endif + /* PA0 */ { 0, 0, 0, 0, 0, 0, 0 } /* */ + }, + + /* + * Port B configuration + * Pin Signal Type Active Initial state + * PB14 docBusyLowIn In Low X + * PB15 gpio1Sig Out High Low + * PB16 fpgaDoneBi In High X + * PB17 swBitOkLowOut Out Low High + * PB19 speakerVolSig Out/Hi-Z High/Low High (Hi-Z) + * PB22 fpgaInitLowBi In Low X + * PB23 batteryOkSig In High X + * PB31 pulseCatcherClr Out High 0 + */ + { /* conf ppar psor pdir podr pdat pint function */ +#if !defined(CONFIG_SC) + /* PB31 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ +#else + /* PB31 */ { 1, 0, 0, 1, 0, 0, 0 }, /* pulseCatcherClr */ +#endif + /* PB30 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB29 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB28 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB27 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB26 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB25 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB24 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ +#if !defined(CONFIG_SC) + /* PB23 */ { 1, 0, 0, 0, 0, 0, 0 }, /* batteryOk */ +#else + /* PB23 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ +#endif + /* PB22 */ { 1, 0, 0, 0, 0, 0, 0 }, /* fpgaInitLowBi */ + /* PB21 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB20 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ +#if !defined(CONFIG_SC) + /* PB19 */ { 1, 0, 0, 1, 1, 1, 0 }, /* speakerVol */ +#else + /* PB19 */ { 0, 0, 0, 1, 1, 1, 0 }, /* */ +#endif + /* PB18 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB17 */ { 1, 0, 0, 1, 0, 1, 0 }, /* swBitOkLow */ + /* PB16 */ { 1, 0, 0, 0, 0, 0, 0 }, /* fpgaDone */ + /* PB15 */ { 1, 0, 0, 1, 0, 0, 0 }, /* gpio1 */ +#if !defined(CONFIG_SC) + /* PB14 */ { 1, 0, 0, 0, 0, 0, 0 } /* docBusyLow */ +#else + /* PB14 */ { 0, 0, 0, 0, 0, 0, 0 } /* */ +#endif + }, + + /* + * Port C configuration + * Pin Signal Type Active Initial state + * PC4 i2cBus1EnSig Out High High + * PC5 i2cBus2EnSig Out High High + * PC6 gpio0Sig Out High Low + * PC8 i2cBus3EnSig Out High High + * PC10 i2cBus4EnSig Out High High + * PC11 fpgaResetLowOut Out Low High + * PC12 systemBitOkIn In High X + * PC15 selfDreqLow In Low X + */ + { /* conf ppar psor pdir podr pdat pint function */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PC15 */ { 1, 0, 0, 0, 0, 0, 0 }, /* selfDreqLowIn */ + /* PC14 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PC13 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ +#if !defined(CONFIG_SC) + /* PC12 */ { 1, 0, 0, 0, 0, 0, 0 }, /* systemBitOkIn */ +#else + /* PC12 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ +#endif + /* PC11 */ { 1, 0, 0, 1, 0, 1, 0 }, /* fpgaResetLowOut */ +#if !defined(CONFIG_SC) + /* PC10 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus4EnSig */ +#else + /* PC10 */ { 0, 0, 0, 1, 0, 1, 0 }, /* */ +#endif + /* PC9 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ +#if !defined(CONFIG_SC) + /* PC8 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus3EnSig */ +#else + /* PC8 */ { 0, 0, 0, 1, 0, 1, 0 }, /* */ +#endif + /* PC7 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PC6 */ { 1, 0, 0, 1, 0, 1, 0 }, /* gpio0 */ +#if !defined(CONFIG_SC) + /* PC5 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus2EnSig */ + /* PC4 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus1EnSig */ +#else + /* PC5 */ { 0, 0, 0, 1, 0, 1, 0 }, /* */ + /* PC4 */ { 0, 0, 0, 1, 0, 1, 0 }, /* */ +#endif + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 } /* */ + }, + + /* + * Port D configuration + */ + { /* conf ppar psor pdir podr pdat pint function */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD15 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD14 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD13 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD12 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD11 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD10 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD9 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD8 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD7 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD6 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD5 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD4 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD3 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 } /* */ + } +}; + +/* + * Configure the MPC8XX I/O ports per the ioport configuration table + * (taken from ./arch/powerpc/cpu/mpc8260/cpu_init.c) + */ +void config_mpc8xx_ioports (volatile immap_t * immr) +{ + int portnum; + + for (portnum = 0; portnum < NUM_PORTS; portnum++) { + uint pmsk = 0, ppar = 0, psor = 0, pdir = 0; + uint podr = 0, pdat = 0, pint = 0; + uint msk = 1; + mpc8xx_iop_conf_t *iopc = + (mpc8xx_iop_conf_t *) & iop_conf_tab[portnum][0]; + mpc8xx_iop_conf_t *eiopc = iopc + PORT_BITS; + + /* + * For all ports except port B, ignore the two don't care entries + * in the configuration tables. + */ + if (portnum != 1) { + iopc = (mpc8xx_iop_conf_t *) & + iop_conf_tab[portnum][2]; + } + + /* + * NOTE: index 0 refers to pin 17, index 17 refers to pin 0 + */ + while (iopc < eiopc) { + if (iopc->conf) { + pmsk |= msk; + if (iopc->ppar) + ppar |= msk; + if (iopc->psor) + psor |= msk; + if (iopc->pdir) + pdir |= msk; + if (iopc->podr) + podr |= msk; + if (iopc->pdat) + pdat |= msk; + if (iopc->pint) + pint |= msk; + } + msk <<= 1; + iopc++; + } + + PRINTF ("%s:%d:\n portnum=%d ", __FUNCTION__, __LINE__, + portnum); +#ifdef IOPORT_DEBUG + switch (portnum) { + case 0: + printf ("(A)\n"); + break; + case 1: + printf ("(B)\n"); + break; + case 2: + printf ("(C)\n"); + break; + case 3: + printf ("(D)\n"); + break; + default: + printf ("(?)\n"); + break; + } +#endif + PRINTF (" ppar=0x%.8x pdir=0x%.8x podr=0x%.8x\n" + " pdat=0x%.8x psor=0x%.8x pint=0x%.8x pmsk=0x%.8x\n", + ppar, pdir, podr, pdat, psor, pint, pmsk); + + /* + * Have to handle the ioports on a port-by-port basis since there + * are three different flavors. + */ + if (pmsk != 0) { + uint tpmsk = ~pmsk; + + if (0 == portnum) { /* port A */ + immr->im_ioport.iop_papar &= tpmsk; + immr->im_ioport.iop_padat = + (immr->im_ioport. + iop_padat & tpmsk) | pdat; + immr->im_ioport.iop_padir = + (immr->im_ioport. + iop_padir & tpmsk) | pdir; + immr->im_ioport.iop_paodr = + (immr->im_ioport. + iop_paodr & tpmsk) | podr; + immr->im_ioport.iop_papar |= ppar; + } else if (1 == portnum) { /* port B */ + immr->im_cpm.cp_pbpar &= tpmsk; + immr->im_cpm.cp_pbdat = + (immr->im_cpm. + cp_pbdat & tpmsk) | pdat; + immr->im_cpm.cp_pbdir = + (immr->im_cpm. + cp_pbdir & tpmsk) | pdir; + immr->im_cpm.cp_pbodr = + (immr->im_cpm. + cp_pbodr & tpmsk) | podr; + immr->im_cpm.cp_pbpar |= ppar; + } else if (2 == portnum) { /* port C */ + immr->im_ioport.iop_pcpar &= tpmsk; + immr->im_ioport.iop_pcdat = + (immr->im_ioport. + iop_pcdat & tpmsk) | pdat; + immr->im_ioport.iop_pcdir = + (immr->im_ioport. + iop_pcdir & tpmsk) | pdir; + immr->im_ioport.iop_pcint = + (immr->im_ioport. + iop_pcint & tpmsk) | pint; + immr->im_ioport.iop_pcso = + (immr->im_ioport. + iop_pcso & tpmsk) | psor; + immr->im_ioport.iop_pcpar |= ppar; + } else if (3 == portnum) { /* port D */ + immr->im_ioport.iop_pdpar &= tpmsk; + immr->im_ioport.iop_pddat = + (immr->im_ioport. + iop_pddat & tpmsk) | pdat; + immr->im_ioport.iop_pddir = + (immr->im_ioport. + iop_pddir & tpmsk) | pdir; + immr->im_ioport.iop_pdpar |= ppar; + } + } + } + + PRINTF ("%s:%d: Port A:\n papar=0x%.4x padir=0x%.4x" + " paodr=0x%.4x\n padat=0x%.4x\n", __FUNCTION__, __LINE__, + immr->im_ioport.iop_papar, immr->im_ioport.iop_padir, + immr->im_ioport.iop_paodr, immr->im_ioport.iop_padat); + PRINTF ("%s:%d: Port B:\n pbpar=0x%.8x pbdir=0x%.8x" + " pbodr=0x%.8x\n pbdat=0x%.8x\n", __FUNCTION__, __LINE__, + immr->im_cpm.cp_pbpar, immr->im_cpm.cp_pbdir, + immr->im_cpm.cp_pbodr, immr->im_cpm.cp_pbdat); + PRINTF ("%s:%d: Port C:\n pcpar=0x%.4x pcdir=0x%.4x" + " pcdat=0x%.4x\n pcso=0x%.4x pcint=0x%.4x\n ", + __FUNCTION__, __LINE__, immr->im_ioport.iop_pcpar, + immr->im_ioport.iop_pcdir, immr->im_ioport.iop_pcdat, + immr->im_ioport.iop_pcso, immr->im_ioport.iop_pcint); + PRINTF ("%s:%d: Port D:\n pdpar=0x%.4x pddir=0x%.4x" + " pddat=0x%.4x\n", __FUNCTION__, __LINE__, + immr->im_ioport.iop_pdpar, immr->im_ioport.iop_pddir, + immr->im_ioport.iop_pddat); +} diff --git a/qemu/roms/u-boot/board/gen860t/ioport.h b/qemu/roms/u-boot/board/gen860t/ioport.h new file mode 100644 index 000000000..4ac2aa4dd --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/ioport.h @@ -0,0 +1,26 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvis.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#define NUM_PORTS 4 +#define PORT_BITS 18 + +/* + * This structure provides configuration information for one port pin. + * We include all fields needed to initialize any of the ioports. + */ +typedef struct { + unsigned char conf:1; /* If 1, configure this port */ + unsigned char ppar:1; /* Port Pin Assignment Register */ + unsigned char psor:1; /* Port Special Options Register */ + unsigned char pdir:1; /* Port Data Direction Register */ + unsigned char podr:1; /* Port Open Drain Register */ + unsigned char pdat:1; /* Port Data Register */ + unsigned char pint:1; /* Port Interrupt Register */ +} mpc8xx_iop_conf_t; + +extern void config_mpc8xx_ioports(volatile immap_t *immr); diff --git a/qemu/roms/u-boot/board/gen860t/u-boot-flashenv.lds b/qemu/roms/u-boot/board/gen860t/u-boot-flashenv.lds new file mode 100644 index 000000000..7a4a7637e --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/u-boot-flashenv.lds @@ -0,0 +1,92 @@ +/* + * Linker command file for the GEN860T board when the environment is + * stored in flash memory. + * + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_ARCH(powerpc) +SECTIONS +{ + /* + * Read-only sections, merged into text segment: + */ + . = + SIZEOF_HEADERS; + .text : + { + arch/powerpc/cpu/mpc8xx/start.o (.text*) + arch/powerpc/cpu/mpc8xx/traps.o (.text*) + + *(.text*) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } + + /* + * Read-write section, merged into data segment: + */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + KEEP(*(.got)) + _GOT2_TABLE_ = .; + KEEP(*(.got2)) + _FIXUP_TABLE_ = .; + KEEP(*(.fixup)) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data: + { + *(.data*) + *(.sdata*) + } + _edata = .; + PROVIDE (edata = .); + + . = .; + + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss (NOLOAD) : + { + *(.bss*) + *(.sbss*) + *(COMMON) + . = ALIGN(4); + } + + __bss_end = . ; + PROVIDE (end = .); + + .ppcenv: + { + . = env_offset; + common/env_embedded.o + } +} diff --git a/qemu/roms/u-boot/board/gen860t/u-boot.lds b/qemu/roms/u-boot/board/gen860t/u-boot.lds new file mode 100644 index 000000000..3371c0a3e --- /dev/null +++ b/qemu/roms/u-boot/board/gen860t/u-boot.lds @@ -0,0 +1,87 @@ +/* + * Linker command file for the GEN860T board. + * + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_ARCH(powerpc) +SECTIONS +{ + /* + * Read-only sections, merged into text segment: + */ + . = + SIZEOF_HEADERS; + .text : + { + arch/powerpc/cpu/mpc8xx/start.o (.text*) + arch/powerpc/cpu/mpc8xx/traps.o (.text*) + + *(.text*) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } + + /* + * Read-write section, merged into data segment: + */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + _GOT2_TABLE_ = .; + KEEP(*(.got2)) + KEEP(*(.got)) + PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4); + _FIXUP_TABLE_ = .; + KEEP(*(.fixup)) + } + __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data*) + *(.sdata*) + } + _edata = .; + PROVIDE (edata = .); + + . = .; + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + + . = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss (NOLOAD) : + { + *(.bss*) + *(.sbss*) + *(COMMON) + . = ALIGN(4); + } + __bss_end = . ; + PROVIDE (end = .); +} |