sb_scd.c revision 210911
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 210911 2010-08-06 05:30:55Z neel $"); 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> 35195333Simp 36195333Simp#include <machine/resource.h> 37203697Sneel#include <machine/hwfunc.h> 38195333Simp 39195333Simp#include "sb_scd.h" 40195333Simp 41205675Sneel/* 42205675Sneel * We compile a 32-bit kernel to run on the SB-1 processor which is a 64-bit 43205675Sneel * processor. It has some registers that must be accessed using 64-bit load 44205675Sneel * and store instructions. 45205675Sneel * 46205675Sneel * We use the mips_ld() and mips_sd() functions to do this for us. 47205675Sneel */ 48210911Sneel#define sb_store64(addr, val) mips3_sd((uint64_t *)(uintptr_t)(addr), (val)) 49210911Sneel#define sb_load64(addr) mips3_ld((uint64_t *)(uintptr_t)(addr)) 50195333Simp 51195333Simp/* 52195333Simp * System Control and Debug (SCD) unit on the Sibyte ZBbus. 53195333Simp */ 54195333Simp 55195333Simp/* 56195333Simp * Extract the value starting at bit position 'b' for 'n' bits from 'x'. 57195333Simp */ 58195333Simp#define GET_VAL_64(x, b, n) (((x) >> (b)) & ((1ULL << (n)) - 1)) 59195333Simp 60203509Sneel#define SYSREV_ADDR MIPS_PHYS_TO_KSEG1(0x10020000) 61203509Sneel#define SYSREV_NUM_PROCESSORS(x) GET_VAL_64((x), 24, 4) 62203509Sneel 63203509Sneel#define SYSCFG_ADDR MIPS_PHYS_TO_KSEG1(0x10020008) 64195333Simp#define SYSCFG_PLLDIV(x) GET_VAL_64((x), 7, 5) 65195333Simp 66205364Sneel#define ZBBUS_CYCLE_COUNT_ADDR MIPS_PHYS_TO_KSEG1(0x10030000) 67205364Sneel 68203509Sneel#define INTSRC_MASK_ADDR(cpu) \ 69203509Sneel (MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13)) 70203509Sneel 71203509Sneel#define INTSRC_MAP_ADDR(cpu, intsrc) \ 72203509Sneel (MIPS_PHYS_TO_KSEG1(0x10020200) | ((cpu) << 13)) + (intsrc * 8) 73203509Sneel 74203509Sneel#define MAILBOX_SET_ADDR(cpu) \ 75203509Sneel (MIPS_PHYS_TO_KSEG1(0x100200C8) | ((cpu) << 13)) 76203509Sneel 77203509Sneel#define MAILBOX_CLEAR_ADDR(cpu) \ 78203509Sneel (MIPS_PHYS_TO_KSEG1(0x100200D0) | ((cpu) << 13)) 79203509Sneel 80203509Sneelstatic uint64_t 81203509Sneelsb_read_syscfg(void) 82203509Sneel{ 83203509Sneel 84203509Sneel return (sb_load64(SYSCFG_ADDR)); 85203509Sneel} 86203509Sneel 87203509Sneelstatic void 88203509Sneelsb_write_syscfg(uint64_t val) 89203509Sneel{ 90203509Sneel 91203509Sneel sb_store64(SYSCFG_ADDR, val); 92203509Sneel} 93203509Sneel 94195333Simpuint64_t 95205364Sneelsb_zbbus_cycle_count(void) 96205364Sneel{ 97205364Sneel 98205364Sneel return (sb_load64(ZBBUS_CYCLE_COUNT_ADDR)); 99205364Sneel} 100205364Sneel 101205364Sneeluint64_t 102195333Simpsb_cpu_speed(void) 103195333Simp{ 104195333Simp int plldiv; 105195333Simp const uint64_t MHZ = 1000000; 106195333Simp 107195333Simp plldiv = SYSCFG_PLLDIV(sb_read_syscfg()); 108195333Simp if (plldiv == 0) { 109195333Simp printf("PLL_DIV is 0 - assuming 6 (300MHz).\n"); 110195333Simp plldiv = 6; 111195333Simp } 112195333Simp 113195333Simp return (plldiv * 50 * MHZ); 114195333Simp} 115195333Simp 116195333Simpvoid 117195333Simpsb_system_reset(void) 118195333Simp{ 119195333Simp uint64_t syscfg; 120195333Simp 121195333Simp const uint64_t SYSTEM_RESET = 1ULL << 60; 122195333Simp const uint64_t EXT_RESET = 1ULL << 59; 123195333Simp const uint64_t SOFT_RESET = 1ULL << 58; 124195333Simp 125195333Simp syscfg = sb_read_syscfg(); 126195333Simp syscfg &= ~SOFT_RESET; 127195333Simp syscfg |= SYSTEM_RESET | EXT_RESET; 128195333Simp sb_write_syscfg(syscfg); 129195333Simp} 130195333Simp 131203509Sneelvoid 132203509Sneelsb_disable_intsrc(int cpu, int src) 133203509Sneel{ 134210911Sneel int regaddr; 135203509Sneel uint64_t val; 136203509Sneel 137203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 138203509Sneel 139203509Sneel val = sb_load64(regaddr); 140203509Sneel val |= 1ULL << src; 141203509Sneel sb_store64(regaddr, val); 142203509Sneel} 143203509Sneel 144203509Sneelvoid 145203509Sneelsb_enable_intsrc(int cpu, int src) 146203509Sneel{ 147210911Sneel int regaddr; 148203509Sneel uint64_t val; 149203509Sneel 150203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 151203509Sneel 152203509Sneel val = sb_load64(regaddr); 153203509Sneel val &= ~(1ULL << src); 154203509Sneel sb_store64(regaddr, val); 155203509Sneel} 156203509Sneel 157203509Sneelvoid 158203509Sneelsb_write_intsrc_mask(int cpu, uint64_t val) 159203509Sneel{ 160210911Sneel int regaddr; 161203509Sneel 162203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 163203509Sneel sb_store64(regaddr, val); 164203509Sneel} 165203509Sneel 166203509Sneeluint64_t 167203509Sneelsb_read_intsrc_mask(int cpu) 168203509Sneel{ 169210911Sneel int regaddr; 170203509Sneel uint64_t val; 171203509Sneel 172203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 173203509Sneel val = sb_load64(regaddr); 174203509Sneel 175203509Sneel return (val); 176203509Sneel} 177203509Sneel 178203509Sneelvoid 179203509Sneelsb_write_intmap(int cpu, int intsrc, int intrnum) 180203509Sneel{ 181210911Sneel int regaddr; 182203509Sneel 183203509Sneel regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 184203509Sneel sb_store64(regaddr, intrnum); 185203509Sneel} 186203509Sneel 187195333Simpint 188203509Sneelsb_read_intmap(int cpu, int intsrc) 189203509Sneel{ 190210911Sneel int regaddr; 191203509Sneel 192203509Sneel regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 193203509Sneel return (sb_load64(regaddr) & 0x7); 194203509Sneel} 195203509Sneel 196203509Sneelint 197195333Simpsb_route_intsrc(int intsrc) 198195333Simp{ 199195333Simp int intrnum; 200195333Simp 201195333Simp KASSERT(intsrc >= 0 && intsrc < NUM_INTSRC, 202195333Simp ("Invalid interrupt source number (%d)", intsrc)); 203195333Simp 204195333Simp /* 205195333Simp * Interrupt 5 is used by sources internal to the CPU (e.g. timer). 206203509Sneel * Use a deterministic mapping for the remaining sources. 207195333Simp */ 208203697Sneel#ifdef SMP 209203697Sneel KASSERT(platform_ipi_intrnum() == 4, 210203697Sneel ("Unexpected interrupt number used for IPI")); 211203697Sneel intrnum = intsrc % 4; 212203697Sneel#else 213195333Simp intrnum = intsrc % 5; 214203697Sneel#endif 215195333Simp 216195333Simp return (intrnum); 217195333Simp} 218195333Simp 219203697Sneel#ifdef SMP 220203697Sneelstatic uint64_t 221203697Sneelsb_read_sysrev(void) 222203697Sneel{ 223203697Sneel 224203697Sneel return (sb_load64(SYSREV_ADDR)); 225203697Sneel} 226203697Sneel 227203697Sneelvoid 228203697Sneelsb_set_mailbox(int cpu, uint64_t val) 229203697Sneel{ 230210911Sneel int regaddr; 231203697Sneel 232203697Sneel regaddr = MAILBOX_SET_ADDR(cpu); 233203697Sneel sb_store64(regaddr, val); 234203697Sneel} 235203697Sneel 236203697Sneelvoid 237203697Sneelsb_clear_mailbox(int cpu, uint64_t val) 238203697Sneel{ 239210911Sneel int regaddr; 240203697Sneel 241203697Sneel regaddr = MAILBOX_CLEAR_ADDR(cpu); 242203697Sneel sb_store64(regaddr, val); 243203697Sneel} 244203697Sneel 245203697Sneelint 246203697Sneelplatform_num_processors(void) 247203697Sneel{ 248203697Sneel 249203697Sneel return (SYSREV_NUM_PROCESSORS(sb_read_sysrev())); 250203697Sneel} 251203697Sneel#endif /* SMP */ 252203697Sneel 253195333Simp#define SCD_PHYSADDR 0x10000000 254195333Simp#define SCD_SIZE 0x00060000 255195333Simp 256195333Simpstatic int 257195333Simpscd_probe(device_t dev) 258195333Simp{ 259195333Simp 260195333Simp device_set_desc(dev, "Broadcom/Sibyte System Control and Debug"); 261195333Simp return (0); 262195333Simp} 263195333Simp 264195333Simpstatic int 265195333Simpscd_attach(device_t dev) 266195333Simp{ 267195333Simp int rid; 268195333Simp struct resource *res; 269195333Simp 270203509Sneel if (bootverbose) 271195333Simp device_printf(dev, "attached.\n"); 272195333Simp 273195333Simp rid = 0; 274195333Simp res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SCD_PHYSADDR, 275195333Simp SCD_PHYSADDR + SCD_SIZE - 1, SCD_SIZE, 0); 276203509Sneel if (res == NULL) 277195333Simp panic("Cannot allocate resource for system control and debug."); 278195333Simp 279195333Simp return (0); 280195333Simp} 281195333Simp 282195333Simpstatic device_method_t scd_methods[] ={ 283195333Simp /* Device interface */ 284195333Simp DEVMETHOD(device_probe, scd_probe), 285195333Simp DEVMETHOD(device_attach, scd_attach), 286195333Simp DEVMETHOD(device_detach, bus_generic_detach), 287195333Simp DEVMETHOD(device_shutdown, bus_generic_shutdown), 288195333Simp DEVMETHOD(device_suspend, bus_generic_suspend), 289195333Simp DEVMETHOD(device_resume, bus_generic_resume), 290195333Simp 291195333Simp { 0, 0 } 292195333Simp}; 293195333Simp 294195333Simpstatic driver_t scd_driver = { 295195333Simp "scd", 296195333Simp scd_methods 297195333Simp}; 298195333Simp 299195333Simpstatic devclass_t scd_devclass; 300195333Simp 301195333SimpDRIVER_MODULE(scd, zbbus, scd_driver, scd_devclass, 0, 0); 302