[U-Boot] [PATCH v2 0/10] sparc: Update SPARC architecture to generic board init

The SPARC architecture has not yet been upgraded to the new generic board init codebase. This patch series is an first attempt at that.
The changes has been tested on a TSIM simulator (grsim_defconfig) and a gr712rc-board. We would appreciate some help with testing.
This series currently does not remove the old init code. That will be done in a later series of patches.
Any feedback, comments or suggestions would be appreciated.
Changes in v2: - Move ambapp command selection to Kconfig - Add patch to relocate the command tables - Split AMBA vendor/device ID work into its own patch - Add snoop detect function to restore lost feature - Update GRSIM memory settings for evaluation version of TSIM - Add patch to cleanup LEON3 init code a bit - The gr712rc-board patches has been split into a separate series
Francois Retief (10): sparc: Add initr function for CMD_AMBAPP command sparc: Add function to fixup command tables sparc: Add more LEON3 AMBA vendor/device IDs sparc: Initial work for generic board-init sparc: Use microseconds instead of ticks for timeout sparc: Reworked LEON3 startup for generic board-init sparc: Major rewrite of the PROM generation code sparc: Update all LEON3 boards to generic board-init sparc: Update GRSIM board with memory settings for TSIM sparc: Cleanup of LEON3 CPU initialisation code
arch/sparc/config.mk | 3 + arch/sparc/cpu/leon2/Makefile | 2 +- arch/sparc/cpu/leon2/cpu.c | 23 + arch/sparc/cpu/leon2/prom.c | 1030 ----------------------------------- arch/sparc/cpu/leon3/Makefile | 5 +- arch/sparc/cpu/leon3/cpu.c | 23 + arch/sparc/cpu/leon3/cpu_init.c | 175 ++++-- arch/sparc/cpu/leon3/interrupts.c | 18 +- arch/sparc/cpu/leon3/prom.c | 1061 ------------------------------------- arch/sparc/cpu/leon3/start.S | 436 ++++++++------- arch/sparc/include/asm/config.h | 3 + arch/sparc/include/asm/machines.h | 4 +- arch/sparc/include/asm/u-boot.h | 7 + arch/sparc/lib/Makefile | 9 +- arch/sparc/lib/bootm.c | 81 +-- arch/sparc/lib/interrupts.c | 7 + arch/sparc/lib/prom-no.c | 319 +++++++++++ arch/sparc/lib/prom-no.h | 40 ++ arch/sparc/lib/prom.c | 960 +++++++++++++++++++++++++++++++++ arch/sparc/lib/srmmu.c | 90 ++++ arch/sparc/lib/time.c | 5 + common/Kconfig | 14 + common/board_f.c | 2 +- common/board_r.c | 34 ++ common/cmd_ambapp.c | 18 +- drivers/net/greth.c | 2 +- include/ambapp.h | 27 +- include/config_cmd_all.h | 1 - include/configs/gr_cpci_ax2000.h | 8 +- include/configs/gr_ep2s60.h | 8 +- include/configs/gr_xc3s_1500.h | 8 +- include/configs/grsim.h | 65 ++- 32 files changed, 2072 insertions(+), 2416 deletions(-) delete mode 100644 arch/sparc/cpu/leon2/prom.c delete mode 100644 arch/sparc/cpu/leon3/prom.c create mode 100644 arch/sparc/lib/prom-no.c create mode 100644 arch/sparc/lib/prom-no.h create mode 100644 arch/sparc/lib/prom.c create mode 100644 arch/sparc/lib/srmmu.c
-- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

Add an initr function in the board_r.c file for the AMBA Plug-n-Play command. Add a Kconfig entry for the ambapp command and remove all CONFIG_CMD_AMBAPP defines from the board configuration headers.
Also add a Kconfig entry to display the AMBA PnP information on startup. This option is off by default. Remove relevent define from board configuration headers.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: - Move ambapp command selection to Kconfig
common/Kconfig | 14 ++++++++++++++ common/board_r.c | 21 +++++++++++++++++++++ include/config_cmd_all.h | 1 - include/configs/gr_cpci_ax2000.h | 4 ---- include/configs/gr_ep2s60.h | 4 ---- include/configs/gr_xc3s_1500.h | 4 ---- include/configs/grsim.h | 4 ---- 7 files changed, 35 insertions(+), 17 deletions(-)
diff --git a/common/Kconfig b/common/Kconfig index 216a8de..5a72ffe 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1,6 +1,20 @@ menu "Command line interface" depends on !SPL_BUILD
+config CMD_AMBAPP + bool "Enable ambapp command" + depends on LEON3 + default y + help + Lists AMBA Plug-n-Play information. + +config SYS_AMBAPP_PRINT_ON_STARTUP + bool "Show AMBA PnP info on startup" + depends on CMD_AMBAPP + default n + help + Show AMBA Plug-n-Play information on startup. + config CMD_BOOTM bool "Enable bootm command" default y diff --git a/common/board_r.c b/common/board_r.c index 7c33900..6d6c7e8 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -45,6 +45,9 @@ #include <stdio_dev.h> #include <trace.h> #include <watchdog.h> +#ifdef CONFIG_CMD_AMBAPP +#include <ambapp.h> +#endif #ifdef CONFIG_ADDR_MAP #include <asm/mmu.h> #endif @@ -566,6 +569,18 @@ static int initr_status_led(void) } #endif
+#if defined(CONFIG_CMD_AMBAPP) && defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP) +extern int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]); + +static int initr_ambapp_print(void) +{ + puts("AMBA:\n"); + do_ambapp_print(NULL, 0, 0, NULL); + + return 0; +} +#endif + #if defined(CONFIG_CMD_SCSI) static int initr_scsi(void) { @@ -857,6 +872,12 @@ init_fnc_t init_sequence_r[] = { #ifdef CONFIG_BOARD_LATE_INIT board_late_init, #endif +#if defined(CONFIG_CMD_AMBAPP) + ambapp_init_reloc, +#if defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP) + initr_ambapp_print, +#endif +#endif #ifdef CONFIG_CMD_SCSI INIT_FUNC_WATCHDOG_RESET initr_scsi, diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h index 2c2a05b..0bb5ea7 100644 --- a/include/config_cmd_all.h +++ b/include/config_cmd_all.h @@ -13,7 +13,6 @@ * Alphabetical list of all possible commands. */
-#define CONFIG_CMD_AMBAPP /* AMBA Plug & Play Bus print utility */ #define CONFIG_CMD_ASKENV /* ask for env variable */ #define CONFIG_CMD_BDI /* bdinfo */ #define CONFIG_CMD_BEDBUG /* Include BedBug Debugger */ diff --git a/include/configs/gr_cpci_ax2000.h b/include/configs/gr_cpci_ax2000.h index 854807d..5e9b3f7 100644 --- a/include/configs/gr_cpci_ax2000.h +++ b/include/configs/gr_cpci_ax2000.h @@ -62,7 +62,6 @@ #include <config_cmd_default.h>
#define CONFIG_CMD_REGINFO -#define CONFIG_CMD_AMBAPP #define CONFIG_CMD_PING #define CONFIG_CMD_DIAG #define CONFIG_CMD_IRQ @@ -314,9 +313,6 @@
/***** Gaisler GRLIB IP-Cores Config ********/
-/* AMBA Plug & Play info display on startup */ -/*#define CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP*/ - #define CONFIG_SYS_GRLIB_SDRAM 0
/* See, GRLIB Docs (grip.pdf) on how to set up diff --git a/include/configs/gr_ep2s60.h b/include/configs/gr_ep2s60.h index ed2dd2a..9e99d07 100644 --- a/include/configs/gr_ep2s60.h +++ b/include/configs/gr_ep2s60.h @@ -56,7 +56,6 @@ #include <config_cmd_default.h>
#define CONFIG_CMD_REGINFO -#define CONFIG_CMD_AMBAPP #define CONFIG_CMD_PING #define CONFIG_CMD_DIAG #define CONFIG_CMD_IRQ @@ -299,9 +298,6 @@
/***** Gaisler GRLIB IP-Cores Config ********/
-/* AMBA Plug & Play info display on startup */ -/*#define CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP*/ - #define CONFIG_SYS_GRLIB_SDRAM 0
/* See, GRLIB Docs (grip.pdf) on how to set up diff --git a/include/configs/gr_xc3s_1500.h b/include/configs/gr_xc3s_1500.h index e3cbb6f..8657a56 100644 --- a/include/configs/gr_xc3s_1500.h +++ b/include/configs/gr_xc3s_1500.h @@ -43,7 +43,6 @@ #include <config_cmd_default.h>
#define CONFIG_CMD_REGINFO -#define CONFIG_CMD_AMBAPP #define CONFIG_CMD_PING #define CONFIG_CMD_DIAG #define CONFIG_CMD_IRQ @@ -262,9 +261,6 @@
/***** Gaisler GRLIB IP-Cores Config ********/
-/* AMBA Plug & Play info display on startup */ -/*#define CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP*/ - #define CONFIG_SYS_GRLIB_SDRAM 0
/* See, GRLIB Docs (grip.pdf) on how to set up diff --git a/include/configs/grsim.h b/include/configs/grsim.h index 1e089a9..50cafb8 100644 --- a/include/configs/grsim.h +++ b/include/configs/grsim.h @@ -47,7 +47,6 @@ /* * Supported commands */ -#define CONFIG_CMD_AMBAPP /* AMBA Plyg&Play information */ #define CONFIG_CMD_BDI /* bdinfo */ #define CONFIG_CMD_CONSOLE /* coninfo */ #define CONFIG_CMD_DIAG @@ -279,9 +278,6 @@
/***** Gaisler GRLIB IP-Cores Config ********/
-/* AMBA Plug & Play info display on startup */ -/*#define CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP*/ - #define CONFIG_SYS_GRLIB_SDRAM 0 #define CONFIG_SYS_GRLIB_MEMCFG1 (0x000000ff | (1<<11)) #if CONFIG_GRSIM -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

