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