sb_scd.c revision 222813
1195333Simp/*- 2195333Simp * Copyright (c) 2009 Neelkanth Natu 3195333Simp * All rights reserved. 4195333Simp * 5195333Simp * Redistribution and use in source and binary forms, with or without 6195333Simp * modification, are permitted provided that the following conditions 7195333Simp * are met: 8195333Simp * 1. Redistributions of source code must retain the above copyright 9195333Simp * notice, this list of conditions and the following disclaimer. 10195333Simp * 2. Redistributions in binary form must reproduce the above copyright 11195333Simp * notice, this list of conditions and the following disclaimer in the 12195333Simp * documentation and/or other materials provided with the distribution. 13195333Simp * 14195333Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15195333Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16195333Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17195333Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18195333Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19195333Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20195333Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21195333Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22195333Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23195333Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24195333Simp * SUCH DAMAGE. 25195333Simp */ 26203509Sneel 27203509Sneel#include <sys/cdefs.h> 28203509Sneel__FBSDID("$FreeBSD: head/sys/mips/sibyte/sb_scd.c 222813 2011-06-07 08:46:13Z attilio $"); 29203509Sneel 30195333Simp#include <sys/param.h> 31195333Simp#include <sys/kernel.h> 32195333Simp#include <sys/systm.h> 33195333Simp#include <sys/module.h> 34195333Simp#include <sys/bus.h> 35222813Sattilio#include <sys/cpuset.h> 36195333Simp 37195333Simp#include <machine/resource.h> 38203697Sneel#include <machine/hwfunc.h> 39195333Simp 40195333Simp#include "sb_scd.h" 41195333Simp 42205675Sneel/* 43205675Sneel * We compile a 32-bit kernel to run on the SB-1 processor which is a 64-bit 44205675Sneel * processor. It has some registers that must be accessed using 64-bit load 45205675Sneel * and store instructions. 46205675Sneel * 47205675Sneel * We use the mips_ld() and mips_sd() functions to do this for us. 48205675Sneel */ 49210911Sneel#define sb_store64(addr, val) mips3_sd((uint64_t *)(uintptr_t)(addr), (val)) 50210911Sneel#define sb_load64(addr) mips3_ld((uint64_t *)(uintptr_t)(addr)) 51195333Simp 52195333Simp/* 53195333Simp * System Control and Debug (SCD) unit on the Sibyte ZBbus. 54195333Simp */ 55195333Simp 56195333Simp/* 57195333Simp * Extract the value starting at bit position 'b' for 'n' bits from 'x'. 58195333Simp */ 59195333Simp#define GET_VAL_64(x, b, n) (((x) >> (b)) & ((1ULL << (n)) - 1)) 60195333Simp 61203509Sneel#define SYSREV_ADDR MIPS_PHYS_TO_KSEG1(0x10020000) 62203509Sneel#define SYSREV_NUM_PROCESSORS(x) GET_VAL_64((x), 24, 4) 63203509Sneel 64203509Sneel#define SYSCFG_ADDR MIPS_PHYS_TO_KSEG1(0x10020008) 65195333Simp#define SYSCFG_PLLDIV(x) GET_VAL_64((x), 7, 5) 66195333Simp 67205364Sneel#define ZBBUS_CYCLE_COUNT_ADDR MIPS_PHYS_TO_KSEG1(0x10030000) 68205364Sneel 69203509Sneel#define INTSRC_MASK_ADDR(cpu) \ 70203509Sneel (MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13)) 71203509Sneel 72203509Sneel#define INTSRC_MAP_ADDR(cpu, intsrc) \ 73203509Sneel (MIPS_PHYS_TO_KSEG1(0x10020200) | ((cpu) << 13)) + (intsrc * 8) 74203509Sneel 75203509Sneel#define MAILBOX_SET_ADDR(cpu) \ 76203509Sneel (MIPS_PHYS_TO_KSEG1(0x100200C8) | ((cpu) << 13)) 77203509Sneel 78203509Sneel#define MAILBOX_CLEAR_ADDR(cpu) \ 79203509Sneel (MIPS_PHYS_TO_KSEG1(0x100200D0) | ((cpu) << 13)) 80203509Sneel 81203509Sneelstatic uint64_t 82203509Sneelsb_read_syscfg(void) 83203509Sneel{ 84203509Sneel 85203509Sneel return (sb_load64(SYSCFG_ADDR)); 86203509Sneel} 87203509Sneel 88203509Sneelstatic void 89203509Sneelsb_write_syscfg(uint64_t val) 90203509Sneel{ 91203509Sneel 92203509Sneel sb_store64(SYSCFG_ADDR, val); 93203509Sneel} 94203509Sneel 95195333Simpuint64_t 96205364Sneelsb_zbbus_cycle_count(void) 97205364Sneel{ 98205364Sneel 99205364Sneel return (sb_load64(ZBBUS_CYCLE_COUNT_ADDR)); 100205364Sneel} 101205364Sneel 102205364Sneeluint64_t 103195333Simpsb_cpu_speed(void) 104195333Simp{ 105195333Simp int plldiv; 106195333Simp const uint64_t MHZ = 1000000; 107195333Simp 108195333Simp plldiv = SYSCFG_PLLDIV(sb_read_syscfg()); 109195333Simp if (plldiv == 0) { 110195333Simp printf("PLL_DIV is 0 - assuming 6 (300MHz).\n"); 111195333Simp plldiv = 6; 112195333Simp } 113195333Simp 114195333Simp return (plldiv * 50 * MHZ); 115195333Simp} 116195333Simp 117195333Simpvoid 118195333Simpsb_system_reset(void) 119195333Simp{ 120195333Simp uint64_t syscfg; 121195333Simp 122195333Simp const uint64_t SYSTEM_RESET = 1ULL << 60; 123195333Simp const uint64_t EXT_RESET = 1ULL << 59; 124195333Simp const uint64_t SOFT_RESET = 1ULL << 58; 125195333Simp 126195333Simp syscfg = sb_read_syscfg(); 127195333Simp syscfg &= ~SOFT_RESET; 128195333Simp syscfg |= SYSTEM_RESET | EXT_RESET; 129195333Simp sb_write_syscfg(syscfg); 130195333Simp} 131195333Simp 132203509Sneelvoid 133203509Sneelsb_disable_intsrc(int cpu, int src) 134203509Sneel{ 135210911Sneel int regaddr; 136203509Sneel uint64_t val; 137203509Sneel 138203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 139203509Sneel 140203509Sneel val = sb_load64(regaddr); 141203509Sneel val |= 1ULL << src; 142203509Sneel sb_store64(regaddr, val); 143203509Sneel} 144203509Sneel 145203509Sneelvoid 146203509Sneelsb_enable_intsrc(int cpu, int src) 147203509Sneel{ 148210911Sneel int regaddr; 149203509Sneel uint64_t val; 150203509Sneel 151203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 152203509Sneel 153203509Sneel val = sb_load64(regaddr); 154203509Sneel val &= ~(1ULL << src); 155203509Sneel sb_store64(regaddr, val); 156203509Sneel} 157203509Sneel 158203509Sneelvoid 159203509Sneelsb_write_intsrc_mask(int cpu, uint64_t val) 160203509Sneel{ 161210911Sneel int regaddr; 162203509Sneel 163203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 164203509Sneel sb_store64(regaddr, val); 165203509Sneel} 166203509Sneel 167203509Sneeluint64_t 168203509Sneelsb_read_intsrc_mask(int cpu) 169203509Sneel{ 170210911Sneel int regaddr; 171203509Sneel uint64_t val; 172203509Sneel 173203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 174203509Sneel val = sb_load64(regaddr); 175203509Sneel 176203509Sneel return (val); 177203509Sneel} 178203509Sneel 179203509Sneelvoid 180203509Sneelsb_write_intmap(int cpu, int intsrc, int intrnum) 181203509Sneel{ 182210911Sneel int regaddr; 183203509Sneel 184203509Sneel regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 185203509Sneel sb_store64(regaddr, intrnum); 186203509Sneel} 187203509Sneel 188195333Simpint 189203509Sneelsb_read_intmap(int cpu, int intsrc) 190203509Sneel{ 191210911Sneel int regaddr; 192203509Sneel 193203509Sneel regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 194203509Sneel return (sb_load64(regaddr) & 0x7); 195203509Sneel} 196203509Sneel 197203509Sneelint 198195333Simpsb_route_intsrc(int intsrc) 199195333Simp{ 200195333Simp int intrnum; 201195333Simp 202195333Simp KASSERT(intsrc >= 0 && intsrc < NUM_INTSRC, 203195333Simp ("Invalid interrupt source number (%d)", intsrc)); 204195333Simp 205195333Simp /* 206195333Simp * Interrupt 5 is used by sources internal to the CPU (e.g. timer). 207203509Sneel * Use a deterministic mapping for the remaining sources. 208195333Simp */ 209203697Sneel#ifdef SMP 210203697Sneel KASSERT(platform_ipi_intrnum() == 4, 211203697Sneel ("Unexpected interrupt number used for IPI")); 212203697Sneel intrnum = intsrc % 4; 213203697Sneel#else 214195333Simp intrnum = intsrc % 5; 215203697Sneel#endif 216195333Simp 217195333Simp return (intrnum); 218195333Simp} 219195333Simp 220203697Sneel#ifdef SMP 221203697Sneelstatic uint64_t 222203697Sneelsb_read_sysrev(void) 223203697Sneel{ 224203697Sneel 225203697Sneel return (sb_load64(SYSREV_ADDR)); 226203697Sneel} 227203697Sneel 228203697Sneelvoid 229203697Sneelsb_set_mailbox(int cpu, uint64_t val) 230203697Sneel{ 231210911Sneel int regaddr; 232203697Sneel 233203697Sneel regaddr = MAILBOX_SET_ADDR(cpu); 234203697Sneel sb_store64(regaddr, val); 235203697Sneel} 236203697Sneel 237203697Sneelvoid 238203697Sneelsb_clear_mailbox(int cpu, uint64_t val) 239203697Sneel{ 240210911Sneel int regaddr; 241203697Sneel 242203697Sneel regaddr = MAILBOX_CLEAR_ADDR(cpu); 243203697Sneel sb_store64(regaddr, val); 244203697Sneel} 245203697Sneel 246222813Sattiliovoid 247222813Sattilioplatform_cpu_mask(cpuset_t *mask) 248203697Sneel{ 249222813Sattilio int i, s; 250203697Sneel 251222813Sattilio CPU_ZERO(mask); 252222813Sattilio s = SYSREV_NUM_PROCESSORS(sb_read_sysrev()); 253222813Sattilio for (i = 0; i < s; i++) 254222813Sattilio CPU_SET(i, mask); 255203697Sneel} 256203697Sneel#endif /* SMP */ 257203697Sneel 258195333Simp#define SCD_PHYSADDR 0x10000000 259195333Simp#define SCD_SIZE 0x00060000 260195333Simp 261195333Simpstatic int 262195333Simpscd_probe(device_t dev) 263195333Simp{ 264195333Simp 265195333Simp device_set_desc(dev, "Broadcom/Sibyte System Control and Debug"); 266195333Simp return (0); 267195333Simp} 268195333Simp 269195333Simpstatic int 270195333Simpscd_attach(device_t dev) 271195333Simp{ 272195333Simp int rid; 273195333Simp struct resource *res; 274195333Simp 275203509Sneel if (bootverbose) 276195333Simp device_printf(dev, "attached.\n"); 277195333Simp 278195333Simp rid = 0; 279195333Simp res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SCD_PHYSADDR, 280195333Simp SCD_PHYSADDR + SCD_SIZE - 1, SCD_SIZE, 0); 281203509Sneel if (res == NULL) 282195333Simp panic("Cannot allocate resource for system control and debug."); 283195333Simp 284195333Simp return (0); 285195333Simp} 286195333Simp 287195333Simpstatic device_method_t scd_methods[] ={ 288195333Simp /* Device interface */ 289195333Simp DEVMETHOD(device_probe, scd_probe), 290195333Simp DEVMETHOD(device_attach, scd_attach), 291195333Simp DEVMETHOD(device_detach, bus_generic_detach), 292195333Simp DEVMETHOD(device_shutdown, bus_generic_shutdown), 293195333Simp DEVMETHOD(device_suspend, bus_generic_suspend), 294195333Simp DEVMETHOD(device_resume, bus_generic_resume), 295195333Simp 296195333Simp { 0, 0 } 297195333Simp}; 298195333Simp 299195333Simpstatic driver_t scd_driver = { 300195333Simp "scd", 301195333Simp scd_methods 302195333Simp}; 303195333Simp 304195333Simpstatic devclass_t scd_devclass; 305195333Simp 306195333SimpDRIVER_MODULE(scd, zbbus, scd_driver, scd_devclass, 0, 0); 307