powerpc: change 86xx SMP boot method

We put the bootpg for the secondary cpus into memory and use
BPTR to get to it.  This is a step towards converting to the
ePAPR boot methodology.  Also, the code is written to
deal properly with more than 4GB of RAM.

Signed-off-by: Becky Bruce <becky.bruce@freescale.com>
This commit is contained in:
Becky Bruce 2008-11-03 15:44:01 -06:00 committed by Jon Loeliger
parent b543156068
commit 1266df8877
10 changed files with 298 additions and 73 deletions

View file

@ -31,6 +31,10 @@ LIB = $(obj)lib$(CPU).a
START = start.o START = start.o
SOBJS = cache.o SOBJS = cache.o
ifneq ($(CONFIG_NUM_CPUS),1)
COBJS-y += mp.o
SOBJS += release.o
endif
COBJS-y += traps.o COBJS-y += traps.o
COBJS-y += cpu.o COBJS-y += cpu.o
COBJS-y += cpu_init.o COBJS-y += cpu_init.o

View file

@ -31,6 +31,7 @@
#include <mpc86xx.h> #include <mpc86xx.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/fsl_law.h> #include <asm/fsl_law.h>
#include "mp.h"
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
@ -121,6 +122,9 @@ void cpu_init_f(void)
*/ */
int cpu_init_r(void) int cpu_init_r(void)
{ {
#if (CONFIG_NUM_CPUS > 1)
setup_mp();
#endif
return 0; return 0;
} }

View file

@ -9,9 +9,17 @@
#include <common.h> #include <common.h>
#include <libfdt.h> #include <libfdt.h>
#include <fdt_support.h> #include <fdt_support.h>
#include "mp.h"
DECLARE_GLOBAL_DATA_PTR;
void ft_cpu_setup(void *blob, bd_t *bd) void ft_cpu_setup(void *blob, bd_t *bd)
{ {
#if (CONFIG_NUM_CPUS > 1)
int off;
u32 bootpg;
#endif
do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
"timebase-frequency", bd->bi_busfreq / 4, 1); "timebase-frequency", bd->bi_busfreq / 4, 1);
do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
@ -32,4 +40,17 @@ void ft_cpu_setup(void *blob, bd_t *bd)
do_fixup_by_compat_u32(blob, "ns16550", do_fixup_by_compat_u32(blob, "ns16550",
"clock-frequency", CONFIG_SYS_NS16550_CLK, 1); "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
#endif #endif
#if (CONFIG_NUM_CPUS > 1)
/* if we have 4G or more of memory, put the boot page at 4Gb-1M */
if (gd->ram_size > 0xfffff000)
bootpg = 0xfff00000;
else
bootpg = gd->ram_size - (1024 * 1024);
/* Reserve the boot page so OSes dont use it */
off = fdt_add_mem_rsv(blob, bootpg, (u64)4096);
if (off < 0)
printf("%s: %s\n", __FUNCTION__, fdt_strerror(off));
#endif
} }

68
cpu/mpc86xx/mp.c Normal file
View file

@ -0,0 +1,68 @@
#include <common.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <ioports.h>
#include <lmb.h>
#include <asm/io.h>
#include "mp.h"
DECLARE_GLOBAL_DATA_PTR;
#if (CONFIG_NUM_CPUS > 1)
void cpu_mp_lmb_reserve(struct lmb *lmb)
{
u32 bootpg;
/* if we have 4G or more of memory, put the boot page at 4Gb-1M */
if ((u64)gd->ram_size > 0xfffff000)
bootpg = 0xfff00000;
else
bootpg = gd->ram_size - (1024 * 1024);
/* tell u-boot we stole a page */
lmb_reserve(lmb, bootpg, 4096);
}
/*
* Copy the code for other cpus to execute into an
* aligned location accessible via BPTR
*/
void setup_mp(void)
{
extern ulong __secondary_start_page;
ulong fixup = (ulong)&__secondary_start_page;
u32 bootpg;
u32 bootpg_va;
/*
* If we have 4G or more of memory, put the boot page at 4Gb-1M.
* Otherwise, put it at the very end of RAM.
*/
if (gd->ram_size > 0xfffff000)
bootpg = 0xfff00000;
else
bootpg = gd->ram_size - (1024 * 1024);
if (bootpg >= CONFIG_SYS_MAX_DDR_BAT_SIZE) {
/* We're not covered by the DDR mapping, set up BAT */
write_bat(DBAT7, CONFIG_SYS_SCRATCH_VA | BATU_BL_128K |
BATU_VS | BATU_VP,
bootpg | BATL_PP_RW | BATL_MEMCOHERENCE);
bootpg_va = CONFIG_SYS_SCRATCH_VA;
} else {
bootpg_va = bootpg;
}
memcpy((void *)bootpg_va, (void *)fixup, 4096);
flush_cache(bootpg_va, 4096);
/* remove the temporary BAT mapping */
if (bootpg >= CONFIG_SYS_MAX_DDR_BAT_SIZE)
write_bat(DBAT7, 0, 0);
/* If the physical location of bootpg is not at fff00000, set BPTR */
if (bootpg != 0xfff00000)
out_be32((uint *)(CONFIG_SYS_CCSRBAR + 0x20), 0x80000000 |
(bootpg >> 12));
}
#endif

