1 /* $NetBSD: obs600_machdep.c,v 1.2 2010/12/20 00:25:32 matt Exp $ */ 2 /* Original: md_machdep.c,v 1.3 2005/01/24 18:47:37 shige Exp $ */ 3 4 /* 5 * Copyright 2001, 2002 Wasabi Systems, Inc. 6 * All rights reserved. 7 * 8 * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed for the NetBSD Project by 21 * Wasabi Systems, Inc. 22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 * or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 41 * Copyright (C) 1995, 1996 TooLs GmbH. 42 * All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by TooLs GmbH. 55 * 4. The name of TooLs GmbH may not be used to endorse or promote products 56 * derived from this software without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 61 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 62 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 63 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 64 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 65 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 66 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 67 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 68 */ 69 70 #include <sys/cdefs.h> 71 __KERNEL_RCSID(0, "$NetBSD: obs600_machdep.c,v 1.2 2010/12/20 00:25:32 matt Exp $"); 72 73 #include "opt_compat_netbsd.h" 74 #include "opt_ddb.h" 75 #include "opt_ipkdb.h" 76 #include "opt_modular.h" 77 78 #include <sys/param.h> 79 #include <sys/bus.h> 80 #include <sys/errno.h> 81 #include <sys/kernel.h> 82 #include <sys/ksyms.h> 83 #include <sys/mount.h> 84 #include <sys/reboot.h> 85 #include <sys/systm.h> 86 #include <sys/device.h> 87 88 #include <uvm/uvm_extern.h> 89 90 #include <machine/bus.h> 91 #include <machine/cpu.h> 92 #include <machine/obs600.h> 93 94 #include <powerpc/ibm4xx/amcc405ex.h> 95 #include <powerpc/ibm4xx/dcr4xx.h> 96 #include <powerpc/ibm4xx/dev/comopbvar.h> 97 #include <powerpc/ibm4xx/dev/gpiicreg.h> 98 #include <powerpc/ibm4xx/dev/opbvar.h> 99 #include <powerpc/ibm4xx/spr.h> 100 #include <powerpc/spr.h> 101 102 #include <dev/ic/comreg.h> 103 104 #include "ksyms.h" 105 106 #include "com.h" 107 #if (NCOM > 0) 108 #include <sys/termios.h> 109 110 #ifndef CONADDR 111 #define CONADDR AMCC405EX_UART0_BASE 112 #endif 113 #ifndef CONSPEED 114 #define CONSPEED B115200 115 #endif 116 #ifndef CONMODE 117 /* 8N1 */ 118 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) 119 #endif 120 #endif /* NCOM */ 121 122 /* 123 * XXXX: 124 * It is very troublesome though we can calculate from various registers. X-< 125 */ 126 #define OBS600_CPU_FREQ (600 * 1000 * 1000) 127 #define OBS600_MEM_SIZE (1 * 1024 * 1024 * 1024) 128 129 #define TLB_PG_SIZE (16 * 1024 * 1024) 130 131 /* 132 * Global variables used here and there 133 */ 134 char bootpath[256]; 135 136 extern paddr_t msgbuf_paddr; 137 138 #if NKSYMS || defined(DDB) || defined(MODULAR) 139 void *startsym, *endsym; 140 #endif 141 142 void initppc(u_int, u_int, int, char *[], char *); 143 int lcsplx(int); 144 static int read_eeprom(int, char *); 145 146 147 void 148 initppc(u_int startkernel, u_int endkernel, int argc, char *argv[], 149 char *argstr) 150 { 151 vaddr_t va; 152 u_int memsize; 153 154 memsize = OBS600_MEM_SIZE; 155 156 /* Linear map kernel memory */ 157 for (va = 0; va < endkernel; va += TLB_PG_SIZE) 158 ppc4xx_tlb_reserve(va, va, TLB_PG_SIZE, TLB_EX); 159 160 /* 161 * Map console and I2C after RAM. (see pmap_tlbmiss()) 162 * All peripherals mapped on a page. 163 */ 164 ppc4xx_tlb_reserve(AMCC405EX_OPB_BASE, roundup(memsize, TLB_PG_SIZE), 165 TLB_PG_SIZE, TLB_I | TLB_G); 166 167 /* Initialize AMCC 405EX CPU */ 168 ibm40x_memsize_init(memsize, startkernel); 169 ibm4xx_init((void (*)(void))ext_intr); 170 171 /* Disable Watchdog, PIT and FIT interrupts. (u-boot uses PIT...) */ 172 mtspr(SPR_TCR, 0); 173 174 /* 175 * Set the page size. 176 */ 177 uvm_setpagesize(); 178 179 /* 180 * Initialize pmap module. 181 */ 182 pmap_bootstrap(startkernel, endkernel); 183 184 185 #if NKSYMS || defined(DDB) || defined(MODULAR) 186 ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 187 #endif 188 #ifdef DDB 189 if (boothowto & RB_KDB) 190 Debugger(); 191 #endif 192 #ifdef IPKDB 193 /* 194 * Now trap to IPKDB 195 */ 196 ipkdb_init(); 197 if (boothowto & RB_KDB) 198 ipkdb_connect(0); 199 #endif 200 } 201 202 void 203 consinit(void) 204 { 205 206 #if (NCOM > 0) 207 com_opb_cnattach(OBS600_COM_FREQ, CONADDR, CONSPEED, CONMODE); 208 #endif /* NCOM */ 209 } 210 211 int 212 lcsplx(int ipl) 213 { 214 215 return spllower(ipl); /* XXX */ 216 } 217 218 219 /* 220 * Machine dependent startup code. 221 */ 222 void 223 cpu_startup(void) 224 { 225 prop_number_t pn; 226 prop_data_t pd; 227 u_char *macaddr, *macaddr1; 228 static u_char buf[16]; /* MAC address x2 buffer */ 229 230 /* 231 * cpu common startup 232 */ 233 ibm4xx_cpu_startup("OpenBlockS600 AMCC PowerPC 405EX Board"); 234 235 /* 236 * Set up the board properties database. 237 */ 238 board_info_init(); 239 240 read_eeprom(sizeof(buf), buf); 241 macaddr = &buf[0]; 242 macaddr1 = &buf[8]; 243 244 pn = prop_number_create_integer(OBS600_CPU_FREQ); 245 KASSERT(pn != NULL); 246 if (prop_dictionary_set(board_properties, "processor-frequency", pn) == 247 false) 248 panic("setting processor-frequency"); 249 prop_object_release(pn); 250 251 pn = prop_number_create_integer(OBS600_MEM_SIZE); 252 KASSERT(pn != NULL); 253 if (prop_dictionary_set(board_properties, "mem-size", pn) == false) 254 panic("setting mem-size"); 255 prop_object_release(pn); 256 257 #define ETHER_ADDR_LEN 6 258 259 pd = prop_data_create_data_nocopy(macaddr, ETHER_ADDR_LEN); 260 KASSERT(pd != NULL); 261 if (prop_dictionary_set(board_properties, "emac0-mac-addr", pd) == 262 false) 263 panic("setting emac0-mac-addr"); 264 prop_object_release(pd); 265 pd = prop_data_create_data_nocopy(macaddr1, ETHER_ADDR_LEN); 266 KASSERT(pd != NULL); 267 if (prop_dictionary_set(board_properties, "emac1-mac-addr", pd) == 268 false) 269 panic("setting emac1-mac-addr"); 270 prop_object_release(pd); 271 272 /* emac0 connects to phy 2 and emac1 to phy 3 via RGMII. */ 273 pn = prop_number_create_integer(2); 274 KASSERT(pn != NULL); 275 if (prop_dictionary_set(board_properties, "emac0-mii-phy", pn) == false) 276 panic("setting emac0-mii-phy"); 277 prop_object_release(pn); 278 pn = prop_number_create_integer(3); 279 KASSERT(pn != NULL); 280 if (prop_dictionary_set(board_properties, "emac1-mii-phy", pn) == false) 281 panic("setting emac1-mii-phy"); 282 prop_object_release(pn); 283 284 /* 285 * Now that we have VM, malloc()s are OK in bus_space. 286 */ 287 bus_space_mallocok(); 288 289 /* 290 * no fake mapiodev 291 */ 292 fake_mapiodev = 0; 293 } 294 295 /* 296 * Halt or reboot the machine after syncing/dumping according to howto. 297 */ 298 void 299 cpu_reboot(int howto, char *what) 300 { 301 static int syncing; 302 static char str[256]; 303 char *ap = str, *ap1 = ap; 304 305 boothowto = howto; 306 if (!cold && !(howto & RB_NOSYNC) && !syncing) { 307 syncing = 1; 308 vfs_shutdown(); /* sync */ 309 resettodr(); /* set wall clock */ 310 } 311 312 splhigh(); 313 314 if (!cold && (howto & RB_DUMP)) 315 ibm4xx_dumpsys(); 316 317 doshutdownhooks(); 318 319 pmf_system_shutdown(boothowto); 320 321 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 322 /* Power off here if we know how...*/ 323 } 324 325 if (howto & RB_HALT) { 326 printf("halted\n\n"); 327 328 #if 0 329 goto reboot; /* XXX for now... */ 330 #endif 331 332 #ifdef DDB 333 printf("dropping to debugger\n"); 334 while(1) 335 Debugger(); 336 #endif 337 } 338 339 printf("rebooting\n\n"); 340 if (what && *what) { 341 if (strlen(what) > sizeof str - 5) 342 printf("boot string too large, ignored\n"); 343 else { 344 strcpy(str, what); 345 ap1 = ap = str + strlen(str); 346 *ap++ = ' '; 347 } 348 } 349 *ap++ = '-'; 350 if (howto & RB_SINGLE) 351 *ap++ = 's'; 352 if (howto & RB_KDB) 353 *ap++ = 'd'; 354 *ap++ = 0; 355 if (ap[-2] == '-') 356 *ap1 = 0; 357 358 /* flush cache for msgbuf */ 359 __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); 360 361 #if 0 362 reboot: 363 #endif 364 ppc4xx_reset(); 365 366 printf("ppc4xx_reset() failed!\n"); 367 #ifdef DDB 368 while(1) 369 Debugger(); 370 #else 371 while (1) 372 /* nothing */; 373 #endif 374 } 375 376 /* This function assume already initialized for I2C... */ 377 static int 378 read_eeprom(int len, char *buf) 379 { 380 bus_space_tag_t bst = opb_get_bus_space_tag(); 381 bus_space_handle_t bsh; 382 uint8_t mdcntl, sts; 383 int cnt, i = 0; 384 385 #define I2C_EEPROM_ADDR 0x52 386 387 if (bus_space_map(bst, AMCC405EX_IIC0_BASE, IIC_NREG, 0, &bsh)) 388 return ENOMEM; /* ??? */ 389 390 /* Clear Stop Complete Bit */ 391 bus_space_write_1(bst, bsh, IIC_STS, IIC_STS_SCMP); 392 /* Check init */ 393 do { 394 /* Get status */ 395 sts = bus_space_read_1(bst, bsh, IIC_STS); 396 } while ((sts & IIC_STS_PT)); 397 398 mdcntl = bus_space_read_1(bst, bsh, IIC_MDCNTL); 399 bus_space_write_1(bst, bsh, IIC_MDCNTL, 400 mdcntl | IIC_MDCNTL_FMDB | IIC_MDCNTL_FSDB); 401 402 /* 7-bit adressing */ 403 bus_space_write_1(bst, bsh, IIC_HMADR, 0); 404 bus_space_write_1(bst, bsh, IIC_LMADR, I2C_EEPROM_ADDR << 1); 405 406 bus_space_write_1(bst, bsh, IIC_MDBUF, 0); 407 bus_space_write_1(bst, bsh, IIC_CNTL, IIC_CNTL_PT); 408 do { 409 /* Get status */ 410 sts = bus_space_read_1(bst, bsh, IIC_STS); 411 } while ((sts & IIC_STS_PT) && !(sts & IIC_STS_ERR)); 412 413 cnt = 0; 414 while (cnt < len) { 415 /* always read 4byte */ 416 bus_space_write_1(bst, bsh, IIC_CNTL, 417 IIC_CNTL_PT | IIC_CNTL_RW | IIC_CNTL_TCT); 418 do { 419 /* Get status */ 420 sts = bus_space_read_1(bst, bsh, IIC_STS); 421 } while ((sts & IIC_STS_PT) && !(sts & IIC_STS_ERR)); 422 423 if ((sts & IIC_STS_PT) || (sts & IIC_STS_ERR)) 424 break; 425 if (sts & IIC_STS_MDBS) { 426 delay(1); 427 /* read 4byte */ 428 for (i = 0; i < 4 && cnt < len; i++, cnt++) 429 buf[cnt] = 430 bus_space_read_1(bst, bsh, IIC_MDBUF); 431 } 432 } 433 for ( ; i < 4; i++) 434 (void) bus_space_read_1(bst, bsh, IIC_MDBUF); 435 436 bus_space_unmap(bst, bsh, IIC_NREG); 437 438 return (cnt == len) ? 0 : EINVAL; 439 } 440