Home | History | Annotate | Line # | Download | only in bebox
      1 /*	$NetBSD: cpu.c,v 1.12 2012/10/20 14:53:37 kiyohara Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by NONAKA Kimihiro.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.12 2012/10/20 14:53:37 kiyohara Exp $");
     34 
     35 #include "opt_multiprocessor.h"
     36 
     37 #include <sys/param.h>
     38 #include <sys/bus.h>
     39 #include <sys/systm.h>
     40 #include <sys/device.h>
     41 
     42 #include <machine/autoconf.h>
     43 #include <machine/cpu.h>
     44 
     45 #include <powerpc/oea/hid.h>
     46 #include <powerpc/oea/spr.h>
     47 #include <powerpc/spr.h>
     48 
     49 #include <uvm/uvm.h>
     50 
     51 
     52 int cpumatch(device_t, cfdata_t, void *);
     53 void cpuattach(device_t, device_t, void *);
     54 
     55 CFATTACH_DECL_NEW(cpu, 0, cpumatch, cpuattach, NULL, NULL);
     56 
     57 extern struct cfdriver cpu_cd;
     58 
     59 int
     60 cpumatch(device_t parent, cfdata_t cfdata, void *aux)
     61 {
     62 	struct confargs *ca = aux;
     63 
     64 	if (strcmp(ca->ca_name, cpu_cd.cd_name) != 0)
     65 		return 0;
     66 	return 1;
     67 }
     68 
     69 void
     70 cpuattach(device_t parent, device_t self, void *aux)
     71 {
     72 	struct confargs *ca = aux;
     73 	struct cpu_info *ci;
     74 	int id = ca->ca_node;
     75 
     76 	ci = cpu_attach_common(self, id);
     77 	if (ci == NULL)
     78 		return;
     79 
     80 #ifdef MULTIPROCESSOR
     81 	if (id > 0)
     82 		cpu_spinup(self, ci);
     83 #endif
     84 }
     85 
     86 
     87 #ifdef MULTIPROCESSOR
     88 
     89 extern volatile u_int cpu_spinstart_ack, cpu_spinstart_cpunum;
     90 
     91 int
     92 md_setup_trampoline(volatile struct cpu_hatch_data *h, struct cpu_info *ci)
     93 {
     94 	int blocks, i;
     95 	extern void cache_flush_invalidate_all(int blocks);
     96 
     97 	/*
     98 	 * Our CPU(603e) supports control protocol for cache only MEI
     99 	 * (Modified/Exclusive/Invalid).  Flush dirty caches myself.
    100 	 */
    101 
    102 	h->hatch_running = -1;
    103 	cpu_spinstart_ack = -1;
    104 
    105 	/* Flush-invalidate all blocks */
    106 	blocks = curcpu()->ci_ci.dcache_size / curcpu()->ci_ci.dcache_line_size;
    107 	cache_flush_invalidate_all(blocks);
    108 
    109 	cpu_spinstart_cpunum = ci->ci_cpuid;
    110 	__asm volatile("dcbf 0,%0"::"r"(&cpu_spinstart_cpunum):"memory");
    111 
    112 	for (i = 0; i < 100000000; i++) {
    113 		if (cpu_spinstart_ack != -1)
    114 			break;
    115 		__asm volatile("dcbi 0,%0"::"r"(&cpu_spinstart_ack):"memory");
    116 		__asm volatile("sync; isync");
    117 	}
    118 	return 1;
    119 }
    120 
    121 void
    122 md_presync_timebase(volatile struct cpu_hatch_data *h)
    123 {
    124 	uint64_t tb;
    125 
    126 	/* Sync timebase. */
    127 	tb = mftb();
    128 	tb += 1000000;	/* 30ms @ 33MHz */
    129 
    130 	h->hatch_tbu = tb >> 32;
    131 	h->hatch_tbl = tb & 0xffffffff;
    132 
    133 	while (tb > mftb())
    134 		;
    135 
    136 	h->hatch_running = 0;
    137 
    138 	delay(500000);
    139 }
    140 
    141 void
    142 md_start_timebase(volatile struct cpu_hatch_data *h)
    143 {
    144 	/* Nothing */
    145 }
    146 
    147 void
    148 md_sync_timebase(volatile struct cpu_hatch_data *h)
    149 {
    150 	u_int tbu, tbl;
    151 
    152 	do {
    153 		__asm volatile("dcbi 0,%0"::"r"(&h->hatch_running):"memory");
    154 		__asm volatile("sync; isync");
    155 
    156 		__asm volatile("dcbst 0,%0"::"r"(&h->hatch_running):"memory");
    157 		__asm volatile("sync; isync");
    158 	} while (h->hatch_running == -1);
    159 
    160 	__asm volatile("dcbi 0,%0"::"r"(&h->hatch_tbu):"memory");
    161 	__asm volatile("dcbi 0,%0"::"r"(&h->hatch_tbl):"memory");
    162 	__asm volatile("sync; isync");
    163 	__asm volatile("dcbst 0,%0"::"r"(&h->hatch_tbu):"memory");
    164 	__asm volatile("dcbst 0,%0"::"r"(&h->hatch_tbl):"memory");
    165 	__asm volatile("sync; isync");
    166 
    167 	/* Sync timebase. */
    168 	tbu = h->hatch_tbu;
    169 	tbl = h->hatch_tbl;
    170 	__asm volatile ("sync; isync");
    171 	__asm volatile ("mttbl %0" :: "r"(0));
    172 	__asm volatile ("mttbu %0" :: "r"(tbu));
    173 	__asm volatile ("mttbl %0" :: "r"(tbl));
    174 }
    175 
    176 void
    177 md_setup_interrupts(void)
    178 {
    179 
    180 	CLEAR_BEBOX_REG(CPU1_INT_MASK, BEBOX_INTR_MASK);
    181 
    182 	/* XXXXXX: We can handle interrupts on CPU0 only now. */
    183 }
    184 
    185 #endif /* MULTIPROCESSOR */
    186