mpc85xx.c revision 209908
1169689Skan/*- 2169689Skan * Copyright (C) 2008 Semihalf, Rafal Jaworowski 3169689Skan * All rights reserved. 4169689Skan * 5169689Skan * Redistribution and use in source and binary forms, with or without 6169689Skan * modification, are permitted provided that the following conditions 7169689Skan * are met: 8169689Skan * 1. Redistributions of source code must retain the above copyright 9169689Skan * notice, this list of conditions and the following disclaimer. 10169689Skan * 2. Redistributions in binary form must reproduce the above copyright 11169689Skan * notice, this list of conditions and the following disclaimer in the 12169689Skan * documentation and/or other materials provided with the distribution. 13169689Skan * 14169689Skan * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24169689Skan * SUCH DAMAGE. 25169689Skan */ 26169689Skan 27169689Skan#include <sys/cdefs.h> 28169689Skan__FBSDID("$FreeBSD: head/sys/powerpc/mpc85xx/mpc85xx.c 209908 2010-07-11 21:08:29Z raj $"); 29169689Skan 30169689Skan#include <sys/param.h> 31169689Skan#include <sys/systm.h> 32169689Skan#include <sys/lock.h> 33169689Skan#include <sys/mutex.h> 34169689Skan#include <sys/rman.h> 35169689Skan 36169689Skan#include <vm/vm.h> 37169689Skan#include <vm/vm_param.h> 38169689Skan 39169689Skan#include <machine/cpu.h> 40169689Skan#include <machine/cpufunc.h> 41169689Skan#include <machine/spr.h> 42169689Skan 43169689Skan#include <powerpc/mpc85xx/mpc85xx.h> 44169689Skan 45169689Skan/* 46169689Skan * MPC85xx system specific routines 47169689Skan */ 48169689Skan 49169689Skanuint32_t 50169689Skanccsr_read4(uintptr_t addr) 51169689Skan{ 52169689Skan volatile uint32_t *ptr = (void *)addr; 53169689Skan 54169689Skan return (*ptr); 55169689Skan} 56169689Skan 57169689Skanvoid 58169689Skanccsr_write4(uintptr_t addr, uint32_t val) 59169689Skan{ 60169689Skan volatile uint32_t *ptr = (void *)addr; 61169689Skan 62169689Skan *ptr = val; 63169689Skan __asm __volatile("eieio; sync"); 64169689Skan} 65169689Skan 66169689Skanint 67169689Skanlaw_getmax(void) 68169689Skan{ 69169689Skan uint32_t ver; 70169689Skan 71169689Skan ver = SVR_VER(mfspr(SPR_SVR)); 72169689Skan if (ver == SVR_MPC8572E || ver == SVR_MPC8572) 73169689Skan return (12); 74169689Skan else if (ver == SVR_MPC8548E || ver == SVR_MPC8548) 75169689Skan return (10); 76169689Skan else 77169689Skan return (8); 78169689Skan} 79169689Skan 80169689Skan#define _LAW_SR(trgt,size) (0x80000000 | (trgt << 20) | (ffsl(size) - 2)) 81169689Skan#define _LAW_BAR(addr) (addr >> 12) 82169689Skan 83169689Skanint 84169689Skanlaw_enable(int trgt, u_long addr, u_long size) 85169689Skan{ 86169689Skan uint32_t bar, sr; 87169689Skan int i, law_max; 88169689Skan 89169689Skan law_max = law_getmax(); 90169689Skan bar = _LAW_BAR(addr); 91169689Skan sr = _LAW_SR(trgt, size); 92169689Skan 93169689Skan /* Bail if already programmed. */ 94169689Skan for (i = 0; i < law_max; i++) 95169689Skan if (sr == ccsr_read4(OCP85XX_LAWSR(i)) && 96169689Skan bar == ccsr_read4(OCP85XX_LAWBAR(i))) 97169689Skan return (0); 98169689Skan 99169689Skan /* Find an unused access window. */ 100169689Skan for (i = 0; i < law_max; i++) 101169689Skan if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0) 102169689Skan break; 103169689Skan 104169689Skan if (i == law_max) 105169689Skan return (ENOSPC); 106169689Skan 107169689Skan ccsr_write4(OCP85XX_LAWBAR(i), bar); 108169689Skan ccsr_write4(OCP85XX_LAWSR(i), sr); 109169689Skan return (0); 110169689Skan} 111169689Skan 112169689Skanint 113169689Skanlaw_disable(int trgt, u_long addr, u_long size) 114169689Skan{ 115169689Skan uint32_t bar, sr; 116169689Skan int i, law_max; 117169689Skan 118169689Skan law_max = law_getmax(); 119169689Skan bar = _LAW_BAR(addr); 120169689Skan sr = _LAW_SR(trgt, size); 121169689Skan 122169689Skan /* Find and disable requested LAW. */ 123169689Skan for (i = 0; i < law_max; i++) 124169689Skan if (sr == ccsr_read4(OCP85XX_LAWSR(i)) && 125169689Skan bar == ccsr_read4(OCP85XX_LAWBAR(i))) { 126169689Skan ccsr_write4(OCP85XX_LAWBAR(i), 0); 127169689Skan ccsr_write4(OCP85XX_LAWSR(i), 0); 128169689Skan return (0); 129169689Skan } 130169689Skan 131169689Skan return (ENOENT); 132169689Skan} 133169689Skan 134169689Skanint 135169689Skanlaw_pci_target(struct resource *res, int *trgt_mem, int *trgt_io) 136169689Skan{ 137169689Skan u_long start; 138169689Skan uint32_t ver; 139169689Skan int trgt, rv; 140169689Skan 141169689Skan ver = SVR_VER(mfspr(SPR_SVR)); 142169689Skan 143169689Skan start = rman_get_start(res) & 0xf000; 144169689Skan 145169689Skan rv = 0; 146169689Skan trgt = -1; 147169689Skan switch (start) { 148169689Skan case 0x8000: 149169689Skan trgt = 0; 150169689Skan break; 151169689Skan case 0x9000: 152169689Skan trgt = 1; 153169689Skan break; 154169689Skan case 0xa000: 155169689Skan if (ver == SVR_MPC8572E || ver == SVR_MPC8572) 156169689Skan trgt = 2; 157169689Skan else 158169689Skan rv = EINVAL; 159169689Skan break; 160169689Skan default: 161169689Skan rv = ENXIO; 162169689Skan } 163169689Skan *trgt_mem = *trgt_io = trgt; 164169689Skan return (rv); 165169689Skan} 166169689Skan 167169689Skanvoid 168169689Skancpu_reset(void) 169169689Skan{ 170169689Skan uint32_t ver = SVR_VER(mfspr(SPR_SVR)); 171169689Skan 172169689Skan if (ver == SVR_MPC8572E || ver == SVR_MPC8572 || 173169689Skan ver == SVR_MPC8548E || ver == SVR_MPC8548) 174169689Skan /* Systems with dedicated reset register */ 175169689Skan ccsr_write4(OCP85XX_RSTCR, 2); 176169689Skan else { 177169689Skan /* Clear DBCR0, disables debug interrupts and events. */ 178169689Skan mtspr(SPR_DBCR0, 0); 179169689Skan __asm __volatile("isync"); 180169689Skan 181169689Skan /* Enable Debug Interrupts in MSR. */ 182169689Skan mtmsr(mfmsr() | PSL_DE); 183169689Skan 184169689Skan /* Enable debug interrupts and issue reset. */ 185169689Skan mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | 186169689Skan DBCR0_RST_SYSTEM); 187169689Skan } 188169689Skan 189169689Skan printf("Reset failed...\n"); 190169689Skan while (1); 191169689Skan} 192169689Skan