7
cpu/mpc86xx/mp.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef __MPC86XX_MP_H_
#define __MPC86XX_MP_H_
void setup_mp(void);
void cpu_mp_lmb_reserve(struct lmb *lmb);
#endif

169
cpu/mpc86xx/release.S Normal file
View file

@ -0,0 +1,169 @@
/*
* Copyright 2004, 2007, 2008 Freescale Semiconductor.
* Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <mpc86xx.h>
#include <version.h>
#include <ppc_asm.tmpl>
#include <ppc_defs.h>
#include <asm/cache.h>
#include <asm/mmu.h>
/* If this is a multi-cpu system then we need to handle the
* 2nd cpu. The assumption is that the 2nd cpu is being
* held in boot holdoff mode until the 1st cpu unlocks it
* from Linux. We'll do some basic cpu init and then pass
* it to the Linux Reset Vector.
* Sri: Much of this initialization is not required. Linux
* rewrites the bats, and the sprs and also enables the L1 cache.
*
* Core 0 must copy this to a 1M aligned region and set BPTR
* to point to it.
*/
#if (CONFIG_NUM_CPUS > 1)
.align 12
.globl __secondary_start_page
__secondary_start_page:
.space 0x100 /* space over to reset vector loc */
mfspr r0, MSSCR0
andi. r0, r0, 0x0020
rlwinm r0,r0,27,31,31
mtspr PIR, r0
/* Invalidate BATs */
li r0, 0
mtspr IBAT0U, r0
mtspr IBAT1U, r0
mtspr IBAT2U, r0
mtspr IBAT3U, r0
mtspr IBAT4U, r0
mtspr IBAT5U, r0
mtspr IBAT6U, r0
mtspr IBAT7U, r0
isync
mtspr DBAT0U, r0
mtspr DBAT1U, r0
mtspr DBAT2U, r0
mtspr DBAT3U, r0
mtspr DBAT4U, r0
mtspr DBAT5U, r0
mtspr DBAT6U, r0
mtspr DBAT7U, r0
isync
sync
/* enable extended addressing */
mfspr r0, HID0
lis r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
ori r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
mtspr HID0, r0
sync
isync
#ifdef CONFIG_SYS_L2
/* init the L2 cache */
addis r3, r0, L2_INIT@h
ori r3, r3, L2_INIT@l
sync
mtspr l2cr, r3
#ifdef CONFIG_ALTIVEC
dssall
#endif
/* invalidate the L2 cache */
mfspr r3, l2cr
rlwinm. r3, r3, 0, 0, 0
beq 1f
mfspr r3, l2cr
rlwinm r3, r3, 0, 1, 31
#ifdef CONFIG_ALTIVEC
dssall
#endif
sync
mtspr l2cr, r3
sync
1: mfspr r3, l2cr
oris r3, r3, L2CR_L2I@h
mtspr l2cr, r3
invl2:
mfspr r3, l2cr
andis. r3, r3, L2CR_L2I@h
bne invl2
sync
#endif
/* enable and invalidate the data cache */
mfspr r3, HID0
li r5, HID0_DCFI|HID0_DLOCK
andc r3, r3, r5
mtspr HID0, r3 /* no invalidate, unlock */
ori r3, r3, HID0_DCE
ori r5, r3, HID0_DCFI
mtspr HID0, r5 /* enable + invalidate */
mtspr HID0, r3 /* enable */
sync
#ifdef CFG_L2
sync
lis r3, L2_ENABLE@h
ori r3, r3, L2_ENABLE@l
mtspr l2cr, r3
isync
sync
#endif
/* enable and invalidate the instruction cache*/
mfspr r3, HID0
li r5, HID0_ICFI|HID0_ILOCK
andc r3, r3, r5
ori r3, r3, HID0_ICE
ori r5, r3, HID0_ICFI
mtspr HID0, r5
mtspr HID0, r3
isync
sync
/* TBEN in HID0 */
mfspr r4, HID0
oris r4, r4, 0x0400
mtspr HID0, r4
sync
isync
/* MCP|SYNCBE|ABE in HID1 */
mfspr r4, HID1
oris r4, r4, 0x8000
ori r4, r4, 0x0C00
mtspr HID1, r4
sync
isync
lis r3, CONFIG_LINUX_RESET_VEC@h
ori r3, r3, CONFIG_LINUX_RESET_VEC@l
mtlr r3
blr
/* Never Returns, Running in Linux Now */
#endif

