sb_scd.c revision 330897
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2009 Neelkanth Natu 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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h> 30__FBSDID("$FreeBSD: stable/11/sys/mips/sibyte/sb_scd.c 330897 2018-03-14 03:19:51Z eadler $"); 31 32#include <sys/param.h> 33#include <sys/kernel.h> 34#include <sys/systm.h> 35#include <sys/module.h> 36#include <sys/bus.h> 37#include <sys/cpuset.h> 38 39#include <machine/resource.h> 40#include <machine/hwfunc.h> 41 42#include "sb_scd.h" 43 44/* 45 * We compile a 32-bit kernel to run on the SB-1 processor which is a 64-bit 46 * processor. It has some registers that must be accessed using 64-bit load 47 * and store instructions. 48 * 49 * We use the mips_ld() and mips_sd() functions to do this for us. 50 */ 51#define sb_store64(addr, val) mips3_sd((uint64_t *)(uintptr_t)(addr), (val)) 52#define sb_load64(addr) mips3_ld((uint64_t *)(uintptr_t)(addr)) 53 54/* 55 * System Control and Debug (SCD) unit on the Sibyte ZBbus. 56 */ 57 58/* 59 * Extract the value starting at bit position 'b' for 'n' bits from 'x'. 60 */ 61#define GET_VAL_64(x, b, n) (((x) >> (b)) & ((1ULL << (n)) - 1)) 62 63#define SYSREV_ADDR MIPS_PHYS_TO_KSEG1(0x10020000) 64#define SYSREV_NUM_PROCESSORS(x) GET_VAL_64((x), 24, 4) 65 66#define SYSCFG_ADDR MIPS_PHYS_TO_KSEG1(0x10020008) 67#define SYSCFG_PLLDIV(x) GET_VAL_64((x), 7, 5) 68 69#define ZBBUS_CYCLE_COUNT_ADDR MIPS_PHYS_TO_KSEG1(0x10030000) 70 71#define INTSRC_MASK_ADDR(cpu) \ 72 (MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13)) 73 74#define INTSRC_MAP_ADDR(cpu, intsrc) \ 75 (MIPS_PHYS_TO_KSEG1(0x10020200) | ((cpu) << 13)) + (intsrc * 8) 76 77#define MAILBOX_SET_ADDR(cpu) \ 78 (MIPS_PHYS_TO_KSEG1(0x100200C8) | ((cpu) << 13)) 79 80#define MAILBOX_CLEAR_ADDR(cpu) \ 81 (MIPS_PHYS_TO_KSEG1(0x100200D0) | ((cpu) << 13)) 82 83static uint64_t 84sb_read_syscfg(void) 85{ 86 87 return (sb_load64(SYSCFG_ADDR)); 88} 89 90static void 91sb_write_syscfg(uint64_t val) 92{ 93 94 sb_store64(SYSCFG_ADDR, val); 95} 96 97uint64_t 98sb_zbbus_cycle_count(void) 99{ 100 101 return (sb_load64(ZBBUS_CYCLE_COUNT_ADDR)); 102} 103 104uint64_t 105sb_cpu_speed(void) 106{ 107 int plldiv; 108 const uint64_t MHZ = 1000000; 109 110 plldiv = SYSCFG_PLLDIV(sb_read_syscfg()); 111 if (plldiv == 0) { 112 printf("PLL_DIV is 0 - assuming 6 (300MHz).\n"); 113 plldiv = 6; 114 } 115 116 return (plldiv * 50 * MHZ); 117} 118 119void 120sb_system_reset(void) 121{ 122 uint64_t syscfg; 123 124 const uint64_t SYSTEM_RESET = 1ULL << 60; 125 const uint64_t EXT_RESET = 1ULL << 59; 126 const uint64_t SOFT_RESET = 1ULL << 58; 127 128 syscfg = sb_read_syscfg(); 129 syscfg &= ~SOFT_RESET; 130 syscfg |= SYSTEM_RESET | EXT_RESET; 131 sb_write_syscfg(syscfg); 132} 133 134void 135sb_disable_intsrc(int cpu, int src) 136{ 137 int regaddr; 138 uint64_t val; 139 140 regaddr = INTSRC_MASK_ADDR(cpu); 141 142 val = sb_load64(regaddr); 143 val |= 1ULL << src; 144 sb_store64(regaddr, val); 145} 146 147void 148sb_enable_intsrc(int cpu, int src) 149{ 150 int regaddr; 151 uint64_t val; 152 153 regaddr = INTSRC_MASK_ADDR(cpu); 154 155 val = sb_load64(regaddr); 156 val &= ~(1ULL << src); 157 sb_store64(regaddr, val); 158} 159 160void 161sb_write_intsrc_mask(int cpu, uint64_t val) 162{ 163 int regaddr; 164 165 regaddr = INTSRC_MASK_ADDR(cpu); 166 sb_store64(regaddr, val); 167} 168 169uint64_t 170sb_read_intsrc_mask(int cpu) 171{ 172 int regaddr; 173 uint64_t val; 174 175 regaddr = INTSRC_MASK_ADDR(cpu); 176 val = sb_load64(regaddr); 177 178 return (val); 179} 180 181void 182sb_write_intmap(int cpu, int intsrc, int intrnum) 183{ 184 int regaddr; 185 186 regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 187 sb_store64(regaddr, intrnum); 188} 189 190int 191sb_read_intmap(int cpu, int intsrc) 192{ 193 int regaddr; 194 195 regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 196 return (sb_load64(regaddr) & 0x7); 197} 198 199int 200sb_route_intsrc(int intsrc) 201{ 202 int intrnum; 203 204 KASSERT(intsrc >= 0 && intsrc < NUM_INTSRC, 205 ("Invalid interrupt source number (%d)", intsrc)); 206 207 /* 208 * Interrupt 5 is used by sources internal to the CPU (e.g. timer). 209 * Use a deterministic mapping for the remaining sources. 210 */ 211#ifdef SMP 212 KASSERT(platform_ipi_intrnum() == 4, 213 ("Unexpected interrupt number used for IPI")); 214 intrnum = intsrc % 4; 215#else 216 intrnum = intsrc % 5; 217#endif 218 219 return (intrnum); 220} 221 222#ifdef SMP 223static uint64_t 224sb_read_sysrev(void) 225{ 226 227 return (sb_load64(SYSREV_ADDR)); 228} 229 230void 231sb_set_mailbox(int cpu, uint64_t val) 232{ 233 int regaddr; 234 235 regaddr = MAILBOX_SET_ADDR(cpu); 236 sb_store64(regaddr, val); 237} 238 239void 240sb_clear_mailbox(int cpu, uint64_t val) 241{ 242 int regaddr; 243 244 regaddr = MAILBOX_CLEAR_ADDR(cpu); 245 sb_store64(regaddr, val); 246} 247 248void 249platform_cpu_mask(cpuset_t *mask) 250{ 251 int i, s; 252 253 CPU_ZERO(mask); 254 s = SYSREV_NUM_PROCESSORS(sb_read_sysrev()); 255 for (i = 0; i < s; i++) 256 CPU_SET(i, mask); 257} 258#endif /* SMP */ 259 260#define SCD_PHYSADDR 0x10000000 261#define SCD_SIZE 0x00060000 262 263static int 264scd_probe(device_t dev) 265{ 266 267 device_set_desc(dev, "Broadcom/Sibyte System Control and Debug"); 268 return (0); 269} 270 271static int 272scd_attach(device_t dev) 273{ 274 int rid; 275 struct resource *res; 276 277 if (bootverbose) 278 device_printf(dev, "attached.\n"); 279 280 rid = 0; 281 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SCD_PHYSADDR, 282 SCD_PHYSADDR + SCD_SIZE - 1, SCD_SIZE, 0); 283 if (res == NULL) 284 panic("Cannot allocate resource for system control and debug."); 285 286 return (0); 287} 288 289static device_method_t scd_methods[] ={ 290 /* Device interface */ 291 DEVMETHOD(device_probe, scd_probe), 292 DEVMETHOD(device_attach, scd_attach), 293 DEVMETHOD(device_detach, bus_generic_detach), 294 DEVMETHOD(device_shutdown, bus_generic_shutdown), 295 DEVMETHOD(device_suspend, bus_generic_suspend), 296 DEVMETHOD(device_resume, bus_generic_resume), 297 298 { 0, 0 } 299}; 300 301static driver_t scd_driver = { 302 "scd", 303 scd_methods 304}; 305 306static devclass_t scd_devclass; 307 308DRIVER_MODULE(scd, zbbus, scd_driver, scd_devclass, 0, 0); 309