sb_scd.c revision 203509
11573Srgrimes/*- 21573Srgrimes * Copyright (c) 2009 Neelkanth Natu 31573Srgrimes * All rights reserved. 41573Srgrimes * 51573Srgrimes * Redistribution and use in source and binary forms, with or without 61573Srgrimes * modification, are permitted provided that the following conditions 71573Srgrimes * are met: 81573Srgrimes * 1. Redistributions of source code must retain the above copyright 91573Srgrimes * notice, this list of conditions and the following disclaimer. 101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111573Srgrimes * notice, this list of conditions and the following disclaimer in the 121573Srgrimes * documentation and/or other materials provided with the distribution. 131573Srgrimes * 141573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241573Srgrimes * SUCH DAMAGE. 251573Srgrimes */ 261573Srgrimes 271573Srgrimes#include <sys/cdefs.h> 281573Srgrimes__FBSDID("$FreeBSD: head/sys/mips/sibyte/sb_scd.c 203509 2010-02-05 03:20:47Z neel $"); 291573Srgrimes 301573Srgrimes#include <sys/param.h> 311573Srgrimes#include <sys/kernel.h> 321573Srgrimes#include <sys/systm.h> 331573Srgrimes#include <sys/module.h> 341573Srgrimes#include <sys/bus.h> 351573Srgrimes 361573Srgrimes#include <machine/resource.h> 371573Srgrimes#include <machine/intr_machdep.h> 381573Srgrimes 391573Srgrimes#include "sb_scd.h" 401573Srgrimes 411573Srgrimesextern void sb_store64(uint32_t addr, uint64_t val); 421573Srgrimesextern uint64_t sb_load64(uint32_t addr); 431573Srgrimes 441573Srgrimes/* 4535125Sjb * System Control and Debug (SCD) unit on the Sibyte ZBbus. 4635125Sjb */ 4735125Sjb 4835125Sjb/* 4935125Sjb * Extract the value starting at bit position 'b' for 'n' bits from 'x'. 5035125Sjb */ 5135125Sjb#define GET_VAL_64(x, b, n) (((x) >> (b)) & ((1ULL << (n)) - 1)) 5235125Sjb 5335125Sjb#define SYSREV_ADDR MIPS_PHYS_TO_KSEG1(0x10020000) 541573Srgrimes#define SYSREV_NUM_PROCESSORS(x) GET_VAL_64((x), 24, 4) 551573Srgrimes 561573Srgrimes#define SYSCFG_ADDR MIPS_PHYS_TO_KSEG1(0x10020008) 571573Srgrimes#define SYSCFG_PLLDIV(x) GET_VAL_64((x), 7, 5) 581573Srgrimes 591573Srgrimes#define INTSRC_MASK_ADDR(cpu) \ 601573Srgrimes (MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13)) 611573Srgrimes 621573Srgrimes#define INTSRC_MAP_ADDR(cpu, intsrc) \ 631573Srgrimes (MIPS_PHYS_TO_KSEG1(0x10020200) | ((cpu) << 13)) + (intsrc * 8) 641573Srgrimes 651573Srgrimes#define MAILBOX_SET_ADDR(cpu) \ 661573Srgrimes (MIPS_PHYS_TO_KSEG1(0x100200C8) | ((cpu) << 13)) 671573Srgrimes 681573Srgrimes#define MAILBOX_CLEAR_ADDR(cpu) \ 691573Srgrimes (MIPS_PHYS_TO_KSEG1(0x100200D0) | ((cpu) << 13)) 70 71static uint64_t 72sb_read_syscfg(void) 73{ 74 75 return (sb_load64(SYSCFG_ADDR)); 76} 77 78static void 79sb_write_syscfg(uint64_t val) 80{ 81 82 sb_store64(SYSCFG_ADDR, val); 83} 84 85uint64_t 86sb_cpu_speed(void) 87{ 88 int plldiv; 89 const uint64_t MHZ = 1000000; 90 91 plldiv = SYSCFG_PLLDIV(sb_read_syscfg()); 92 if (plldiv == 0) { 93 printf("PLL_DIV is 0 - assuming 6 (300MHz).\n"); 94 plldiv = 6; 95 } 96 97 return (plldiv * 50 * MHZ); 98} 99 100void 101sb_system_reset(void) 102{ 103 uint64_t syscfg; 104 105 const uint64_t SYSTEM_RESET = 1ULL << 60; 106 const uint64_t EXT_RESET = 1ULL << 59; 107 const uint64_t SOFT_RESET = 1ULL << 58; 108 109 syscfg = sb_read_syscfg(); 110 syscfg &= ~SOFT_RESET; 111 syscfg |= SYSTEM_RESET | EXT_RESET; 112 sb_write_syscfg(syscfg); 113} 114 115void 116sb_disable_intsrc(int cpu, int src) 117{ 118 uint32_t regaddr; 119 uint64_t val; 120 121 regaddr = INTSRC_MASK_ADDR(cpu); 122 123 val = sb_load64(regaddr); 124 val |= 1ULL << src; 125 sb_store64(regaddr, val); 126} 127 128void 129sb_enable_intsrc(int cpu, int src) 130{ 131 uint32_t regaddr; 132 uint64_t val; 133 134 regaddr = INTSRC_MASK_ADDR(cpu); 135 136 val = sb_load64(regaddr); 137 val &= ~(1ULL << src); 138 sb_store64(regaddr, val); 139} 140 141void 142sb_write_intsrc_mask(int cpu, uint64_t val) 143{ 144 uint32_t regaddr; 145 146 regaddr = INTSRC_MASK_ADDR(cpu); 147 sb_store64(regaddr, val); 148} 149 150uint64_t 151sb_read_intsrc_mask(int cpu) 152{ 153 uint32_t regaddr; 154 uint64_t val; 155 156 regaddr = INTSRC_MASK_ADDR(cpu); 157 val = sb_load64(regaddr); 158 159 return (val); 160} 161 162void 163sb_write_intmap(int cpu, int intsrc, int intrnum) 164{ 165 uint32_t regaddr; 166 167 regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 168 sb_store64(regaddr, intrnum); 169} 170 171int 172sb_read_intmap(int cpu, int intsrc) 173{ 174 uint32_t regaddr; 175 176 regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 177 return (sb_load64(regaddr) & 0x7); 178} 179 180int 181sb_route_intsrc(int intsrc) 182{ 183 int intrnum; 184 185 KASSERT(intsrc >= 0 && intsrc < NUM_INTSRC, 186 ("Invalid interrupt source number (%d)", intsrc)); 187 188 /* 189 * Interrupt 5 is used by sources internal to the CPU (e.g. timer). 190 * Use a deterministic mapping for the remaining sources. 191 */ 192 intrnum = intsrc % 5; 193 194 return (intrnum); 195} 196 197#define SCD_PHYSADDR 0x10000000 198#define SCD_SIZE 0x00060000 199 200static int 201scd_probe(device_t dev) 202{ 203 204 device_set_desc(dev, "Broadcom/Sibyte System Control and Debug"); 205 return (0); 206} 207 208static int 209scd_attach(device_t dev) 210{ 211 int rid; 212 struct resource *res; 213 214 if (bootverbose) 215 device_printf(dev, "attached.\n"); 216 217 rid = 0; 218 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SCD_PHYSADDR, 219 SCD_PHYSADDR + SCD_SIZE - 1, SCD_SIZE, 0); 220 if (res == NULL) 221 panic("Cannot allocate resource for system control and debug."); 222 223 return (0); 224} 225 226static device_method_t scd_methods[] ={ 227 /* Device interface */ 228 DEVMETHOD(device_probe, scd_probe), 229 DEVMETHOD(device_attach, scd_attach), 230 DEVMETHOD(device_detach, bus_generic_detach), 231 DEVMETHOD(device_shutdown, bus_generic_shutdown), 232 DEVMETHOD(device_suspend, bus_generic_suspend), 233 DEVMETHOD(device_resume, bus_generic_resume), 234 235 { 0, 0 } 236}; 237 238static driver_t scd_driver = { 239 "scd", 240 scd_methods 241}; 242 243static devclass_t scd_devclass; 244 245DRIVER_MODULE(scd, zbbus, scd_driver, scd_devclass, 0, 0); 246