View file

@ -179,20 +179,10 @@ _end_of_vectors:
boot_cold: boot_cold:
boot_warm: boot_warm:
/*
/* if this is a multi-core system we need to check which cpu * NOTE: Only Cpu 0 will ever come here. Other cores go to an
* this is, if it is not cpu 0 send the cpu to the linux reset * address specified by the BPTR
* vector */ */
#if (CONFIG_NUM_CPUS > 1)
mfspr r0, MSSCR0
andi. r0, r0, 0x0020
rlwinm r0,r0,27,31,31
mtspr PIR, r0
beq 1f
bl secondary_cpu_setup
#endif
1: 1:
#ifdef CONFIG_SYS_RAMBOOT #ifdef CONFIG_SYS_RAMBOOT
/* disable everything */ /* disable everything */
@ -978,63 +968,4 @@ unlock_ram_in_cache:
#endif #endif
#endif #endif
/* If this is a multi-cpu system then we need to handle the
* 2nd cpu. The assumption is that the 2nd cpu is being
* held in boot holdoff mode until the 1st cpu unlocks it
* from Linux. We'll do some basic cpu init and then pass
* it to the Linux Reset Vector.
* Sri: Much of this initialization is not required. Linux
* rewrites the bats, and the sprs and also enables the L1 cache.
*/
#if (CONFIG_NUM_CPUS > 1)
.globl secondary_cpu_setup
secondary_cpu_setup:
/* Do only core setup on all cores except cpu0 */
bl invalidate_bats
sync
bl enable_ext_addr
#ifdef CONFIG_SYS_L2
/* init the L2 cache */
addis r3, r0, L2_INIT@h
ori r3, r3, L2_INIT@l
sync
mtspr l2cr, r3
#ifdef CONFIG_ALTIVEC
dssall
#endif
/* invalidate the L2 cache */
bl l2cache_invalidate
sync
#endif
/* enable and invalidate the data cache */
bl dcache_enable
sync
/* enable and invalidate the instruction cache*/
bl icache_enable
sync
/* TBEN in HID0 */
mfspr r4, HID0
oris r4, r4, 0x0400
mtspr HID0, r4
sync
isync
/* MCP|SYNCBE|ABE in HID1 */
mfspr r4, HID1
oris r4, r4, 0x8000
ori r4, r4, 0x0C00
mtspr HID1, r4
sync
isync
lis r3, CONFIG_LINUX_RESET_VEC@h
ori r3, r3, CONFIG_LINUX_RESET_VEC@l
mtlr r3
blr
/* Never Returns, Running in Linux Now */
#endif

View file

