1/* $NetBSD: locore_octeon.S,v 1.10 2016/07/27 09:32:35 skrll Exp $ */ 2 3/* 4 * Copyright (c) 2007 Internet Initiative Japan, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <mips/asm.h> 30RCSID("$NetBSD: locore_octeon.S,v 1.10 2016/07/27 09:32:35 skrll Exp $") 31 32#include "cpunode.h" /* for NWDOG */ 33#include "opt_cputype.h" 34#include "opt_ddb.h" 35#include "opt_multiprocessor.h" 36 37#include <mips/cpuregs.h> 38#include <arch/mips/cavium/dev/octeon_corereg.h> 39 40RCSID("$NetBSD: locore_octeon.S,v 1.10 2016/07/27 09:32:35 skrll Exp $") 41 42#include "assym.h" 43 44#define _CP0_READ64(_cp0) \ 45 dmfc0 v0, _cp0; \ 46 j ra; \ 47 nop 48 49#define _CP0_WRITE64(_cp0) \ 50 dmtc0 a0, _cp0; \ 51 j ra; \ 52 nop 53 54 .set noreorder 55 .set noat 56 .set arch=octeon 57 58 .text 59 60LEAF(mips_cp0_cvmctl_read) 61 _CP0_READ64(CP0_CVMCTL) 62END(mips_cp0_cvmctl_read) 63 64LEAF(mips_cp0_cvmctl_write) 65 _CP0_WRITE64(CP0_CVMCTL) 66END(mips_cp0_cvmctl_write) 67 68LEAF(mips_cp0_cvmmemctl_read) 69 _CP0_READ64(CP0_CVMMEMCTL) 70END(mips_cp0_cvmmemctl_read) 71 72LEAF(mips_cp0_cvmmemctl_write) 73 _CP0_WRITE64(CP0_CVMMEMCTL) 74END(mips_cp0_cvmmemctl_write) 75 76LEAF(mips_cp0_cvmcnt_read) 77 _CP0_READ64(CP0_CVMCNT) 78END(mips_cp0_cvmcnt_read) 79 80LEAF(mips_cp0_cvmcnt_write) 81 _CP0_WRITE64(CP0_CVMCNT) 82END(mips_cp0_cvmcnt_write) 83 84LEAF(mips_cp0_performance_counter_control0_read) 85 _CP0_READ64(CP0_PCCTL) 86END(mips_cp0_performance_counter_control0_read) 87 88LEAF(mips_cp0_performance_counter_control0_write) 89 _CP0_WRITE64(CP0_PCCTL) 90END(mips_cp0_performance_counter_control0_write) 91 92LEAF(mips_cp0_performance_counter_control1_read) 93 _CP0_READ64(CP0_PCCTL1) 94END(mips_cp0_performance_counter_control1_read) 95 96LEAF(mips_cp0_performance_counter_control1_write) 97 _CP0_WRITE64(CP0_PCCTL1) 98END(mips_cp0_performance_counter_control1_write) 99 100LEAF(mips_cp0_performance_counter_counter0_read) 101 _CP0_READ64(CP0_PCCNT) 102END(mips_cp0_performance_counter_counter0_read) 103 104LEAF(mips_cp0_performance_counter_counter0_write) 105 _CP0_WRITE64(CP0_PCCNT) 106END(mips_cp0_performance_counter_counter0_write) 107 108LEAF(mips_cp0_performance_counter_counter1_read) 109 _CP0_READ64(CP0_PCCNT1) 110END(mips_cp0_performance_counter_counter1_read) 111 112LEAF(mips_cp0_performance_counter_counter1_write) 113 _CP0_WRITE64(CP0_PCCNT1) 114END(mips_cp0_performance_counter_counter1_write) 115 116#ifdef MULTIPROCESSOR 117 118NESTED_NOPROFILE(octeon_cpu_spinup, 0, ra) 119 // 120 // Since the OCTEON cpus doesn't a COP0 OSCONTEXT register, each core 121 // must has its own exception vector page. The exceptions will be 122 // modified to refer to that CPU's cpu_info structure. 123 // 124 mfc0 s1, MIPS_COP_0_EBASE # get EBASE 125 ext s0, s1, 0, 10 # fetch cpunum (MIPSNNR2) 126 ins s1, zero, 0, 10 # clear it (MIPSNNR2) 127 ins s1, s0, 12, 10 # insert cpunum as exception address 128 ehb 129 mtc0 s1, MIPS_COP_0_EBASE # set EBASE 130 COP0_SYNC 131 132 // we only can deal with 2 cores 133 li v0, 1 134 beq s0, v0, 2f 135 nop 136 // spin if this isn't cpu 1 1371: wait 138 b 1b 139 nop 140 141 // Indicate this CPU was started by u-boot 1422: PTR_LA t0, _C_LABEL(cpus_booted) # get addr for kcpuset 1433: sync 144 PTR_L a0, (t0) # get kcpuset 145 beqz a0, 3b # loop until not NULL 146 nop 147 jal _C_LABEL(kcpuset_atomic_set) 148 move a1, s0 # pass it our cpu number 149 150 // Wait until cpuid_infos[cpunum] is not NULL. 151 PTR_LA a1, _C_LABEL(cpuid_infos) 152 dsll v0, s0, PTR_SCALESHIFT # cpunum -> array index 153 PTR_ADD t0, a1, v0 # add to array start 1544: sync 155 PTR_L a1, (t0) # get cpu_info pointer 156 beqz a1, 4b # loop until non-NULL 157 nop 158 159 j _C_LABEL(cpu_trampoline) 160 nop 161END(octeon_cpu_spinup) 162#endif /* MULTIPROCESSOR */ 163 164#if NWDOG > 0 || defined(DDB) 165 166#define UINT64_C(x) (x) 167 168#include <mips/cavium/dev/octeon_ciureg.h> 169 170NESTED_NOPROFILE(octeon_reset_vector, 0, ra) 171 mfc0 k0, MIPS_COP_0_STATUS # get cp0 status 172 bbit1 k0, V_MIPS3_SR_SR, 1f # MIPS3_SR_SR 173 ins k0, zero, V_MIPS_SR_BEV, 1 # clear boot exception vectors 174 mtc0 k0, MIPS_COP_0_STATUS # write cp0 status 175 ehb # hazard barrier 176#ifdef MULTIPROCESSOR 177 mfc0 k0, MIPS_COP_0_EBASE # get EBASE 178 ext k0, k0, 0, 10 # select cpunum 179 dsll k0, k0, PTR_SCALESHIFT # cpunum -> array index 180 PTR_LA k1, _C_LABEL(cpuid_infos) 181 PTR_ADDU k1, k1, k0 # add to array start 182 PTR_L k0, (k1) # get cpu_info 183#else 184 PTR_LA k0, _C_LABEL(cpu_info_store) # get cpu_info 185#endif 186 j _C_LABEL(mips64r2_kern_nonmaskable_intr) 187 sd zero, CIU_NMI_OFFSET(k1)# clear NMI 1881: 189 li k1, ((MIPS_XKPHYS_START|CIU_BASE) >> 32) # CIU base (MSW) 190 dsll k1, 32 # shift it place 191 ld k0, CIU_FUSE_OFFSET(k1) # get mask of CPUs 192 sd k0, CIU_SOFT_RST_OFFSET(k1) # reset them 193 ld v0, CIU_SOFT_RST_OFFSET(k1) # force a load 194 sd k0, CIU_SOFT_RST_OFFSET(k1) # do it again. 1952: 196 wait # wait forever 197 b 2b # and loop until reset 198 nop 199END(octeon_reset_vector) 200#endif 201