platform_bare.c revision 212054
1192067Snwhitehorn/*- 2192067Snwhitehorn * Copyright (c) 2008-2009 Semihalf, Rafal Jaworowski 3192067Snwhitehorn * All rights reserved. 4192067Snwhitehorn * 5192067Snwhitehorn * Redistribution and use in source and binary forms, with or without 6192067Snwhitehorn * modification, are permitted provided that the following conditions 7192067Snwhitehorn * are met: 8192067Snwhitehorn * 9192067Snwhitehorn * 1. Redistributions of source code must retain the above copyright 10192067Snwhitehorn * notice, this list of conditions and the following disclaimer. 11192067Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 12192067Snwhitehorn * notice, this list of conditions and the following disclaimer in the 13192067Snwhitehorn * documentation and/or other materials provided with the distribution. 14192067Snwhitehorn * 15192067Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16192067Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17192067Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18192067Snwhitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19192067Snwhitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20192067Snwhitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21192067Snwhitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22192067Snwhitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23192067Snwhitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24192067Snwhitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25192067Snwhitehorn */ 26192067Snwhitehorn 27192067Snwhitehorn#include <sys/cdefs.h> 28192067Snwhitehorn__FBSDID("$FreeBSD: head/sys/powerpc/booke/platform_bare.c 212054 2010-08-31 15:27:46Z nwhitehorn $"); 29192067Snwhitehorn 30192067Snwhitehorn#include <sys/param.h> 31192067Snwhitehorn#include <sys/systm.h> 32192067Snwhitehorn#include <sys/kernel.h> 33192067Snwhitehorn#include <sys/bus.h> 34192067Snwhitehorn#include <sys/pcpu.h> 35192067Snwhitehorn#include <sys/proc.h> 36192067Snwhitehorn#include <sys/smp.h> 37192067Snwhitehorn 38192067Snwhitehorn#include <machine/bus.h> 39192067Snwhitehorn#include <machine/cpu.h> 40192067Snwhitehorn#include <machine/hid.h> 41192067Snwhitehorn#include <machine/platform.h> 42192067Snwhitehorn#include <machine/platformvar.h> 43192067Snwhitehorn#include <machine/smp.h> 44192067Snwhitehorn#include <machine/spr.h> 45192067Snwhitehorn#include <machine/vmparam.h> 46192067Snwhitehorn 47209908Sraj#include <dev/fdt/fdt_common.h> 48209908Sraj#include <dev/ofw/ofw_bus.h> 49209908Sraj#include <dev/ofw/ofw_bus_subr.h> 50209908Sraj#include <dev/ofw/openfirm.h> 51209908Sraj 52192067Snwhitehorn#include <powerpc/mpc85xx/mpc85xx.h> 53192067Snwhitehorn 54192067Snwhitehorn#include "platform_if.h" 55192067Snwhitehorn 56192532Sraj#ifdef SMP 57192532Srajextern void *ap_pcpu; 58192532Srajextern uint8_t __boot_page[]; /* Boot page body */ 59192532Srajextern uint32_t kernload; /* Kernel physical load address */ 60192532Sraj#endif 61192532Sraj 62193492Srajstatic int cpu, maxcpu; 63192067Snwhitehorn 64192067Snwhitehornstatic int bare_probe(platform_t); 65192067Snwhitehornstatic void bare_mem_regions(platform_t, struct mem_region **phys, int *physsz, 66192067Snwhitehorn struct mem_region **avail, int *availsz); 67192067Snwhitehornstatic u_long bare_timebase_freq(platform_t, struct cpuref *cpuref); 68192067Snwhitehornstatic int bare_smp_first_cpu(platform_t, struct cpuref *cpuref); 69192067Snwhitehornstatic int bare_smp_next_cpu(platform_t, struct cpuref *cpuref); 70192067Snwhitehornstatic int bare_smp_get_bsp(platform_t, struct cpuref *cpuref); 71192067Snwhitehornstatic int bare_smp_start_cpu(platform_t, struct pcpu *cpu); 72192067Snwhitehorn 73212054Snwhitehornstatic void e500_reset(platform_t); 74212054Snwhitehorn 75192067Snwhitehornstatic platform_method_t bare_methods[] = { 76192067Snwhitehorn PLATFORMMETHOD(platform_probe, bare_probe), 77192067Snwhitehorn PLATFORMMETHOD(platform_mem_regions, bare_mem_regions), 78192067Snwhitehorn PLATFORMMETHOD(platform_timebase_freq, bare_timebase_freq), 79192067Snwhitehorn 80192067Snwhitehorn PLATFORMMETHOD(platform_smp_first_cpu, bare_smp_first_cpu), 81192067Snwhitehorn PLATFORMMETHOD(platform_smp_next_cpu, bare_smp_next_cpu), 82192067Snwhitehorn PLATFORMMETHOD(platform_smp_get_bsp, bare_smp_get_bsp), 83192067Snwhitehorn PLATFORMMETHOD(platform_smp_start_cpu, bare_smp_start_cpu), 84192067Snwhitehorn 85212054Snwhitehorn PLATFORMMETHOD(platform_reset, e500_reset); 86212054Snwhitehorn 87192067Snwhitehorn { 0, 0 } 88192067Snwhitehorn}; 89192067Snwhitehorn 90192067Snwhitehornstatic platform_def_t bare_platform = { 91192067Snwhitehorn "bare metal", 92192067Snwhitehorn bare_methods, 93192067Snwhitehorn 0 94192067Snwhitehorn}; 95192067Snwhitehorn 96192067SnwhitehornPLATFORM_DEF(bare_platform); 97192067Snwhitehorn 98192067Snwhitehornstatic int 99192067Snwhitehornbare_probe(platform_t plat) 100192067Snwhitehorn{ 101209908Sraj uint32_t ver, sr; 102209908Sraj int i, law_max, tgt; 103192067Snwhitehorn 104193492Sraj ver = SVR_VER(mfspr(SPR_SVR)); 105193492Sraj if (ver == SVR_MPC8572E || ver == SVR_MPC8572) 106193492Sraj maxcpu = 2; 107193492Sraj else 108193492Sraj maxcpu = 1; 109193492Sraj 110209908Sraj /* 111209908Sraj * Clear local access windows. Skip DRAM entries, so we don't shoot 112209908Sraj * ourselves in the foot. 113209908Sraj */ 114209908Sraj law_max = law_getmax(); 115209908Sraj for (i = 0; i < law_max; i++) { 116209908Sraj sr = ccsr_read4(OCP85XX_LAWSR(i)); 117209908Sraj if ((sr & 0x80000000) == 0) 118209908Sraj continue; 119209908Sraj tgt = (sr & 0x01f00000) >> 20; 120209908Sraj if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 || 121209908Sraj tgt == OCP85XX_TGTIF_RAM_INTL) 122209908Sraj continue; 123209908Sraj 124209908Sraj ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff); 125209908Sraj } 126209908Sraj 127192067Snwhitehorn return (BUS_PROBE_GENERIC); 128192067Snwhitehorn} 129192067Snwhitehorn 130192067Snwhitehorn#define MEM_REGIONS 8 131192067Snwhitehornstatic struct mem_region avail_regions[MEM_REGIONS]; 132192067Snwhitehorn 133192067Snwhitehornvoid 134192067Snwhitehornbare_mem_regions(platform_t plat, struct mem_region **phys, int *physsz, 135192067Snwhitehorn struct mem_region **avail, int *availsz) 136192067Snwhitehorn{ 137209908Sraj uint32_t memsize; 138209908Sraj int i, rv; 139192067Snwhitehorn 140209908Sraj rv = fdt_get_mem_regions(avail_regions, availsz, &memsize); 141209908Sraj 142209908Sraj if (rv != 0) 143209908Sraj return; 144209908Sraj 145209908Sraj for (i = 0; i < *availsz; i++) { 146209908Sraj if (avail_regions[i].mr_start < 1048576) { 147209908Sraj avail_regions[i].mr_size = 148209908Sraj avail_regions[i].mr_size - 149209908Sraj (1048576 - avail_regions[i].mr_start); 150192067Snwhitehorn avail_regions[i].mr_start = 1048576; 151192067Snwhitehorn } 152192067Snwhitehorn } 153192067Snwhitehorn *avail = avail_regions; 154192067Snwhitehorn 155192067Snwhitehorn /* On the bare metal platform phys == avail memory */ 156192067Snwhitehorn *physsz = *availsz; 157192067Snwhitehorn *phys = *avail; 158192067Snwhitehorn} 159192067Snwhitehorn 160192067Snwhitehornstatic u_long 161192067Snwhitehornbare_timebase_freq(platform_t plat, struct cpuref *cpuref) 162192067Snwhitehorn{ 163192067Snwhitehorn u_long ticks = -1; 164209908Sraj phandle_t cpus, child; 165209908Sraj pcell_t freq; 166192067Snwhitehorn 167209908Sraj if ((cpus = OF_finddevice("/cpus")) == 0) 168209908Sraj goto out; 169209908Sraj 170209908Sraj if ((child = OF_child(cpus)) == 0) 171209908Sraj goto out; 172209908Sraj 173209908Sraj if (OF_getprop(child, "bus-frequency", (void *)&freq, 174209908Sraj sizeof(freq)) <= 0) 175209908Sraj goto out; 176192067Snwhitehorn /* 177192067Snwhitehorn * Time Base and Decrementer are updated every 8 CCB bus clocks. 178192067Snwhitehorn * HID0[SEL_TBCLK] = 0 179192067Snwhitehorn */ 180209908Sraj ticks = freq / 8; 181209908Srajout: 182192067Snwhitehorn if (ticks <= 0) 183192067Snwhitehorn panic("Unable to determine timebase frequency!"); 184192067Snwhitehorn 185192067Snwhitehorn return (ticks); 186192067Snwhitehorn} 187192067Snwhitehorn 188192067Snwhitehornstatic int 189192067Snwhitehornbare_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 190192067Snwhitehorn{ 191192067Snwhitehorn 192192067Snwhitehorn cpu = 0; 193192067Snwhitehorn cpuref->cr_cpuid = cpu; 194192067Snwhitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 195192067Snwhitehorn if (bootverbose) 196192067Snwhitehorn printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid); 197192067Snwhitehorn cpu++; 198192067Snwhitehorn 199192067Snwhitehorn return (0); 200192067Snwhitehorn} 201192067Snwhitehorn 202192067Snwhitehornstatic int 203192067Snwhitehornbare_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 204192067Snwhitehorn{ 205192067Snwhitehorn 206193492Sraj if (cpu >= maxcpu) 207192067Snwhitehorn return (ENOENT); 208192067Snwhitehorn 209192067Snwhitehorn cpuref->cr_cpuid = cpu++; 210192067Snwhitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 211192067Snwhitehorn if (bootverbose) 212192067Snwhitehorn printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid); 213192067Snwhitehorn 214192067Snwhitehorn return (0); 215192067Snwhitehorn} 216192067Snwhitehorn 217192067Snwhitehornstatic int 218192067Snwhitehornbare_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 219192067Snwhitehorn{ 220192067Snwhitehorn 221192067Snwhitehorn cpuref->cr_cpuid = mfspr(SPR_PIR); 222192067Snwhitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 223192067Snwhitehorn 224192067Snwhitehorn return (0); 225192067Snwhitehorn} 226192067Snwhitehorn 227192067Snwhitehornstatic int 228192067Snwhitehornbare_smp_start_cpu(platform_t plat, struct pcpu *pc) 229192067Snwhitehorn{ 230192532Sraj#ifdef SMP 231192532Sraj uint32_t bptr, eebpcr; 232192532Sraj int timeout; 233192067Snwhitehorn 234192532Sraj eebpcr = ccsr_read4(OCP85XX_EEBPCR); 235192532Sraj if ((eebpcr & (pc->pc_cpumask << 24)) != 0) { 236192532Sraj printf("%s: CPU=%d already out of hold-off state!\n", 237192532Sraj __func__, pc->pc_cpuid); 238192532Sraj return (ENXIO); 239192532Sraj } 240192532Sraj 241192532Sraj ap_pcpu = pc; 242192532Sraj __asm __volatile("msync; isync"); 243192532Sraj 244192532Sraj /* 245192532Sraj * Set BPTR to the physical address of the boot page 246192532Sraj */ 247192532Sraj bptr = ((uint32_t)__boot_page - KERNBASE) + kernload; 248192532Sraj ccsr_write4(OCP85XX_BPTR, (bptr >> 12) | 0x80000000); 249192532Sraj 250192532Sraj /* 251192532Sraj * Release AP from hold-off state 252192532Sraj */ 253192532Sraj eebpcr |= (pc->pc_cpumask << 24); 254192532Sraj ccsr_write4(OCP85XX_EEBPCR, eebpcr); 255192532Sraj __asm __volatile("isync; msync"); 256192532Sraj 257192532Sraj timeout = 500; 258192532Sraj while (!pc->pc_awake && timeout--) 259192532Sraj DELAY(1000); /* wait 1ms */ 260192532Sraj 261192532Sraj return ((pc->pc_awake) ? 0 : EBUSY); 262192532Sraj#else 263192067Snwhitehorn /* No SMP support */ 264192067Snwhitehorn return (ENXIO); 265192532Sraj#endif 266192067Snwhitehorn} 267212054Snwhitehorn 268212054Snwhitehornstatic void 269212054Snwhitehorne500_reset(platform_t plat) 270212054Snwhitehorn{ 271212054Snwhitehorn uint32_t ver = SVR_VER(mfspr(SPR_SVR)); 272212054Snwhitehorn 273212054Snwhitehorn if (ver == SVR_MPC8572E || ver == SVR_MPC8572 || 274212054Snwhitehorn ver == SVR_MPC8548E || ver == SVR_MPC8548) 275212054Snwhitehorn /* Systems with dedicated reset register */ 276212054Snwhitehorn ccsr_write4(OCP85XX_RSTCR, 2); 277212054Snwhitehorn else { 278212054Snwhitehorn /* Clear DBCR0, disables debug interrupts and events. */ 279212054Snwhitehorn mtspr(SPR_DBCR0, 0); 280212054Snwhitehorn __asm __volatile("isync"); 281212054Snwhitehorn 282212054Snwhitehorn /* Enable Debug Interrupts in MSR. */ 283212054Snwhitehorn mtmsr(mfmsr() | PSL_DE); 284212054Snwhitehorn 285212054Snwhitehorn /* Enable debug interrupts and issue reset. */ 286212054Snwhitehorn mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | 287212054Snwhitehorn DBCR0_RST_SYSTEM); 288212054Snwhitehorn } 289212054Snwhitehorn 290212054Snwhitehorn printf("Reset failed...\n"); 291212054Snwhitehorn while (1); 292212054Snwhitehorn} 293212054Snwhitehorn 294