1 /* $NetBSD: pic.c,v 1.9 2004/11/12 23:01:01 sekiya Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Steve Rumble 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.9 2004/11/12 23:01:01 sekiya Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/device.h> 35 #include <sys/systm.h> 36 37 #include <machine/cpu.h> 38 #include <machine/locore.h> 39 #include <machine/autoconf.h> 40 #include <machine/bus.h> 41 #include <machine/machtype.h> 42 #include <machine/sysconf.h> 43 44 #include <sgimips/dev/picreg.h> 45 46 #include "locators.h" 47 48 struct pic_softc { 49 struct device sc_dev; 50 51 bus_space_tag_t iot; 52 bus_space_handle_t ioh; 53 54 }; 55 56 static int pic_match(struct device *, struct cfdata *, void *); 57 static void pic_attach(struct device *, struct device *, void *); 58 static int pic_print(void *, const char *); 59 static void pic_bus_reset(void); 60 static void pic_watchdog_enable(void); 61 static void pic_watchdog_disable(void); 62 static void pic_watchdog_tickle(void); 63 64 CFATTACH_DECL(pic, sizeof(struct pic_softc), 65 pic_match, pic_attach, NULL, NULL); 66 67 struct pic_attach_args { 68 const char *iaa_name; 69 70 bus_space_tag_t iaa_st; 71 bus_space_handle_t iaa_sh; 72 }; 73 74 static struct pic_softc psc; 75 76 static int 77 pic_match(struct device * parent, struct cfdata * match, void *aux) 78 { 79 /* 80 * PIC exists on IP12 systems. It appears to be the immediate 81 * ancestor of the mc, for mips1 processors. 82 */ 83 if (mach_type == MACH_SGI_IP12) 84 return (1); 85 else 86 return (0); 87 } 88 89 static void 90 pic_attach(struct device * parent, struct device * self, void *aux) 91 { 92 u_int32_t reg; 93 struct pic_attach_args iaa; 94 struct mainbus_attach_args *ma = aux; 95 96 psc.iot = SGIMIPS_BUS_SPACE_HPC; 97 if (bus_space_map(psc.iot, ma->ma_addr, 0, 98 BUS_SPACE_MAP_LINEAR, &psc.ioh)) 99 panic("pic_attach: could not allocate memory\n"); 100 101 platform.bus_reset = pic_bus_reset; 102 platform.watchdog_enable = pic_watchdog_enable; 103 platform.watchdog_disable = pic_watchdog_disable; 104 platform.watchdog_reset = pic_watchdog_tickle; 105 106 reg = bus_space_read_4(psc.iot, psc.ioh, PIC_SYSID); 107 reg = (reg >> PIC_SYSID_REVSHIFT) & PIC_SYSID_REVMASK; 108 printf("\npic0: Revision %c", reg + 64); 109 110 /* enable refresh, set big-endian, memory parity, allow slave access */ 111 reg = bus_space_read_4(psc.iot, psc.ioh, PIC_CPUCTRL); 112 reg |= (PIC_CPUCTRL_REFRESH | PIC_CPUCTRL_BIGENDIAN | PIC_CPUCTRL_MPR | 113 PIC_CPUCTRL_SLAVE); 114 bus_space_write_4(psc.iot, psc.ioh, PIC_CPUCTRL, reg); 115 116 /* query the mode register to see what's going on */ 117 reg = bus_space_read_4(psc.iot, psc.ioh, PIC_MODE); 118 printf(": dblk (0x%x), iblk (0x%x)\n", reg & PIC_MODE_DBSIZ, 119 reg & PIC_MODE_IBSIZ); 120 121 /* display the machine type, board revision */ 122 printf("pic0: "); 123 124 switch (mach_subtype) { 125 case MACH_SGI_IP12_4D_3X: 126 printf("Personal Iris 4D/3x"); 127 break; 128 case MACH_SGI_IP12_VIP12: 129 printf("VME IP12"); 130 break; 131 case MACH_SGI_IP12_HP1: 132 printf("Indigo R3000"); 133 break; 134 case MACH_SGI_IP12_HPLC: 135 printf("Hollywood Light"); 136 break; 137 default: 138 printf("unknown machine"); 139 break; 140 } 141 printf(", board revision %x\n", mach_boardrev); 142 143 printf("pic0: "); 144 145 if (reg & PIC_MODE_NOCACHE) 146 printf("cache disabled"); 147 else 148 printf("cache enabled"); 149 150 if (reg & PIC_MODE_ISTREAM) 151 printf(", instr streaming"); 152 153 if (reg & PIC_MODE_STOREPARTIAL) 154 printf(", store partial"); 155 156 if (reg & PIC_MODE_BUSDRIVE) 157 printf(", bus drive"); 158 159 /* gio32 allow master, real time devices */ 160 reg = bus_space_read_4(psc.iot, psc.ioh, PIC_GIO32ARB_SLOT0); 161 reg &= ~(PIC_GIO32ARB_SLOT_SLAVE | PIC_GIO32ARB_SLOT_LONG); 162 bus_space_write_4(psc.iot, psc.ioh, PIC_GIO32ARB_SLOT0, reg); 163 164 reg = bus_space_read_4(psc.iot, psc.ioh, PIC_GIO32ARB_SLOT1); 165 reg &= ~(PIC_GIO32ARB_SLOT_SLAVE | PIC_GIO32ARB_SLOT_LONG); 166 bus_space_write_4(psc.iot, psc.ioh, PIC_GIO32ARB_SLOT1, reg); 167 168 /* default gio32 burst time */ 169 bus_space_write_4(psc.iot, psc.ioh, PIC_GIO32ARB_BURST, 170 PIC_GIO32ARB_DEFBURST); 171 172 /* default gio32 delay time */ 173 bus_space_write_4(psc.iot, psc.ioh, PIC_GIO32ARB_DELAY, 174 PIC_GIO32ARB_DEFDELAY); 175 176 printf("\n"); 177 178 /* 179 * A GIO bus exists on all IP12's. However, Personal Iris 180 * machines use VME for their expansion bus. 181 */ 182 iaa.iaa_name = "gio"; 183 (void) config_found(self, (void *) &iaa, pic_print); 184 185 pic_watchdog_enable(); 186 } 187 188 189 static int 190 pic_print(void *aux, const char *name) 191 { 192 struct pic_attach_args *iaa = aux; 193 194 if (name) 195 aprint_normal("%s at %s", iaa->iaa_name, name); 196 197 return (UNCONF); 198 } 199 200 static void 201 pic_bus_reset(void) 202 { 203 bus_space_write_4(psc.iot, psc.ioh, PIC_PARITY_ERROR, 0); 204 } 205 206 static void 207 pic_watchdog_enable(void) 208 { 209 uint32_t reg; 210 211 reg = bus_space_read_4(psc.iot, psc.ioh, PIC_CPUCTRL); 212 reg |= PIC_CPUCTRL_WDOG; 213 bus_space_write_4(psc.iot, psc.ioh, PIC_CPUCTRL, reg); 214 } 215 216 static void 217 pic_watchdog_disable(void) 218 { 219 uint32_t reg; 220 221 reg = bus_space_read_4(psc.iot, psc.ioh, PIC_CPUCTRL); 222 reg &= ~(PIC_CPUCTRL_WDOG); 223 bus_space_write_4(psc.iot, psc.ioh, PIC_CPUCTRL, reg); 224 } 225 226 static void 227 pic_watchdog_tickle(void) 228 { 229 230 pic_watchdog_disable(); 231 pic_watchdog_enable(); 232 } 233