@ -36,6 +36,12 @@
#define CONFIG_SYS_RESET_ADDRESS 0xfff00100 #define CONFIG_SYS_RESET_ADDRESS 0xfff00100
/*
* virtual address to be used for temporary mappings. There
* should be 128k free at this VA.
*/
#define CONFIG_SYS_SCRATCH_VA 0xc0000000
#define CONFIG_PCI 1 /* Enable PCI/PCIE*/ #define CONFIG_PCI 1 /* Enable PCI/PCIE*/
#define CONFIG_PCI1 1 /* PCI controler 1 */ #define CONFIG_PCI1 1 /* PCI controler 1 */
#define CONFIG_PCIE1 1 /* PCIe 1 connected to ULI bridge */ #define CONFIG_PCIE1 1 /* PCIe 1 connected to ULI bridge */
@ -92,6 +98,7 @@
#define CONFIG_SYS_DDR_SDRAM_BASE 0x00000000 /* DDR is system memory*/ #define CONFIG_SYS_DDR_SDRAM_BASE 0x00000000 /* DDR is system memory*/
#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_DDR_SDRAM_BASE #define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_DDR_SDRAM_BASE
#define CONFIG_SYS_MAX_DDR_BAT_SIZE 0x80000000 /* BAT mapping size */
#define CONFIG_VERY_BIG_RAM #define CONFIG_VERY_BIG_RAM
#define MPC86xx_DDR_SDRAM_CLK_CNTL #define MPC86xx_DDR_SDRAM_CLK_CNTL

View file

@ -45,6 +45,12 @@
#define CONFIG_SYS_RESET_ADDRESS 0xfff00100 #define CONFIG_SYS_RESET_ADDRESS 0xfff00100
/*
* virtual address to be used for temporary mappings. There
* should be 128k free at this VA.
*/
#define CONFIG_SYS_SCRATCH_VA 0xe0000000
/* /*
* set this to enable Rapid IO. PCI and RIO are mutually exclusive * set this to enable Rapid IO. PCI and RIO are mutually exclusive
*/ */
@ -109,6 +115,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
#define CONFIG_SYS_DDR_SDRAM_BASE 0x00000000 /* DDR is system memory*/ #define CONFIG_SYS_DDR_SDRAM_BASE 0x00000000 /* DDR is system memory*/
#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_DDR_SDRAM_BASE #define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_DDR_SDRAM_BASE
#define CONFIG_SYS_MAX_DDR_BAT_SIZE 0x80000000 /* BAT mapping size */
#define CONFIG_VERY_BIG_RAM #define CONFIG_VERY_BIG_RAM
#define MPC86xx_DDR_SDRAM_CLK_CNTL #define MPC86xx_DDR_SDRAM_CLK_CNTL

View file

@ -49,6 +49,12 @@
#define CONFIG_SYS_RESET_ADDRESS 0xfff00100 #define CONFIG_SYS_RESET_ADDRESS 0xfff00100
/*
* virtual address to be used for temporary mappings. There
* should be 128k free at this VA.
*/
#define CONFIG_SYS_SCRATCH_VA 0xe8000000
#define CONFIG_PCI 1 /* Enable PCIE */ #define CONFIG_PCI 1 /* Enable PCIE */
#define CONFIG_PCI1 1 /* PCIE controler 1 (slot 1) */ #define CONFIG_PCI1 1 /* PCIE controler 1 (slot 1) */
#define CONFIG_PCI2 1 /* PCIE controler 2 (slot 2) */ #define CONFIG_PCI2 1 /* PCIE controler 2 (slot 2) */
@ -108,6 +114,7 @@
#define CONFIG_SYS_DDR_SDRAM_BASE2 0x10000000 /* DDR bank 2 */ #define CONFIG_SYS_DDR_SDRAM_BASE2 0x10000000 /* DDR bank 2 */
#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_DDR_SDRAM_BASE #define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_DDR_SDRAM_BASE
#define CONFIG_SYS_SDRAM_BASE2 CONFIG_SYS_DDR_SDRAM_BASE2 #define CONFIG_SYS_SDRAM_BASE2 CONFIG_SYS_DDR_SDRAM_BASE2
#define CONFIG_SYS_MAX_DDR_BAT_SIZE 0x80000000 /* BAT mapping size */
#define CONFIG_VERY_BIG_RAM #define CONFIG_VERY_BIG_RAM
#define MPC86xx_DDR_SDRAM_CLK_CNTL #define MPC86xx_DDR_SDRAM_CLK_CNTL