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/lwmon | |
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/lwmon')
-rw-r--r-- | qemu/roms/u-boot/board/lwmon/Makefile | 8 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/lwmon/README.keybd | 126 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/lwmon/flash.c | 632 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/lwmon/lwmon.c | 1071 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/lwmon/pcmcia.c | 234 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/lwmon/u-boot.lds | 82 | ||||
-rw-r--r-- | qemu/roms/u-boot/board/lwmon/u-boot.lds.debug | 122 |
7 files changed, 2275 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/board/lwmon/Makefile b/qemu/roms/u-boot/board/lwmon/Makefile new file mode 100644 index 000000000..599a61378 --- /dev/null +++ b/qemu/roms/u-boot/board/lwmon/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2001-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = lwmon.o flash.o pcmcia.o diff --git a/qemu/roms/u-boot/board/lwmon/README.keybd b/qemu/roms/u-boot/board/lwmon/README.keybd new file mode 100644 index 000000000..5e5144e56 --- /dev/null +++ b/qemu/roms/u-boot/board/lwmon/README.keybd @@ -0,0 +1,126 @@ + +Tastaturabfrage: + +Die Implementierung / Decodierung beruht auf den Angaben aus dem Do- +kument "PIC LWE-Tastatur" in der Fassung vom 9. 3. 2001, insbesonde- +re Tabelle 3 im Kapitel 4.3 Tastencodes. In U-Boot werden die vom +Keyboard-Controller gelesenen Daten hexadezimal codiert in der auto- +matisch angelegten Environment-Variablen "keybd" übergeben. Ist kei- +ne Taste gedrückt worden, steht dort: + + keybd=000000000000000000 + +Der decodierte Tastencode ("keybd") kann mit den "bootargs" an den +Linux-Kernel übergeben und dort z. B. in einem Device-Treiber oder +einer Applikation ausgewertet werden. + + +Sonderfunktionen beim Booten: + +Es lassen sich eine oder mehrere (beliebig viele) Tasten oder Tasten- +kombinationen definieren, die Sonderfunktionen auslösen, wenn diese +Tasten beim Booten (Reset) gedrückt sind. + +Wird eine eingestellte Taste bzw. Tastenkombination erkannt, so wird +in U-Boot noch vor dem Start des "Countdown" und somit vor jedem an- +deren Kommando der Inhalt einer dieser Taste bzw. Tastenkombination +zugeordneten Environment-Variablen ausführen. + + +Die Environment-Variable "magic_keys" wird als Liste von Zeichen ver- +standen, die als Suffix an den Namen "key_magic" angefügt werden und +so die Namen der Environment-Variablen definieren, mit denen die +Tasten (-kombinationen) festgelegt werden: + +Ist "magic_keys" NICHT definiert, so wird nur die in der Environment- +Variablen "key_magic" codierte Tasten (-kombination) geprüft, und +ggf. der Inhalt der Environment-Variablen "key_cmd" ausgeführt (ge- +nauer: der Inhalt von "key_cmd" wird der Variablen "preboot" zugewie- +sen, die ausgeführt wird, unmittelbar bevor die interaktive Kommando- +interpretation beginnt). + +Enthält "magic_keys" z. B. die Zeichenkette "0123CB*", so werden +nacheinander folgende Aktionen ausgeführt: + + prüfe Tastencode ggf. führe aus Kommando + in Variable in Variable + ----------------------------------- + key_magic0 ==> key_cmd0 + key_magic1 ==> key_cmd1 + key_magic2 ==> key_cmd2 + key_magic3 ==> key_cmd3 + key_magicC ==> key_cmdC + key_magicB ==> key_cmdB + key_magicA ==> key_cmdA + key_magic* ==> key_cmd* + +Hinweis: sobald ein aktivierter Tastencode erkannt wurde, wird die +Bearbeitung abgebrochen; es wird daher höchstens eines der definier- +ten Kommandos ausgeführt, wobei die Priorität durch die Suchreihen- +folge festgelegt wird, also durch die Reihenfolge der Zeichen in der +Varuiablen "magic_keys". + + +Die Codierung der Tasten, die beim Booten gedrückt werden müssen, um +eine Funktion auszulösen, erfolgt nach der Tastaturtabelle. + +Die Definitionen + + => setenv key_magic0 3a+3b + => setenv key_cmd0 setenv bootdelay 30 + +bedeuten dementsprechend, daß die Tasten mit den Codes 0x3A (Taste +"F1") und 0x3B (Taste "F2") gleichzeitig gedrückt werden müssen. Sie +können dort eine beliebige Tastenkombination eintragen (jeweils 2 +Zeichen für die Hex-Codes der Tasten, und '+' als Trennzeichen). + +Wird die eingestellte Tastenkombination erkannt, so wird in U-Boot +noch vor dem Start des "Countdown" und somit vor jedem anderen Kom- +mando das angebene Kommando ausgeführt und somit ein langes Boot- +Delay eingetragen. + +Praktisch könnten Sie also in U-Boot "bootdelay" auf 0 setzen und +somit stets ohne jede User-Interaktion automatisch booten, außer, +wenn die beiden Tasten "F1" und "F2" beim Booten gedrückt werden: +dann würde ein Boot-Delay von 30 Sekunden eingefügt. + + +Hinweis: dem Zeichen '#' kommt innerhalb von "magic_keys" eine beson- +dere Bedeutung zu: die dadurch definierte Key-Sequenz schaltet den +Monitor in den "Debug-Modus" - das bedeutet zunächst, daß alle weite- +ren Meldungen von U-Boot über das LCD-Display ausgegeben werden; +außerdem kann man durch das mit dieser Tastenkombination verknüpfte +Kommando z. B. die Linux-Bootmeldungen ebenfalls auf das LCD-Display +legen, so daß der Boot-Vorgang direkt und ohne weitere Hilfsmittel +analysiert werden kann. + +Beispiel: + +In U-Boot werden folgende Environment-Variablen gesetzt und abgespei- +chert: + +(1) => setenv magic_keys 01234#X +(2) => setenv key_cmd# setenv addfb setenv bootargs \\${bootargs} console=tty0 console=ttyS1,\\${baudrate} +(3) => setenv nfsargs setenv bootargs root=/dev/nfs rw nfsroot=\${serverip}:\${rootpath} +(4) => setenv addip setenv bootargs \${bootargs} ip=\${ipaddr}:\${serverip}:\${gatewayip}:\${netmask}:\${hostname}::off panic=1 +(5) => setenv addfb setenv bootargs \${bootargs} console=ttyS1,\${baudrate} +(6) => setenv bootcmd bootp\;run nfsargs\;run addip\;run addfb\;bootm + +Hierbei wird die Linux Commandline (in der Variablen "bootargs") im +Boot-Kommando "bootcmd" (6) schrittweise zusammengesetzt: zunächst +werden die für Root-Filesystem über NFS erforderlichen Optionen ge- +setzt ("run nfsargs", vgl. (3)), dann die Netzwerkkonfiguration an- +gefügt ("run addip", vgl. (4)), und schließlich die Systemconsole +definiert ("run addfb"). + +Dabei wird im Normalfall die Definition (5) verwendt; wurde aller- +dings beim Reset die entsprechende Taste gedrückt gehalten, so wird +diese Definition bei der Ausführung des in (2) definierten Kommandos +überschrieben, so daß Linux die Bootmeldungen auch über das Frame- +buffer-Device (=LCD-Display) ausgibt. + +Beachten Sie die Verdoppelung der '\'-Escapes in der Definition von +"key_cmd#" - diese ist erforderlich, weil der String _zweimal_ inter- +pretiert wird: das erste Mal bei der Eingabe von "key_cmd#", das +zweite Mal, wenn der String (als Inhalt von "preboot") ausgeführt +wird. diff --git a/qemu/roms/u-boot/board/lwmon/flash.c b/qemu/roms/u-boot/board/lwmon/flash.c new file mode 100644 index 000000000..cb60c418a --- /dev/null +++ b/qemu/roms/u-boot/board/lwmon/flash.c @@ -0,0 +1,632 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* #define DEBUG */ + +#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 + +/*---------------------------------------------------------------------*/ + +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_data (flash_info_t *info, ulong dest, ulong data); +#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE +static int write_data_buf (flash_info_t * info, ulong dest, uchar * cp, int len); +#endif +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + */ + +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, size_b1; + int i; + + /* Init: no FLASHes known */ + for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + debug ("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_PRELIM); + + size_b0 = flash_get_size((vu_long *)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); + } + + debug ("## Get flash bank 2 size @ 0x%08x\n",FLASH_BASE1_PRELIM); + + size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); + + debug ("## Prelim. Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1); + + if (size_b1 > size_b0) { + printf ("## ERROR: " + "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n", + size_b1, size_b1<<20, + size_b0, size_b0<<20 + ); + flash_info[0].flash_id = FLASH_UNKNOWN; + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[0].sector_count = -1; + flash_info[1].sector_count = -1; + flash_info[0].size = 0; + flash_info[1].size = 0; + return (0); + } + + debug ("## Before remap: " + "BR0: 0x%08x OR0: 0x%08x " + "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) | CONFIG_SYS_OR_TIMING_FLASH | + OR_CSNT_SAM | OR_ACS_DIV1; + memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_PS_32 | BR_V; + + debug ("## 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_long *)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 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 + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1, + &flash_info[0]); +#endif + + if (size_b1) { + memctl->memc_or1 = (-size_b1 & 0xFFFF8000) | CONFIG_SYS_OR_TIMING_FLASH | + OR_CSNT_SAM | OR_ACS_DIV1; + memctl->memc_br1 = ((CONFIG_SYS_FLASH_BASE + size_b0) & BR_BA_MSK) | + BR_PS_32 | BR_V; + + debug ("## BR1: 0x%08x OR1: 0x%08x\n", + memctl->memc_br1, memctl->memc_or1); + + /* Re-do sizing to get full correct info */ + size_b1 = flash_get_size((vu_long *)(CONFIG_SYS_FLASH_BASE + size_b0), + &flash_info[1]); + + flash_info[1].size = size_b1; + + flash_get_offsets (CONFIG_SYS_FLASH_BASE + size_b0, &flash_info[1]); + +#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_SYS_MONITOR_BASE, + CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1, + &flash_info[1]); +#endif + +#ifdef CONFIG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1, + &flash_info[1]); +#endif + } else { + memctl->memc_br1 = 0; /* invalidate bank */ + memctl->memc_or1 = 0; /* invalidate bank */ + + debug ("## DISABLE BR1: 0x%08x OR1: 0x%08x\n", + memctl->memc_br1, memctl->memc_or1); + + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[1].sector_count = -1; + flash_info[1].size = 0; + } + + debug ("## Final Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1); + + return (size_b0 + size_b1); +} + +/*----------------------------------------------------------------------- + */ +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 += 0x00020000 * 2; /* 128k * 2 chips per bank */ + } + return; + + default: + printf ("Don't know sector ofsets for flash type 0x%lx\n", + info->flash_id); + return; + } +} + +/*----------------------------------------------------------------------- + */ +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_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("Fujitsu "); break; + case FLASH_MAN_SST: printf ("SST "); break; + case FLASH_MAN_STM: printf ("STM "); break; + case FLASH_MAN_INTEL: printf ("Intel "); break; + case FLASH_MAN_MT: printf ("MT "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F320J3A: printf ("28F320J3A (32Mbit = 128K x 32)\n"); + break; + case FLASH_28F640J3A: printf ("28F640J3A (64Mbit = 128K x 64)\n"); + break; + case FLASH_28F128J3A: printf ("28F128J3A (128Mbit = 128K x 128)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + if (info->size >= (1 << 20)) { + 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; +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + ulong value; + + /* Read Manufacturer ID */ + addr[0] = 0x00900090; + value = addr[0]; + + debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value); + + switch (value) { + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + case STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; + case INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + addr[0] = 0x00FF00FF; /* restore read mode */ + return (0); /* no or unknown flash */ + } + + value = addr[1]; /* device ID */ + + debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value); + + switch (value) { + case INTEL_ID_28F320J3A: + info->flash_id += FLASH_28F320J3A; + info->sector_count = 32; + info->size = 0x00400000 * 2; + break; /* => 8 MB */ + + case INTEL_ID_28F640J3A: + info->flash_id += FLASH_28F640J3A; + info->sector_count = 64; + info->size = 0x00800000 * 2; + break; /* => 16 MB */ + + case INTEL_ID_28F128J3A: + info->flash_id += FLASH_28F128J3A; + info->sector_count = 128; + info->size = 0x01000000 * 2; + break; /* => 32 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + addr[0] = 0x00FF00FF; /* restore read mode */ + return (0); /* => no or unknown 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; + } + + addr[0] = 0x00FF00FF; /* restore read mode */ + + return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + int flag, prot, sect; + ulong start, now, last; + + debug ("flash_erase: first: %d last: %d\n", s_first, s_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_long *addr = (vu_long *)(info->start[sect]); + unsigned long status; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + *addr = 0x00600060; /* clear lock bit setup */ + *addr = 0x00D000D0; /* clear lock bit confirm */ + + udelay (1000); + /* This takes awfully long - up to 50 ms and more */ + while (((status = *addr) & 0x00800080) != 0x00800080) { + if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + *addr = 0x00FF00FF; /* reset to read mode */ + return 1; + } + + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + udelay (1000); /* to trigger the watchdog */ + } + + *addr = 0x00500050; /* clear status register */ + *addr = 0x00200020; /* erase setup */ + *addr = 0x00D000D0; /* erase confirm */ + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + while (((status = *addr) & 0x00800080) != 0x00800080) { + if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + *addr = 0x00B000B0; /* suspend erase */ + *addr = 0x00FF00FF; /* reset to read mode */ + return 1; + } + + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + udelay (1000); /* to trigger the watchdog */ + } + + *addr = 0x00FF00FF; /* reset to read mode */ + } + } + printf (" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - Flash not identified + */ + +#define FLASH_WIDTH 4 /* flash bus width in bytes */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + + if (info->flash_id == FLASH_UNKNOWN) { + return 4; + } + + wp = (addr & ~(FLASH_WIDTH-1)); /* get lower FLASH_WIDTH aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i=0, cp=wp; i<l; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + for (; i<FLASH_WIDTH && cnt>0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + if ((rc = write_data(info, wp, data)) != 0) { + return (rc); + } + wp += FLASH_WIDTH; + } + + /* + * handle FLASH_WIDTH aligned part + */ +#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE + while(cnt >= FLASH_WIDTH) { + i = CONFIG_SYS_FLASH_BUFFER_SIZE > cnt ? + (cnt & ~(FLASH_WIDTH - 1)) : CONFIG_SYS_FLASH_BUFFER_SIZE; + if((rc = write_data_buf(info, wp, src,i)) != 0) + return rc; + wp += i; + src += i; + cnt -=i; + } +#else + while (cnt >= FLASH_WIDTH) { + data = 0; + for (i=0; i<FLASH_WIDTH; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_data(info, wp, data)) != 0) { + return (rc); + } + wp += FLASH_WIDTH; + cnt -= FLASH_WIDTH; + } +#endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */ + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i<FLASH_WIDTH; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + return (write_data(info, wp, data)); +} + +/*----------------------------------------------------------------------- + * Check flash status, returns: + * 0 - OK + * 1 - timeout + */ +static int flash_status_check(vu_long *addr, ulong tout, char * prompt) +{ + ulong status; + ulong start; + + /* Wait for command completion */ + start = get_timer (0); + while(((status = *addr) & 0x00800080) != 0x00800080) { + if (get_timer(start) > tout) { + printf("Flash %s timeout at address %p\n", prompt, addr); + *addr = 0x00FF00FF; /* restore read mode */ + return (1); + } + } + return 0; +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_data (flash_info_t *info, ulong dest, ulong data) +{ + vu_long *addr = (vu_long *)dest; + 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 = 0x00400040; /* write setup */ + *addr = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + if (flash_status_check(addr, CONFIG_SYS_FLASH_WRITE_TOUT, "write") != 0) { + return (1); + } + + *addr = 0x00FF00FF; /* restore read mode */ + + return (0); +} + +#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE +/*----------------------------------------------------------------------- + * Write a buffer to Flash, returns: + * 0 - OK + * 1 - write timeout + */ +static int write_data_buf(flash_info_t * info, ulong dest, uchar * cp, int len) +{ + vu_long *addr = (vu_long *)dest; + int sector; + int cnt; + int retcode; + vu_long * src = (vu_long *)cp; + vu_long * dst = (vu_long *)dest; + + /* find sector */ + for(sector = info->sector_count - 1; sector >= 0; sector--) { + if(dest >= info->start[sector]) + break; + } + + *addr = 0x00500050; /* clear status */ + *addr = 0x00e800e8; /* write buffer */ + + if((retcode = flash_status_check(addr, CONFIG_SYS_FLASH_BUFFER_WRITE_TOUT, + "write to buffer")) == 0) { + cnt = len / FLASH_WIDTH; + *addr = (cnt-1) | ((cnt-1) << 16); + while(cnt-- > 0) { + *dst++ = *src++; + } + *addr = 0x00d000d0; /* write buffer confirm */ + retcode = flash_status_check(addr, CONFIG_SYS_FLASH_BUFFER_WRITE_TOUT, + "buffer write"); + } + *addr = 0x00FF00FF; /* restore read mode */ + *addr = 0x00500050; /* clear status */ + return retcode; +} +#endif /* CONFIG_SYS_USE_FLASH_BUFFER_WRITE */ + +/*----------------------------------------------------------------------- + */ diff --git a/qemu/roms/u-boot/board/lwmon/lwmon.c b/qemu/roms/u-boot/board/lwmon/lwmon.c new file mode 100644 index 000000000..225b1ef25 --- /dev/null +++ b/qemu/roms/u-boot/board/lwmon/lwmon.c @@ -0,0 +1,1071 @@ +/*********************************************************************** + * +M* Modul: lwmon.c +M* +M* Content: LWMON specific U-Boot commands. + * + * (C) Copyright 2001, 2002 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + * + * SPDX-License-Identifier: GPL-2.0+ + ***********************************************************************/ + +/*---------------------------- Headerfiles ----------------------------*/ +#include <common.h> +#include <mpc8xx.h> +#include <commproc.h> +#include <i2c.h> +#include <command.h> +#include <malloc.h> +#include <post.h> +#include <serial.h> + +#include <linux/types.h> +#include <linux/string.h> /* for strdup */ + +DECLARE_GLOBAL_DATA_PTR; + +/*------------------------ Local prototypes ---------------------------*/ +static long int dram_size (long int, long int *, long int); +static void kbd_init (void); +static int compare_magic (uchar *kbd_data, uchar *str); + + +/*--------------------- Local macros and constants --------------------*/ +#define _NOT_USED_ 0xFFFFFFFF + +#ifdef CONFIG_MODEM_SUPPORT +static int key_pressed(void); +extern void disable_putc(void); +#endif /* CONFIG_MODEM_SUPPORT */ + +/* + * 66 MHz SDRAM access using UPM A + */ +const uint sdram_table[] = +{ +#if defined(CONFIG_SYS_MEMORY_75) || defined(CONFIG_SYS_MEMORY_8E) + /* + * Single Read. (Offset 0 in UPM RAM) + */ + 0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBAFC00, + 0x1FF5FC47, /* last */ + /* + * SDRAM Initialization (offset 5 in UPM RAM) + * + * This is no UPM entry point. The following definition uses + * the remaining space to establish an initialization + * sequence, which is executed by a RUN command. + * + */ + 0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */ + /* + * Burst Read. (Offset 8 in UPM RAM) + */ + 0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00, + 0xF0AFFC00, 0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Single Write. (Offset 18 in UPM RAM) + */ + 0x1F2DFC04, 0xEEABBC00, 0x01B27C04, 0x1FF5FC47, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Burst Write. (Offset 20 in UPM RAM) + */ + 0x1F0DFC04, 0xEEABBC00, 0x10A77C00, 0xF0AFFC00, + 0xF0AFFC00, 0xE1BAFC04, 0x01FF5FC47, /* last */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Refresh (Offset 30 in UPM RAM) + */ + 0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, + 0xFFFFFC84, 0xFFFFFC07, /* last */ + _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Exception. (Offset 3c in UPM RAM) + */ + 0x7FFFFC07, /* last */ + 0xFFFFFCFF, 0xFFFFFCFF, 0xFFFFFCFF, +#endif +#ifdef CONFIG_SYS_MEMORY_7E + /* + * Single Read. (Offset 0 in UPM RAM) + */ + 0x0E2DBC04, 0x11AF7C04, 0xEFBAFC00, 0x1FF5FC47, /* last */ + _NOT_USED_, + /* + * SDRAM Initialization (offset 5 in UPM RAM) + * + * This is no UPM entry point. The following definition uses + * the remaining space to establish an initialization + * sequence, which is executed by a RUN command. + * + */ + 0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */ + /* + * Burst Read. (Offset 8 in UPM RAM) + */ + 0x0E2DBC04, 0x10AF7C04, 0xF0AFFC00, 0xF0AFFC00, + 0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Single Write. (Offset 18 in UPM RAM) + */ + 0x0E29BC04, 0x01B27C04, 0x1FF5FC47, /* last */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Burst Write. (Offset 20 in UPM RAM) + */ + 0x0E29BC04, 0x10A77C00, 0xF0AFFC00, 0xF0AFFC00, + 0xE1BAFC04, 0x1FF5FC47, /* last */ + _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Refresh (Offset 30 in UPM RAM) + */ + 0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, + 0xFFFFFC84, 0xFFFFFC07, /* last */ + _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Exception. (Offset 3c in UPM RAM) + */ + 0x7FFFFC07, /* last */ + 0xFFFFFCFF, 0xFFFFFCFF, 0xFFFFFCFF, +#endif +}; + +/* + * Check Board Identity: + * + */ + +/*********************************************************************** +F* Function: int checkboard (void) P*A*Z* + * +P* Parameters: none +P* +P* Returnvalue: int - 0 is always returned + * +Z* Intention: This function is the checkboard() method implementation +Z* for the lwmon board. Only a standard message is printed. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +int checkboard (void) +{ + puts ("Board: LICCON Konsole LCD3\n"); + return (0); +} + +/*********************************************************************** +F* Function: phys_size_t initdram (int board_type) P*A*Z* + * +P* Parameters: int board_type +P* - Usually type of the board - ignored here. +P* +P* Returnvalue: long int +P* - Size of initialized memory + * +Z* Intention: This function is the initdram() method implementation +Z* for the lwmon board. +Z* The memory controller is initialized to access the +Z* DRAM. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +phys_size_t initdram (int board_type) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + volatile memctl8xx_t *memctl = &immr->im_memctl; + long int size_b0; + long int size8, size9; + int i; + + /* + * Configure UPMA for SDRAM + */ + upmconfig (UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint)); + + memctl->memc_mptpr = CONFIG_SYS_MPTPR; + + /* burst length=4, burst type=sequential, CAS latency=2 */ + memctl->memc_mar = CONFIG_SYS_MAR; + + /* + * Map controller bank 3 to the SDRAM bank at preliminary address. + */ + memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM; + memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM; + + /* initialize memory address register */ + memctl->memc_mamr = CONFIG_SYS_MAMR_8COL; /* refresh not enabled yet */ + + /* mode initialization (offset 5) */ + udelay (200); /* 0x80006105 */ + memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS3 | MCR_MLCF (1) | MCR_MAD (0x05); + + /* run 2 refresh sequence with 4-beat refresh burst (offset 0x30) */ + udelay (1); /* 0x80006130 */ + memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS3 | MCR_MLCF (1) | MCR_MAD (0x30); + udelay (1); /* 0x80006130 */ + memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS3 | MCR_MLCF (1) | MCR_MAD (0x30); + + udelay (1); /* 0x80006106 */ + memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS3 | MCR_MLCF (1) | MCR_MAD (0x06); + + memctl->memc_mamr |= MAMR_PTAE; /* refresh enabled */ + + udelay (200); + + /* Need at least 10 DRAM accesses to stabilize */ + for (i = 0; i < 10; ++i) { + volatile unsigned long *addr = + (volatile unsigned long *) SDRAM_BASE3_PRELIM; + unsigned long val; + + val = *(addr + i); + *(addr + i) = val; + } + + /* + * Check Bank 0 Memory Size for re-configuration + * + * try 8 column mode + */ + size8 = dram_size (CONFIG_SYS_MAMR_8COL, (long *)SDRAM_BASE3_PRELIM, SDRAM_MAX_SIZE); + + udelay (1000); + + /* + * try 9 column mode + */ + size9 = dram_size (CONFIG_SYS_MAMR_9COL, (long *)SDRAM_BASE3_PRELIM, SDRAM_MAX_SIZE); + + if (size8 < size9) { /* leave configuration at 9 columns */ + size_b0 = size9; + memctl->memc_mamr = CONFIG_SYS_MAMR_9COL | MAMR_PTAE; + udelay (500); + } else { /* back to 8 columns */ + size_b0 = size8; + memctl->memc_mamr = CONFIG_SYS_MAMR_8COL | MAMR_PTAE; + udelay (500); + } + + /* + * Final mapping: + */ + + memctl->memc_or3 = ((-size_b0) & 0xFFFF0000) | + OR_CSNT_SAM | OR_G5LS | SDRAM_TIMING; + memctl->memc_br3 = (CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; + udelay (1000); + + return (size_b0); +} + +/*********************************************************************** +F* Function: static long int dram_size (long int mamr_value, +F* long int *base, +F* long int maxsize) P*A*Z* + * +P* Parameters: long int mamr_value +P* - Value for MAMR for the test +P* long int *base +P* - Base address for the test +P* long int maxsize +P* - Maximum size to test for +P* +P* Returnvalue: long int +P* - Size of probed memory + * +Z* Intention: Check memory range for valid RAM. A simple memory test +Z* determines the actually available RAM size between +Z* addresses `base' and `base + maxsize'. Some (not all) +Z* hardware errors are detected: +Z* - short between address lines +Z* - short between data lines + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +static long int dram_size (long int mamr_value, long int *base, long int maxsize) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + volatile memctl8xx_t *memctl = &immr->im_memctl; + + memctl->memc_mamr = mamr_value; + + return (get_ram_size(base, maxsize)); +} + +/* ------------------------------------------------------------------------- */ + +#ifndef PB_ENET_TENA +# define PB_ENET_TENA ((uint)0x00002000) /* PB 18 */ +#endif + +/*********************************************************************** +F* Function: int board_early_init_f (void) P*A*Z* + * +P* Parameters: none +P* +P* Returnvalue: int +P* - 0 is always returned. + * +Z* Intention: This function is the board_early_init_f() method implementation +Z* for the lwmon board. +Z* Disable Ethernet TENA on Port B. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +int board_early_init_f (void) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + + /* Disable Ethernet TENA on Port B + * Necessary because of pull up in COM3 port. + * + * This is just a preliminary fix, intended to turn off TENA + * as soon as possible to avoid noise on the network. Once + * I2C is running we will make sure the interface is + * correctly initialized. + */ + immr->im_cpm.cp_pbpar &= ~PB_ENET_TENA; + immr->im_cpm.cp_pbodr &= ~PB_ENET_TENA; + immr->im_cpm.cp_pbdat &= ~PB_ENET_TENA; /* set to 0 = disabled */ + immr->im_cpm.cp_pbdir |= PB_ENET_TENA; + + return (0); +} + +/* ------------------------------------------------------------------------- */ + +/*********************************************************************** +F* Function: void reset_phy (void) P*A*Z* + * +P* Parameters: none +P* +P* Returnvalue: none + * +Z* Intention: Reset the PHY. In the lwmon case we do this by the +Z* signaling the PIC I/O expander. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +void reset_phy (void) +{ + uchar c; + +#ifdef DEBUG + printf ("### Switch on Ethernet for SCC2 ###\n"); +#endif + c = pic_read (0x61); +#ifdef DEBUG + printf ("Old PIC read: reg_61 = 0x%02x\n", c); +#endif + c |= 0x40; /* disable COM3 */ + c &= ~0x80; /* enable Ethernet */ + pic_write (0x61, c); +#ifdef DEBUG + c = pic_read (0x61); + printf ("New PIC read: reg_61 = 0x%02x\n", c); +#endif + udelay (1000); +} + + +/*------------------------- Keyboard controller -----------------------*/ +/* command codes */ +#define KEYBD_CMD_READ_KEYS 0x01 +#define KEYBD_CMD_READ_VERSION 0x02 +#define KEYBD_CMD_READ_STATUS 0x03 +#define KEYBD_CMD_RESET_ERRORS 0x10 + +/* status codes */ +#define KEYBD_STATUS_MASK 0x3F +#define KEYBD_STATUS_H_RESET 0x20 +#define KEYBD_STATUS_BROWNOUT 0x10 +#define KEYBD_STATUS_WD_RESET 0x08 +#define KEYBD_STATUS_OVERLOAD 0x04 +#define KEYBD_STATUS_ILLEGAL_WR 0x02 +#define KEYBD_STATUS_ILLEGAL_RD 0x01 + +/* Number of bytes returned from Keyboard Controller */ +#define KEYBD_VERSIONLEN 2 /* version information */ +#define KEYBD_DATALEN 9 /* normal key scan data */ + +/* maximum number of "magic" key codes that can be assigned */ + +static uchar kbd_addr = CONFIG_SYS_I2C_KEYBD_ADDR; + +static uchar *key_match (uchar *); + +#define KEYBD_SET_DEBUGMODE '#' /* Magic key to enable debug output */ + +/*********************************************************************** +F* Function: int board_postclk_init (void) P*A*Z* + * +P* Parameters: none +P* +P* Returnvalue: int +P* - 0 is always returned. + * +Z* Intention: This function is the board_postclk_init() method implementation +Z* for the lwmon board. + * + ***********************************************************************/ +int board_postclk_init (void) +{ + kbd_init(); + +#ifdef CONFIG_MODEM_SUPPORT + if (key_pressed()) { + disable_putc(); /* modem doesn't understand banner etc */ + gd->do_mdm_init = 1; + } +#endif + + return (0); +} + +struct serial_device * default_serial_console (void) +{ + return gd->do_mdm_init ? &serial_scc_device : &serial_smc_device; +} + +static void kbd_init (void) +{ + uchar kbd_data[KEYBD_DATALEN]; + uchar tmp_data[KEYBD_DATALEN]; + uchar val, errcd; + int i; + + i2c_set_bus_num(0); + + gd->arch.kbd_status = 0; + + /* Forced by PIC. Delays <= 175us loose */ + udelay(1000); + + /* Read initial keyboard error code */ + val = KEYBD_CMD_READ_STATUS; + i2c_write (kbd_addr, 0, 0, &val, 1); + i2c_read (kbd_addr, 0, 0, &errcd, 1); + /* clear unused bits */ + errcd &= KEYBD_STATUS_MASK; + /* clear "irrelevant" bits. Recommended by Martin Rajek, LWN */ + errcd &= ~(KEYBD_STATUS_H_RESET|KEYBD_STATUS_BROWNOUT); + if (errcd) { + gd->arch.kbd_status |= errcd << 8; + } + /* Reset error code and verify */ + val = KEYBD_CMD_RESET_ERRORS; + i2c_write (kbd_addr, 0, 0, &val, 1); + udelay(1000); /* delay NEEDED by keyboard PIC !!! */ + + val = KEYBD_CMD_READ_STATUS; + i2c_write (kbd_addr, 0, 0, &val, 1); + i2c_read (kbd_addr, 0, 0, &val, 1); + + val &= KEYBD_STATUS_MASK; /* clear unused bits */ + if (val) { /* permanent error, report it */ + gd->arch.kbd_status |= val; + return; + } + + /* + * Read current keyboard state. + * + * After the error reset it may take some time before the + * keyboard PIC picks up a valid keyboard scan - the total + * scan time is approx. 1.6 ms (information by Martin Rajek, + * 28 Sep 2002). We read a couple of times for the keyboard + * to stabilize, using a big enough delay. + * 10 times should be enough. If the data is still changing, + * we use what we get :-( + */ + + memset (tmp_data, 0xFF, KEYBD_DATALEN); /* impossible value */ + for (i=0; i<10; ++i) { + val = KEYBD_CMD_READ_KEYS; + i2c_write (kbd_addr, 0, 0, &val, 1); + i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN); + + if (memcmp(kbd_data, tmp_data, KEYBD_DATALEN) == 0) { + /* consistent state, done */ + break; + } + /* remeber last state, delay, and retry */ + memcpy (tmp_data, kbd_data, KEYBD_DATALEN); + udelay (5000); + } +} + +/*********************************************************************** +F* Function: int misc_init_r (void) P*A*Z* + * +P* Parameters: none +P* +P* Returnvalue: int +P* - 0 is always returned, even in the case of a keyboard +P* error. + * +Z* Intention: This function is the misc_init_r() method implementation +Z* for the lwmon board. +Z* The keyboard controller is initialized and the result +Z* of a read copied to the environment variable "keybd". +Z* If KEYBD_SET_DEBUGMODE is defined, a check is made for +Z* this key, and if found display to the LCD will be enabled. +Z* The keys in "keybd" are checked against the magic +Z* keycommands defined in the environment. +Z* See also key_match(). + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +int misc_init_r (void) +{ + uchar kbd_data[KEYBD_DATALEN]; + char keybd_env[2 * KEYBD_DATALEN + 1]; + uchar kbd_init_status = gd->arch.kbd_status >> 8; + uchar kbd_status = gd->arch.kbd_status; + uchar val; + char *str; + int i; + + if (kbd_init_status) { + printf ("KEYBD: Error %02X\n", kbd_init_status); + } + if (kbd_status) { /* permanent error, report it */ + printf ("*** Keyboard error code %02X ***\n", kbd_status); + sprintf (keybd_env, "%02X", kbd_status); + setenv ("keybd", keybd_env); + return 0; + } + + /* + * Now we know that we have a working keyboard, so disable + * all output to the LCD except when a key press is detected. + */ + + if ((console_assign (stdout, "serial") < 0) || + (console_assign (stderr, "serial") < 0)) { + printf ("Can't assign serial port as output device\n"); + } + + /* Read Version */ + val = KEYBD_CMD_READ_VERSION; + i2c_write (kbd_addr, 0, 0, &val, 1); + i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_VERSIONLEN); + printf ("KEYBD: Version %d.%d\n", kbd_data[0], kbd_data[1]); + + /* Read current keyboard state */ + val = KEYBD_CMD_READ_KEYS; + i2c_write (kbd_addr, 0, 0, &val, 1); + i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN); + + for (i = 0; i < KEYBD_DATALEN; ++i) { + sprintf (keybd_env + i + i, "%02X", kbd_data[i]); + } + setenv ("keybd", keybd_env); + + str = strdup ((char *)key_match (kbd_data)); /* decode keys */ +#ifdef KEYBD_SET_DEBUGMODE + if (kbd_data[0] == KEYBD_SET_DEBUGMODE) { /* set debug mode */ + if ((console_assign (stdout, "lcd") < 0) || + (console_assign (stderr, "lcd") < 0)) { + printf ("Can't assign LCD display as output device\n"); + } + } +#endif /* KEYBD_SET_DEBUGMODE */ +#ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */ + setenv ("preboot", str); /* set or delete definition */ +#endif /* CONFIG_PREBOOT */ + if (str != NULL) { + free (str); + } + return (0); +} + +#ifdef CONFIG_PREBOOT + +static uchar kbd_magic_prefix[] = "key_magic"; +static uchar kbd_command_prefix[] = "key_cmd"; + +static int compare_magic (uchar *kbd_data, uchar *str) +{ + uchar compare[KEYBD_DATALEN-1]; + char *nxt; + int i; + + /* Don't include modifier byte */ + memcpy (compare, kbd_data+1, KEYBD_DATALEN-1); + + for (; str != NULL; str = (*nxt) ? (uchar *)(nxt+1) : (uchar *)nxt) { + uchar c; + int k; + + c = (uchar) simple_strtoul ((char *)str, (char **) (&nxt), 16); + + if (str == (uchar *)nxt) { /* invalid character */ + break; + } + + /* + * Check if this key matches the input. + * Set matches to zero, so they match only once + * and we can find duplicates or extra keys + */ + for (k = 0; k < sizeof(compare); ++k) { + if (compare[k] == '\0') /* only non-zero entries */ + continue; + if (c == compare[k]) { /* found matching key */ + compare[k] = '\0'; + break; + } + } + if (k == sizeof(compare)) { + return -1; /* unmatched key */ + } + } + + /* + * A full match leaves no keys in the `compare' array, + */ + for (i = 0; i < sizeof(compare); ++i) { + if (compare[i]) + { + return -1; + } + } + + return 0; +} + +/*********************************************************************** +F* Function: static uchar *key_match (uchar *kbd_data) P*A*Z* + * +P* Parameters: uchar *kbd_data +P* - The keys to match against our magic definitions +P* +P* Returnvalue: uchar * +P* - != NULL: Pointer to the corresponding command(s) +P* NULL: No magic is about to happen + * +Z* Intention: Check if pressed key(s) match magic sequence, +Z* and return the command string associated with that key(s). +Z* +Z* If no key press was decoded, NULL is returned. +Z* +Z* Note: the first character of the argument will be +Z* overwritten with the "magic charcter code" of the +Z* decoded key(s), or '\0'. +Z* +Z* Note: the string points to static environment data +Z* and must be saved before you call any function that +Z* modifies the environment. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +static uchar *key_match (uchar *kbd_data) +{ + char magic[sizeof (kbd_magic_prefix) + 1]; + uchar *suffix; + char *kbd_magic_keys; + + /* + * The following string defines the characters that can pe appended + * to "key_magic" to form the names of environment variables that + * hold "magic" key codes, i. e. such key codes that can cause + * pre-boot actions. If the string is empty (""), then only + * "key_magic" is checked (old behaviour); the string "125" causes + * checks for "key_magic1", "key_magic2" and "key_magic5", etc. + */ + if ((kbd_magic_keys = getenv ("magic_keys")) == NULL) + kbd_magic_keys = ""; + + /* loop over all magic keys; + * use '\0' suffix in case of empty string + */ + for (suffix=(uchar *)kbd_magic_keys; *suffix || suffix==(uchar *)kbd_magic_keys; ++suffix) { + sprintf (magic, "%s%c", kbd_magic_prefix, *suffix); +#if 0 + printf ("### Check magic \"%s\"\n", magic); +#endif + if (compare_magic(kbd_data, (uchar *)getenv(magic)) == 0) { + char cmd_name[sizeof (kbd_command_prefix) + 1]; + char *cmd; + + sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix); + + cmd = getenv (cmd_name); +#if 0 + printf ("### Set PREBOOT to $(%s): \"%s\"\n", + cmd_name, cmd ? cmd : "<<NULL>>"); +#endif + *kbd_data = *suffix; + return ((uchar *)cmd); + } + } +#if 0 + printf ("### Delete PREBOOT\n"); +#endif + *kbd_data = '\0'; + return (NULL); +} +#endif /* CONFIG_PREBOOT */ + +#ifdef CONFIG_LCD_INFO +#include <lcd.h> +#include <version.h> +#include <timestamp.h> + +void lcd_show_board_info(void) +{ + char temp[32]; + + lcd_printf ("%s (%s - %s)\n", U_BOOT_VERSION, U_BOOT_DATE, U_BOOT_TIME); + lcd_printf ("(C) 2008 DENX Software Engineering GmbH\n"); + lcd_printf (" Wolfgang DENK, wd@denx.de\n"); +#ifdef CONFIG_LCD_INFO_BELOW_LOGO + lcd_printf ("MPC823 CPU at %s MHz\n", + strmhz(temp, gd->cpu_clk)); + lcd_printf (" %ld MB RAM, %ld MB Flash\n", + gd->ram_size >> 20, + gd->bd->bi_flashsize >> 20 ); +#else + /* leave one blank line */ + lcd_printf ("\nMPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash\n", + strmhz(temp, gd->cpu_clk), + gd->ram_size >> 20, + gd->bd->bi_flashsize >> 20 ); +#endif /* CONFIG_LCD_INFO_BELOW_LOGO */ +} +#endif /* CONFIG_LCD_INFO */ + +/*---------------Board Special Commands: PIC read/write ---------------*/ + +#if defined(CONFIG_CMD_BSP) +/*********************************************************************** +F* Function: int do_pic (cmd_tbl_t *cmdtp, int flag, +F* int argc, char * const argv[]) P*A*Z* + * +P* Parameters: cmd_tbl_t *cmdtp +P* - Pointer to our command table entry +P* int flag +P* - If the CMD_FLAG_REPEAT bit is set, then this call is +P* a repetition +P* int argc +P* - Argument count +P* char * const argv[] +P* - Array of the actual arguments +P* +P* Returnvalue: int +P* - 0 The command was handled successfully +P* 1 An error occurred + * +Z* Intention: Implement the "pic [read|write]" commands. +Z* The read subcommand takes one argument, the register, +Z* whereas the write command takes two, the register and +Z* the new value. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +int do_pic (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uchar reg, val; + + switch (argc) { + case 3: /* PIC read reg */ + if (strcmp (argv[1], "read") != 0) + break; + + reg = simple_strtoul (argv[2], NULL, 16); + + printf ("PIC read: reg %02x: %02x\n\n", reg, pic_read (reg)); + + return 0; + case 4: /* PIC write reg val */ + if (strcmp (argv[1], "write") != 0) + break; + + reg = simple_strtoul (argv[2], NULL, 16); + val = simple_strtoul (argv[3], NULL, 16); + + printf ("PIC write: reg %02x val 0x%02x: %02x => ", + reg, val, pic_read (reg)); + pic_write (reg, val); + printf ("%02x\n\n", pic_read (reg)); + return 0; + default: + break; + } + return cmd_usage(cmdtp); +} +U_BOOT_CMD( + pic, 4, 1, do_pic, + "read and write PIC registers", + "read reg - read PIC register `reg'\n" + "pic write reg val - write value `val' to PIC register `reg'" +); + +/*********************************************************************** +F* Function: int do_kbd (cmd_tbl_t *cmdtp, int flag, +F* int argc, char * const argv[]) P*A*Z* + * +P* Parameters: cmd_tbl_t *cmdtp +P* - Pointer to our command table entry +P* int flag +P* - If the CMD_FLAG_REPEAT bit is set, then this call is +P* a repetition +P* int argc +P* - Argument count +P* char * const argv[] +P* - Array of the actual arguments +P* +P* Returnvalue: int +P* - 0 is always returned. + * +Z* Intention: Implement the "kbd" command. +Z* The keyboard status is read. The result is printed on +Z* the console and written into the "keybd" environment +Z* variable. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uchar kbd_data[KEYBD_DATALEN]; + char keybd_env[2 * KEYBD_DATALEN + 1]; + uchar val; + int i; + +#if 0 /* Done in kbd_init */ + i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +#endif + + /* Read keys */ + val = KEYBD_CMD_READ_KEYS; + i2c_write (kbd_addr, 0, 0, &val, 1); + i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN); + + puts ("Keys:"); + for (i = 0; i < KEYBD_DATALEN; ++i) { + sprintf (keybd_env + i + i, "%02X", kbd_data[i]); + printf (" %02x", kbd_data[i]); + } + putc ('\n'); + setenv ("keybd", keybd_env); + return 0; +} + +U_BOOT_CMD( + kbd, 1, 1, do_kbd, + "read keyboard status", + "" +); + +/* Read and set LSB switch */ +#define CONFIG_SYS_PC_TXD1_ENA 0x0008 /* PC.12 */ + +/*********************************************************************** +F* Function: int do_lsb (cmd_tbl_t *cmdtp, int flag, +F* int argc, char * const argv[]) P*A*Z* + * +P* Parameters: cmd_tbl_t *cmdtp +P* - Pointer to our command table entry +P* int flag +P* - If the CMD_FLAG_REPEAT bit is set, then this call is +P* a repetition +P* int argc +P* - Argument count +P* char * const argv[] +P* - Array of the actual arguments +P* +P* Returnvalue: int +P* - 0 The command was handled successfully +P* 1 An error occurred + * +Z* Intention: Implement the "lsb [on|off]" commands. +Z* The lsb is switched according to the first parameter by +Z* by signaling the PIC I/O expander. +Z* Called with no arguments, the current setting is +Z* printed. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +int do_lsb (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uchar val; + immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + + switch (argc) { + case 1: /* lsb - print setting */ + val = pic_read (0x60); + printf ("LSB is o%s\n", (val & 0x20) ? "n" : "ff"); + return 0; + case 2: /* lsb on or lsb off - set switch */ + val = pic_read (0x60); + + if (strcmp (argv[1], "on") == 0) { + val |= 0x20; + immr->im_ioport.iop_pcpar &= ~(CONFIG_SYS_PC_TXD1_ENA); + immr->im_ioport.iop_pcdat |= CONFIG_SYS_PC_TXD1_ENA; + immr->im_ioport.iop_pcdir |= CONFIG_SYS_PC_TXD1_ENA; + } else if (strcmp (argv[1], "off") == 0) { + val &= ~0x20; + immr->im_ioport.iop_pcpar &= ~(CONFIG_SYS_PC_TXD1_ENA); + immr->im_ioport.iop_pcdat &= ~(CONFIG_SYS_PC_TXD1_ENA); + immr->im_ioport.iop_pcdir |= CONFIG_SYS_PC_TXD1_ENA; + } else { + break; + } + pic_write (0x60, val); + return 0; + default: + break; + } + return cmd_usage(cmdtp); +} + +U_BOOT_CMD( + lsb, 2, 1, do_lsb, + "check and set LSB switch", + "on - switch LSB on\n" + "lsb off - switch LSB off\n" + "lsb - print current setting" +); + +#endif + +/*----------------------------- Utilities -----------------------------*/ +/*********************************************************************** +F* Function: uchar pic_read (uchar reg) P*A*Z* + * +P* Parameters: uchar reg +P* - Register to read +P* +P* Returnvalue: uchar +P* - Value read from register + * +Z* Intention: Read a register from the PIC I/O expander. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +uchar pic_read (uchar reg) +{ + return (i2c_reg_read (CONFIG_SYS_I2C_PICIO_ADDR, reg)); +} + +/*********************************************************************** +F* Function: void pic_write (uchar reg, uchar val) P*A*Z* + * +P* Parameters: uchar reg +P* - Register to read +P* uchar val +P* - Value to write +P* +P* Returnvalue: none + * +Z* Intention: Write to a register on the PIC I/O expander. + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +void pic_write (uchar reg, uchar val) +{ + i2c_reg_write (CONFIG_SYS_I2C_PICIO_ADDR, reg, val); +} + +/*---------------------- Board Control Functions ----------------------*/ +/*********************************************************************** +F* Function: void board_poweroff (void) P*A*Z* + * +P* Parameters: none +P* +P* Returnvalue: none + * +Z* Intention: Turn off the battery power and loop endless, so this +Z* should better be the last function you call... + * +D* Design: wd@denx.de +C* Coding: wd@denx.de +V* Verification: dzu@denx.de + ***********************************************************************/ +void board_poweroff (void) +{ + /* Turn battery off */ + ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat &= ~(1 << (31 - 13)); + + while (1); +} + +#ifdef CONFIG_MODEM_SUPPORT +static int key_pressed(void) +{ + uchar kbd_data[KEYBD_DATALEN]; + uchar val; + + /* Read keys */ + val = KEYBD_CMD_READ_KEYS; + i2c_write (kbd_addr, 0, 0, &val, 1); + i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN); + + return (compare_magic(kbd_data, (uchar *)CONFIG_MODEM_KEY_MAGIC) == 0); +} +#endif /* CONFIG_MODEM_SUPPORT */ + +#ifdef CONFIG_POST +/* + * Returns 1 if keys pressed to start the power-on long-running tests + * Called from board_init_f(). + */ +int post_hotkeys_pressed(void) +{ + uchar kbd_data[KEYBD_DATALEN]; + uchar val; + + /* Read keys */ + val = KEYBD_CMD_READ_KEYS; + i2c_write (kbd_addr, 0, 0, &val, 1); + i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN); + + return (compare_magic(kbd_data, (uchar *)CONFIG_POST_KEY_MAGIC) == 0); +} +#endif diff --git a/qemu/roms/u-boot/board/lwmon/pcmcia.c b/qemu/roms/u-boot/board/lwmon/pcmcia.c new file mode 100644 index 000000000..b9894cf01 --- /dev/null +++ b/qemu/roms/u-boot/board/lwmon/pcmcia.c @@ -0,0 +1,234 @@ +#include <common.h> +#include <mpc8xx.h> +#include <pcmcia.h> +#include <i2c.h> + +#undef CONFIG_PCMCIA + +#if defined(CONFIG_CMD_PCMCIA) +#define CONFIG_PCMCIA +#endif + +#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) +#define CONFIG_PCMCIA +#endif + +#ifdef CONFIG_PCMCIA + +#define PCMCIA_BOARD_MSG "LWMON" + +/* #define's for MAX1604 Power Switch */ +#define MAX1604_OP_SUS 0x80 +#define MAX1604_VCCBON 0x40 +#define MAX1604_VCC_35 0x20 +#define MAX1604_VCCBHIZ 0x10 +#define MAX1604_VPPBON 0x08 +#define MAX1604_VPPBPBPGM 0x04 +#define MAX1604_VPPBHIZ 0x02 +/* reserved 0x01 */ + +int pcmcia_hardware_enable(int slot) +{ + volatile pcmconf8xx_t *pcmp; + volatile sysconf8xx_t *sysp; + uint reg, mask; + uchar val; + + + debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + /* Switch on PCMCIA port in PIC register 0x60 */ + reg = pic_read (0x60); + debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg); + reg &= ~0x10; + /* reg |= 0x08; Vpp not needed */ + pic_write (0x60, reg); +#ifdef DEBUG + reg = pic_read (0x60); + printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg); +#endif + udelay(10000); + + sysp = (sysconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_siu_conf)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia)); + + /* + * Configure SIUMCR to enable PCMCIA port B + * (VFLS[0:1] are not used for debugging, we connect FRZ# instead) + */ + sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK(_slot_); + pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_); + + /* + * Disable interrupts, DMA, and PCMCIA buffers + * (isolate the interface) and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = 0; + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay(10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", + __LINE__,__FUNCTION__, + &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); + if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) { + printf (" No Card found\n"); + return (1); + } + + /* + * Power On. + */ + mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); + reg = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", + reg, + (reg&PCMCIA_VS1(slot))?"n":"ff", + (reg&PCMCIA_VS2(slot))?"n":"ff"); + if ((reg & mask) == mask) { + val = 0; /* VCCB3/5 = 0 ==> use Vx = 5.0 V */ + puts (" 5.0V card found: "); + } else { + val = MAX1604_VCC_35; /* VCCB3/5 = 1 ==> use Vy = 3.3 V */ + puts (" 3.3V card found: "); + } + + /* switch VCC on */ + val |= MAX1604_OP_SUS | MAX1604_VCCBON; + i2c_set_bus_num(0); + i2c_write (CONFIG_SYS_I2C_POWER_A_ADDR, 0, 0, &val, 1); + + udelay(500000); + + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return (0); +} + + +#if defined(CONFIG_CMD_PCMCIA) +int pcmcia_hardware_disable(int slot) +{ + volatile immap_t *immap; + volatile pcmconf8xx_t *pcmp; + u_long reg; + uchar val; + + debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + immap = (immap_t *)CONFIG_SYS_IMMR; + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia)); + + /* remove all power, put output in high impedance state */ + val = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ; + i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + i2c_write (CONFIG_SYS_I2C_POWER_A_ADDR, 0, 0, &val, 1); + + /* Configure PCMCIA General Control Register */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = 0; + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + /* Switch off PCMCIA port in PIC register 0x60 */ + reg = pic_read (0x60); + debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg); + reg |= 0x10; + reg &= ~0x08; + pic_write (0x60, reg); +#ifdef DEBUG + reg = pic_read (0x60); + printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg); +#endif + udelay(10000); + + return (0); +} +#endif + + +int pcmcia_voltage_set(int slot, int vcc, int vpp) +{ + volatile pcmconf8xx_t *pcmp; + u_long reg; + uchar val; + + debug ("voltage_set: " + PCMCIA_BOARD_MSG + " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", + 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); + + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia)); + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Turn off all power (switch to high impedance) + */ + debug ("PCMCIA power OFF\n"); + val = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ; + i2c_set_bus_num(0); + i2c_write (CONFIG_SYS_I2C_POWER_A_ADDR, 0, 0, &val, 1); + + val = 0; + switch(vcc) { + case 0: break; + case 33: val = MAX1604_VCC_35; break; + case 50: break; + default: goto done; + } + + /* Checking supported voltages */ + + debug ("PIPR: 0x%x --> %s\n", + pcmp->pcmc_pipr, + (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); + + i2c_write (CONFIG_SYS_I2C_POWER_A_ADDR, 0, 0, &val, 1); + if (val) { + debug ("PCMCIA powered at %sV\n", + (val & MAX1604_VCC_35) ? "3.3" : "5.0"); + } else { + debug ("PCMCIA powered down\n"); + } + +done: + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", + slot+'A'); + return (0); +} + +#endif /* CONFIG_PCMCIA */ diff --git a/qemu/roms/u-boot/board/lwmon/u-boot.lds b/qemu/roms/u-boot/board/lwmon/u-boot.lds new file mode 100644 index 000000000..90e2e2ed0 --- /dev/null +++ b/qemu/roms/u-boot/board/lwmon/u-boot.lds @@ -0,0 +1,82 @@ +/* + * (C) Copyright 2001-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: */ + . = (. + 0x0FF) & 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 = .); +} diff --git a/qemu/roms/u-boot/board/lwmon/u-boot.lds.debug b/qemu/roms/u-boot/board/lwmon/u-boot.lds.debug new file mode 100644 index 000000000..75a133717 --- /dev/null +++ b/qemu/roms/u-boot/board/lwmon/u-boot.lds.debug @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_ARCH(powerpc) +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + arch/powerpc/cpu/mpc8xx/start.o (.text) + common/dlmalloc.o (.text) + lib/vsprintf.o (.text) + lib/crc32.o (.text) + arch/powerpc/lib/extable.o (.text) + + . = env_offset; + common/env_embedded.o(.text) + + *(.text) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + __bss_end = . ; + PROVIDE (end = .); +} |