sb_scd.c revision 203509
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 203509 2010-02-05 03:20:47Z 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> 37203509Sneel#include <machine/intr_machdep.h> 38195333Simp 39195333Simp#include "sb_scd.h" 40195333Simp 41203509Sneelextern void sb_store64(uint32_t addr, uint64_t val); 42203509Sneelextern uint64_t sb_load64(uint32_t addr); 43195333Simp 44195333Simp/* 45195333Simp * System Control and Debug (SCD) unit on the Sibyte ZBbus. 46195333Simp */ 47195333Simp 48195333Simp/* 49195333Simp * Extract the value starting at bit position 'b' for 'n' bits from 'x'. 50195333Simp */ 51195333Simp#define GET_VAL_64(x, b, n) (((x) >> (b)) & ((1ULL << (n)) - 1)) 52195333Simp 53203509Sneel#define SYSREV_ADDR MIPS_PHYS_TO_KSEG1(0x10020000) 54203509Sneel#define SYSREV_NUM_PROCESSORS(x) GET_VAL_64((x), 24, 4) 55203509Sneel 56203509Sneel#define SYSCFG_ADDR MIPS_PHYS_TO_KSEG1(0x10020008) 57195333Simp#define SYSCFG_PLLDIV(x) GET_VAL_64((x), 7, 5) 58195333Simp 59203509Sneel#define INTSRC_MASK_ADDR(cpu) \ 60203509Sneel (MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13)) 61203509Sneel 62203509Sneel#define INTSRC_MAP_ADDR(cpu, intsrc) \ 63203509Sneel (MIPS_PHYS_TO_KSEG1(0x10020200) | ((cpu) << 13)) + (intsrc * 8) 64203509Sneel 65203509Sneel#define MAILBOX_SET_ADDR(cpu) \ 66203509Sneel (MIPS_PHYS_TO_KSEG1(0x100200C8) | ((cpu) << 13)) 67203509Sneel 68203509Sneel#define MAILBOX_CLEAR_ADDR(cpu) \ 69203509Sneel (MIPS_PHYS_TO_KSEG1(0x100200D0) | ((cpu) << 13)) 70203509Sneel 71203509Sneelstatic uint64_t 72203509Sneelsb_read_syscfg(void) 73203509Sneel{ 74203509Sneel 75203509Sneel return (sb_load64(SYSCFG_ADDR)); 76203509Sneel} 77203509Sneel 78203509Sneelstatic void 79203509Sneelsb_write_syscfg(uint64_t val) 80203509Sneel{ 81203509Sneel 82203509Sneel sb_store64(SYSCFG_ADDR, val); 83203509Sneel} 84203509Sneel 85195333Simpuint64_t 86195333Simpsb_cpu_speed(void) 87195333Simp{ 88195333Simp int plldiv; 89195333Simp const uint64_t MHZ = 1000000; 90195333Simp 91195333Simp plldiv = SYSCFG_PLLDIV(sb_read_syscfg()); 92195333Simp if (plldiv == 0) { 93195333Simp printf("PLL_DIV is 0 - assuming 6 (300MHz).\n"); 94195333Simp plldiv = 6; 95195333Simp } 96195333Simp 97195333Simp return (plldiv * 50 * MHZ); 98195333Simp} 99195333Simp 100195333Simpvoid 101195333Simpsb_system_reset(void) 102195333Simp{ 103195333Simp uint64_t syscfg; 104195333Simp 105195333Simp const uint64_t SYSTEM_RESET = 1ULL << 60; 106195333Simp const uint64_t EXT_RESET = 1ULL << 59; 107195333Simp const uint64_t SOFT_RESET = 1ULL << 58; 108195333Simp 109195333Simp syscfg = sb_read_syscfg(); 110195333Simp syscfg &= ~SOFT_RESET; 111195333Simp syscfg |= SYSTEM_RESET | EXT_RESET; 112195333Simp sb_write_syscfg(syscfg); 113195333Simp} 114195333Simp 115203509Sneelvoid 116203509Sneelsb_disable_intsrc(int cpu, int src) 117203509Sneel{ 118203509Sneel uint32_t regaddr; 119203509Sneel uint64_t val; 120203509Sneel 121203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 122203509Sneel 123203509Sneel val = sb_load64(regaddr); 124203509Sneel val |= 1ULL << src; 125203509Sneel sb_store64(regaddr, val); 126203509Sneel} 127203509Sneel 128203509Sneelvoid 129203509Sneelsb_enable_intsrc(int cpu, int src) 130203509Sneel{ 131203509Sneel uint32_t regaddr; 132203509Sneel uint64_t val; 133203509Sneel 134203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 135203509Sneel 136203509Sneel val = sb_load64(regaddr); 137203509Sneel val &= ~(1ULL << src); 138203509Sneel sb_store64(regaddr, val); 139203509Sneel} 140203509Sneel 141203509Sneelvoid 142203509Sneelsb_write_intsrc_mask(int cpu, uint64_t val) 143203509Sneel{ 144203509Sneel uint32_t regaddr; 145203509Sneel 146203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 147203509Sneel sb_store64(regaddr, val); 148203509Sneel} 149203509Sneel 150203509Sneeluint64_t 151203509Sneelsb_read_intsrc_mask(int cpu) 152203509Sneel{ 153203509Sneel uint32_t regaddr; 154203509Sneel uint64_t val; 155203509Sneel 156203509Sneel regaddr = INTSRC_MASK_ADDR(cpu); 157203509Sneel val = sb_load64(regaddr); 158203509Sneel 159203509Sneel return (val); 160203509Sneel} 161203509Sneel 162203509Sneelvoid 163203509Sneelsb_write_intmap(int cpu, int intsrc, int intrnum) 164203509Sneel{ 165203509Sneel uint32_t regaddr; 166203509Sneel 167203509Sneel regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 168203509Sneel sb_store64(regaddr, intrnum); 169203509Sneel} 170203509Sneel 171195333Simpint 172203509Sneelsb_read_intmap(int cpu, int intsrc) 173203509Sneel{ 174203509Sneel uint32_t regaddr; 175203509Sneel 176203509Sneel regaddr = INTSRC_MAP_ADDR(cpu, intsrc); 177203509Sneel return (sb_load64(regaddr) & 0x7); 178203509Sneel} 179203509Sneel 180203509Sneelint 181195333Simpsb_route_intsrc(int intsrc) 182195333Simp{ 183195333Simp int intrnum; 184195333Simp 185195333Simp KASSERT(intsrc >= 0 && intsrc < NUM_INTSRC, 186195333Simp ("Invalid interrupt source number (%d)", intsrc)); 187195333Simp 188195333Simp /* 189195333Simp * Interrupt 5 is used by sources internal to the CPU (e.g. timer). 190203509Sneel * Use a deterministic mapping for the remaining sources. 191195333Simp */ 192195333Simp intrnum = intsrc % 5; 193195333Simp 194195333Simp return (intrnum); 195195333Simp} 196195333Simp 197195333Simp#define SCD_PHYSADDR 0x10000000 198195333Simp#define SCD_SIZE 0x00060000 199195333Simp 200195333Simpstatic int 201195333Simpscd_probe(device_t dev) 202195333Simp{ 203195333Simp 204195333Simp device_set_desc(dev, "Broadcom/Sibyte System Control and Debug"); 205195333Simp return (0); 206195333Simp} 207195333Simp 208195333Simpstatic int 209195333Simpscd_attach(device_t dev) 210195333Simp{ 211195333Simp int rid; 212195333Simp struct resource *res; 213195333Simp 214203509Sneel if (bootverbose) 215195333Simp device_printf(dev, "attached.\n"); 216195333Simp 217195333Simp rid = 0; 218195333Simp res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SCD_PHYSADDR, 219195333Simp SCD_PHYSADDR + SCD_SIZE - 1, SCD_SIZE, 0); 220203509Sneel if (res == NULL) 221195333Simp panic("Cannot allocate resource for system control and debug."); 222195333Simp 223195333Simp return (0); 224195333Simp} 225195333Simp 226195333Simpstatic device_method_t scd_methods[] ={ 227195333Simp /* Device interface */ 228195333Simp DEVMETHOD(device_probe, scd_probe), 229195333Simp DEVMETHOD(device_attach, scd_attach), 230195333Simp DEVMETHOD(device_detach, bus_generic_detach), 231195333Simp DEVMETHOD(device_shutdown, bus_generic_shutdown), 232195333Simp DEVMETHOD(device_suspend, bus_generic_suspend), 233195333Simp DEVMETHOD(device_resume, bus_generic_resume), 234195333Simp 235195333Simp { 0, 0 } 236195333Simp}; 237195333Simp 238195333Simpstatic driver_t scd_driver = { 239195333Simp "scd", 240195333Simp scd_methods 241195333Simp}; 242195333Simp 243195333Simpstatic devclass_t scd_devclass; 244195333Simp 245195333SimpDRIVER_MODULE(scd, zbbus, scd_driver, scd_devclass, 0, 0); 246