platform_bare.c revision 193492
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 193492 2009-06-05 09:46:00Z raj $"); 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/bootinfo.h> 39192067Snwhitehorn#include <machine/bus.h> 40192067Snwhitehorn#include <machine/cpu.h> 41192067Snwhitehorn#include <machine/hid.h> 42192067Snwhitehorn#include <machine/platform.h> 43192067Snwhitehorn#include <machine/platformvar.h> 44192067Snwhitehorn#include <machine/smp.h> 45192067Snwhitehorn#include <machine/spr.h> 46192067Snwhitehorn#include <machine/vmparam.h> 47192067Snwhitehorn 48192067Snwhitehorn#include <powerpc/mpc85xx/mpc85xx.h> 49192067Snwhitehorn#include <powerpc/mpc85xx/ocpbus.h> 50192067Snwhitehorn 51192067Snwhitehorn#include "platform_if.h" 52192067Snwhitehorn 53192532Sraj#ifdef SMP 54192532Srajextern void *ap_pcpu; 55192532Srajextern uint8_t __boot_page[]; /* Boot page body */ 56192532Srajextern uint32_t kernload; /* Kernel physical load address */ 57192532Sraj#endif 58192532Sraj 59193492Srajstatic int cpu, maxcpu; 60192067Snwhitehorn 61192067Snwhitehornstatic int bare_probe(platform_t); 62192067Snwhitehornstatic void bare_mem_regions(platform_t, struct mem_region **phys, int *physsz, 63192067Snwhitehorn struct mem_region **avail, int *availsz); 64192067Snwhitehornstatic u_long bare_timebase_freq(platform_t, struct cpuref *cpuref); 65192067Snwhitehornstatic int bare_smp_first_cpu(platform_t, struct cpuref *cpuref); 66192067Snwhitehornstatic int bare_smp_next_cpu(platform_t, struct cpuref *cpuref); 67192067Snwhitehornstatic int bare_smp_get_bsp(platform_t, struct cpuref *cpuref); 68192067Snwhitehornstatic int bare_smp_start_cpu(platform_t, struct pcpu *cpu); 69192067Snwhitehorn 70192067Snwhitehornstatic platform_method_t bare_methods[] = { 71192067Snwhitehorn PLATFORMMETHOD(platform_probe, bare_probe), 72192067Snwhitehorn PLATFORMMETHOD(platform_mem_regions, bare_mem_regions), 73192067Snwhitehorn PLATFORMMETHOD(platform_timebase_freq, bare_timebase_freq), 74192067Snwhitehorn 75192067Snwhitehorn PLATFORMMETHOD(platform_smp_first_cpu, bare_smp_first_cpu), 76192067Snwhitehorn PLATFORMMETHOD(platform_smp_next_cpu, bare_smp_next_cpu), 77192067Snwhitehorn PLATFORMMETHOD(platform_smp_get_bsp, bare_smp_get_bsp), 78192067Snwhitehorn PLATFORMMETHOD(platform_smp_start_cpu, bare_smp_start_cpu), 79192067Snwhitehorn 80192067Snwhitehorn { 0, 0 } 81192067Snwhitehorn}; 82192067Snwhitehorn 83192067Snwhitehornstatic platform_def_t bare_platform = { 84192067Snwhitehorn "bare metal", 85192067Snwhitehorn bare_methods, 86192067Snwhitehorn 0 87192067Snwhitehorn}; 88192067Snwhitehorn 89192067SnwhitehornPLATFORM_DEF(bare_platform); 90192067Snwhitehorn 91192067Snwhitehornstatic int 92192067Snwhitehornbare_probe(platform_t plat) 93192067Snwhitehorn{ 94193492Sraj uint32_t ver; 95192067Snwhitehorn 96193492Sraj ver = SVR_VER(mfspr(SPR_SVR)); 97193492Sraj if (ver == SVR_MPC8572E || ver == SVR_MPC8572) 98193492Sraj maxcpu = 2; 99193492Sraj else 100193492Sraj maxcpu = 1; 101193492Sraj 102192067Snwhitehorn return (BUS_PROBE_GENERIC); 103192067Snwhitehorn} 104192067Snwhitehorn 105192067Snwhitehorn#define MEM_REGIONS 8 106192067Snwhitehornstatic struct mem_region avail_regions[MEM_REGIONS]; 107192067Snwhitehorn 108192067Snwhitehornvoid 109192067Snwhitehornbare_mem_regions(platform_t plat, struct mem_region **phys, int *physsz, 110192067Snwhitehorn struct mem_region **avail, int *availsz) 111192067Snwhitehorn{ 112192067Snwhitehorn struct bi_mem_region *mr; 113192067Snwhitehorn int i; 114192067Snwhitehorn 115192067Snwhitehorn /* Initialize memory regions table */ 116192067Snwhitehorn mr = bootinfo_mr(); 117192067Snwhitehorn for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++) { 118192067Snwhitehorn if (i == MEM_REGIONS) 119192067Snwhitehorn break; 120192067Snwhitehorn if (mr->mem_base < 1048576) { 121192067Snwhitehorn avail_regions[i].mr_start = 1048576; 122192067Snwhitehorn avail_regions[i].mr_size = mr->mem_size - 123192067Snwhitehorn (1048576 - mr->mem_base); 124192067Snwhitehorn } else { 125192067Snwhitehorn avail_regions[i].mr_start = mr->mem_base; 126192067Snwhitehorn avail_regions[i].mr_size = mr->mem_size; 127192067Snwhitehorn } 128192067Snwhitehorn } 129192067Snwhitehorn *availsz = i; 130192067Snwhitehorn *avail = avail_regions; 131192067Snwhitehorn 132192067Snwhitehorn /* On the bare metal platform phys == avail memory */ 133192067Snwhitehorn *physsz = *availsz; 134192067Snwhitehorn *phys = *avail; 135192067Snwhitehorn} 136192067Snwhitehorn 137192067Snwhitehornstatic u_long 138192067Snwhitehornbare_timebase_freq(platform_t plat, struct cpuref *cpuref) 139192067Snwhitehorn{ 140192067Snwhitehorn u_long ticks = -1; 141192067Snwhitehorn 142192067Snwhitehorn /* 143192067Snwhitehorn * Time Base and Decrementer are updated every 8 CCB bus clocks. 144192067Snwhitehorn * HID0[SEL_TBCLK] = 0 145192067Snwhitehorn */ 146192067Snwhitehorn ticks = bootinfo->bi_bus_clk / 8; 147192067Snwhitehorn if (ticks <= 0) 148192067Snwhitehorn panic("Unable to determine timebase frequency!"); 149192067Snwhitehorn 150192067Snwhitehorn return (ticks); 151192067Snwhitehorn} 152192067Snwhitehorn 153192067Snwhitehornstatic int 154192067Snwhitehornbare_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 155192067Snwhitehorn{ 156192067Snwhitehorn 157192067Snwhitehorn cpu = 0; 158192067Snwhitehorn cpuref->cr_cpuid = cpu; 159192067Snwhitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 160192067Snwhitehorn if (bootverbose) 161192067Snwhitehorn printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid); 162192067Snwhitehorn cpu++; 163192067Snwhitehorn 164192067Snwhitehorn return (0); 165192067Snwhitehorn} 166192067Snwhitehorn 167192067Snwhitehornstatic int 168192067Snwhitehornbare_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 169192067Snwhitehorn{ 170192067Snwhitehorn 171193492Sraj if (cpu >= maxcpu) 172192067Snwhitehorn return (ENOENT); 173192067Snwhitehorn 174192067Snwhitehorn cpuref->cr_cpuid = cpu++; 175192067Snwhitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 176192067Snwhitehorn if (bootverbose) 177192067Snwhitehorn printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid); 178192067Snwhitehorn 179192067Snwhitehorn return (0); 180192067Snwhitehorn} 181192067Snwhitehorn 182192067Snwhitehornstatic int 183192067Snwhitehornbare_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 184192067Snwhitehorn{ 185192067Snwhitehorn 186192067Snwhitehorn cpuref->cr_cpuid = mfspr(SPR_PIR); 187192067Snwhitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 188192067Snwhitehorn 189192067Snwhitehorn return (0); 190192067Snwhitehorn} 191192067Snwhitehorn 192192067Snwhitehornstatic int 193192067Snwhitehornbare_smp_start_cpu(platform_t plat, struct pcpu *pc) 194192067Snwhitehorn{ 195192532Sraj#ifdef SMP 196192532Sraj uint32_t bptr, eebpcr; 197192532Sraj int timeout; 198192067Snwhitehorn 199192532Sraj eebpcr = ccsr_read4(OCP85XX_EEBPCR); 200192532Sraj if ((eebpcr & (pc->pc_cpumask << 24)) != 0) { 201192532Sraj printf("%s: CPU=%d already out of hold-off state!\n", 202192532Sraj __func__, pc->pc_cpuid); 203192532Sraj return (ENXIO); 204192532Sraj } 205192532Sraj 206192532Sraj ap_pcpu = pc; 207192532Sraj __asm __volatile("msync; isync"); 208192532Sraj 209192532Sraj /* 210192532Sraj * Set BPTR to the physical address of the boot page 211192532Sraj */ 212192532Sraj bptr = ((uint32_t)__boot_page - KERNBASE) + kernload; 213192532Sraj ccsr_write4(OCP85XX_BPTR, (bptr >> 12) | 0x80000000); 214192532Sraj 215192532Sraj /* 216192532Sraj * Release AP from hold-off state 217192532Sraj */ 218192532Sraj eebpcr |= (pc->pc_cpumask << 24); 219192532Sraj ccsr_write4(OCP85XX_EEBPCR, eebpcr); 220192532Sraj __asm __volatile("isync; msync"); 221192532Sraj 222192532Sraj timeout = 500; 223192532Sraj while (!pc->pc_awake && timeout--) 224192532Sraj DELAY(1000); /* wait 1ms */ 225192532Sraj 226192532Sraj return ((pc->pc_awake) ? 0 : EBUSY); 227192532Sraj#else 228192067Snwhitehorn /* No SMP support */ 229192067Snwhitehorn return (ENXIO); 230192532Sraj#endif 231192067Snwhitehorn} 232