Add a function to fixup the command tables to board_init_r.c file when the CONFIG_NEEDS_MANUAL_RELOC variable has been defined. This is used by the SPARC, AVR32, NDS32 and M68K architectures.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: - Add patch to relocate the command tables
common/board_r.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/common/board_r.c b/common/board_r.c index 6d6c7e8..04d2e61 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -569,6 +569,16 @@ static int initr_status_led(void) } #endif
+#if defined(CONFIG_NEEDS_MANUAL_RELOC) +static int initr_cmdtable_reloc(void) +{ + /* We have to relocate the command table manually */ + fixup_cmdtable( ll_entry_start(cmd_tbl_t, cmd), + ll_entry_count(cmd_tbl_t, cmd) ); + return 0; +} +#endif + #if defined(CONFIG_CMD_AMBAPP) && defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP) extern int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]);
@@ -872,6 +882,9 @@ init_fnc_t init_sequence_r[] = { #ifdef CONFIG_BOARD_LATE_INIT board_late_init, #endif +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + initr_cmdtable_reloc, +#endif #if defined(CONFIG_CMD_AMBAPP) ambapp_init_reloc, #if defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP) -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

Add more LEON3 AMBA vendor/device ID pairs from GRLIB. The upcomming PROM work and new gr712rc board need these values.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: - Split AMBA vendor/device ID work into its own patch
common/cmd_ambapp.c | 18 +++++++++++++++++- include/ambapp.h | 27 +++++++++++++++++++++------ 2 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/common/cmd_ambapp.c b/common/cmd_ambapp.c index 2a1995a..aa32234 100644 --- a/common/cmd_ambapp.c +++ b/common/cmd_ambapp.c @@ -50,7 +50,7 @@ static ambapp_device_name gaisler_devices[] = { {GAISLER_PCITRACE, "GAISLER_PCITRACE"}, {GAISLER_AHBTRACE, "GAISLER_AHBTRACE"}, {GAISLER_ETHDSU, "GAISLER_ETHDSU"}, - {GAISLER_PIOPORT, "GAISLER_PIOPORT"}, + {GAISLER_GPIO, "GAISLER_GPIO"}, {GAISLER_AHBJTAG, "GAISLER_AHBJTAG"}, {GAISLER_ATACTRL, "GAISLER_ATACTRL"}, {GAISLER_VGA, "GAISLER_VGA"}, @@ -62,9 +62,25 @@ static ambapp_device_name gaisler_devices[] = { {GAISLER_SPW2, "GAISLER_SPW2"}, {GAISLER_EHCI, "GAISLER_EHCI"}, {GAISLER_UHCI, "GAISLER_UHCI"}, + {GAISLER_I2CMST, "GAISLER_I2CMST"}, + {GAISLER_SPICTRL, "GAISLER_SPICTRL"}, {GAISLER_AHBSTAT, "GAISLER_AHBSTAT"}, {GAISLER_DDR2SPA, "GAISLER_DDR2SPA"}, {GAISLER_DDRSPA, "GAISLER_DDRSPA"}, + {GAISLER_LEON3FT, "GAISLER_LEON3FT"}, + {GAISLER_FTMCTRL, "GAISLER_FTMCTRL"}, + {GAISLER_B1553BRM, "GAISLER_B1553BRM"}, + {GAISLER_FTAHBRAM, "GAISLER_FTAHBRAM"}, + {GAISLER_CANAHB, "GAISLER_CANAHB"}, + {GAISLER_SATCAN, "GAISLER_SATCAN"}, + {GAISLER_CANMUX, "GAISLER_CANMUX"}, + {GAISLER_SLINK, "GAISLER_SLINK"}, + {GAISLER_GRTM, "GAISLER_GRTM"}, + {GAISLER_GRTC, "GAISLER_GRTC"}, + {GAISLER_GRTIMER, "GAISLER_GRTIMER"}, + {GAISLER_CLKGATE, "GAISLER_CLKGATE"}, + {GAISLER_GPREG, "GAISLER_GPREG"}, + {GAISLER_ASCS, "GAISLER_ASCS"}, {0, NULL} };
diff --git a/include/ambapp.h b/include/ambapp.h index 405637d..dfd6fa9 100644 --- a/include/ambapp.h +++ b/include/ambapp.h @@ -62,20 +62,35 @@ #define GAISLER_PCIDMA 0x016 #define GAISLER_AHBTRACE 0x017 #define GAISLER_ETHDSU 0x018 -#define GAISLER_PIOPORT 0x01A -#define GAISLER_AHBJTAG 0x01c -#define GAISLER_SPW 0x01f -#define GAISLER_ATACTRL 0x024 -#define GAISLER_VGA 0x061 -#define GAISLER_KBD 0X060 +#define GAISLER_CANAHB 0x019 +#define GAISLER_GPIO 0x01A +#define GAISLER_AHBJTAG 0x01C #define GAISLER_ETHMAC 0x01D +#define GAISLER_SPW 0x01F +#define GAISLER_ATACTRL 0x024 #define GAISLER_DDRSPA 0x025 #define GAISLER_EHCI 0x026 #define GAISLER_UHCI 0x027 +#define GAISLER_I2CMST 0x028 #define GAISLER_SPW2 0x029 +#define GAISLER_CLKGATE 0x02C +#define GAISLER_SPICTRL 0x02D #define GAISLER_DDR2SPA 0x02E +#define GAISLER_SLINK 0x02F +#define GAISLER_GRTM 0x030 +#define GAISLER_GRTC 0x031 +#define GAISLER_GRTIMER 0x038 +#define GAISLER_ASCS 0x043 +#define GAISLER_FTAHBRAM 0x050 #define GAISLER_AHBSTAT 0x052 +#define GAISLER_LEON3FT 0x053 #define GAISLER_FTMCTRL 0x054 +#define GAISLER_KBD 0x060 +#define GAISLER_VGA 0x061 +#define GAISLER_B1553BRM 0x072 +#define GAISLER_SATCAN 0x080 +#define GAISLER_CANMUX 0x081 +#define GAISLER_GPREG 0x087
#define GAISLER_L2TIME 0xffd /* internal device: leon2 timer */ #define GAISLER_L2C 0xffe /* internal device: leon2compat */ -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

Initial work in preperation for generic board init for the SPARC architecture.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: None
arch/sparc/config.mk | 3 +++ arch/sparc/cpu/leon2/cpu.c | 23 ++++++++++++++++ arch/sparc/cpu/leon3/cpu.c | 23 ++++++++++++++++ arch/sparc/cpu/leon3/cpu_init.c | 57 +++++++++++++++++++++++++++++++++++++++ arch/sparc/cpu/leon3/interrupts.c | 14 ++++++++++ arch/sparc/include/asm/config.h | 1 + arch/sparc/include/asm/u-boot.h | 7 +++++ arch/sparc/lib/Makefile | 7 ++++- arch/sparc/lib/interrupts.c | 7 +++++ arch/sparc/lib/time.c | 5 ++++ common/board_f.c | 2 +- 11 files changed, 147 insertions(+), 2 deletions(-)
diff --git a/arch/sparc/config.mk b/arch/sparc/config.mk index d615f29..6d342a1 100644 --- a/arch/sparc/config.mk +++ b/arch/sparc/config.mk @@ -17,3 +17,6 @@ CONFIG_STANDALONE_LOAD_ADDR ?= 0x00000000 -L $(gcclibdir) \ PLATFORM_CPPFLAGS += -D__sparc__
PLATFORM_RELFLAGS += -fPIC + +# Support generic board on SPARC +__HAVE_ARCH_GENERIC_BOARD := y diff --git a/arch/sparc/cpu/leon2/cpu.c b/arch/sparc/cpu/leon2/cpu.c index 380c397..d1c804e 100644 --- a/arch/sparc/cpu/leon2/cpu.c +++ b/arch/sparc/cpu/leon2/cpu.c @@ -15,6 +15,17 @@ DECLARE_GLOBAL_DATA_PTR;
extern void _reset_reloc(void);
+int arch_cpu_init(void) +{ + gd->cpu_clk = CONFIG_SYS_CLK_FREQ; + gd->bus_clk = CONFIG_SYS_CLK_FREQ; + gd->ram_size = CONFIG_SYS_SDRAM_SIZE; + + return 0; +} + +#ifndef CONFIG_SYS_GENERIC_BOARD + int checkcpu(void) { /* check LEON version here */ @@ -22,6 +33,18 @@ int checkcpu(void) return 0; }
+#endif + +#ifdef CONFIG_DISPLAY_CPUINFO + +int print_cpuinfo(void) +{ + printf("CPU: LEON2\n"); + return 0; +} + +#endif + /* ------------------------------------------------------------------------- */
void cpu_reset(void) diff --git a/arch/sparc/cpu/leon3/cpu.c b/arch/sparc/cpu/leon3/cpu.c index 8ab3150..5786751 100644 --- a/arch/sparc/cpu/leon3/cpu.c +++ b/arch/sparc/cpu/leon3/cpu.c @@ -18,6 +18,17 @@ DECLARE_GLOBAL_DATA_PTR;
extern void _reset_reloc(void);
+int arch_cpu_init(void) +{ + gd->cpu_clk = CONFIG_SYS_CLK_FREQ; + gd->bus_clk = CONFIG_SYS_CLK_FREQ; + gd->ram_size = CONFIG_SYS_SDRAM_SIZE; + + return 0; +} + +#ifndef CONFIG_SYS_GENERIC_BOARD + int checkcpu(void) { /* check LEON version here */ @@ -25,6 +36,18 @@ int checkcpu(void) return 0; }
+#endif + +#ifdef CONFIG_DISPLAY_CPUINFO + +int print_cpuinfo(void) +{ + printf("CPU: LEON3\n"); + return 0; +} + +#endif + /* ------------------------------------------------------------------------- */
void cpu_reset(void) diff --git a/arch/sparc/cpu/leon3/cpu_init.c b/arch/sparc/cpu/leon3/cpu_init.c index 2f41d88..1144610 100644 --- a/arch/sparc/cpu/leon3/cpu_init.c +++ b/arch/sparc/cpu/leon3/cpu_init.c @@ -94,11 +94,17 @@ void cpu_init_f(void) /* cache */ }
+#ifndef CONFIG_SYS_GENERIC_BOARD + void cpu_init_f2(void) {
}
+#endif + +#ifndef CONFIG_SYS_GENERIC_BOARD + /* * initialize higher level parts of CPU like time base and timers */ @@ -128,6 +134,8 @@ int cpu_init_r(void) return (0); }
+#endif + /* find & setup memory controller */ int init_memory_ctrl() { @@ -196,6 +204,8 @@ int init_memory_ctrl() return not_found_mctrl; }
+#ifndef CONFIG_SYS_GENERIC_BOARD + /* Uses Timer 0 to get accurate * pauses. Max 2 raised to 32 ticks * @@ -206,6 +216,10 @@ void cpu_wait_ticks(unsigned long ticks) while (get_timer(start) < ticks) ; }
+#endif + +#ifndef CONFIG_SYS_GENERIC_BOARD + /* initiate and setup timer0 interrupt to configured HZ. Base clock is 1MHz. * Return irq number for timer int or a negative number for * dealing with self @@ -222,11 +236,14 @@ int timer_interrupt_init_cpu(void) return gptimer_irq; }
+#endif + ulong get_tbclk(void) { return TIMER_BASE_CLK; }
+#ifndef CONFIG_SYS_GENERIC_BOARD /* * This function is intended for SHORT delays only. */ @@ -241,3 +258,43 @@ unsigned long cpu_ticks2usec(unsigned long ticks) { return ticks * US_PER_TICK; } + +#endif + +#ifdef CONFIG_SYS_GENERIC_BOARD + +static ambapp_dev_gptimer_element *tmr = NULL; + +int timer_init(void) +{ + ambapp_apbdev apbdev; + + if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_GPTIMER, &apbdev) != 1) { + printf("%s: gptimer not found!\n", __func__); + return 1; + } + gptimer = (ambapp_dev_gptimer *) apbdev.address; + gptimer_irq = apbdev.irq; + + /* initialize prescaler common to all timers to 1MHz */ + gptimer->scalar = gptimer->scalar_reload = + (((CONFIG_SYS_CLK_FREQ / 1000) + 500) / 1000) - 1; + + tmr = (ambapp_dev_gptimer_element *)&gptimer->e[0]; /* user timer 0 */ + + tmr->val = 0; + tmr->rld = ~0; + tmr->ctrl = LEON3_GPTIMER_EN | LEON3_GPTIMER_RL | LEON3_GPTIMER_LD; + + return 0; +} + +unsigned long timer_read_counter(void) +{ + if (tmr == NULL && timer_init()) + return 0; + + return ~tmr->val; +} + +#endif diff --git a/arch/sparc/cpu/leon3/interrupts.c b/arch/sparc/cpu/leon3/interrupts.c index a834aa0..20e295c 100644 --- a/arch/sparc/cpu/leon3/interrupts.c +++ b/arch/sparc/cpu/leon3/interrupts.c @@ -116,12 +116,24 @@ void leon3_force_int(int irq)
int interrupt_init_cpu(void) { +#ifdef CONFIG_SYS_GENERIC_BOARD + ambapp_apbdev apbdev; + + /* + * Find AMBA APB IRQMP Controller, + * When we come so far we know there is a IRQMP available + */ + ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev); + irqmp = (ambapp_dev_irqmp *) apbdev.address; +#endif
return (0); }
/****************************************************************************/
+#ifndef CONFIG_SYS_GENERIC_BOARD + /* Handle Timer 0 IRQ */ void timer_interrupt_cpu(void *arg) { @@ -132,6 +144,8 @@ void timer_interrupt_cpu(void *arg) return; }
+#endif + /****************************************************************************/
/* diff --git a/arch/sparc/include/asm/config.h b/arch/sparc/include/asm/config.h index fd0b551..66cde58 100644 --- a/arch/sparc/include/asm/config.h +++ b/arch/sparc/include/asm/config.h @@ -8,6 +8,7 @@ #define _ASM_CONFIG_H_
#define CONFIG_NEEDS_MANUAL_RELOC +#define CONFIG_SYS_GENERIC_GLOBAL_DATA
#define CONFIG_LMB #define CONFIG_SYS_BOOT_RAMDISK_HIGH diff --git a/arch/sparc/include/asm/u-boot.h b/arch/sparc/include/asm/u-boot.h index 5f12e58..4c4b5f2 100644 --- a/arch/sparc/include/asm/u-boot.h +++ b/arch/sparc/include/asm/u-boot.h @@ -17,6 +17,11 @@ #ifndef __U_BOOT_H__ #define __U_BOOT_H__
+#ifdef CONFIG_SYS_GENERIC_BOARD +/* Use the generic board which requires a unified bd_info */ +#include <asm-generic/u-boot.h> +#else + /* * Currently, this Board information is not passed to * Linux kernel from U-Boot, but may be passed to other @@ -44,6 +49,8 @@ typedef struct bd_info {
#endif /* __ASSEMBLY__ */
+#endif /* !CONFIG_SYS_GENERIC_BOARD */ + /* For image.h:image_check_target_arch() */ #define IH_ARCH_DEFAULT IH_ARCH_SPARC
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index e69b9ba..84c3ac2 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -5,5 +5,10 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-y = board.o cache.o interrupts.o time.o +obj-y = cache.o interrupts.o time.o + obj-$(CONFIG_CMD_BOOTM) += bootm.o + +ifndef CONFIG_SYS_GENERIC_BOARD +obj-y += board.o +endif diff --git a/arch/sparc/lib/interrupts.c b/arch/sparc/lib/interrupts.c index b7c3993..93479a9 100644 --- a/arch/sparc/lib/interrupts.c +++ b/arch/sparc/lib/interrupts.c @@ -17,8 +17,11 @@
/* Implemented by SPARC CPUs */ extern int interrupt_init_cpu(void); + +#ifndef CONFIG_SYS_GENERIC_BOARD extern void timer_interrupt_cpu(void *arg); extern int timer_interrupt_init_cpu(void); +#endif
int intLock(void) { @@ -60,6 +63,8 @@ int interrupt_init(void) return ret; }
+#ifndef CONFIG_SYS_GENERIC_BOARD + /* timer interrupt/overflow counter */ static volatile ulong timestamp = 0;
@@ -94,3 +99,5 @@ void timer_interrupt_init(void) /* register interrupt handler for timer */ irq_install_handler(irq, (void (*)(void *))timer_interrupt, NULL); } + +#endif diff --git a/arch/sparc/lib/time.c b/arch/sparc/lib/time.c index 50a09ad..257b41b 100644 --- a/arch/sparc/lib/time.c +++ b/arch/sparc/lib/time.c @@ -10,6 +10,8 @@
#include <common.h>
+#ifndef CONFIG_SYS_GENERIC_BOARD + /* Implemented by SPARC CPUs */ extern void cpu_wait_ticks(unsigned long ticks); extern unsigned long cpu_usec2ticks(unsigned long usec); @@ -32,6 +34,7 @@ unsigned long usec2ticks(unsigned long usec)
/* ------------------------------------------------------------------------- */
+ /* * We implement the delay by converting the delay (the number of * microseconds to wait) into a number of time base ticks; then we @@ -59,4 +62,6 @@ int init_timebase(void) return (0); }
+#endif + /* ------------------------------------------------------------------------- */ diff --git a/common/board_f.c b/common/board_f.c index b5bebc9..c97a1f8 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -842,7 +842,7 @@ static init_fnc_t init_sequence_f[] = { /* TODO: can we rename this to timer_init()? */ init_timebase, #endif -#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_BLACKFIN) +#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_BLACKFIN) || defined(CONFIG_SPARC) timer_init, /* initialize timer */ #endif #ifdef CONFIG_SYS_ALLOC_DPRAM -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

We now use the generic delay method which specifies the timeout as microseconds instead of ticks.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: None
drivers/net/greth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/greth.c b/drivers/net/greth.c index c817af4..7784684 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -237,7 +237,7 @@ int greth_init_phy(greth_priv * dev, bd_t * bis) debug("GRETH PHY ADDRESS: %d\n", phyaddr);
/* X msecs to ticks */ - timeout = usec2ticks(GRETH_PHY_TIMEOUT_MS * 1000); + timeout = GRETH_PHY_TIMEOUT_MS * 1000;
/* Get system timer0 current value * Total timeout is 5s -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

Reworked the LEON3 startup code to call board_init_f function at startup. Also implemented the relocate_code function in assembly to relocate the monitor and setup the stack pointer before calling board_init_r.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: - Add snoop detect function to restore lost feature
arch/sparc/cpu/leon3/cpu_init.c | 13 +- arch/sparc/cpu/leon3/start.S | 436 ++++++++++++++++++++++------------------ 2 files changed, 248 insertions(+), 201 deletions(-)
diff --git a/arch/sparc/cpu/leon3/cpu_init.c b/arch/sparc/cpu/leon3/cpu_init.c index 1144610..b0c7088 100644 --- a/arch/sparc/cpu/leon3/cpu_init.c +++ b/arch/sparc/cpu/leon3/cpu_init.c @@ -29,13 +29,23 @@ ambapp_dev_irqmp *irqmp = NULL; ambapp_dev_mctrl memctrl; ambapp_dev_gptimer *gptimer = NULL; unsigned int gptimer_irq = 0; -int leon3_snooping_avail = 0; +int leon3_snooping_avail = 0; /* used by arch/sparc/cpu/leon3/usb_uhci.c */
struct { gd_t gd_area; bd_t bd; } global_data;
+/* If CACHE snooping is available in hardware the result will be set + * to 0x800000, otherwise 0. + */ +static unsigned int snoop_detect(void) +{ + unsigned int result; + asm("lda [%%g0] 2, %0" : "=r"(result)); + return result & 0x00800000; +} + /* * Breath some life into the CPU... * @@ -92,6 +102,7 @@ void cpu_init_f(void) irqmp->cpu_force[0] = 0; /* no force IRQ on CPU 0 */
/* cache */ + leon3_snooping_avail = snoop_detect(); }
#ifndef CONFIG_SYS_GENERIC_BOARD diff --git a/arch/sparc/cpu/leon3/start.S b/arch/sparc/cpu/leon3/start.S index cf897f6..5cd791c 100644 --- a/arch/sparc/cpu/leon3/start.S +++ b/arch/sparc/cpu/leon3/start.S @@ -179,15 +179,6 @@ _trap_table: SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f4-f7 SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f8-fb SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! fc-ff -/* - * Version string - */ - - .data - .extern leon3_snooping_avail - .globl version_string -version_string: - .ascii U_BOOT_VERSION_STRING, "\0"
.section ".text" .align 4 @@ -232,151 +223,237 @@ clear_window: bge clear_window save
-wininit: +wiminit: set WIM_INIT, %g3 mov %g3, %wim
-stackp: +stack_init: set CONFIG_SYS_INIT_SP_OFFSET, %fp andn %fp, 0x0f, %fp sub %fp, 64, %sp
+tbr_init: + set CONFIG_SYS_TEXT_BASE, %g2 + wr %g0, %g2, %tbr + nop + nop + nop + +#ifdef CONFIG_TARGET_GR712RC_BOARD /* can't do this here, if we run from flash, we will be writing to flash! */ +clr_bss: + call 1f ! Use call to get hold of address for data table + nop + /* addresses of BSS segment */ + .word __bss_start ! 0x08 + .word __bss_end ! 0x0C +1: ld [%o7+0x08], %g2 ! __bss_start + ld [%o7+0x0C], %g3 ! __bss_stop + /* clearing 16byte a time ==> linker script need to align to 16 byte offset */ + clr %g1 /* std %g0 uses g0 and g1 */ +2: std %g0, [%g2] + std %g0, [%g2+8] + inc 16, %g2 ! ptr += 16 + cmp %g2, %g3 + bcs 2b ! while (ptr < end) + nop +#endif + cpu_init_unreloc: call cpu_init_f - nop + nop
-/* un relocated start address of monitor */ -#define TEXT_START _text - -/* un relocated end address of monitor */ -#define DATA_END __init_end - -reloc: - set TEXT_START,%g2 - set DATA_END,%g3 - set CONFIG_SYS_RELOC_MONITOR_BASE,%g4 -reloc_loop: - ldd [%g2],%l0 - ldd [%g2+8],%l2 - std %l0,[%g4] - std %l2,[%g4+8] - inc 16,%g2 - subcc %g3,%g2,%g0 - bne reloc_loop - inc 16,%g4 - - clr %l0 - clr %l1 - clr %l2 - clr %l3 - clr %g2 +board_init_unreloc: + call board_init_f + clr %o0 ! boot_flags + +dead: + mov 1, %g1 ! For GRMON2 to exit normally + ta 0 ! if call returns.. (unlikely) + nop + +!-------------------------------------------------------------------------------
-/* register g4 contain address to start - * This means that BSS must be directly after data and code segments +/* + * void relocate_code (addr_sp, gd, addr_moni) * - * g3 is length of bss = (__bss_end-__bss_start) + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. * + * %i0 = Relocated stack pointer + * %i1 = Relocated global data pointer + * %i2 = Relocated text pointer */ - -clr_bss: -/* clear bss area (the relocated) */ - set __bss_start,%g2 - set __bss_end,%g3 - sub %g3,%g2,%g3 - add %g3,%g4,%g3 - clr %g1 /* std %g0 uses g0 and g1 */ -/* clearing 16byte a time ==> linker script need to align to 16 byte offset */ -clr_bss_16: - std %g0,[%g4] - std %g0,[%g4+8] - inc 16,%g4 - cmp %g3,%g4 - bne clr_bss_16 + .globl relocate_code + .type relocate_code, #function +relocate_code: + call 1f ! Use call to get hold of the actual address our data table + nop + /* final function to call */ + .word board_init_r ! 0x00 + /* start address of text segment */ + .word _text ! 0x04 + /* addresses of BSS segment */ + .word __bss_start ! 0x08 + .word __bss_end ! 0x0C + /* addresses of GOT segment */ + .word __got_start ! 0x10 + .word __got_end ! 0x14 +1: + add %o7, 0x08, %g5 ! data table address + + /* disable traps */ +! mov %psr, %l0 +! and %l0, 0xFFFFFFDF, %l0 +! mov %l0, %psr + + ! %o0 = Relocated stack pointer + ! %o1 = Relocated global data pointer + ! %o2 = Relocated text pointer + ! %o7 = Actual address of relocate_code + + ! %g5 = Data table address + ! %g6 = Relocation offset + +_reloc: + ld [%g5+0x04], %g2 ! _text + sub %o2, %g2, %g6 ! relocation offset + ld [%g5+0x0C], %g3 ! __bss_stop + mov %o2, %g4 ! relocation pointer + /* copy text & bss to relocated address */ +10: ldd [%g2], %l0 + ldd [%g2+8], %l2 + std %l0, [%g4] + std %l2, [%g4+8] + inc 16, %g2 + cmp %g2, %g3 + bcs 10b ! while (ptr < end) + inc 16, %g4 + + /* add offsets to GOT table */ +_fixup_got: + ld [%g5+0x10], %g4 ! __got_start + add %g4, %g6, %g4 + ld [%g5+0x14], %g3 ! __got_end + add %g3, %g6, %g3 +30: ld [%g4], %l0 +#ifdef CONFIG_RELOC_GOT_SKIP_NULL + cmp %l0, 0 + be 32f +#endif + add %l0, %g6, %l0 ! relocate GOT pointer + st %l0, [%g4] +32: inc 4, %g4 + cmp %g4, %g3 + bcs 30b ! while (ptr < end) + nop + + ! %o0 = stack pointer (relocated) + ! %o1 = global data pointer (relocated) + ! %o2 = text pointer (relocated) + + ! %g5 = data table address + ! %g6 = relocation offset + + /* Trap table has been moved, tell CPU about new trap table address */ +_update_trap_table_address: + wr %g0, %o2, %tbr + nop + nop nop
-/* add offsets to GOT table */ -fixup_got: - set __got_start,%g4 - set __got_end,%g3 +_update_stack_pointers: + mov %o0, %fp + andn %fp, 0x0f, %fp ! align to 16 bytes + add %fp, -64, %fp ! make space for a window push + mov %fp, %sp ! setup stack pointer + +_jump_board_init_r: + mov %o1, %o0 ! relocated global data pointer + mov %o2, %o1 ! relocated text pointer + + ld [%g5+0x00], %o3 ! board_init_r + add %o3, %g6, %o3 ! relocate address + call %o3 + nop + + mov 1, %g1 ! should not reach this point + ta 0 + nop + +!------------------------------------------------------------------------------- + /* - * new got offset = (old GOT-PTR (read with ld) - - * CONFIG_SYS_RELOC_MONITOR_BASE(from define) ) + - * Destination Address (from define) + * Window overflow trap handler */ - set CONFIG_SYS_RELOC_MONITOR_BASE,%g2 - set TEXT_START, %g1 - add %g4,%g2,%g4 - sub %g4,%g1,%g4 - add %g3,%g2,%g3 - sub %g3,%g1,%g3 - sub %g2,%g1,%g2 ! prepare register with (new base address) - - ! (old base address) -got_loop: - ld [%g4],%l0 ! load old GOT-PTR - add %l0,%g2,%l0 ! increase with (new base address) - - ! (old base) - st %l0,[%g4] - inc 4,%g4 - cmp %g3,%g4 - bne got_loop + .global _window_overflow +_window_overflow: + mov %wim, %l3 ! Calculate next WIM + sll %l3, (CONFIG_SYS_SPARC_NWINDOWS-1) , %l4 + srl %l3, 1, %l3 + or %l3, %l4, %l3 + + mov %g0, %wim ! Disable WIM traps + nop + nop nop
-prom_relocate: - set __prom_start, %g2 - set __prom_end, %g3 - set CONFIG_SYS_PROM_OFFSET, %g4 - -prom_relocate_loop: - ldd [%g2],%l0 - ldd [%g2+8],%l2 - std %l0,[%g4] - std %l2,[%g4+8] - inc 16,%g2 - subcc %g3,%g2,%g0 - bne prom_relocate_loop - inc 16,%g4 - -/* Trap table has been moved, lets tell CPU about - * the new trap table address - */ + save ! Get into window to be saved
- set CONFIG_SYS_RELOC_MONITOR_BASE, %g2 - wr %g0, %g2, %tbr + std %l0, [%sp + 0] ! Save window to the stack + std %l2, [%sp + 8] + std %l4, [%sp + 16] + std %l6, [%sp + 24] + std %i0, [%sp + 32] + std %i2, [%sp + 40] + std %i4, [%sp + 48] + std %i6, [%sp + 56] + + restore ! Go back to trap window + + mov %l3, %wim ! Set new WIM trap nop nop nop
-/* If CACHE snooping is available in hardware the - * variable leon3_snooping_avail will be set to - * 0x800000 else 0. + jmp %l1 ! Re-execute save + rett %l2 + +!------------------------------------------------------------------------------- + +/* + * Window underflow trap handler */ -snoop_detect: - sethi %hi(0x00800000), %o0 - lda [%g0] 2, %o1 - and %o0, %o1, %o0 - sethi %hi(leon3_snooping_avail+CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %o1 - st %o0, [%lo(leon3_snooping_avail+CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE)+%o1] - -/* call relocate*/ + .global _window_underflow +_window_underflow: + mov %wim, %l3 ! Calculate next WIM + srl %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l4 + sll %l3, 1, %l3 + or %l3, %l4, %l3 + + mov %l3, %wim ! set new value of window + nop + nop nop -/* Call relocated init functions */ -jump: - set cpu_init_f2,%o1 - set CONFIG_SYS_RELOC_MONITOR_BASE,%o2 - add %o1,%o2,%o1 - sub %o1,%g1,%o1 - call %o1 - clr %o0
- set board_init_f,%o1 - set CONFIG_SYS_RELOC_MONITOR_BASE,%o2 - add %o1,%o2,%o1 - sub %o1,%g1,%o1 - call %o1 - clr %o0 + restore ! Two restores to get into the + restore ! window to restore
-dead: ta 0 ! if call returns... - nop + ldd [%sp + 0], %l0 ! Restore window from the stack + ldd [%sp + 8], %l2 + ldd [%sp + 16], %l4 + ldd [%sp + 24], %l6 + ldd [%sp + 32], %i0 + ldd [%sp + 40], %i2 + ldd [%sp + 48], %i4 + ldd [%sp + 56], %i6 + + save ! Get back to the trap window + save + + jmp %l1 ! Re-execute restore + rett %l2 + +!-------------------------------------------------------------------------------
/* Interrupt handler caller, * reg L7: interrupt number @@ -386,7 +463,25 @@ dead: ta 0 ! if call returns... * reg L3: wim */ _irq_entry: - SAVE_ALL + mov %o7, %l5 ! save original %o7 + call 1f + ld [%o7+0x08], %l4 ! trap_setup + .word trap_setup ! 0x08 +#ifdef CONFIG_SYS_GENERIC_BOARD + .word _irq_entry ! 0x0c + !SAVE_ALL +1: + ld [%o7+0x0C], %l6 ! _irq_entry + sub %o7, %l6, %l6 ! relocation offset (+4) + sub %l6, 4, %l6 ! relocation offset +#else + .word handler_irq ! 0x0c + !SAVE_ALL +1: set (CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %l6 +#endif + add %l4, %l6, %l4 ! relocated trap_setup + jmpl %l4, %l6 + mov %l5, %o7 ! restore orignal %o7
or %l0, PSR_PIL, %g2 wr %g2, 0x0, %psr @@ -394,10 +489,15 @@ _irq_entry: wr %g2, PSR_ET, %psr WRITE_PAUSE mov %l7, %o0 ! irq level - set handler_irq, %o1 +#ifdef CONFIG_SYS_GENERIC_BOARD + call handler_irq ! relative jump to handle_irq +#else + sub %l6, 0x18, %o2 ! calculate _irq_entry address + ld [%o2 + 0x0c], %o1 ! handler_irq set (CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %o2 add %o1, %o2, %o1 call %o1 +#endif add %sp, SF_REGS_SZ, %o1 ! pt_regs ptr or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq wr %g2, PSR_ET, %psr ! keep ET up @@ -405,79 +505,9 @@ _irq_entry:
RESTORE_ALL
-!Window overflow trap handler. - .global _window_overflow - -_window_overflow: - - mov %wim, %l3 ! Calculate next WIM - mov %g1, %l7 - srl %l3, 1, %g1 - sll %l3, (CONFIG_SYS_SPARC_NWINDOWS-1) , %l4 - or %l4, %g1, %g1 +!-------------------------------------------------------------------------------
- save ! Get into window to be saved. - mov %g1, %wim - nop; - nop; nop - st %l0, [%sp + 0]; - st %l1, [%sp + 4]; - st %l2, [%sp + 8]; - st %l3, [%sp + 12]; - st %l4, [%sp + 16]; - st %l5, [%sp + 20]; - st %l6, [%sp + 24]; - st %l7, [%sp + 28]; - st %i0, [%sp + 32]; - st %i1, [%sp + 36]; - st %i2, [%sp + 40]; - st %i3, [%sp + 44]; - st %i4, [%sp + 48]; - st %i5, [%sp + 52]; - st %i6, [%sp + 56]; - st %i7, [%sp + 60]; - restore ! Go back to trap window. - mov %l7, %g1 - jmp %l1 ! Re-execute save. - rett %l2 - -/* Window underflow trap handler. */ - - .global _window_underflow - -_window_underflow: - - mov %wim, %l3 ! Calculate next WIM - sll %l3, 1, %l4 - srl %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l5 - or %l5, %l4, %l5 - mov %l5, %wim - nop; nop; nop - restore ! Two restores to get into the - restore ! window to restore - ld [%sp + 0], %l0; ! Restore window from the stack - ld [%sp + 4], %l1; - ld [%sp + 8], %l2; - ld [%sp + 12], %l3; - ld [%sp + 16], %l4; - ld [%sp + 20], %l5; - ld [%sp + 24], %l6; - ld [%sp + 28], %l7; - ld [%sp + 32], %i0; - ld [%sp + 36], %i1; - ld [%sp + 40], %i2; - ld [%sp + 44], %i3; - ld [%sp + 48], %i4; - ld [%sp + 52], %i5; - ld [%sp + 56], %i6; - ld [%sp + 60], %i7; - save ! Get back to the trap window. - save - jmp %l1 ! Re-execute restore. - rett %l2 - - retl
_nmi_trap: nop @@ -597,6 +627,12 @@ ret_trap_entry: * It resets the system by jumping to _start */ _reset_reloc: - set start, %l0 +#if 1 /* DEBUG: When we run in GRMON, use the trap to exit normally. */ + mov 1, %g1 + ta 0 ! Cause program to exit normally in GRMON + nop +#else + set CONFIG_SYS_RELOC_MONITOR_BASE, %l0 call %l0 - nop + nop +#endif -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

Rewrote the PROM generation code to dynamically build the PROM from the AMBA PnP data on the LEON3. Also combined the LEON2/LEON3 code into one file and moved it to the arch/sparc/lib folder. The new code generates the PROM data rather than having it embedded as data and copying it over. The algorithm is also optimized to reduce the size of the resulting PROM data, e.g. pointers is encoded into 16-bit values and duplicate names point to the same copy of the string.
Refactored the SRMMU handling code into a seperate file. Added a function to build the default page tables instead of adding them at compile time.
The bootm.c file were also updated to search for the kernel header, instead of being a hard coded offset.
This code has been tested against a Linux v3.10.20 kernel.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: None
arch/sparc/cpu/leon2/Makefile | 2 +- arch/sparc/cpu/leon2/prom.c | 1030 ----------------------------------- arch/sparc/cpu/leon3/Makefile | 5 +- arch/sparc/cpu/leon3/prom.c | 1061 ------------------------------------- arch/sparc/include/asm/config.h | 2 + arch/sparc/include/asm/machines.h | 4 +- arch/sparc/lib/Makefile | 4 +- arch/sparc/lib/bootm.c | 81 +-- arch/sparc/lib/prom-no.c | 319 +++++++++++ arch/sparc/lib/prom-no.h | 40 ++ arch/sparc/lib/prom.c | 960 +++++++++++++++++++++++++++++++++ arch/sparc/lib/srmmu.c | 90 ++++ 12 files changed, 1472 insertions(+), 2126 deletions(-) delete mode 100644 arch/sparc/cpu/leon2/prom.c delete mode 100644 arch/sparc/cpu/leon3/prom.c create mode 100644 arch/sparc/lib/prom-no.c create mode 100644 arch/sparc/lib/prom-no.h create mode 100644 arch/sparc/lib/prom.c create mode 100644 arch/sparc/lib/srmmu.c
diff --git a/arch/sparc/cpu/leon2/Makefile b/arch/sparc/cpu/leon2/Makefile index 8c95ca5..1a2dae6 100644 --- a/arch/sparc/cpu/leon2/Makefile +++ b/arch/sparc/cpu/leon2/Makefile @@ -6,4 +6,4 @@ #
extra-y = start.o -obj-y = cpu_init.o serial.o cpu.o interrupts.o prom.o +obj-y = cpu_init.o serial.o cpu.o interrupts.o diff --git a/arch/sparc/cpu/leon2/prom.c b/arch/sparc/cpu/leon2/prom.c deleted file mode 100644 index cd2571f..0000000 --- a/arch/sparc/cpu/leon2/prom.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* prom.c - emulates a sparc v0 PROM for the linux kernel. - * - * Copyright (C) 2003 Konrad Eisele eiselekd@web.de - * Copyright (C) 2004 Stefan Holst mail@s-holst.de - * Copyright (C) 2007 Daniel Hellstrom daniel@gaisler.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/prom.h> -#include <asm/machines.h> -#include <asm/srmmu.h> -#include <asm/processor.h> -#include <asm/irq.h> -#include <asm/leon.h> - -#include <config.h> -/* -#define PRINT_ROM_VEC -*/ -extern struct linux_romvec *kernel_arg_promvec; - -#define PROM_PGT __attribute__ ((__section__ (".prom.pgt"))) -#define PROM_TEXT __attribute__ ((__section__ (".prom.text"))) -#define PROM_DATA __attribute__ ((__section__ (".prom.data"))) - -/* for __va */ -extern int __prom_start; -#define PAGE_OFFSET 0xf0000000 -#define phys_base CONFIG_SYS_SDRAM_BASE -#define PROM_OFFS 8192 -#define PROM_SIZE_MASK (PROM_OFFS-1) -#define __va(x) ( \ - (void *)( ((unsigned long)(x))-PROM_OFFS+ \ - (CONFIG_SYS_PROM_OFFSET-phys_base)+PAGE_OFFSET-CONFIG_SYS_TEXT_BASE ) \ - ) -#define __phy(x) ((void *)(((unsigned long)(x))-PROM_OFFS+CONFIG_SYS_PROM_OFFSET-CONFIG_SYS_TEXT_BASE)) - -struct property { - char *name; - char *value; - int length; -}; - -struct node { - int level; - struct property *properties; -}; - -static void leon_reboot(char *bcommand); -static void leon_halt(void); -static int leon_nbputchar(int c); -static int leon_nbgetchar(void); - -static int no_nextnode(int node); -static int no_child(int node); -static int no_proplen(int node, char *name); -static int no_getprop(int node, char *name, char *value); -static int no_setprop(int node, char *name, char *value, int len); -static char *no_nextprop(int node, char *name); - -static struct property PROM_TEXT *find_property(int node, char *name); -static int PROM_TEXT leon_strcmp(const char *s1, const char *s2); -static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n); -static void PROM_TEXT leon_reboot_physical(char *bcommand); - -void __inline__ leon_flush_cache_all(void) -{ - __asm__ __volatile__(" flush "); - __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH):"memory"); -} - -void __inline__ leon_flush_tlb_all(void) -{ - leon_flush_cache_all(); - __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400), - "i"(ASI_MMUFLUSH):"memory"); -} - -typedef struct { - unsigned int ctx_table[256]; - unsigned int pgd_table[256]; -} sparc_srmmu_setup; - -sparc_srmmu_setup srmmu_tables PROM_PGT = { - {0}, - {0x1e, - 0x10001e, - 0x20001e, - 0x30001e, - 0x40001e, - 0x50001e, - 0x60001e, - 0x70001e, - 0x80001e, - 0x90001e, - 0xa0001e, - 0xb0001e, - 0xc0001e, - 0xd0001e, - 0xe0001e, - 0xf0001e, - 0x100001e, - 0x110001e, - 0x120001e, - 0x130001e, - 0x140001e, - 0x150001e, - 0x160001e, - 0x170001e, - 0x180001e, - 0x190001e, - 0x1a0001e, - 0x1b0001e, - 0x1c0001e, - 0x1d0001e, - 0x1e0001e, - 0x1f0001e, - 0x200001e, - 0x210001e, - 0x220001e, - 0x230001e, - 0x240001e, - 0x250001e, - 0x260001e, - 0x270001e, - 0x280001e, - 0x290001e, - 0x2a0001e, - 0x2b0001e, - 0x2c0001e, - 0x2d0001e, - 0x2e0001e, - 0x2f0001e, - 0x300001e, - 0x310001e, - 0x320001e, - 0x330001e, - 0x340001e, - 0x350001e, - 0x360001e, - 0x370001e, - 0x380001e, - 0x390001e, - 0x3a0001e, - 0x3b0001e, - 0x3c0001e, - 0x3d0001e, - 0x3e0001e, - 0x3f0001e, - 0x400001e, - 0x410001e, - 0x420001e, - 0x430001e, - 0x440001e, - 0x450001e, - 0x460001e, - 0x470001e, - 0x480001e, - 0x490001e, - 0x4a0001e, - 0x4b0001e, - 0x4c0001e, - 0x4d0001e, - 0x4e0001e, - 0x4f0001e, - 0x500001e, - 0x510001e, - 0x520001e, - 0x530001e, - 0x540001e, - 0x550001e, - 0x560001e, - 0x570001e, - 0x580001e, - 0x590001e, - 0x5a0001e, - 0x5b0001e, - 0x5c0001e, - 0x5d0001e, - 0x5e0001e, - 0x5f0001e, - 0x600001e, - 0x610001e, - 0x620001e, - 0x630001e, - 0x640001e, - 0x650001e, - 0x660001e, - 0x670001e, - 0x680001e, - 0x690001e, - 0x6a0001e, - 0x6b0001e, - 0x6c0001e, - 0x6d0001e, - 0x6e0001e, - 0x6f0001e, - 0x700001e, - 0x710001e, - 0x720001e, - 0x730001e, - 0x740001e, - 0x750001e, - 0x760001e, - 0x770001e, - 0x780001e, - 0x790001e, - 0x7a0001e, - 0x7b0001e, - 0x7c0001e, - 0x7d0001e, - 0x7e0001e, - 0x7f0001e, - 0x800001e, - 0x810001e, - 0x820001e, - 0x830001e, - 0x840001e, - 0x850001e, - 0x860001e, - 0x870001e, - 0x880001e, - 0x890001e, - 0x8a0001e, - 0x8b0001e, - 0x8c0001e, - 0x8d0001e, - 0x8e0001e, - 0x8f0001e, - 0x900001e, - 0x910001e, - 0x920001e, - 0x930001e, - 0x940001e, - 0x950001e, - 0x960001e, - 0x970001e, - 0x980001e, - 0x990001e, - 0x9a0001e, - 0x9b0001e, - 0x9c0001e, - 0x9d0001e, - 0x9e0001e, - 0x9f0001e, - 0xa00001e, - 0xa10001e, - 0xa20001e, - 0xa30001e, - 0xa40001e, - 0xa50001e, - 0xa60001e, - 0xa70001e, - 0xa80001e, - 0xa90001e, - 0xaa0001e, - 0xab0001e, - 0xac0001e, - 0xad0001e, - 0xae0001e, - 0xaf0001e, - 0xb00001e, - 0xb10001e, - 0xb20001e, - 0xb30001e, - 0xb40001e, - 0xb50001e, - 0xb60001e, - 0xb70001e, - 0xb80001e, - 0xb90001e, - 0xba0001e, - 0xbb0001e, - 0xbc0001e, - 0xbd0001e, - 0xbe0001e, - 0xbf0001e, - 0xc00001e, - 0xc10001e, - 0xc20001e, - 0xc30001e, - 0xc40001e, - 0xc50001e, - 0xc60001e, - 0xc70001e, - 0xc80001e, - 0xc90001e, - 0xca0001e, - 0xcb0001e, - 0xcc0001e, - 0xcd0001e, - 0xce0001e, - 0xcf0001e, - 0xd00001e, - 0xd10001e, - 0xd20001e, - 0xd30001e, - 0xd40001e, - 0xd50001e, - 0xd60001e, - 0xd70001e, - 0xd80001e, - 0xd90001e, - 0xda0001e, - 0xdb0001e, - 0xdc0001e, - 0xdd0001e, - 0xde0001e, - 0xdf0001e, - 0xe00001e, - 0xe10001e, - 0xe20001e, - 0xe30001e, - 0xe40001e, - 0xe50001e, - 0xe60001e, - 0xe70001e, - 0xe80001e, - 0xe90001e, - 0xea0001e, - 0xeb0001e, - 0xec0001e, - 0xed0001e, - 0xee0001e, - 0xef0001e, - 0x400001e /* default */ - } -}; - -/* a self contained prom info structure */ -struct leon_reloc_func { - struct property *(*find_property) (int node, char *name); - int (*strcmp) (char *s1, char *s2); - void *(*memcpy) (void *dest, const void *src, size_t n); - void (*reboot_physical) (char *cmd); -}; - -struct leon_prom_info { - int freq_khz; - int leon_nctx; - int mids[32]; - int baudrates[2]; - struct leon_reloc_func reloc_funcs; - struct property root_properties[4]; - struct property cpu_properties[7]; -#undef CPUENTRY -#define CPUENTRY(idx) struct property cpu_properties##idx[4] - CPUENTRY(1); - CPUENTRY(2); - CPUENTRY(3); - CPUENTRY(4); - CPUENTRY(5); - CPUENTRY(6); - CPUENTRY(7); - CPUENTRY(8); - CPUENTRY(9); - CPUENTRY(10); - CPUENTRY(11); - CPUENTRY(12); - CPUENTRY(13); - CPUENTRY(14); - CPUENTRY(15); - CPUENTRY(16); - CPUENTRY(17); - CPUENTRY(18); - CPUENTRY(19); - CPUENTRY(20); - CPUENTRY(21); - CPUENTRY(22); - CPUENTRY(23); - CPUENTRY(24); - CPUENTRY(25); - CPUENTRY(26); - CPUENTRY(27); - CPUENTRY(28); - CPUENTRY(29); - CPUENTRY(30); - CPUENTRY(31); - struct idprom idprom; - struct linux_nodeops nodeops; - struct linux_mlist_v0 *totphys_p; - struct linux_mlist_v0 totphys; - struct linux_mlist_v0 *avail_p; - struct linux_mlist_v0 avail; - struct linux_mlist_v0 *prommap_p; - void (*synchook) (void); - struct linux_arguments_v0 *bootargs_p; - struct linux_arguments_v0 bootargs; - struct linux_romvec romvec; - struct node nodes[35]; - char s_device_type[12]; - char s_cpu[4]; - char s_mid[4]; - char s_idprom[7]; - char s_compatability[14]; - char s_leon2[6]; - char s_mmu_nctx[9]; - char s_frequency[16]; - char s_uart1_baud[11]; - char s_uart2_baud[11]; - char arg[256]; -}; - -/* static prom info */ -static struct leon_prom_info PROM_DATA spi = { - CONFIG_SYS_CLK_FREQ / 1000, - 256, - { -#undef CPUENTRY -#define CPUENTRY(idx) idx - CPUENTRY(0), - CPUENTRY(1), - CPUENTRY(2), - CPUENTRY(3), - CPUENTRY(4), - CPUENTRY(5), - CPUENTRY(6), - CPUENTRY(7), - CPUENTRY(8), - CPUENTRY(9), - CPUENTRY(10), - CPUENTRY(11), - CPUENTRY(12), - CPUENTRY(13), - CPUENTRY(14), - CPUENTRY(15), - CPUENTRY(16), - CPUENTRY(17), - CPUENTRY(18), - CPUENTRY(19), - CPUENTRY(20), - CPUENTRY(21), - CPUENTRY(22), - CPUENTRY(23), - CPUENTRY(24), - CPUENTRY(25), - CPUENTRY(26), - CPUENTRY(27), - CPUENTRY(28), - CPUENTRY(29), - CPUENTRY(30), - 31}, - {38400, 38400}, - { - __va(find_property), - __va(leon_strcmp), - __va(leon_memcpy), - __phy(leon_reboot_physical), - }, - { - {__va(spi.s_device_type), __va(spi.s_idprom), 4}, - {__va(spi.s_idprom), (char *)__va(&spi.idprom), sizeof(struct idprom)}, - {__va(spi.s_compatability), __va(spi.s_leon2), 5}, - {NULL, NULL, -1} - }, - { - {__va(spi.s_device_type), __va(spi.s_cpu), 4}, - {__va(spi.s_mid), __va(&spi.mids[0]), 4}, - {__va(spi.s_mmu_nctx), (char *)__va(&spi.leon_nctx), 4}, - {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, - {__va(spi.s_uart1_baud), (char *)__va(&spi.baudrates[0]), 4}, - {__va(spi.s_uart2_baud), (char *)__va(&spi.baudrates[1]), 4}, - {NULL, NULL, -1} - }, -#undef CPUENTRY -#define CPUENTRY(idx) \ - { /* cpu_properties */ \ - {__va(spi.s_device_type), __va(spi.s_cpu), 4}, \ - {__va(spi.s_mid), __va(&spi.mids[idx]), 4}, \ - {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, \ - {NULL, NULL, -1} \ - } - CPUENTRY(1), - CPUENTRY(2), - CPUENTRY(3), - CPUENTRY(4), - CPUENTRY(5), - CPUENTRY(6), - CPUENTRY(7), - CPUENTRY(8), - CPUENTRY(9), - CPUENTRY(10), - CPUENTRY(11), - CPUENTRY(12), - CPUENTRY(13), - CPUENTRY(14), - CPUENTRY(15), - CPUENTRY(16), - CPUENTRY(17), - CPUENTRY(18), - CPUENTRY(19), - CPUENTRY(20), - CPUENTRY(21), - CPUENTRY(22), - CPUENTRY(23), - CPUENTRY(24), - CPUENTRY(25), - CPUENTRY(26), - CPUENTRY(27), - CPUENTRY(28), - CPUENTRY(29), - CPUENTRY(30), - CPUENTRY(31), - { - 0x01, /* format */ - M_LEON2 | M_LEON2_SOC, /* machine type */ - {0, 0, 0, 0, 0, 0}, /* eth */ - 0, /* date */ - 0, /* sernum */ - 0, /* checksum */ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* reserved */ - }, - { - __va(no_nextnode), - __va(no_child), - __va(no_proplen), - __va(no_getprop), - __va(no_setprop), - __va(no_nextprop) - }, - __va(&spi.totphys), - { - NULL, - (char *)CONFIG_SYS_SDRAM_BASE, - 0, - }, - __va(&spi.avail), - { - NULL, - (char *)CONFIG_SYS_SDRAM_BASE, - 0, - }, - NULL, /* prommap_p */ - NULL, - __va(&spi.bootargs), - { - {NULL, __va(spi.arg), NULL /*... */ }, - /*... */ - }, - { - 0, - 0, /* sun4c v0 prom */ - 0, 0, - {__va(&spi.totphys_p), __va(&spi.prommap_p), __va(&spi.avail_p)}, - __va(&spi.nodeops), - NULL, {NULL /* ... */ }, - NULL, NULL, - NULL, NULL, /* pv_getchar, pv_putchar */ - __va(leon_nbgetchar), __va(leon_nbputchar), - NULL, - __va(leon_reboot), - NULL, - NULL, - NULL, - __va(leon_halt), - __va(&spi.synchook), - {NULL}, - __va(&spi.bootargs_p) - /*... */ - }, - { - {0, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ }, - {0, __va(spi.root_properties)}, - /* cpu 0, must be spi.nodes[2] see leon_prom_init() */ - {1, __va(spi.cpu_properties)}, - -#undef CPUENTRY -#define CPUENTRY(idx) \ - {1, __va(spi.cpu_properties##idx) } /* cpu <idx> */ - CPUENTRY(1), - CPUENTRY(2), - CPUENTRY(3), - CPUENTRY(4), - CPUENTRY(5), - CPUENTRY(6), - CPUENTRY(7), - CPUENTRY(8), - CPUENTRY(9), - CPUENTRY(10), - CPUENTRY(11), - CPUENTRY(12), - CPUENTRY(13), - CPUENTRY(14), - CPUENTRY(15), - CPUENTRY(16), - CPUENTRY(17), - CPUENTRY(18), - CPUENTRY(19), - CPUENTRY(20), - CPUENTRY(21), - CPUENTRY(22), - CPUENTRY(23), - CPUENTRY(24), - CPUENTRY(25), - CPUENTRY(26), - CPUENTRY(27), - CPUENTRY(28), - CPUENTRY(29), - CPUENTRY(30), - CPUENTRY(31), - {-1, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ } - }, - "device_type", - "cpu", - "mid", - "idprom", - "compatability", - "leon2", - "mmu-nctx", - "clock-frequency", - "uart1_baud", - "uart2_baud", - CONFIG_DEFAULT_KERNEL_COMMAND_LINE -}; - -/* from arch/sparc/kernel/setup.c */ -#define RAMDISK_LOAD_FLAG 0x4000 -extern unsigned short root_flags; -extern unsigned short root_dev; -extern unsigned short ram_flags; -extern unsigned int sparc_ramdisk_image; -extern unsigned int sparc_ramdisk_size; -extern int root_mountflags; - -extern char initrd_end, initrd_start; - -/* Reboot the CPU = jump to beginning of flash again. - * - * Make sure that all function are inlined here. - */ -static void PROM_TEXT leon_reboot(char *bcommand) -{ - register char *arg = bcommand; - void __attribute__ ((noreturn)) (*reboot_physical) (char *cmd); - - /* get physical address */ - struct leon_prom_info *pspi = - (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - unsigned int *srmmu_ctx_table; - - /* Turn of Interrupts */ - set_pil(0xf); - - /* Set kernel's context, context zero */ - srmmu_set_context(0); - - /* Get physical address of the MMU shutdown routine */ - reboot_physical = (void *) - SPARC_BYPASS_READ(&pspi->reloc_funcs.reboot_physical); - - /* Now that we know the physical address of the function - * we can make the MMU allow jumping to it. - */ - srmmu_ctx_table = (unsigned int *)srmmu_get_ctable_ptr(); - - srmmu_ctx_table = (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table); - - /* get physical address of kernel's context table (assume ptd) */ - srmmu_ctx_table = (unsigned int *) - (((unsigned int)srmmu_ctx_table & 0xfffffffc) << 4); - - /* enable access to physical address of MMU shutdown function */ - SPARC_BYPASS_WRITE(&srmmu_ctx_table - [((unsigned int)reboot_physical) >> 24], - (((unsigned int)reboot_physical & 0xff000000) >> 4) | - 0x1e); - - /* flush TLB cache */ - leon_flush_tlb_all(); - - /* flash instruction & data cache */ - sparc_icache_flush_all(); - sparc_dcache_flush_all(); - - /* jump to physical address function - * so that when the MMU is disabled - * we can continue to execute - */ - reboot_physical(arg); -} - -static void PROM_TEXT leon_reboot_physical(char *bcommand) -{ - void __attribute__ ((noreturn)) (*reset) (void); - - /* Turn off MMU */ - srmmu_set_mmureg(0); - - /* Hardcoded start address */ - reset = CONFIG_SYS_MONITOR_BASE; - - /* flush data cache */ - sparc_dcache_flush_all(); - - /* flush instruction cache */ - sparc_icache_flush_all(); - - /* Jump to start in Flash */ - reset(); -} - -static void PROM_TEXT leon_halt(void) -{ - while (1) ; -} - -/* get single char, don't care for blocking*/ -static int PROM_TEXT leon_nbgetchar(void) -{ - return -1; -} - -/* put single char, don't care for blocking*/ -static int PROM_TEXT leon_nbputchar(int c) -{ - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - - /***** put char in buffer... *********** - * Make sure all functions are inline! * - ***************************************/ - - /* Wait for last character to go. */ - while (!(SPARC_BYPASS_READ(&leon2->UART_Status_1) - & LEON2_UART_STAT_THE)) ; - - /* Send data */ - SPARC_BYPASS_WRITE(&leon2->UART_Channel_1, c); - - /* Wait for data to be sent */ - while (!(SPARC_BYPASS_READ(&leon2->UART_Status_1) - & LEON2_UART_STAT_TSE)) ; - - return 0; -} - -/* node ops */ - -/*#define nodes ((struct node *)__va(&pspi->nodes))*/ -#define nodes ((struct node *)(pspi->nodes)) - -static int PROM_TEXT no_nextnode(int node) -{ - /* get physical address */ - struct leon_prom_info *pspi = - (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - if (nodes[node].level == nodes[node + 1].level) - return node + 1; - return -1; -} - -static int PROM_TEXT no_child(int node) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - if (nodes[node].level == nodes[node + 1].level - 1) - return node + 1; - return -1; -} - -static struct property PROM_TEXT *find_property(int node, char *name) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - struct property *prop = &nodes[node].properties[0]; - while (prop && prop->name) { - if (pspi->reloc_funcs.strcmp(prop->name, name) == 0) - return prop; - prop++; - } - return NULL; -} - -static int PROM_TEXT no_proplen(int node, char *name) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - struct property *prop = pspi->reloc_funcs.find_property(node, name); - if (prop) - return prop->length; - return -1; -} - -static int PROM_TEXT no_getprop(int node, char *name, char *value) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - struct property *prop = pspi->reloc_funcs.find_property(node, name); - if (prop) { - pspi->reloc_funcs.memcpy(value, prop->value, prop->length); - return 1; - } - return -1; -} - -static int PROM_TEXT no_setprop(int node, char *name, char *value, int len) -{ - return -1; -} - -static char PROM_TEXT *no_nextprop(int node, char *name) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - struct property *prop; - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - if (!name || !name[0]) - return nodes[node].properties[0].name; - - prop = pspi->reloc_funcs.find_property(node, name); - if (prop) - return prop[1].name; - return NULL; -} - -static int PROM_TEXT leon_strcmp(const char *s1, const char *s2) -{ - register char result; - - while (1) { - result = *s1 - *s2; - if (result || !*s1) - break; - s2++; - s1++; - } - - return result; -} - -static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n) -{ - char *dst = (char *)dest, *source = (char *)src; - - while (n--) { - *dst = *source; - dst++; - source++; - } - return dest; -} - -#define GETREGSP(sp) __asm__ __volatile__("mov %%sp, %0" : "=r" (sp)) - -void leon_prom_init(struct leon_prom_info *pspi) -{ - unsigned long i; - unsigned char cksum, *ptr; - char *addr_str, *end; - unsigned long sp; - GETREGSP(sp); - - pspi->freq_khz = CONFIG_SYS_CLK_FREQ / 1000; - - /* Set Available main memory size */ - pspi->totphys.num_bytes = CONFIG_SYS_PROM_OFFSET - CONFIG_SYS_SDRAM_BASE; - pspi->avail.num_bytes = pspi->totphys.num_bytes; - -#undef nodes - pspi->nodes[3].level = -1; - pspi->nodes[3].properties = __va(spi.root_properties + 3); - - /* Set Ethernet MAC address from environment */ - if ((addr_str = getenv("ethaddr")) != NULL) { - for (i = 0; i < 6; i++) { - pspi->idprom.id_ethaddr[i] = addr_str ? - simple_strtoul(addr_str, &end, 16) : 0; - if (addr_str) { - addr_str = (*end) ? end + 1 : end; - } - } - } else { - /* HW Address not found in environment, - * Set default HW address - */ - pspi->idprom.id_ethaddr[0] = 0; - pspi->idprom.id_ethaddr[1] = 0; - pspi->idprom.id_ethaddr[2] = 0; - pspi->idprom.id_ethaddr[3] = 0; - pspi->idprom.id_ethaddr[4] = 0; - pspi->idprom.id_ethaddr[5] = 0; - } - - ptr = (unsigned char *)&pspi->idprom; - for (i = cksum = 0; i <= 0x0E; i++) - cksum ^= *ptr++; - pspi->idprom.id_cksum = cksum; -} - -static inline void set_cache(unsigned long regval) -{ - asm volatile ("sta %0, [%%g0] %1\n\t":: "r" (regval), "i"(2):"memory"); -} - -extern unsigned short bss_start, bss_end; - -/* mark as section .img.main.text, to be referenced in linker script */ -int prom_init(void) -{ - struct leon_prom_info *pspi = (void *) - ((((unsigned int)&spi) & PROM_SIZE_MASK) + CONFIG_SYS_PROM_OFFSET); - - /* disable mmu */ - srmmu_set_mmureg(0x00000000); - __asm__ __volatile__("flush\n\t"); - - /* init prom info struct */ - leon_prom_init(pspi); - - kernel_arg_promvec = &pspi->romvec; -#ifdef PRINT_ROM_VEC - printf("Kernel rom vec: 0x%lx\n", (unsigned int)(&pspi->romvec)); -#endif - return 0; -} - -/* Copy current kernel boot argument to ROMvec */ -void prepare_bootargs(char *bootargs) -{ - struct leon_prom_info *pspi; - char *src, *dst; - int left; - - /* if no bootargs set, skip copying ==> default bootline */ - if (bootargs && (*bootargs != '\0')) { - pspi = (void *)((((unsigned int)&spi) & PROM_SIZE_MASK) + - CONFIG_SYS_PROM_OFFSET); - src = bootargs; - dst = &pspi->arg[0]; - left = 255; /* max len */ - while (*src && left > 0) { - *dst++ = *src++; - left--; - } - /* terminate kernel command line string */ - *dst = 0; - } -} - -void srmmu_init_cpu(unsigned int entry) -{ - sparc_srmmu_setup *psrmmu_tables = (void *) - ((((unsigned int)&srmmu_tables) & PROM_SIZE_MASK) + - CONFIG_SYS_PROM_OFFSET); - - /* Make context 0 (kernel's context) point - * to our prepared memory mapping - */ -#define PTD 1 - psrmmu_tables->ctx_table[0] = - ((unsigned int)&psrmmu_tables->pgd_table[0x00]) >> 4 | PTD; - - /* Set virtual kernel address 0xf0000000 - * to SRAM/SDRAM address. - * Make it READ/WRITE/EXEC to SuperUser - */ -#define PTE 2 -#define ACC_SU_ALL 0x1c - psrmmu_tables->pgd_table[0xf0] = - (CONFIG_SYS_SDRAM_BASE >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf1] = - ((CONFIG_SYS_SDRAM_BASE + 0x1000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf2] = - ((CONFIG_SYS_SDRAM_BASE + 0x2000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf3] = - ((CONFIG_SYS_SDRAM_BASE + 0x3000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf4] = - ((CONFIG_SYS_SDRAM_BASE + 0x4000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf5] = - ((CONFIG_SYS_SDRAM_BASE + 0x5000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf6] = - ((CONFIG_SYS_SDRAM_BASE + 0x6000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf7] = - ((CONFIG_SYS_SDRAM_BASE + 0x7000000) >> 4) | ACC_SU_ALL | PTE; - - /* convert rom vec pointer to virtual address */ - kernel_arg_promvec = (struct linux_romvec *) - (((unsigned int)kernel_arg_promvec & 0x0fffffff) | 0xf0000000); - - /* Set Context pointer to point to context table - * 256 contexts supported. - */ - srmmu_set_ctable_ptr((unsigned int)&psrmmu_tables->ctx_table[0]); - - /* Set kernel's context, context zero */ - srmmu_set_context(0); - - /* Invalidate all Cache */ - __asm__ __volatile__("flush\n\t"); - - srmmu_set_mmureg(0x00000001); - leon_flush_tlb_all(); - leon_flush_cache_all(); -} diff --git a/arch/sparc/cpu/leon3/Makefile b/arch/sparc/cpu/leon3/Makefile index 4f13ec3..0131f22 100644 --- a/arch/sparc/cpu/leon3/Makefile +++ b/arch/sparc/cpu/leon3/Makefile @@ -6,4 +6,7 @@ #
extra-y = start.o -obj-y = cpu_init.o serial.o cpu.o ambapp.o interrupts.o prom.o usb_uhci.o + +obj-y = cpu_init.o serial.o cpu.o ambapp.o interrupts.o + +obj-$(CONFIG_USB_UHCI) += usb_uhci.o diff --git a/arch/sparc/cpu/leon3/prom.c b/arch/sparc/cpu/leon3/prom.c deleted file mode 100644 index b83776b..0000000 --- a/arch/sparc/cpu/leon3/prom.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* prom.c - emulates a sparc v0 PROM for the linux kernel. - * - * Copyright (C) 2003 Konrad Eisele eiselekd@web.de - * Copyright (C) 2004 Stefan Holst mail@s-holst.de - * Copyright (C) 2007 Daniel Hellstrom daniel@gaisler.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/prom.h> -#include <asm/machines.h> -#include <asm/srmmu.h> -#include <asm/processor.h> -#include <asm/irq.h> -#include <asm/leon.h> -#include <ambapp.h> - -#include <config.h> -/* -#define PRINT_ROM_VEC -*/ -extern struct linux_romvec *kernel_arg_promvec; -extern ambapp_dev_apbuart *leon3_apbuart; - -#define PROM_PGT __attribute__ ((__section__ (".prom.pgt"))) -#define PROM_TEXT __attribute__ ((__section__ (".prom.text"))) -#define PROM_DATA __attribute__ ((__section__ (".prom.data"))) - -ambapp_dev_gptimer *gptimer; - -/* for __va */ -extern int __prom_start; -#define PAGE_OFFSET 0xf0000000 -#define phys_base CONFIG_SYS_SDRAM_BASE -#define PROM_OFFS 8192 -#define PROM_SIZE_MASK (PROM_OFFS-1) -#define __va(x) ( \ - (void *)( ((unsigned long)(x))-PROM_OFFS+ \ - (CONFIG_SYS_PROM_OFFSET-phys_base)+PAGE_OFFSET-CONFIG_SYS_TEXT_BASE ) \ - ) -#define __phy(x) ((void *)(((unsigned long)(x))-PROM_OFFS+CONFIG_SYS_PROM_OFFSET-CONFIG_SYS_TEXT_BASE)) - -struct property { - char *name; - char *value; - int length; -}; - -struct node { - int level; - struct property *properties; -}; - -static void leon_reboot(char *bcommand); -static void leon_halt(void); -static int leon_nbputchar(int c); -static int leon_nbgetchar(void); - -static int no_nextnode(int node); -static int no_child(int node); -static int no_proplen(int node, char *name); -static int no_getprop(int node, char *name, char *value); -static int no_setprop(int node, char *name, char *value, int len); -static char *no_nextprop(int node, char *name); - -static struct property PROM_TEXT *find_property(int node, char *name); -static int PROM_TEXT leon_strcmp(const char *s1, const char *s2); -static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n); -static void PROM_TEXT leon_reboot_physical(char *bcommand); - -void __inline__ leon_flush_cache_all(void) -{ - __asm__ __volatile__(" flush "); - __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH):"memory"); -} - -void __inline__ leon_flush_tlb_all(void) -{ - leon_flush_cache_all(); - __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400), - "i"(ASI_MMUFLUSH):"memory"); -} - -typedef struct { - unsigned int ctx_table[256]; - unsigned int pgd_table[256]; -} sparc_srmmu_setup; - -sparc_srmmu_setup srmmu_tables PROM_PGT = { - {0}, - {0x1e, - 0x10001e, - 0x20001e, - 0x30001e, - 0x40001e, - 0x50001e, - 0x60001e, - 0x70001e, - 0x80001e, - 0x90001e, - 0xa0001e, - 0xb0001e, - 0xc0001e, - 0xd0001e, - 0xe0001e, - 0xf0001e, - 0x100001e, - 0x110001e, - 0x120001e, - 0x130001e, - 0x140001e, - 0x150001e, - 0x160001e, - 0x170001e, - 0x180001e, - 0x190001e, - 0x1a0001e, - 0x1b0001e, - 0x1c0001e, - 0x1d0001e, - 0x1e0001e, - 0x1f0001e, - 0x200001e, - 0x210001e, - 0x220001e, - 0x230001e, - 0x240001e, - 0x250001e, - 0x260001e, - 0x270001e, - 0x280001e, - 0x290001e, - 0x2a0001e, - 0x2b0001e, - 0x2c0001e, - 0x2d0001e, - 0x2e0001e, - 0x2f0001e, - 0x300001e, - 0x310001e, - 0x320001e, - 0x330001e, - 0x340001e, - 0x350001e, - 0x360001e, - 0x370001e, - 0x380001e, - 0x390001e, - 0x3a0001e, - 0x3b0001e, - 0x3c0001e, - 0x3d0001e, - 0x3e0001e, - 0x3f0001e, - 0x400001e, - 0x410001e, - 0x420001e, - 0x430001e, - 0x440001e, - 0x450001e, - 0x460001e, - 0x470001e, - 0x480001e, - 0x490001e, - 0x4a0001e, - 0x4b0001e, - 0x4c0001e, - 0x4d0001e, - 0x4e0001e, - 0x4f0001e, - 0x500001e, - 0x510001e, - 0x520001e, - 0x530001e, - 0x540001e, - 0x550001e, - 0x560001e, - 0x570001e, - 0x580001e, - 0x590001e, - 0x5a0001e, - 0x5b0001e, - 0x5c0001e, - 0x5d0001e, - 0x5e0001e, - 0x5f0001e, - 0x600001e, - 0x610001e, - 0x620001e, - 0x630001e, - 0x640001e, - 0x650001e, - 0x660001e, - 0x670001e, - 0x680001e, - 0x690001e, - 0x6a0001e, - 0x6b0001e, - 0x6c0001e, - 0x6d0001e, - 0x6e0001e, - 0x6f0001e, - 0x700001e, - 0x710001e, - 0x720001e, - 0x730001e, - 0x740001e, - 0x750001e, - 0x760001e, - 0x770001e, - 0x780001e, - 0x790001e, - 0x7a0001e, - 0x7b0001e, - 0x7c0001e, - 0x7d0001e, - 0x7e0001e, - 0x7f0001e, - 0x800001e, - 0x810001e, - 0x820001e, - 0x830001e, - 0x840001e, - 0x850001e, - 0x860001e, - 0x870001e, - 0x880001e, - 0x890001e, - 0x8a0001e, - 0x8b0001e, - 0x8c0001e, - 0x8d0001e, - 0x8e0001e, - 0x8f0001e, - 0x900001e, - 0x910001e, - 0x920001e, - 0x930001e, - 0x940001e, - 0x950001e, - 0x960001e, - 0x970001e, - 0x980001e, - 0x990001e, - 0x9a0001e, - 0x9b0001e, - 0x9c0001e, - 0x9d0001e, - 0x9e0001e, - 0x9f0001e, - 0xa00001e, - 0xa10001e, - 0xa20001e, - 0xa30001e, - 0xa40001e, - 0xa50001e, - 0xa60001e, - 0xa70001e, - 0xa80001e, - 0xa90001e, - 0xaa0001e, - 0xab0001e, - 0xac0001e, - 0xad0001e, - 0xae0001e, - 0xaf0001e, - 0xb00001e, - 0xb10001e, - 0xb20001e, - 0xb30001e, - 0xb40001e, - 0xb50001e, - 0xb60001e, - 0xb70001e, - 0xb80001e, - 0xb90001e, - 0xba0001e, - 0xbb0001e, - 0xbc0001e, - 0xbd0001e, - 0xbe0001e, - 0xbf0001e, - 0xc00001e, - 0xc10001e, - 0xc20001e, - 0xc30001e, - 0xc40001e, - 0xc50001e, - 0xc60001e, - 0xc70001e, - 0xc80001e, - 0xc90001e, - 0xca0001e, - 0xcb0001e, - 0xcc0001e, - 0xcd0001e, - 0xce0001e, - 0xcf0001e, - 0xd00001e, - 0xd10001e, - 0xd20001e, - 0xd30001e, - 0xd40001e, - 0xd50001e, - 0xd60001e, - 0xd70001e, - 0xd80001e, - 0xd90001e, - 0xda0001e, - 0xdb0001e, - 0xdc0001e, - 0xdd0001e, - 0xde0001e, - 0xdf0001e, - 0xe00001e, - 0xe10001e, - 0xe20001e, - 0xe30001e, - 0xe40001e, - 0xe50001e, - 0xe60001e, - 0xe70001e, - 0xe80001e, - 0xe90001e, - 0xea0001e, - 0xeb0001e, - 0xec0001e, - 0xed0001e, - 0xee0001e, - 0xef0001e, - 0x400001e /* default */ - } -}; - -/* a self contained prom info structure */ -struct leon_reloc_func { - struct property *(*find_property) (int node, char *name); - int (*strcmp) (char *s1, char *s2); - void *(*memcpy) (void *dest, const void *src, size_t n); - void (*reboot_physical) (char *cmd); - ambapp_dev_apbuart *leon3_apbuart; -}; - -struct leon_prom_info { - int freq_khz; - int leon_nctx; - int mids[32]; - int baudrates[2]; - struct leon_reloc_func reloc_funcs; - struct property root_properties[4]; - struct property cpu_properties[7]; -#undef CPUENTRY -#define CPUENTRY(idx) struct property cpu_properties##idx[4] - CPUENTRY(1); - CPUENTRY(2); - CPUENTRY(3); - CPUENTRY(4); - CPUENTRY(5); - CPUENTRY(6); - CPUENTRY(7); - CPUENTRY(8); - CPUENTRY(9); - CPUENTRY(10); - CPUENTRY(11); - CPUENTRY(12); - CPUENTRY(13); - CPUENTRY(14); - CPUENTRY(15); - CPUENTRY(16); - CPUENTRY(17); - CPUENTRY(18); - CPUENTRY(19); - CPUENTRY(20); - CPUENTRY(21); - CPUENTRY(22); - CPUENTRY(23); - CPUENTRY(24); - CPUENTRY(25); - CPUENTRY(26); - CPUENTRY(27); - CPUENTRY(28); - CPUENTRY(29); - CPUENTRY(30); - CPUENTRY(31); - struct idprom idprom; - struct linux_nodeops nodeops; - struct linux_mlist_v0 *totphys_p; - struct linux_mlist_v0 totphys; - struct linux_mlist_v0 *avail_p; - struct linux_mlist_v0 avail; - struct linux_mlist_v0 *prommap_p; - void (*synchook) (void); - struct linux_arguments_v0 *bootargs_p; - struct linux_arguments_v0 bootargs; - struct linux_romvec romvec; - struct node nodes[35]; - char s_device_type[12]; - char s_cpu[4]; - char s_mid[4]; - char s_idprom[7]; - char s_compatability[14]; - char s_leon2[6]; - char s_mmu_nctx[9]; - char s_frequency[16]; - char s_uart1_baud[11]; - char s_uart2_baud[11]; - char arg[256]; -}; - -/* static prom info */ -static struct leon_prom_info PROM_DATA spi = { - CONFIG_SYS_CLK_FREQ / 1000, - 256, - { -#undef CPUENTRY -#define CPUENTRY(idx) idx - CPUENTRY(0), - CPUENTRY(1), - CPUENTRY(2), - CPUENTRY(3), - CPUENTRY(4), - CPUENTRY(5), - CPUENTRY(6), - CPUENTRY(7), - CPUENTRY(8), - CPUENTRY(9), - CPUENTRY(10), - CPUENTRY(11), - CPUENTRY(12), - CPUENTRY(13), - CPUENTRY(14), - CPUENTRY(15), - CPUENTRY(16), - CPUENTRY(17), - CPUENTRY(18), - CPUENTRY(19), - CPUENTRY(20), - CPUENTRY(21), - CPUENTRY(22), - CPUENTRY(23), - CPUENTRY(24), - CPUENTRY(25), - CPUENTRY(26), - CPUENTRY(27), - CPUENTRY(28), - CPUENTRY(29), - CPUENTRY(30), - 31}, - {38400, 38400}, - { - __va(find_property), - __va(leon_strcmp), - __va(leon_memcpy), - __phy(leon_reboot_physical), - }, - { - {__va(spi.s_device_type), __va(spi.s_idprom), 4}, - {__va(spi.s_idprom), (char *)__va(&spi.idprom), sizeof(struct idprom)}, - {__va(spi.s_compatability), __va(spi.s_leon2), 5}, - {NULL, NULL, -1} - }, - { - {__va(spi.s_device_type), __va(spi.s_cpu), 4}, - {__va(spi.s_mid), __va(&spi.mids[0]), 4}, - {__va(spi.s_mmu_nctx), (char *)__va(&spi.leon_nctx), 4}, - {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, - {__va(spi.s_uart1_baud), (char *)__va(&spi.baudrates[0]), 4}, - {__va(spi.s_uart2_baud), (char *)__va(&spi.baudrates[1]), 4}, - {NULL, NULL, -1} - }, -#undef CPUENTRY -#define CPUENTRY(idx) \ - { /* cpu_properties */ \ - {__va(spi.s_device_type), __va(spi.s_cpu), 4}, \ - {__va(spi.s_mid), __va(&spi.mids[idx]), 4}, \ - {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, \ - {NULL, NULL, -1} \ - } - CPUENTRY(1), - CPUENTRY(2), - CPUENTRY(3), - CPUENTRY(4), - CPUENTRY(5), - CPUENTRY(6), - CPUENTRY(7), - CPUENTRY(8), - CPUENTRY(9), - CPUENTRY(10), - CPUENTRY(11), - CPUENTRY(12), - CPUENTRY(13), - CPUENTRY(14), - CPUENTRY(15), - CPUENTRY(16), - CPUENTRY(17), - CPUENTRY(18), - CPUENTRY(19), - CPUENTRY(20), - CPUENTRY(21), - CPUENTRY(22), - CPUENTRY(23), - CPUENTRY(24), - CPUENTRY(25), - CPUENTRY(26), - CPUENTRY(27), - CPUENTRY(28), - CPUENTRY(29), - CPUENTRY(30), - CPUENTRY(31), - { - 0x01, /* format */ - M_LEON2 | M_LEON2_SOC, /* machine type */ - {0, 0, 0, 0, 0, 0}, /* eth */ - 0, /* date */ - 0, /* sernum */ - 0, /* checksum */ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* reserved */ - }, - { - __va(no_nextnode), - __va(no_child), - __va(no_proplen), - __va(no_getprop), - __va(no_setprop), - __va(no_nextprop) - }, - __va(&spi.totphys), - { - NULL, - (char *)CONFIG_SYS_SDRAM_BASE, - 0, - }, - __va(&spi.avail), - { - NULL, - (char *)CONFIG_SYS_SDRAM_BASE, - 0, - }, - NULL, /* prommap_p */ - NULL, - __va(&spi.bootargs), - { - {NULL, __va(spi.arg), NULL /*... */ }, - /*... */ - }, - { - 0, - 0, /* sun4c v0 prom */ - 0, 0, - {__va(&spi.totphys_p), __va(&spi.prommap_p), __va(&spi.avail_p)}, - __va(&spi.nodeops), - NULL, {NULL /* ... */ }, - NULL, NULL, - NULL, NULL, /* pv_getchar, pv_putchar */ - __va(leon_nbgetchar), __va(leon_nbputchar), - NULL, - __va(leon_reboot), - NULL, - NULL, - NULL, - __va(leon_halt), - __va(&spi.synchook), - {NULL}, - __va(&spi.bootargs_p) - /*... */ - }, - { - {0, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ }, - {0, __va(spi.root_properties)}, - /* cpu 0, must be spi.nodes[2] see leon_prom_init() */ - {1, __va(spi.cpu_properties)}, - -#undef CPUENTRY -#define CPUENTRY(idx) \ - {1, __va(spi.cpu_properties##idx) } /* cpu <idx> */ - CPUENTRY(1), - CPUENTRY(2), - CPUENTRY(3), - CPUENTRY(4), - CPUENTRY(5), - CPUENTRY(6), - CPUENTRY(7), - CPUENTRY(8), - CPUENTRY(9), - CPUENTRY(10), - CPUENTRY(11), - CPUENTRY(12), - CPUENTRY(13), - CPUENTRY(14), - CPUENTRY(15), - CPUENTRY(16), - CPUENTRY(17), - CPUENTRY(18), - CPUENTRY(19), - CPUENTRY(20), - CPUENTRY(21), - CPUENTRY(22), - CPUENTRY(23), - CPUENTRY(24), - CPUENTRY(25), - CPUENTRY(26), - CPUENTRY(27), - CPUENTRY(28), - CPUENTRY(29), - CPUENTRY(30), - CPUENTRY(31), - {-1, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ } - }, - "device_type", - "cpu", - "mid", - "idprom", - "compatability", - "leon2", - "mmu-nctx", - "clock-frequency", - "uart1_baud", - "uart2_baud", - CONFIG_DEFAULT_KERNEL_COMMAND_LINE -}; - -/* from arch/sparc/kernel/setup.c */ -#define RAMDISK_LOAD_FLAG 0x4000 -extern unsigned short root_flags; -extern unsigned short root_dev; -extern unsigned short ram_flags; -extern unsigned int sparc_ramdisk_image; -extern unsigned int sparc_ramdisk_size; -extern int root_mountflags; - -extern char initrd_end, initrd_start; - -/* Reboot the CPU = jump to beginning of flash again. - * - * Make sure that all function are inlined here. - */ -static void PROM_TEXT leon_reboot(char *bcommand) -{ - register char *arg = bcommand; - void __attribute__ ((noreturn)) (*reboot_physical) (char *cmd); - - /* get physical address */ - struct leon_prom_info *pspi = - (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - unsigned int *srmmu_ctx_table; - - /* Turn of Interrupts */ - set_pil(0xf); - - /* Set kernel's context, context zero */ - srmmu_set_context(0); - - /* Get physical address of the MMU shutdown routine */ - reboot_physical = (void *) - SPARC_BYPASS_READ(&pspi->reloc_funcs.reboot_physical); - - /* Now that we know the physical address of the function - * we can make the MMU allow jumping to it. - */ - srmmu_ctx_table = (unsigned int *)srmmu_get_ctable_ptr(); - - srmmu_ctx_table = (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table); - - /* get physical address of kernel's context table (assume ptd) */ - srmmu_ctx_table = (unsigned int *) - (((unsigned int)srmmu_ctx_table & 0xfffffffc) << 4); - - /* enable access to physical address of MMU shutdown function */ - SPARC_BYPASS_WRITE(&srmmu_ctx_table - [((unsigned int)reboot_physical) >> 24], - (((unsigned int)reboot_physical & 0xff000000) >> 4) | - 0x1e); - - /* flush TLB cache */ - leon_flush_tlb_all(); - - /* flash instruction & data cache */ - sparc_icache_flush_all(); - sparc_dcache_flush_all(); - - /* jump to physical address function - * so that when the MMU is disabled - * we can continue to execute - */ - reboot_physical(arg); -} - -static void PROM_TEXT leon_reboot_physical(char *bcommand) -{ - void __attribute__ ((noreturn)) (*reset) (void); - - /* Turn off MMU */ - srmmu_set_mmureg(0); - - /* Hardcoded start address */ - reset = CONFIG_SYS_MONITOR_BASE; - - /* flush data cache */ - sparc_dcache_flush_all(); - - /* flush instruction cache */ - sparc_icache_flush_all(); - - /* Jump to start in Flash */ - reset(); -} - -static void PROM_TEXT leon_halt(void) -{ - while (1) ; -} - -/* get single char, don't care for blocking*/ -static int PROM_TEXT leon_nbgetchar(void) -{ - return -1; -} - -/* put single char, don't care for blocking*/ -static int PROM_TEXT leon_nbputchar(int c) -{ - ambapp_dev_apbuart *uart; - - /* get physical address */ - struct leon_prom_info *pspi = - (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - uart = (ambapp_dev_apbuart *) - SPARC_BYPASS_READ(&pspi->reloc_funcs.leon3_apbuart); - - /* no UART? */ - if (!uart) - return 0; - - /***** put char in buffer... *********** - * Make sure all functions are inline! * - ***************************************/ - - /* Wait for last character to go. */ - while (!(SPARC_BYPASS_READ(&uart->status) - & LEON_REG_UART_STATUS_THE)) ; - - /* Send data */ - SPARC_BYPASS_WRITE(&uart->data, c); - - /* Wait for data to be sent */ - while (!(SPARC_BYPASS_READ(&uart->status) - & LEON_REG_UART_STATUS_TSE)) ; - - return 0; -} - -/* node ops */ - -/*#define nodes ((struct node *)__va(&pspi->nodes))*/ -#define nodes ((struct node *)(pspi->nodes)) - -static int PROM_TEXT no_nextnode(int node) -{ - /* get physical address */ - struct leon_prom_info *pspi = - (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - if (nodes[node].level == nodes[node + 1].level) - return node + 1; - return -1; -} - -static int PROM_TEXT no_child(int node) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - if (nodes[node].level == nodes[node + 1].level - 1) - return node + 1; - return -1; -} - -static struct property PROM_TEXT *find_property(int node, char *name) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - struct property *prop = &nodes[node].properties[0]; - while (prop && prop->name) { - if (pspi->reloc_funcs.strcmp(prop->name, name) == 0) - return prop; - prop++; - } - return NULL; -} - -static int PROM_TEXT no_proplen(int node, char *name) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - struct property *prop = pspi->reloc_funcs.find_property(node, name); - if (prop) - return prop->length; - return -1; -} - -static int PROM_TEXT no_getprop(int node, char *name, char *value) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - struct property *prop = pspi->reloc_funcs.find_property(node, name); - if (prop) { - pspi->reloc_funcs.memcpy(value, prop->value, prop->length); - return 1; - } - return -1; -} - -static int PROM_TEXT no_setprop(int node, char *name, char *value, int len) -{ - return -1; -} - -static char PROM_TEXT *no_nextprop(int node, char *name) -{ - /* get physical address */ - struct leon_prom_info *pspi = (struct leon_prom_info *) - (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables)); - struct property *prop; - - /* convert into virtual address */ - pspi = (struct leon_prom_info *) - (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); - - if (!name || !name[0]) - return nodes[node].properties[0].name; - - prop = pspi->reloc_funcs.find_property(node, name); - if (prop) - return prop[1].name; - return NULL; -} - -static int PROM_TEXT leon_strcmp(const char *s1, const char *s2) -{ - register char result; - - while (1) { - result = *s1 - *s2; - if (result || !*s1) - break; - s2++; - s1++; - } - - return result; -} - -static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n) -{ - char *dst = (char *)dest, *source = (char *)src; - - while (n--) { - *dst = *source; - dst++; - source++; - } - return dest; -} - -#define GETREGSP(sp) __asm__ __volatile__("mov %%sp, %0" : "=r" (sp)) - -void leon_prom_init(struct leon_prom_info *pspi) -{ - unsigned long i; - unsigned char cksum, *ptr; - char *addr_str, *end; - unsigned long sp; - GETREGSP(sp); - - pspi->freq_khz = CONFIG_SYS_CLK_FREQ / 1000; - - /* Set Available main memory size */ - pspi->totphys.num_bytes = CONFIG_SYS_PROM_OFFSET - CONFIG_SYS_SDRAM_BASE; - pspi->avail.num_bytes = pspi->totphys.num_bytes; - - /* Set the pointer to the Console UART in romvec */ - pspi->reloc_funcs.leon3_apbuart = leon3_apbuart; - - { - int j = 1; -#ifdef CONFIG_SMP - ambapp_dev_irqmp *b; - b = (ambapp_dev_irqmp *) leon3_getapbbase(VENDOR_GAISLER, - GAISLER_IRQMP); - if (b) { - j = 1 + ((LEON3_BYPASS_LOAD_PA(&(b->mpstatus)) - >> LEON3_IRQMPSTATUS_CPUNR) & 0xf); - } -#endif -#undef nodes - pspi->nodes[2 + j].level = -1; - pspi->nodes[2 + j].properties = __va(spi.root_properties + 3); - } - - /* Set Ethernet MAC address from environment */ - if ((addr_str = getenv("ethaddr")) != NULL) { - for (i = 0; i < 6; i++) { - pspi->idprom.id_ethaddr[i] = addr_str ? - simple_strtoul(addr_str, &end, 16) : 0; - if (addr_str) { - addr_str = (*end) ? end + 1 : end; - } - } - } else { - /* HW Address not found in environment, - * Set default HW address - */ - pspi->idprom.id_ethaddr[0] = 0; - pspi->idprom.id_ethaddr[1] = 0; - pspi->idprom.id_ethaddr[2] = 0; - pspi->idprom.id_ethaddr[3] = 0; - pspi->idprom.id_ethaddr[4] = 0; - pspi->idprom.id_ethaddr[5] = 0; - } - - ptr = (unsigned char *)&pspi->idprom; - for (i = cksum = 0; i <= 0x0E; i++) - cksum ^= *ptr++; - pspi->idprom.id_cksum = cksum; -} - -static inline void set_cache(unsigned long regval) -{ - asm volatile ("sta %0, [%%g0] %1\n\t":: "r" (regval), "i"(2):"memory"); -} - -extern unsigned short bss_start, bss_end; - -/* mark as section .img.main.text, to be referenced in linker script */ -int prom_init(void) -{ - struct leon_prom_info *pspi = (void *) - ((((unsigned int)&spi) & PROM_SIZE_MASK) + CONFIG_SYS_PROM_OFFSET); - - /* disable mmu */ - srmmu_set_mmureg(0x00000000); - __asm__ __volatile__("flush\n\t"); - - /* init prom info struct */ - leon_prom_init(pspi); - - kernel_arg_promvec = &pspi->romvec; -#ifdef PRINT_ROM_VEC - printf("Kernel rom vec: 0x%lx\n", (unsigned int)(&pspi->romvec)); -#endif - return 0; -} - -/* Copy current kernel boot argument to ROMvec */ -void prepare_bootargs(char *bootargs) -{ - struct leon_prom_info *pspi; - char *src, *dst; - int left; - - /* if no bootargs set, skip copying ==> default bootline */ - if (bootargs && (*bootargs != '\0')) { - pspi = (void *)((((unsigned int)&spi) & PROM_SIZE_MASK) + - CONFIG_SYS_PROM_OFFSET); - src = bootargs; - dst = &pspi->arg[0]; - left = 255; /* max len */ - while (*src && left > 0) { - *dst++ = *src++; - left--; - } - /* terminate kernel command line string */ - *dst = 0; - } -} - -void srmmu_init_cpu(unsigned int entry) -{ - sparc_srmmu_setup *psrmmu_tables = (void *) - ((((unsigned int)&srmmu_tables) & PROM_SIZE_MASK) + - CONFIG_SYS_PROM_OFFSET); - - /* Make context 0 (kernel's context) point - * to our prepared memory mapping - */ -#define PTD 1 - psrmmu_tables->ctx_table[0] = - ((unsigned int)&psrmmu_tables->pgd_table[0x00]) >> 4 | PTD; - - /* Set virtual kernel address 0xf0000000 - * to SRAM/SDRAM address. - * Make it READ/WRITE/EXEC to SuperUser - */ -#define PTE 2 -#define ACC_SU_ALL 0x1c - psrmmu_tables->pgd_table[0xf0] = - (CONFIG_SYS_SDRAM_BASE >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf1] = - ((CONFIG_SYS_SDRAM_BASE + 0x1000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf2] = - ((CONFIG_SYS_SDRAM_BASE + 0x2000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf3] = - ((CONFIG_SYS_SDRAM_BASE + 0x3000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf4] = - ((CONFIG_SYS_SDRAM_BASE + 0x4000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf5] = - ((CONFIG_SYS_SDRAM_BASE + 0x5000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf6] = - ((CONFIG_SYS_SDRAM_BASE + 0x6000000) >> 4) | ACC_SU_ALL | PTE; - psrmmu_tables->pgd_table[0xf7] = - ((CONFIG_SYS_SDRAM_BASE + 0x7000000) >> 4) | ACC_SU_ALL | PTE; - - /* convert rom vec pointer to virtual address */ - kernel_arg_promvec = (struct linux_romvec *) - (((unsigned int)kernel_arg_promvec & 0x0fffffff) | 0xf0000000); - - /* Set Context pointer to point to context table - * 256 contexts supported. - */ - srmmu_set_ctable_ptr((unsigned int)&psrmmu_tables->ctx_table[0]); - - /* Set kernel's context, context zero */ - srmmu_set_context(0); - - /* Invalidate all Cache */ - __asm__ __volatile__("flush\n\t"); - - srmmu_set_mmureg(0x00000001); - leon_flush_tlb_all(); - leon_flush_cache_all(); -} diff --git a/arch/sparc/include/asm/config.h b/arch/sparc/include/asm/config.h index 66cde58..ed79456 100644 --- a/arch/sparc/include/asm/config.h +++ b/arch/sparc/include/asm/config.h @@ -13,4 +13,6 @@ #define CONFIG_LMB #define CONFIG_SYS_BOOT_RAMDISK_HIGH
+#define CONFIG_SYS_MEM_TOP_HIDE 16384 /* Reserve 16 KiB for PROM and page tables */ + #endif diff --git a/arch/sparc/include/asm/machines.h b/arch/sparc/include/asm/machines.h index e209f3f..1abbd13 100644 --- a/arch/sparc/include/asm/machines.h +++ b/arch/sparc/include/asm/machines.h @@ -37,7 +37,7 @@ extern struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES];
#define SM_ARCH_MASK 0xf0 #define SM_SUN4 0x20 -#define M_LEON2 0x30 +#define M_LEON 0x30 #define SM_SUN4C 0x50 #define SM_SUN4M 0x70 #define SM_SUN4M_OBP 0x80 @@ -51,6 +51,8 @@ extern struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES];
/* Leon machines */ #define M_LEON2_SOC 0x01 /* Leon2 SoC */ +#define M_LEON3_SOC 0x02 /* Leon3 SoC */ +#define M_LEON4_SOC 0x03 /* Leon4 SoC */
/* Sun4c machines Full Name - PROM NAME */ #define SM_4C_SS1 0x01 /* Sun4c SparcStation 1 - Sun 4/60 */ diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index 84c3ac2..bf2de51 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -5,7 +5,9 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-y = cache.o interrupts.o time.o +obj-y = cache.o interrupts.o time.o srmmu.o + +obj-y += prom.o prom-no.o
obj-$(CONFIG_CMD_BOOTM) += bootm.o
diff --git a/arch/sparc/lib/bootm.c b/arch/sparc/lib/bootm.c index 9e2b784..1d38e43 100644 --- a/arch/sparc/lib/bootm.c +++ b/arch/sparc/lib/bootm.c @@ -15,32 +15,22 @@
#define PRINT_KERNEL_HEADER
-extern image_header_t header; -extern void srmmu_init_cpu(unsigned int entry); -extern void prepare_bootargs(char *bootargs); +DECLARE_GLOBAL_DATA_PTR; + +extern void *srmmu_init_tlb_tables(void *table, size_t *table_len); +extern void srmmu_init_cpu(void *ctx_table); +extern struct linux_romvec *prom_init(void *prom_base);
#ifdef CONFIG_USB_UHCI extern int usb_lowlevel_stop(int index); #endif
-/* sparc kernel argument (the ROM vector) */ -struct linux_romvec *kernel_arg_promvec; - /* page szie is 4k */ #define PAGE_SIZE 0x1000 #define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 struct __attribute__ ((packed)) { - char traptable[PAGE_SIZE]; - char swapper_pg_dir[PAGE_SIZE]; - char pg0[PAGE_SIZE]; - char pg1[PAGE_SIZE]; - char pg2[PAGE_SIZE]; - char pg3[PAGE_SIZE]; - char empty_bad_page[PAGE_SIZE]; - char empty_bad_page_table[PAGE_SIZE]; - char empty_zero_page[PAGE_SIZE]; unsigned char hdr[4]; /* ascii "HdrS" */ /* 00.02.06.0b is for Linux kernel 2.6.11 */ unsigned char linuxver_mega_major; @@ -63,22 +53,52 @@ struct __attribute__ ((packed)) { } hdr_input; } *linux_hdr;
-/* temporary initrd image holder */ -image_header_t ihdr; +#ifdef CONFIG_LMB
void arch_lmb_reserve(struct lmb *lmb) { +#if 0 /* disabled (why do we need this?) */ + /* Reserve the space used by PROM and stack. This is done * to avoid that the RAM image is copied over stack or * PROM. */ lmb_reserve(lmb, CONFIG_SYS_RELOC_MONITOR_BASE, CONFIG_SYS_RAM_END); + +#endif +} + +#endif /* CONFIG_LMB */ + +static void *find_linux_hdr(void *base) +{ + const char hdr_token[4] = { 'H', 'd', 'r', 'S' }; + void *end = base + 32 * PAGE_SIZE; + + while (base < end) { + unsigned long * const hdr1 = (unsigned long *) base; + unsigned long * const hdr2 = (unsigned long *) hdr_token; + + if (*hdr1 == *hdr2) + return base; + + /* advance one page */ + base += PAGE_SIZE; + } + + /* no header found */ + return NULL; }
/* boot the linux kernel */ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t * images) { - char *bootargs; + /* sparc kernel argument (the ROM vector) */ + struct linux_romvec *kernel_arg_promvec; + + size_t ctx_table_len; + void *ctx_table; + ulong rd_len; void (*kernel) (struct linux_romvec *, void *); int ret; @@ -92,16 +112,13 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t * im if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) return 1;
- /* Get virtual address of kernel start */ - linux_hdr = (void *)images->os.load; - - /* */ + /* Kernel entry point */ kernel = (void (*)(struct linux_romvec *, void *))images->ep;
- /* check for a SPARC kernel */ - if ((linux_hdr->hdr[0] != 'H') || - (linux_hdr->hdr[1] != 'd') || - (linux_hdr->hdr[2] != 'r') || (linux_hdr->hdr[3] != 'S')) { + /* Search for the SPARC kernel header */ + linux_hdr = find_linux_hdr((void *)images->os.load); + + if (!linux_hdr) { puts("Error reading header of SPARC Linux kernel, aborting\n"); goto error; } @@ -153,12 +170,14 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t * im */ }
- /* Copy bootargs from bootargs variable to kernel readable area */ - bootargs = getenv("bootargs"); - prepare_bootargs(bootargs); + /* Setup the context tables, returns table pointer and length */ + ctx_table = srmmu_init_tlb_tables((void*)gd->ram_top, &ctx_table_len); + + /* Turn on MMU and page tables for process 0 (kernel) */ + srmmu_init_cpu(ctx_table);
- /* turn on mmu & setup context table & page table for process 0 (kernel) */ - srmmu_init_cpu((unsigned int)kernel); + /* Prepare the PROM and RomVector structures for Linux kernel*/ + kernel_arg_promvec = prom_init(ctx_table + ctx_table_len);
/* Enter SPARC Linux kernel * From now on the only code in u-boot that will be diff --git a/arch/sparc/lib/prom-no.c b/arch/sparc/lib/prom-no.c new file mode 100644 index 0000000..19f87bf --- /dev/null +++ b/arch/sparc/lib/prom-no.c @@ -0,0 +1,319 @@ +#include <common.h> +#include <asm/prom.h> +#include "prom-no.h" + +#define PROM_TEXT __attribute__ ((__section__ (".prom.text"))) +#define PROM_DATA __attribute__ ((__section__ (".prom.data"))) + +//------------------------------------------------------------------------------ + +static inline void * PROM_TEXT prop_ptr(struct prom_prop *prop, int offset) +{ + return (void *)prop + offset * 4; +} + +static inline void * PROM_TEXT prom_ptr(struct prom_node *node, int offset) +{ + if (offset == 0) + return NULL; + + return (void *)node + offset * 4; +} + +//------------------------------------------------------------------------------ + +struct prom_priv PROM_DATA __prom_entry; + +static int PROM_TEXT prom_strcmp(const char *a, const char *b); + +//------------------------------------------------------------------------------ + +/* This is here to fix a compiler issue that insert a GOT lookup with using the result */ + +struct prom_prop * PROM_TEXT dummy(struct prom_node *n, const char *name) +{ + if (n && name && *name) { + struct prom_prop *p = &n->props[0]; + struct prom_prop *e = &n->props[n->num_props]; + for (; p < e; ++p) { + if (prom_strcmp(prop_ptr(p, p->name), name) == 0) + return p; + } + } + + return NULL; +} + +//------------------------------------------------------------------------------ + +/* Retrieve pointer to prom_entry without using the GOT (relative to PC only) */ +struct prom_priv * PROM_TEXT prom_get_entry(void) +{ + register int link asm("%o7"); + register int self asm("%o1"); + register int entry asm("%o2"); + /* I would dearly like to know how we can do this beter. */ + asm("98: call 99f; nop"); + asm(".word 98b"); + asm(".word __prom_entry"); /* store address to prom_entry in code */ + asm("99:"); + asm("ld [%%o7 + 8], %0" : "=r"(self) : ); + asm("ld [%%o7 + 12], %0" : "=r"(entry) : ); + return (void *)(entry + (link - self)); +} + +//------------------------------------------------------------------------------ + +/* Helper methods */ + +static void *PROM_TEXT prom_memcpy(void *dest, void *source, size_t len) +{ + (void)dummy; // prevent compiler from optimizing out the dummy function + + char *dst = dest; + char *src = source; + char *end = src + len; + + while (src < end) + *dst++ = *src++; + + return dest; +} + +static int PROM_TEXT prom_strcmp(const char *a, const char *b) +{ + register char d = *a - *b; + + while (d == 0 && *a != '\0') + d = *(++a) - *(++b); + + return d; +} + +static struct prom_prop * PROM_TEXT prop_find(struct prom_node *n, const char *name) +{ + if (n && name && *name) { + struct prom_prop *p = &n->props[0]; + struct prom_prop *e = &n->props[n->num_props]; + for (; p < e; ++p) { + if (prom_strcmp(prop_ptr(p, p->name), name) == 0) + return p; + } + } + + return NULL; +} + +//------------------------------------------------------------------------------ + +int PROM_TEXT prom_no_nextnode(int node) +{ + struct prom_node *n = (struct prom_node *) node; + + if (n) + return (int) prom_ptr(n, n->next); + + /* retrieve pointer to root node */ + n = prom_get_entry()->root_node; + + if (n) + return (int) n; + + return -1; +} + +int PROM_TEXT prom_no_getchild(int node) +{ + struct prom_node *n = (struct prom_node *) node; + + if (n) + return (int) prom_ptr(n, n->child); + + return -1; +} + +char * PROM_TEXT prom_no_nextprop(int node, char *name) +{ + struct prom_node *n = (struct prom_node *) node; + struct prom_prop *p = NULL; + + if (name && *name) { + p = prop_find(n, name); + + if (p) { + struct prom_prop *e = &n->props[n->num_props]; + if (++p >= e) /* advance to next prop */ + p = NULL; /* past end of list */ + } + } else { + if (n->num_props > 0) + p = &n->props[0]; + } + + return p ? prop_ptr(p, p->name) : NULL; +} + +int PROM_TEXT prom_no_proplen(int node, char *name) +{ + struct prom_node *n = (struct prom_node *) node; + struct prom_prop *p = prop_find(n, name); + + return p ? p->length : -1; +} + +int PROM_TEXT prom_no_getprop(int node, char *name, char *val) +{ + struct prom_node *n = (struct prom_node *) node; + struct prom_prop *p = prop_find(n, name); + + if (p && p->length >= 0) { + if (val && p->length) { + if (p->length > sizeof(p->value)) { + prom_memcpy(val, prop_ptr(p, (int)p->value), p->length); + } else { + /* small values is encoded directly in the pointer */ + unsigned int *dst = (void *)val; + unsigned int *src = (void *)&p->value; + *dst = *src; /* copy value */ + } + } + + return p->length; + } + + return -1; +} + +int PROM_TEXT prom_no_setprop(int node, char *name, char *val, int len) +{ + return -1; /* not implemented */ +} + +//------------------------------------------------------------------------------ + +/* get single char, don't care for blocking*/ +int PROM_TEXT prom_nb_getchar(void) +{ + return -1; /* not implemented */ +} + +/* put single char, don't care for blocking*/ +int PROM_TEXT prom_nb_putchar(int c) +{ + ambapp_dev_apbuart *uart = prom_get_entry()->uart; + + if (!uart) + return 0; + + /* Wait for last character to go */ + while (!(SPARC_BYPASS_READ(&uart->status) & LEON_REG_UART_STATUS_THE)) ; + + /* Send data */ + SPARC_BYPASS_WRITE(&uart->data, c); + + return 1; +} + +void PROM_TEXT prom_halt(void) +{ + // FIXME: not fully implemented yet + prom_nb_putchar('\r'); + prom_nb_putchar('\n'); + prom_nb_putchar('H'); + prom_nb_putchar('A'); + prom_nb_putchar('L'); + prom_nb_putchar('T'); + prom_nb_putchar('!'); +//#ifdef DEBUG + asm("mov 1, %g1; ta 0; nop"); +//#endif + while (1) ; + // TODO: go into low power mode +} + +void PROM_TEXT prom_reboot(char *bcommand) +{ + prom_halt(); // FIXME: not implemented yet +} + +//------------------------------------------------------------------------------ + +#if 0 + +/* Reboot the CPU = jump to beginning of flash again. + * + * Make sure that all function are inlined here. + */ +static void PROM_TEXT leon_reboot(char *bcommand) +{ + register char *arg = bcommand; + void __attribute__ ((noreturn)) (*reboot_physical) (char *cmd); + + /* get physical address */ + struct leon_prom_info *pspi = + (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(sparc_srmmu_setup)); + + unsigned int *srmmu_ctx_table; + + /* Turn of Interrupts */ + set_pil(0xf); + + /* Set kernel's context, context zero */ + srmmu_set_context(0); + + /* Get physical address of the MMU shutdown routine */ + reboot_physical = (void *) + SPARC_BYPASS_READ(&pspi->reloc_funcs.reboot_physical); + + /* Now that we know the physical address of the function + * we can make the MMU allow jumping to it. + */ + srmmu_ctx_table = (unsigned int *)srmmu_get_ctable_ptr(); + + srmmu_ctx_table = (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table); + + /* get physical address of kernel's context table (assume ptd) */ + srmmu_ctx_table = (unsigned int *) + (((unsigned int)srmmu_ctx_table & 0xfffffffc) << 4); + + /* enable access to physical address of MMU shutdown function */ + SPARC_BYPASS_WRITE(&srmmu_ctx_table + [((unsigned int)reboot_physical) >> 24], + (((unsigned int)reboot_physical & 0xff000000) >> 4) | + 0x1e); + + /* flush TLB cache */ + leon_flush_tlb_all(); + + /* flash instruction & data cache */ + sparc_icache_flush_all(); + sparc_dcache_flush_all(); + + /* jump to physical address function + * so that when the MMU is disabled + * we can continue to execute + */ + reboot_physical(arg); +} + +static void PROM_TEXT leon_reboot_physical(char *bcommand) +{ + void __attribute__ ((noreturn)) (*reset) (void); + + /* Turn off MMU */ + srmmu_set_mmureg(0); + + /* Hardcoded start address */ + reset = (void*)CONFIG_SYS_MONITOR_BASE; + + /* flush data cache */ + sparc_dcache_flush_all(); + + /* flush instruction cache */ + sparc_icache_flush_all(); + + /* Jump to start in Flash */ + reset(); +} + +#endif diff --git a/arch/sparc/lib/prom-no.h b/arch/sparc/lib/prom-no.h new file mode 100644 index 0000000..ef369a1 --- /dev/null +++ b/arch/sparc/lib/prom-no.h @@ -0,0 +1,40 @@ +#ifndef __PROM_NO_H__ +#define __PROM_NO_H__ + +#include <ambapp.h> + +struct prom_prop { + short name; + short length; + void *value; +}; + +struct prom_node { + short next; + short child; + int num_props; + struct prom_prop props[0]; +}; + +struct prom_priv { + struct prom_node *root_node; + ambapp_dev_apbuart *uart; +}; + +/* structure that holds entry pointers */ +extern struct prom_priv __prom_entry; + +extern int prom_no_nextnode(int); +extern int prom_no_getchild(int); +extern char *prom_no_nextprop(int, char *); +extern int prom_no_proplen(int, char *); +extern int prom_no_getprop(int, char *, char *); +extern int prom_no_setprop(int, char *, char *, int); + +extern int prom_nb_getchar(void); +extern int prom_nb_putchar(int); + +extern void prom_reboot(char *); +extern void prom_halt(void); + +#endif /* __PROM_NO_H__ */ diff --git a/arch/sparc/lib/prom.c b/arch/sparc/lib/prom.c new file mode 100644 index 0000000..2e6be41 --- /dev/null +++ b/arch/sparc/lib/prom.c @@ -0,0 +1,960 @@ +/* prom.c - Emulates a SPARC v0 PROM for the Linux kernel. + * + * Copyright (C) 2003 Konrad Eisele eiselekd@web.de + * Copyright (C) 2004 Stefan Holst mail@s-holst.de + * Copyright (C) 2007 Daniel Hellstrom daniel@gaisler.com + * Copyright (C) 2014 Francois Retief fgretief@spaceteq.co.za + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <malloc.h> +#include <asm/leon.h> +#include <asm/prom.h> +#include <asm/machines.h> + +#include "prom-no.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* Defined in arch/sparc/cpu/leon3/serial.c */ +extern ambapp_dev_apbuart *leon3_apbuart; + +//----------------------------------------------------------------------------- + +//#undef assert +#ifndef assert + +static void prom_assert_fail(const char *file, int line, const char *func, const char *cond) +{ + serial_printf("## assert '%s' failed at %s:%d in %s.", cond, file, line, func); +} + +#define assert(cond) do { \ + if (!(cond)) \ + prom_assert_fail(__FILE__, __LINE__, __func__, #cond); \ +} while(0) + +#endif + +//----------------------------------------------------------------------------- + +struct prop { + const char *name; + int length; + void *value; +}; + +struct node { + int num_props; + struct prop *props; + int num_nodes; + struct node *nodes; +}; + +#define PROP_ENTRY_DATA(n,d,l) { .name = prop_s_##n, .value = (d), .length = (l) } +#define PROP_ENTRY(n,v) { .name = prop_s_##n, .value = &(v), .length = sizeof(v) } + +#define NODE_ENTRY(n) { \ + .num_props = ARRAY_SIZE(n##_properties), \ + .props = n##_properties, \ + .num_nodes = 0, \ + .nodes = NULL, \ +} + +#define NODE_ENTRY_L1(n) { \ + .num_props = ARRAY_SIZE(n##_properties), \ + .props = n##_properties, \ + .num_nodes = ARRAY_SIZE(n##_child_nodes), \ + .nodes = n##_child_nodes, \ +} + +//----------------------------------------------------------------------------- + +#define PROP_STRING(s) char prop_s_##s[] = #s + +static PROP_STRING(mid); +static PROP_STRING(uart1_baud); +static PROP_STRING(uart2_baud); +static PROP_STRING(name); +static PROP_STRING(device_type); +static PROP_STRING(systemid); +static PROP_STRING(ioarea); +static PROP_STRING(ipl_num); +static PROP_STRING(compatible); +static PROP_STRING(compatability); +static PROP_STRING(idprom); + +/* exceptions on the rule */ +static char prop_s_mmu_nctx[] = "mmu-nctx"; +static char prop_s_clock_frequency[] = "clock-frequency"; + +//----------------------------------------------------------------------------- + +#ifdef CONFIG_USE_CUSTOM_AMBA_NODES + +static PROP_STRING(vendor); +static PROP_STRING(device); +static PROP_STRING(version); +static PROP_STRING(reg); +static PROP_STRING(interrupts); +static PROP_STRING(freq); + +static char apbuart_name[] = "GAISLER_APBUART"; +static unsigned long apbuart_vendor = 1; +static unsigned long apbuart_device = 12; +static unsigned long apbuart_reg[] = { 0x80000100, 0x100 }; +static unsigned long apbuart_irq[] = { 2 }; +static unsigned long apbuart_freq = CONFIG_SYS_CLK_FREQ; + +static struct prop apbuart_properties[] = { + PROP_ENTRY(name, apbuart_name), + PROP_ENTRY(vendor, apbuart_vendor), + PROP_ENTRY(device, apbuart_device), + PROP_ENTRY(reg, apbuart_reg), + PROP_ENTRY(interrupts, apbuart_irq), + PROP_ENTRY(freq, apbuart_freq), +}; + +static char irqmp_name[] = "GAISLER_IRQMP"; +static unsigned long irqmp_vendor = 1; +static unsigned long irqmp_device = 13; +static unsigned long irqmp_reg[] = { 0x80000200, 0x100 }; + +static struct prop irqmp_properties[] = { + PROP_ENTRY(name, irqmp_name), + PROP_ENTRY(vendor, irqmp_vendor), + PROP_ENTRY(device, irqmp_device), + PROP_ENTRY(reg, irqmp_reg), +}; + +static char gptimer_name[] = "GAISLER_GPTIMER"; +static unsigned long gptimer_vendor = 1; +static unsigned long gptimer_device = 17; +static unsigned long gptimer_reg[] = { 0x80000300, 0x100 }; +static unsigned long gptimer_irq[] = { 8, 9, 10, 11 }; + +static struct prop gptimer_properties[] = { + PROP_ENTRY(name, gptimer_name), + PROP_ENTRY(vendor, gptimer_vendor), + PROP_ENTRY(device, gptimer_device), + PROP_ENTRY(reg, gptimer_reg), + PROP_ENTRY(interrupts, gptimer_irq), +}; + +static char ethmac_name[] = "GAISLER_ETHMAC"; +static unsigned long ethmac_vendor = 1; +static unsigned long ethmac_device = 0x01d; +static unsigned long ethmac_reg[] = { 0x80000e00, 0x100 }; +static unsigned long ethmac_irq[] = { 14 }; + +static struct prop ethmac_properties[] = { + PROP_ENTRY(name, ethmac_name), + PROP_ENTRY(vendor, ethmac_vendor), + PROP_ENTRY(device, ethmac_device), + PROP_ENTRY(reg, ethmac_reg), + PROP_ENTRY(interrupts, ethmac_irq), +}; + +#endif /* CONFIG_USE_CUSTOM_AMBA_NODES */ + +//----------------------------------------------------------------------------- + +static char ambapp_device_type[] = "ambapp"; +static char ambapp_name[] = "ambapp0"; +static unsigned long ambapp_systemid = 0x07120e70; +static unsigned long ambapp_ioarea = 0xFFF00000; +static unsigned long ambapp_ipl_num = 0; + +static struct prop ambapp_properties[] = { + PROP_ENTRY(device_type, ambapp_device_type), + PROP_ENTRY(name, ambapp_name), + PROP_ENTRY(systemid, ambapp_systemid), + PROP_ENTRY(ioarea, ambapp_ioarea), + PROP_ENTRY(ipl_num, ambapp_ipl_num), +}; + +static struct node ambapp_child_nodes[] = { +#ifdef CONFIG_USE_CUSTOM_AMBA_NODES + NODE_ENTRY(apbuart), + NODE_ENTRY(irqmp), + NODE_ENTRY(gptimer), + NODE_ENTRY(ethmac), +#endif +}; + +//----------------------------------------------------------------------------- + +static char cpu0_device_type[] = "cpu"; +static char cpu0_name[6] = "cpu0"; /* length must be 6 for cpu15 */ +static unsigned long cpu0_mid = 0; /* processor ID */ +static unsigned long cpu0_mmu_nctx = 256; +static unsigned long cpu0_freq_kHz = CONFIG_SYS_CLK_FREQ / 1000; +static unsigned long cpu0_baudrate[] = { CONFIG_BAUDRATE, CONFIG_BAUDRATE }; + +static struct prop cpu0_properties[] = { + PROP_ENTRY(device_type, cpu0_device_type), + PROP_ENTRY(name, cpu0_name), + PROP_ENTRY(mid, cpu0_mid), + PROP_ENTRY(mmu_nctx, cpu0_mmu_nctx), + PROP_ENTRY(clock_frequency, cpu0_freq_kHz), + PROP_ENTRY(uart1_baud, cpu0_baudrate[0]), + PROP_ENTRY(uart2_baud, cpu0_baudrate[1]), +}; + +//----------------------------------------------------------------------------- + +static char serial_device_type[] = "serial"; +static char serial_name[] = "a:"; + +static struct prop serial_properties[] = { + PROP_ENTRY(device_type, serial_device_type), + PROP_ENTRY(name, serial_name), +}; + +//----------------------------------------------------------------------------- + +static char root_device_type[] = "idprom"; +static char root_leon[] = "leon"; +static struct idprom root_idprom = { }; + +static struct prop root_properties[] = { + PROP_ENTRY(device_type, root_device_type), + PROP_ENTRY(idprom, root_idprom), + PROP_ENTRY(compatible, root_leon), + PROP_ENTRY(compatability, root_leon), +}; + +static struct node root_child_nodes[] = { + NODE_ENTRY(cpu0), + NODE_ENTRY(serial), + NODE_ENTRY_L1(ambapp), +}; + +//----------------------------------------------------------------------------- + +static struct node root_node = { + .num_props = ARRAY_SIZE(root_properties), + .props = root_properties, + .num_nodes = ARRAY_SIZE(root_child_nodes), + .nodes = root_child_nodes, +}; + +//----------------------------------------------------------------------------- + +void prom_reloc_prop(struct prop *p) +{ + if (gd->flags & GD_FLG_RELOC) { + if (p->name) + p->name = (void *)p->name + gd->reloc_off; + if (p->value) + p->value = (void *)p->value + gd->reloc_off; + } +} + +void prom_reloc_node(struct node *n) +{ + int i; + + if (gd->flags & GD_FLG_RELOC) { + if (n->props) + n->props = (void *)n->props + gd->reloc_off; + if (n->nodes) + n->nodes = (void *)n->nodes + gd->reloc_off; + } + + for (i = 0; i < n->num_props; ++i) { + prom_reloc_prop( &n->props[i] ); + } + + for (i = 0; i < n->num_nodes; ++i) { + prom_reloc_node( &n->nodes[i] ); + } +} + +//----------------------------------------------------------------------------- + +/* These two variables are defined in the linker script */ +extern unsigned long __prom_start; +extern unsigned long __prom_end; + +static unsigned long prom_malloc_end; +static unsigned long prom_va_base; + +#define _va(x) ((void*)( (unsigned long)(x) - (unsigned long)&__prom_start + prom_va_base )) + +static void prom_set_malloc_base(void *base) +{ + assert(base != NULL); + + prom_malloc_end = ((unsigned long)base + 3) & ~3; + prom_va_base = prom_malloc_end; +} + +static inline void *prom_malloc(int size) +{ + void *result = (void *)prom_malloc_end; + + prom_malloc_end = (prom_malloc_end + size + 3) & ~3; + return result; +} + +static void *prom_calloc(int size) +{ + void *result = (void *)prom_malloc_end; + + unsigned long *ptr = (void *)prom_malloc_end; + unsigned long *end = (void *)ptr + size; + + while (ptr < end) + *ptr++ = 0; + + prom_malloc_end = (unsigned long)ptr; + return result; +} + +static void *prom_malloc_string(const char *s) +{ + void *result = (void *)prom_malloc_end; + + char *dst = (char *)prom_malloc_end; + + /* copy string to destination */ + while (*s) + *dst++ = *s++; + *dst++ = '\0'; + + prom_malloc_end = ((unsigned long)dst + 3) & ~3; + return result; +} + +static void *prom_malloc_data(void *data, int length) +{ + void *result = (void *)prom_malloc_end; + + char *dst = (char *)prom_malloc_end; + const char *src = data; + const char *end = data + length; + + /* copy data to destination */ + while (src < end) + *dst++ = *src++; + + prom_malloc_end = ((unsigned long)dst + 3) & ~3; + return result; +} + +static char *prom_malloc_byte(char value) +{ + void *result = (void *)prom_malloc_end; + + char *dst = (char *)prom_malloc_end; + + /* copy value to destination */ + *dst++ = value; + + prom_malloc_end = ((unsigned long)dst + 3) & ~3; + return result; +} + +//----------------------------------------------------------------------------- + +/* This section implements a small string cache for the names. This helps us + * find duplicates, reducing the PROM size by quite a bit. + */ +static const char **str_cache; +static int str_cache_len = 0; + +static void prom_cache_init(void) +{ + str_cache = (const char **)calloc(256, sizeof(str_cache[0])); +} + +static void prom_cache_free(void) +{ + free(str_cache); +} + +static const char *prom_cache_find(const char *name) +{ + if (name && *name) { + const char **ptr = str_cache; + const char **end = &ptr[256]; + + while (ptr < end && *ptr) { + if (strcmp(name, *ptr) == 0) + break; + ptr++; + } + + return *ptr; + } + + return NULL; +} + +static const char *prom_cache_append(const char *name) +{ + str_cache[str_cache_len] = name; + str_cache_len += 1; + return name; +} + +static const char *prom_cache_or_malloc(const char *name) +{ + const char *entry = prom_cache_find(name); + + if (entry == NULL) { + entry = prom_malloc_string(name); + prom_cache_append(entry); + } + + return entry; +} + +//----------------------------------------------------------------------------- + +struct amba_dev { + void *source; + unsigned int type; + unsigned int index; + unsigned int vendor; + unsigned int device; + unsigned int version; + unsigned int irq; + unsigned int addr; +}; + +static int amba_apb_foreach(unsigned long apb_base, void (*action)(struct amba_dev *dev, void *ctx), void *ctx) +{ + int i; + apbctrl_pp_dev *apb = (apbctrl_pp_dev *)(apb_base | LEON3_CONF_AREA); + + for (i = 0; i < 16; ++i, ++apb) { + if (apb->conf == 0) + continue; + + struct amba_dev dev; + + dev.type = 4; /* APB Slave */ + dev.index = i; + dev.source = apb; + + dev.vendor = amba_vendor(apb->conf); + dev.device = amba_device(apb->conf); + dev.version = amba_ver(apb->conf); + dev.irq = amba_irq(apb->conf); + + dev.addr = amba_iobar_start(apb_base, apb->bar); + + action(&dev, ctx); + } + + return 0; +} + +static int amba_ahb_foreach(int type, void (*action)(struct amba_dev *dev, void *ctx), void *ctx) +{ + int i = 0; + int num = (64+64); /* Both Master and Slave */ + ahbctrl_pp_dev *ahb = (ahbctrl_pp_dev *)(LEON3_IO_AREA | LEON3_CONF_AREA); + + if ((type & 7) == 0) + return 0; /* Nothing to do */ + if ((type & 3) == 1) + num = 64; /* Only Master */ + if ((type & 3) == 2) + i = 64; /* Only Slave */ + + for (; i < num; ++i) { + if (ahb[i].conf == 0) + continue; + + if (type & 3) { + struct amba_dev dev; + + dev.type = (i < 64) ? 1 : 2; /* Master or Slave */ + dev.index = i % 64; + dev.source = &ahb[i]; + + dev.vendor = amba_vendor(ahb[i].conf); + dev.device = amba_device(ahb[i].conf); + dev.version = amba_ver(ahb[i].conf); + dev.irq = amba_irq(ahb[i].conf); + + dev.addr = amba_membar_start(ahb[i].bars[0]); + + action(&dev, ctx); + } + + if (type & 4) { + /* Check for AMBA APB Master */ + if (amba_vendor(ahb[i].conf) == VENDOR_GAISLER && + amba_device(ahb[i].conf) == GAISLER_APBMST) { + amba_apb_foreach(amba_membar_start(ahb[i].bars[0]), action, ctx); + } + } + } + + return 0; +} + +//----------------------------------------------------------------------------- + +static inline int prop_offset(struct prom_prop *prop, void *target) +{ + assert(((int)prop & 3) == 0); + assert(((int)target & 3) == 0); + return ( (int)target - (int)prop ) / 4; +} + +static inline int prom_offset(struct prom_node *node, void *target) +{ + assert(((int)node & 3) == 0); + assert(((int)target & 3) == 0); + + if (target == NULL) + return 0; + + return ( (int)target - (int)node ) / 4; +} + +//----------------------------------------------------------------------------- + +static void prom_build_prop(struct prom_prop *prop, struct prop *p) +{ + prop->name = prop_offset(prop, (void *)prom_cache_or_malloc(p->name)); + + prop->length = p->length; + + if (p->length > sizeof(p->value)) { + prop->value = (void *)prop_offset(prop, prom_malloc_data(p->value, p->length)); + } else { + /* small values is encoded directly in the pointer */ + unsigned int *dst = (void *)&prop->value; + unsigned int *src = (void *)p->value; + *dst = *src; /* copy value */ + } +} + +static struct prom_node *prom_create_node(struct prop *p, int num_props) +{ + struct prom_node *node; + int i, size = sizeof(node[0]) + num_props * sizeof(node->props[0]); + + node = (struct prom_node *) prom_malloc(size); + + node->next = 0; + node->child = 0; + + node->num_props = num_props; + for (i = 0; i < num_props; ++i) + prom_build_prop( &node->props[i], &p[i] ); + + return node; +} + +static struct prom_node *prom_build_leaf_node(struct prom_node *sibling, struct prop *props, int num_props) +{ + struct prom_node *node = prom_create_node(props, num_props); + + if (sibling) + sibling->next = prom_offset(sibling, node); + + return node; +} + +static struct prom_node *prom_build_node(struct prom_node *prev_node, struct node *n) +{ + struct prom_node *node = prom_create_node(n->props, n->num_props); + + if (prev_node) + prev_node->next = prom_offset(prev_node, node); + + if (n->num_nodes > 0) { + int i; + struct prom_node *prev = prom_build_node(NULL, &n->nodes[0]); + + node->child = prom_offset(node, prev); + + for (i = 1; i < n->num_nodes; ++i) + prev = prom_build_node(prev, &n->nodes[i]); + } + + return node; +} + +struct nlist { + struct prom_node *first; + struct prom_node *last; +}; + +static void prom_create_amba_node_iter(struct amba_dev *dev, void *ctx) +{ + struct nlist *list = ctx; + +#ifdef CONFIG_MINIMAL_CORES + if (dev->vendor != VENDOR_GAISLER) + return; + if (dev->device != GAISLER_IRQMP && + dev->device != GAISLER_GPTIMER && + dev->device != GAISLER_APBUART && + dev->device != GAISLER_ETHMAC) + return; + //if (dev->device == GAISLER_APBUART && dev->addr != 0x80000100) + // return; +#endif + if (dev->type == 1) + return; // skip AHB Master nodes + if (dev->type == 2 && !(dev->vendor == VENDOR_GAISLER && dev->device == GAISLER_APBMST)) + return; // skip AHB Slave nodes, except APBMST + + int dummy = 0; + + int i2cmst_reg_shift = 2; + int gpio_num_cells = 2; + int cpu_freq = CONFIG_SYS_CLK_FREQ; + + unsigned int dev_reg[2] = { (unsigned int)dev->addr, 0x100 }; + + static char s_spictrl_compatible[] = "aeroflexgaisler,spictrl"; + static char s_i2cmst_compatible[] = "aeroflexgaisler,i2cmst"; + static char s_canahb_compatible[] = "aeroflexgaisler,can_oc\0nxp,sja1000"; + + char sbuf[9]; + char *nameStr; +#ifdef CONFIG_CMD_AMBAPP + nameStr = ambapp_device_id2str(dev->vendor, dev->device); + if (!nameStr || !nameStr[0]) +#endif + { + sprintf(sbuf, "%02x_%03x", dev->vendor, dev->device); + nameStr = &sbuf[0]; + } + + struct prop props[16]; + struct node n = { .props = &props[0], .num_props = 0 }; + +#define PROP_ADD(m,v,l) do { \ + struct prop *_p = &n.props[n.num_props++]; \ + _p->name = (m); _p->value = (v); _p->length = (l); \ +} while(0) +#define PROP_ADD_STRING(n,s) PROP_ADD((n), (s), 1+strlen(s)) +#define PROP_ADD_DATA(n,d) PROP_ADD((n), &(d), sizeof(d)) + + PROP_ADD_STRING("name", nameStr); + PROP_ADD_DATA("vendor", dev->vendor); + PROP_ADD_DATA("device", dev->device); + PROP_ADD_DATA("version", dev->version); + + if (dev->irq != 0) + PROP_ADD_DATA("interrupts", dev->irq); + + if (dev->addr != 0) + PROP_ADD_DATA("reg", dev_reg); + + //PROP_ADD("devmsk", ...); // TODO + //PROP_ADD("userdef", ...); // TODO + + if (dev->vendor == VENDOR_GAISLER && dev->device == GAISLER_APBUART) { + PROP_ADD_DATA("freq", cpu_freq); + } + + if (dev->vendor == VENDOR_GAISLER && dev->device == GAISLER_I2CMST) { + PROP_ADD_DATA("compatible", s_i2cmst_compatible); + PROP_ADD_DATA("clock-frequency", cpu_freq); + PROP_ADD_DATA("reg-shift", i2cmst_reg_shift); + } + + if (dev->vendor == VENDOR_GAISLER && dev->device == GAISLER_SPICTRL) { + PROP_ADD_DATA("compatible", s_spictrl_compatible); + PROP_ADD_DATA("clock-frequency", cpu_freq); + } + + if (dev->vendor == VENDOR_GAISLER && dev->device == GAISLER_CANAHB) { + PROP_ADD_DATA("compatible", s_canahb_compatible); + PROP_ADD_DATA("nxp,external-clock-frequency", cpu_freq); + } + + if (dev->vendor == VENDOR_GAISLER && dev->device == GAISLER_GPIO) { + PROP_ADD("nbits", &dummy, sizeof(dummy)); // gp->nbits + PROP_ADD("irqmap", &dummy, sizeof(dummy)); // fixme: array of something + PROP_ADD("gpiocontroller", NULL, 0); /* empty array */ + PROP_ADD("#gpio-cells", &gpio_num_cells, sizeof(gpio_num_cells)); + } + + PROP_ADD_DATA("index", dev->index); + //PROP_ADD("ampopts", ...) // TODO + //PROP_ADD("description", ...); // TODO + +#undef PROP_ADD_DATA +#undef PROP_ADD_STRING +#undef PROP_ADD + + /* Create a leaf node */ + struct prom_node *node = prom_build_leaf_node(list->last, &n.props[0], n.num_props); + /* Register node in link list */ + list->last = node; + if (list->first == NULL) + list->first = node; + + /* Here we branch into the APB bus and add child nodes to that node */ + if (dev->vendor == VENDOR_GAISLER && dev->device == GAISLER_APBMST) { + struct nlist apb_list = { NULL, NULL }; + amba_apb_foreach(dev->addr, prom_create_amba_node_iter, &apb_list); + node->child = prom_offset(node, apb_list.first); + } +} + +#if 0 +static void prom_create_amba_node_iter_DBUG(struct amba_dev *dev, void *ctx) +{ + printf("PROM:%02d: vendor=%x, device = %03x, version=%02d, irq=%02d, addr=%08x\n", + dev->index, dev->vendor, dev->device, dev->version, dev->irq, dev->addr); + prom_create_amba_node_iter(dev, ctx); +} +#endif + +static struct prom_node *prom_build_amba_nodes(struct prom_node *sibling, struct node *n) +{ + struct prom_node *node = prom_build_leaf_node(sibling, n->props, n->num_props); + +#ifdef CONFIG_USE_CUSTOM_AMBA_NODES + if (n->num_nodes > 0) { + int i; + struct prom_node *prev = prom_build_node(NULL, &n->nodes[0]); + + node->child = prom_offset(node, prev); + + for (i = 1; i < n->num_nodes; ++i) { + prev = prom_build_node(prev, &n->nodes[i]); + } + } +#else + struct nlist list = { NULL, NULL }; + amba_ahb_foreach(4, prom_create_amba_node_iter, &list); + node->child = prom_offset(node, list.first); +#endif + + return node; +} + +static struct prom_node *prom_build_root_node(void) +{ + struct prom_node *prev, *node; + struct node *n = &root_node; + int i, ncpu = 1; + +#ifdef CONFIG_SMP + ambapp_apbdev apbdev; + if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev) == 1) { + ambapp_dev_irqmp *irqmp = (ambapp_dev_irqmp *) apbdev.address; + /* Determine the number of CPUs in the SoC */ + ncpu += (irqmp->mstatus >> 28) & 0x0f; + } +#endif + + node = prom_create_node(n->props, n->num_props); + + /* Add cpu0 node */ + prev = prom_build_node(NULL, &n->nodes[0]); + + node->child = prom_offset(node, prev); + + /* Add the rest of the cpuN nodes */ + n->nodes[0].num_props -= 2; /* remove UART entries */ + for (i = 1; i < ncpu; ++i) { + /* Update properties for cpuN node */ + cpu0_mid = i; + snprintf(cpu0_name, 6, "cpu%d", i); + /* Add cpuN nodes */ + prev = prom_build_node(prev, &n->nodes[0]); + } + +#ifdef CONFIG_LEON2 + (void)prom_build_amba_nodes; /* silence compiler warning */ +#else + + /* Add serial node */ + prev = prom_build_node(prev, &n->nodes[1]); + + /* Add ambapp0 node */ + prev = prom_build_amba_nodes(prev, &n->nodes[2]); + +#endif + return node; +} + +static void *prom_init_nodes_init(void) +{ + void *prom_root; + void *prom_base = (void *)prom_malloc_end; + + prom_reloc_node(&root_node); + + prom_cache_init(); + prom_root = prom_build_root_node(); + prom_cache_free(); + + int size = (int)prom_malloc_end - (int)prom_base; + printf("PROM cached had %d entries\n", str_cache_len); + printf("PROM allocated %d bytes\n", size); + printf("PROM ended at %p\n", (void*)prom_malloc_end); + printf("SDRAM ends at %p\n", (void*)(CONFIG_SYS_SDRAM_END|0xF0000000)); + + assert(prom_malloc_end < (CONFIG_SYS_SDRAM_END|0xF0000000)); + return prom_root; +} + +//----------------------------------------------------------------------------- + +static unsigned char prom_calc_checksum(void *buf, size_t len) +{ + unsigned char *ptr = (unsigned char *)buf; + unsigned char *end = ptr + len; + unsigned char cksum = 0; + while (ptr < end) + cksum ^= *ptr++; + return cksum; +} + +static void *prom_init_idprom(struct idprom *idprom) +{ + assert(idprom != NULL); + memset(idprom, 0, sizeof(idprom[0])); + + idprom->id_format = 0x01; +#ifdef CONFIG_LEON2 + idprom->id_machtype = M_LEON | M_LEON2_SOC; +#else + idprom->id_machtype = M_LEON | M_LEON3_SOC; +#endif + +#ifdef CONFIG_CMD_NET + /* Set Ethernet MAC address from environment */ + eth_getenv_enetaddr("ethaddr", idprom->id_ethaddr); +#endif + + /* Calculate the checksum for the IDPROM structure */ + idprom->id_cksum = prom_calc_checksum(idprom, 0x0E); + + return idprom; +} + +//----------------------------------------------------------------------------- + +static void *prom_init_linux_mem_v0(struct linux_mem_v0 *mem) +{ + struct linux_mlist_v0 **entry; + + mem->v0_prommap = prom_malloc(sizeof(struct linux_mlist_v0 *)); + mem->v0_prommap[0] = NULL; + + /* Set total main memory */ + + mem->v0_totphys = entry = prom_malloc(sizeof(struct linux_mlist_v0 *)); + mem->v0_totphys[0] = prom_malloc(sizeof(struct linux_mlist_v0)); + mem->v0_totphys[0]->start_adr = (void *)CONFIG_SYS_SDRAM_BASE; + mem->v0_totphys[0]->num_bytes = (int)gd->ram_top - (int)CONFIG_SYS_SDRAM_BASE; + mem->v0_totphys[0]->theres_more = NULL; + + /* Set available main memory */ + + mem->v0_available = prom_malloc(sizeof(struct linux_mlist_v0 *)); + mem->v0_available[0] = prom_malloc(sizeof(struct linux_mlist_v0)); + mem->v0_available[0]->start_adr = (void *)CONFIG_SYS_SDRAM_BASE; + mem->v0_available[0]->num_bytes = (int)gd->ram_top - (int)CONFIG_SYS_SDRAM_BASE; + mem->v0_available[0]->theres_more = NULL; + + return (void *)mem; +} + +static void *prom_init_linux_arguments_v0(const char *bootargs) +{ + struct linux_arguments_v0 *args = prom_calloc(sizeof(struct linux_arguments_v0)); + + if (bootargs && *bootargs) { + const char **argv = (const char **)&(args->argv[0]); + + argv[1] = prom_malloc_string(bootargs); + } + + return prom_malloc_data(&args, sizeof(args)); +} + +static void *prom_init_romvec(struct linux_romvec *rv) +{ + assert(rv != NULL); + memset(rv, 0, sizeof(rv[0])); + + /* Version numbers. */ + rv->pv_magic_cookie = 0; + rv->pv_romvers = 0; /* sun4c v0 prom */ + rv->pv_plugin_revision = 0; + rv->pv_printrev = 0; + + rv->pv_stdin = rv->pv_stdout = prom_malloc_byte(PROMDEV_TTYA); + + /* Functions */ + rv->pv_nbgetchar = _va(prom_nb_getchar); + rv->pv_nbputchar = _va(prom_nb_putchar); + rv->pv_halt = _va(prom_halt); + rv->pv_reboot = _va(prom_reboot); + + /* Allocate memory where a pointer can be stored */ + rv->pv_synchook = prom_malloc(sizeof(void *)); + + /* Node operations. */ + rv->pv_nodeops = prom_malloc(sizeof(struct linux_nodeops)); + rv->pv_nodeops->no_nextnode = _va(prom_no_nextnode); + rv->pv_nodeops->no_child = _va(prom_no_getchild); + rv->pv_nodeops->no_nextprop = _va(prom_no_nextprop); + rv->pv_nodeops->no_proplen = _va(prom_no_proplen); + rv->pv_nodeops->no_getprop = _va(prom_no_getprop); + rv->pv_nodeops->no_setprop = _va(prom_no_setprop); + + /* Version 0 memory descriptors. */ + prom_init_linux_mem_v0(&rv->pv_v0mem); + + /* Linux boot arguments */ + rv->pv_v0bootargs = prom_init_linux_arguments_v0( getenv("bootargs") ); + + return rv; +} + +//----------------------------------------------------------------------------- + +struct linux_romvec *prom_init(void *prom_base) +{ + struct prom_priv *prom_entry_va; + size_t prom_size = (int)&__prom_end - (int)&__prom_start; + + /* Set the virtual PROM base address */ + prom_set_malloc_base((void *)((unsigned long)prom_base|0xF0000000)); + + /* Copy PROM code/data to virtual memory */ + memcpy(prom_malloc(prom_size), (void *)&__prom_start, prom_size); + + /* Initialise the ROM vector */ + struct linux_romvec *prom_romvec = + prom_init_romvec(prom_malloc(sizeof(struct linux_romvec))); + + /* Initialise the root IDPROM structure */ + prom_init_idprom(&root_idprom); + + /* Setup entry pointer for PROM functions */ + prom_entry_va = _va(&__prom_entry); + + /* Create the PROM node tree */ + prom_entry_va->root_node = prom_init_nodes_init(); + + /* Set UART address for getc/putc functions */ +#ifdef CONFIG_LEON2 + prom_entry_va->uart = (void *) &((LEON2_regs *)LEON2_PREGS)->UART_Channel_1; +#else + prom_entry_va->uart = leon3_apbuart; +#endif + + return prom_romvec; +} diff --git a/arch/sparc/lib/srmmu.c b/arch/sparc/lib/srmmu.c new file mode 100644 index 0000000..fbff9db --- /dev/null +++ b/arch/sparc/lib/srmmu.c @@ -0,0 +1,90 @@ +#include <common.h> +#include <asm/srmmu.h> + +DECLARE_GLOBAL_DATA_PTR; + +static void __inline__ leon_flush_cache_all(void) +{ + __asm__ __volatile__(" flush "); + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH):"memory"); +} + +static void __inline__ leon_flush_tlb_all(void) +{ + leon_flush_cache_all(); + __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400), "i"(ASI_MMUFLUSH):"memory"); +} + +/* The code below sets up the virtual address space as follows: + * + * Only context 0 is valid. Context 0 address map using 1 levels: + * + * 0x00000000 - 0xEFFFFFFF : 1:1 mapping to physical memory + * 0xF0000000 - 0xFBFFFFFF : Maps to main memory (low 192MiB memory only) + * 0xFC000000 - 0xFFFFFFFF : Not mapped + */ +void *srmmu_init_tlb_tables(void *table, size_t *table_len) +{ + int i; + + assert(((unsigned long)table & (0x2000-1)) == 0); /* must be 8KiB aligned */ + + /* SRMMU as alignment requirements on tables that must be fulfilled: + * - Context Table: align 0x2000, size 0x400, 256 entries + * - Level 1 Table: align 0x0400, size 0x400, 256 entries + */ + unsigned long *_mmu_ctx_table = (void *)(((unsigned long)table + (0x2000-1)) & ~(0x2000-1)); + unsigned long *_mmu_ctx0_level1 = &_mmu_ctx_table[256]; + + /* Setup context table: context 0 point to level 1 table */ + _mmu_ctx_table[0] = (((unsigned long)&_mmu_ctx0_level1[0] >> 4) & ~SRMMU_ET_MASK) | SRMMU_ET_PTD; + for (i = 1; i < 256; ++i) { + _mmu_ctx_table[i] = SRMMU_ET_INVALID; + } + + /* Setup level 1 address space, 16MiB/entry + * + * 0x00000000-0xF0000000: 1:1 mapping (non-cachable) + * 0xF0000000-0xFC000000: Map to RAM memory (low memory only) + * 0xFC000000-0xFEFFFFFF: INVALID + * 0xFF000000-0xFFFFFFFF: 1:1 mapping (non-cachable) + */ + for (i = 0; i < 240; ++i) { + _mmu_ctx0_level1[i] = (i << 20) | + SRMMU_NOREAD | SRMMU_EXEC | SRMMU_WRITE | SRMMU_ET_PTE; + } + for (; i < 252; i++) { + _mmu_ctx0_level1[i] = ((CONFIG_SYS_SDRAM_BASE >> 4) | ((i-240)<<20)) | + SRMMU_CACHE | SRMMU_NOREAD | SRMMU_EXEC | SRMMU_WRITE | SRMMU_ET_PTE; + } + for (; i < 256; i++) { + _mmu_ctx0_level1[i] = SRMMU_ET_INVALID; + } + + /* AMBA Configuration area */ + _mmu_ctx0_level1[255] = ((0xFF000000 >> 4) | (0x0F<<20)) | + SRMMU_NOREAD | SRMMU_EXEC | SRMMU_WRITE | SRMMU_ET_PTE; + + if (table_len) + *table_len = (unsigned long)&_mmu_ctx0_level1[256] - (unsigned long)_mmu_ctx_table; + + return (void *)_mmu_ctx_table; +} + +void srmmu_init_cpu(void *ctx_table) +{ + /* alignment check, must be aligned on 8KiB boundary */ + assert(((unsigned long)ctx_table & (0x2000-1)) == 0); + /* Set the MMU page tables */ + srmmu_set_ctable_ptr((unsigned long)ctx_table); + /* Set kernel's context, context zero */ + srmmu_set_context(0); + /* Invalidate all Cache */ + __asm__ __volatile__("flush\n\t"); + /* Flush TLB */ + leon_flush_tlb_all(); + /* Enable MMU */ + srmmu_set_mmureg(0x00000001); + /* Flush all cache */ + leon_flush_cache_all(); +} -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

Add the CONFIG_SYS_GENERIC_BOARD variable to all the LEON3 boards.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: None
include/configs/gr_cpci_ax2000.h | 4 +++- include/configs/gr_ep2s60.h | 4 +++- include/configs/gr_xc3s_1500.h | 4 +++- include/configs/grsim.h | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/include/configs/gr_cpci_ax2000.h b/include/configs/gr_cpci_ax2000.h index 5e9b3f7..3029f42 100644 --- a/include/configs/gr_cpci_ax2000.h +++ b/include/configs/gr_cpci_ax2000.h @@ -14,6 +14,8 @@ #ifndef __CONFIG_H__ #define __CONFIG_H__
+#define CONFIG_SYS_GENERIC_BOARD 1 + /* * High Level Configuration Options * (easy to change) @@ -346,7 +348,7 @@ ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10)
/* Identification string */ -#define CONFIG_IDENT_STRING "GAISLER LEON3 GR-CPCI-AX2000" +#define CONFIG_IDENT_STRING " Gaisler LEON3 GR-CPCI-AX2000"
/* default kernel command line */ #define CONFIG_DEFAULT_KERNEL_COMMAND_LINE "console=ttyS0,38400\0\0" diff --git a/include/configs/gr_ep2s60.h b/include/configs/gr_ep2s60.h index 9e99d07..32ee7c9 100644 --- a/include/configs/gr_ep2s60.h +++ b/include/configs/gr_ep2s60.h @@ -15,6 +15,8 @@ #ifndef __CONFIG_H__ #define __CONFIG_H__
+#define CONFIG_SYS_GENERIC_BOARD 1 + /* * High Level Configuration Options * (easy to change) @@ -321,7 +323,7 @@ ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10)
/* Identification string */ -#define CONFIG_IDENT_STRING "GAISLER LEON3 EP2S60" +#define CONFIG_IDENT_STRING " Gaisler LEON3 EP2S60"
/* default kernel command line */ #define CONFIG_DEFAULT_KERNEL_COMMAND_LINE "console=ttyS0,38400\0\0" diff --git a/include/configs/gr_xc3s_1500.h b/include/configs/gr_xc3s_1500.h index 8657a56..565310e 100644 --- a/include/configs/gr_xc3s_1500.h +++ b/include/configs/gr_xc3s_1500.h @@ -13,6 +13,8 @@ #ifndef __CONFIG_H__ #define __CONFIG_H__
+#define CONFIG_SYS_GENERIC_BOARD 1 + /* * High Level Configuration Options * (easy to change) @@ -286,7 +288,7 @@ ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10)
/* Identification string */ -#define CONFIG_IDENT_STRING "GAISLER LEON3 GR-XC3S-1500" +#define CONFIG_IDENT_STRING " Gaisler LEON3 GR-XC3S-1500"
/* default kernel command line */ #define CONFIG_DEFAULT_KERNEL_COMMAND_LINE "console=ttyS0,38400\0\0" diff --git a/include/configs/grsim.h b/include/configs/grsim.h index 50cafb8..5a727f2 100644 --- a/include/configs/grsim.h +++ b/include/configs/grsim.h @@ -13,6 +13,8 @@ #ifndef __CONFIG_H__ #define __CONFIG_H__
+#define CONFIG_SYS_GENERIC_BOARD 1 + /* * High Level Configuration Options * (easy to change) @@ -306,6 +308,6 @@ /* default kernel command line */ #define CONFIG_DEFAULT_KERNEL_COMMAND_LINE "console=ttyS0,38400\0\0"
-#define CONFIG_IDENT_STRING "Gaisler GRSIM" +#define CONFIG_IDENT_STRING " Gaisler GRSIM"
#endif /* __CONFIG_H */ -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

Update the GRSIM board with the memory settings for the evaluation version of TSIM.
We only have access to this version of TSIM for testing.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: - Update GRSIM memory settings for evaluation version of TSIM
include/configs/grsim.h | 57 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 12 deletions(-)
diff --git a/include/configs/grsim.h b/include/configs/grsim.h index 5a727f2..3b70983 100644 --- a/include/configs/grsim.h +++ b/include/configs/grsim.h @@ -21,9 +21,13 @@ * * Select between TSIM or GRSIM by setting CONFIG_GRSIM or CONFIG_TSIM to 1. * - * TSIM command - * tsim-leon3 -sdram 0 -ram 32000 -rom 8192 -mmu + * TSIM command: + * $ tsim-leon3 -sdram 32768 -ram 4096 -rom 2048 -mmu -cas * + * In the evaluation version of TSIM, the -sdram/-ram/-rom arguments are + * hard-coded to these values and need not be specified. (see below) + * + * Get TSIM from http://www.gaisler.com/index.php/downloads/simulators */
#define CONFIG_GRSIM 0 /* ... not running on GRSIM */ @@ -199,18 +203,18 @@ /* * Memory map */ -#define CONFIG_SYS_SDRAM_BASE 0x40000000 -#define CONFIG_SYS_SDRAM_SIZE 0x02000000 -#define CONFIG_SYS_SDRAM_END (CONFIG_SYS_SDRAM_BASE+CONFIG_SYS_SDRAM_SIZE) +#define CONFIG_SYS_SDRAM_BASE 0x60000000 +#define CONFIG_SYS_SDRAM_SIZE 0x02000000 /* 32MiB SDRAM */ +#define CONFIG_SYS_SDRAM_END (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE)
-/* no SRAM available */ -#undef CONFIG_SYS_SRAM_BASE -#undef CONFIG_SYS_SRAM_SIZE +#define CONFIG_SYS_SRAM_BASE 0x40000000 +#define CONFIG_SYS_SRAM_SIZE 0x00400000 /* 4MiB SRAM */ +#define CONFIG_SYS_SRAM_END (CONFIG_SYS_SRAM_BASE + CONFIG_SYS_SRAM_SIZE)
/* Always Run U-Boot from SDRAM */ -#define CONFIG_SYS_RAM_BASE CONFIG_SYS_SDRAM_BASE -#define CONFIG_SYS_RAM_SIZE CONFIG_SYS_SDRAM_SIZE -#define CONFIG_SYS_RAM_END CONFIG_SYS_SDRAM_END +#define CONFIG_SYS_RAM_BASE CONFIG_SYS_SDRAM_BASE +#define CONFIG_SYS_RAM_SIZE CONFIG_SYS_SDRAM_SIZE +#define CONFIG_SYS_RAM_END CONFIG_SYS_SDRAM_END
#define CONFIG_SYS_GBL_DATA_OFFSET (CONFIG_SYS_RAM_END - GENERATED_GBL_DATA_SIZE)
@@ -239,6 +243,7 @@ /* make un relocated address from relocated address */ #define UN_RELOC(address) (address-(CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE))
+#ifdef CONFIG_CMD_NET /* * Ethernet configuration */ @@ -260,6 +265,8 @@ /* #define CONFIG_GRETH_10MBIT 1 */ #define CONFIG_PHY_ADDR 0x00
+#endif /* CONFIG_CMD_NET */ + /* * Miscellaneous configurable options */ @@ -281,13 +288,14 @@ /***** Gaisler GRLIB IP-Cores Config ********/
#define CONFIG_SYS_GRLIB_SDRAM 0 + #define CONFIG_SYS_GRLIB_MEMCFG1 (0x000000ff | (1<<11)) #if CONFIG_GRSIM /* GRSIM configuration */ #define CONFIG_SYS_GRLIB_MEMCFG2 0x82206000 #else /* TSIM configuration */ -#define CONFIG_SYS_GRLIB_MEMCFG2 0x00001820 +#define CONFIG_SYS_GRLIB_MEMCFG2 0x81805220 #endif #define CONFIG_SYS_GRLIB_MEMCFG3 0x00136000
@@ -310,4 +318,29 @@
#define CONFIG_IDENT_STRING " Gaisler GRSIM"
+/* TSIM command: + * $ ./tsim-leon3 -mmu -cas + * + * This TSIM evaluation version will expire 2015-04-02 + * + * + * TSIM/LEON3 SPARC simulator, version 2.0.35 (evaluation version) + * + * Copyright (C) 2014, Aeroflex Gaisler - all rights reserved. + * This software may only be used with a valid license. + * For latest updates, go to http://www.gaisler.com/ + * Comments or bug-reports to support@gaisler.com + * + * serial port A on stdin/stdout + * allocated 4096 K SRAM memory, in 1 bank + * allocated 32 M SDRAM memory, in 1 bank + * allocated 2048 K ROM memory + * icache: 1 * 4 kbytes, 16 bytes/line (4 kbytes total) + * dcache: 1 * 4 kbytes, 16 bytes/line (4 kbytes total) + * tsim> leon + * 0x80000000 Memory configuration register 1 0x000002ff + * 0x80000004 Memory configuration register 2 0x81805220 + * 0x80000008 Memory configuration register 3 0x00000000 + */ + #endif /* __CONFIG_H */ -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/

This changeset do some cleanup of the LEON3 CPU initialization code.
We move the interrupt initialization into a separate function for beter modularity. In the memory controller initialization function, we put amount of code in the function. Thus your board only need to define the variables needed for your device and no more.
Create the cpu_panic function so that a back-trace can show us that we ended up in a panic situation. Previously we could not identify where we were inside the cpu_init_f() function during a panic.
Signed-off-by: Francois Retief fgretief@spaceteq.co.za ---
Changes in v2: - Add patch to cleanup LEON3 init code a bit - The gr712rc-board patches has been split into a separate series
arch/sparc/cpu/leon3/cpu_init.c | 109 +++++++++++++++++++++----------------- arch/sparc/cpu/leon3/interrupts.c | 4 +- 2 files changed, 64 insertions(+), 49 deletions(-)
diff --git a/arch/sparc/cpu/leon3/cpu_init.c b/arch/sparc/cpu/leon3/cpu_init.c index b0c7088..462b4a6 100644 --- a/arch/sparc/cpu/leon3/cpu_init.c +++ b/arch/sparc/cpu/leon3/cpu_init.c @@ -19,23 +19,12 @@
DECLARE_GLOBAL_DATA_PTR;
-/* reset CPU (jump to 0, without reset) */ -void start(void); - /* find & initialize the memory controller */ -int init_memory_ctrl(void); +static int init_memory_ctrl(void); +static int init_intr_ctrl(void);
-ambapp_dev_irqmp *irqmp = NULL; -ambapp_dev_mctrl memctrl; -ambapp_dev_gptimer *gptimer = NULL; -unsigned int gptimer_irq = 0; int leon3_snooping_avail = 0; /* used by arch/sparc/cpu/leon3/usb_uhci.c */
-struct { - gd_t gd_area; - bd_t bd; -} global_data; - /* If CACHE snooping is available in hardware the result will be set * to 0x800000, otherwise 0. */ @@ -46,6 +35,12 @@ static unsigned int snoop_detect(void) return result & 0x00800000; }
+void cpu_panic(void) +{ + /* TODO: add some logic to print a warning on uart */ + while (1) ; +} + /* * Breath some life into the CPU... * @@ -60,9 +55,6 @@ static unsigned int snoop_detect(void)
void cpu_init_f(void) { - /* these varaiable must not be initialized */ - ambapp_dev_irqmp *irqmp; - ambapp_apbdev apbdev; register unsigned int apbmst;
/* find AMBA APB Master */ @@ -73,33 +65,18 @@ void cpu_init_f(void) * no AHB/APB bridge, something is wrong * ==> jump to start (or hang) */ - while (1) ; + cpu_panic(); } + /* Init memory controller */ - if (init_memory_ctrl()) { - while (1) ; - } + if (init_memory_ctrl()) + cpu_panic();
/**************************************************** * From here we can use the main memory and the stack. */ - - /* Find AMBA APB IRQMP Controller */ - if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev) != 1) { - /* no IRQ controller, something is wrong - * ==> jump to start (or hang) - */ - while (1) ; - } - irqmp = (ambapp_dev_irqmp *) apbdev.address; - - /* initialize the IRQMP */ - irqmp->ilevel = 0xf; /* all IRQ off */ - irqmp->iforce = 0; - irqmp->ipend = 0; - irqmp->iclear = 0xfffe; /* clear all old pending interrupts */ - irqmp->cpu_mask[0] = 0; /* mask all IRQs on CPU 0 */ - irqmp->cpu_force[0] = 0; /* no force IRQ on CPU 0 */ + if (init_intr_ctrl()) + cpu_panic();
/* cache */ leon3_snooping_avail = snoop_detect(); @@ -136,7 +113,6 @@ int cpu_init_r(void) return 1; } gptimer = (ambapp_dev_gptimer *) apbdev.address; - gptimer_irq = apbdev.irq;
/* initialize prescaler common to all timers to 1MHz */ gptimer->scalar = gptimer->scalar_reload = @@ -148,19 +124,19 @@ int cpu_init_r(void) #endif
/* find & setup memory controller */ -int init_memory_ctrl() +static int init_memory_ctrl() { - register ambapp_dev_mctrl *mctrl; - register ambapp_dev_sdctrl *sdctrl; - register ambapp_dev_ddrspa *ddrspa; - register ambapp_dev_ddr2spa *ddr2spa; register ahbctrl_pp_dev *ahb; register unsigned int base; register int not_found_mctrl = -1;
+#if defined(CONFIG_SYS_GRLIB_MEMCFG1) && \ + defined(CONFIG_SYS_GRLIB_MEMCFG2) && \ + defined(CONFIG_SYS_GRLIB_MEMCFG3) /* find ESA Memory controller */ base = ambapp_apb_next_nomem(VENDOR_ESA, ESA_MCTRL, 0); if (base) { + register ambapp_dev_mctrl *mctrl = (ambapp_dev_mctrl *) base; mctrl = (ambapp_dev_mctrl *) base;
/* config MCTRL memory controller */ @@ -169,11 +145,15 @@ int init_memory_ctrl() mctrl->mcfg3 = CONFIG_SYS_GRLIB_MEMCFG3; not_found_mctrl = 0; } +#endif
+#if defined(CONFIG_SYS_GRLIB_FT_MEMCFG1) && \ + defined(CONFIG_SYS_GRLIB_FT_MEMCFG2) && \ + defined(CONFIG_SYS_GRLIB_FT_MEMCFG3) /* find Gaisler Fault Tolerant Memory controller */ base = ambapp_apb_next_nomem(VENDOR_GAISLER, GAISLER_FTMCTRL, 0); if (base) { - mctrl = (ambapp_dev_mctrl *) base; + register ambapp_dev_mctrl *mctrl = (ambapp_dev_mctrl *) base;
/* config MCTRL memory controller */ mctrl->mcfg1 = CONFIG_SYS_GRLIB_FT_MEMCFG1 | (mctrl->mcfg1 & 0x300); @@ -181,40 +161,73 @@ int init_memory_ctrl() mctrl->mcfg3 = CONFIG_SYS_GRLIB_FT_MEMCFG3; not_found_mctrl = 0; } +#endif
+#if defined(CONFIG_SYS_GRLIB_SDRAM) /* find SDRAM controller */ base = ambapp_apb_next_nomem(VENDOR_GAISLER, GAISLER_SDCTRL, 0); if (base) { - sdctrl = (ambapp_dev_sdctrl *) base; + register ambapp_dev_sdctrl *sdctrl = (ambapp_dev_sdctrl *) base;
/* config memory controller */ sdctrl->sdcfg = CONFIG_SYS_GRLIB_SDRAM; not_found_mctrl = 0; } +#endif
+#if defined(CONFIG_SYS_GRLIB_DDR2_CFG1) && \ + defined(CONFIG_SYS_GRLIB_DDR2_CFG3) ahb = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_DDR2SPA, 1, 0); if (ahb) { - ddr2spa = (ambapp_dev_ddr2spa *) ambapp_ahb_get_info(ahb, 1); + register ambapp_dev_ddr2spa *ddr2spa = + (ambapp_dev_ddr2spa *) ambapp_ahb_get_info(ahb, 1);
/* Config DDR2 memory controller */ ddr2spa->cfg1 = CONFIG_SYS_GRLIB_DDR2_CFG1; ddr2spa->cfg3 = CONFIG_SYS_GRLIB_DDR2_CFG3; not_found_mctrl = 0; } +#endif
+#if defined(CONFIG_SYS_GRLIB_DDR_CFG) ahb = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_DDRSPA, 1, 0); if (ahb) { - ddrspa = (ambapp_dev_ddrspa *) ambapp_ahb_get_info(ahb, 1); + register ambapp_dev_ddrspa *ddrspa = + (ambapp_dev_ddrspa *) ambapp_ahb_get_info(ahb, 1);
/* Config DDR memory controller */ ddrspa->ctrl = CONFIG_SYS_GRLIB_DDR_CFG; not_found_mctrl = 0; } +#endif
/* failed to find any memory controller */ return not_found_mctrl; }
+static int init_intr_ctrl(void) +{ + ambapp_apbdev apbdev; + ambapp_dev_irqmp *irqmp; + + /* look for AMBA APB IRQMP controller... */ + if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev) != 1) + return -1; /* no IRQ controller */ + + /* found irqmp, let's init .. */ + irqmp = (ambapp_dev_irqmp *) apbdev.address; + + /* initialize the IRQMP */ + irqmp->ilevel = 0xf; /* all IRQ off */ + irqmp->iforce = 0; + irqmp->ipend = 0; + irqmp->iclear = 0xfffe; /* clear all old pending interrupts */ + irqmp->cpu_mask[0] = 0; /* mask all IRQs on CPU 0 */ + irqmp->cpu_force[0] = 0; /* no force IRQ on CPU 0 */ + + return 0; +} + #ifndef CONFIG_SYS_GENERIC_BOARD
/* Uses Timer 0 to get accurate @@ -278,6 +291,7 @@ static ambapp_dev_gptimer_element *tmr = NULL;
int timer_init(void) { + ambapp_dev_gptimer *gptimer; ambapp_apbdev apbdev;
if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_GPTIMER, &apbdev) != 1) { @@ -285,7 +299,6 @@ int timer_init(void) return 1; } gptimer = (ambapp_dev_gptimer *) apbdev.address; - gptimer_irq = apbdev.irq;
/* initialize prescaler common to all timers to 1MHz */ gptimer->scalar = gptimer->scalar_reload = diff --git a/arch/sparc/cpu/leon3/interrupts.c b/arch/sparc/cpu/leon3/interrupts.c index 20e295c..369fcb6 100644 --- a/arch/sparc/cpu/leon3/interrupts.c +++ b/arch/sparc/cpu/leon3/interrupts.c @@ -33,8 +33,10 @@ struct irq_action { unsigned int count; };
-extern ambapp_dev_irqmp *irqmp; +ambapp_dev_irqmp *irqmp = NULL; +#ifndef CONFIG_SYS_GENERIC_BOARD extern ambapp_dev_gptimer *gptimer; +#endif
static struct irq_action irq_handlers[NR_IRQS] = { {0}, }; static int spurious_irq_cnt = 0; -- 1.9.3
________________________________ Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za http://www.spaceteq.co.za/home/emaildisclaimer/
participants (1)
-
Francois Retief