sb_scd.c revision 256281
172317Sphantom/*- 272317Sphantom * Copyright (c) 2009 Neelkanth Natu 372317Sphantom * All rights reserved. 472317Sphantom * 572317Sphantom * Redistribution and use in source and binary forms, with or without 672317Sphantom * modification, are permitted provided that the following conditions 772317Sphantom * are met: 872317Sphantom * 1. Redistributions of source code must retain the above copyright 972317Sphantom * notice, this list of conditions and the following disclaimer. 1072317Sphantom * 2. Redistributions in binary form must reproduce the above copyright 11136496Skeramida * notice, this list of conditions and the following disclaimer in the 1272317Sphantom * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/10/sys/mips/sibyte/sb_scd.c 222813 2011-06-07 08:46:13Z attilio $"); 29 30#include <sys/param.h> 31#include <sys/kernel.h> 32#include <sys/systm.h> 33#include <sys/module.h> 34#include <sys/bus.h> 35#include <sys/cpuset.h> 36 37#include <machine/resource.h> 38#include <machine/hwfunc.h> 39 40#include "sb_scd.h" 41 42/* 43 * We compile a 32-bit kernel to run on the SB-1 processor which is a 64-bit 44 * processor. It has some registers that must be accessed using 64-bit load 45 * and store instructions. 46 * 47 * We use the mips_ld() and mips_sd() functions to do this for us. 48 */ 49#define sb_store64(addr, val) mips3_sd((uint64_t *)(uintptr_t)(addr), (val)) 50#define sb_load64(addr) mips3_ld((uint64_t *)(uintptr_t)(addr)) 51 52/* 53 * System Control and Debug (SCD) unit on the Sibyte ZBbus. 54 */ 55 56/* 57 * Extract the value starting at bit position 'b' for 'n' bits from 'x'. 58 */ 59#define GET_VAL_64(x, b, n) (((x) >> (b)) & ((1ULL << (n)) - 1)) 60 61#define SYSREV_ADDR MIPS_PHYS_TO_KSEG1(0x10020000) 62#define SYSREV_NUM_PROCESSORS(x) GET_VAL_64((x), 24, 4) 63 64#define SYSCFG_ADDR MIPS_PHYS_TO_KSEG1(0x10020008) 65#define SYSCFG_PLLDIV(x) GET_VAL_64((x), 7, 5) 66 67#define ZBBUS_CYCLE_COUNT_ADDR MIPS_PHYS_TO_KSEG1(0x10030000) 68 69#define INTSRC_MASK_ADDR(cpu) \ 70 (MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13)) 71 72#define INTSRC_MAP_ADDR(cpu, intsrc) \ 73 (MIPS_PHYS_TO_KSEG1(0x10020200) | ((cpu) << 13)) + (intsrc * 8) 74 75#define MAILBOX_SET_ADDR(cpu) \ 76 (MIPS_PHYS_TO_KSEG1(0x100200C8) | ((cpu) << 13)) 77 78#define MAILBOX_CLEAR_ADDR(cpu) \ 79 (MIPS_PHYS_TO_KSEG1(0x100200D0) | ((cpu) << 13)) 80 81static uint64_t 82sb_read_syscfg(void) 83{ 84 85 return (sb_load64(SYSCFG_ADDR)); 86} 87 88static void 89sb_write_syscfg(uint64_t val) 90{ 91 92 sb_store64(SYSCFG_ADDR, val); 93} 94 95uint64_t 96sb_zbbus_cycle_count(void) 97{ 98 99 return (sb_load64(ZBBUS_CYCLE_COUNT_ADDR)); 100} 101 102uint64_t 103sb_cpu_speed(void) 104{ 105 int plldiv; 106 const uint64_t MHZ = 1000000; 107 108 plldiv = SYSCFG_PLLDIV(sb_read_syscfg()); 109 if (plldiv == 0) { 110 printf("PLL_DIV is 0 - assuming 6 (300MHz).\n"); 111 plldiv = 6; 112 } 113 114 return (plldiv * 50 * MHZ); 115} 116 117void 118sb_system_reset(void) 119{ 120 uint64_t syscfg; 121 122 const uint64_t SYSTEM_RESET = 1ULL << 60; 123 const uint64_t EXT_RESET = 1ULL << 59; 124 const uint64_t SOFT_RESET = 1ULL << 58; 125 126 syscfg = sb_read_syscfg(); 127 syscfg &= ~SOFT_RESET; 128 syscfg |= SYSTEM_RESET | EXT_RESET; 129 sb_write_syscfg(syscfg); 130} 131 132void 133sb_disable_intsrc(int cpu, int src) 134{ 135 int regaddr; 136 uint64_t val; 137 138 regaddr = INTSRC_MASK_ADDR(cpu); 139 140 val = sb_load64(regaddr); 141 val |= 1ULL << src; 142 sb_store64(regaddr, val); 143} 144 145void 146sb_enable_intsrc(int cpu, int src) 147{ 148 int regaddr; 149 uint64_t val; 150 151 regaddr = INTSRC_MASK_ADDR(cpu); 152 153 val = sb_load64(regaddr); 154 val &= ~(1ULL << src); 155 sb_store64(regaddr, val); 156} 157 158void 159sb_write_intsrc_mask(int cpu, uint64_t val) 160{ 161 int regaddr; 162 163 regaddr = INTSRC_MASK_ADDR(cpu); 164 sb_store64(regaddr, val); 165} 166 167uint64_t 168sb_read_intsrc_mask(int cpu) 169{ 170 int regaddr; 171 uint64_t val; 172 173 regaddr = INTSRC_MASK_ADDR(cpu); 174 val = sb_load64(regaddr); 175 176 return (val); 177} 178 179void 180sb_write_intmap(int cpu, int intsrc, int intrnum) 181{ 182 int regaddr; 183 184 regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 185 sb_store64(regaddr, intrnum); 186} 187 188int 189sb_read_intmap(int cpu, int intsrc) 190{ 191 int regaddr; 192 193 regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 194 return (sb_load64(regaddr) & 0x7); 195} 196 197int 198sb_route_intsrc(int intsrc) 199{ 200 int intrnum; 201 202 KASSERT(intsrc >= 0 && intsrc < NUM_INTSRC, 203 ("Invalid interrupt source number (%d)", intsrc)); 204 205 /* 206 * Interrupt 5 is used by sources internal to the CPU (e.g. timer). 207 * Use a deterministic mapping for the remaining sources. 208 */ 209#ifdef SMP 210 KASSERT(platform_ipi_intrnum() == 4, 211 ("Unexpected interrupt number used for IPI")); 212 intrnum = intsrc % 4; 213#else 214 intrnum = intsrc % 5; 215#endif 216 217 return (intrnum); 218} 219 220#ifdef SMP 221static uint64_t 222sb_read_sysrev(void) 223{ 224 225 return (sb_load64(SYSREV_ADDR)); 226} 227 228void 229sb_set_mailbox(int cpu, uint64_t val) 230{ 231 int regaddr; 232 233 regaddr = MAILBOX_SET_ADDR(cpu); 234 sb_store64(regaddr, val); 235} 236 237void 238sb_clear_mailbox(int cpu, uint64_t val) 239{ 240 int regaddr; 241 242 regaddr = MAILBOX_CLEAR_ADDR(cpu); 243 sb_store64(regaddr, val); 244} 245 246void 247platform_cpu_mask(cpuset_t *mask) 248{ 249 int i, s; 250 251 CPU_ZERO(mask); 252 s = SYSREV_NUM_PROCESSORS(sb_read_sysrev()); 253 for (i = 0; i < s; i++) 254 CPU_SET(i, mask); 255} 256#endif /* SMP */ 257 258#define SCD_PHYSADDR 0x10000000 259#define SCD_SIZE 0x00060000 260 261static int 262scd_probe(device_t dev) 263{ 264 265 device_set_desc(dev, "Broadcom/Sibyte System Control and Debug"); 266 return (0); 267} 268 269static int 270scd_attach(device_t dev) 271{ 272 int rid; 273 struct resource *res; 274 275 if (bootverbose) 276 device_printf(dev, "attached.\n"); 277 278 rid = 0; 279 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SCD_PHYSADDR, 280 SCD_PHYSADDR + SCD_SIZE - 1, SCD_SIZE, 0); 281 if (res == NULL) 282 panic("Cannot allocate resource for system control and debug."); 283 284 return (0); 285} 286 287static device_method_t scd_methods[] ={ 288 /* Device interface */ 289 DEVMETHOD(device_probe, scd_probe), 290 DEVMETHOD(device_attach, scd_attach), 291 DEVMETHOD(device_detach, bus_generic_detach), 292 DEVMETHOD(device_shutdown, bus_generic_shutdown), 293 DEVMETHOD(device_suspend, bus_generic_suspend), 294 DEVMETHOD(device_resume, bus_generic_resume), 295 296 { 0, 0 } 297}; 298 299static driver_t scd_driver = { 300 "scd", 301 scd_methods 302}; 303 304static devclass_t scd_devclass; 305 306DRIVER_MODULE(scd, zbbus, scd_driver, scd_devclass, 0, 0); 307