1 /* $NetBSD: am79c930.c,v 1.7 2001/11/13 13:14:34 lukem Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Bill Sommerfeld 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 by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND 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 THE FOUNDATION OR CONTRIBUTORS 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 * Am79c930 chip driver. 41 * 42 * This is used by the awi driver to use the shared 43 * memory attached to the 79c930 to communicate with the firmware running 44 * in the 930's on-board 80188 core. 45 * 46 * The 79c930 can be mapped into just I/O space, or also have a 47 * memory mapping; the mapping must be set up by the bus front-end 48 * before am79c930_init is called. 49 */ 50 51 /* 52 * operations: 53 * 54 * read_8, read_16, read_32, read_64, read_bytes 55 * write_8, write_16, write_32, write_64, write_bytes 56 * (two versions, depending on whether memory-space or i/o space is in use). 57 * 58 * interrupt E.C. 59 * start isr 60 * end isr 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: am79c930.c,v 1.7 2001/11/13 13:14:34 lukem Exp $"); 65 66 #include <sys/param.h> 67 #include <sys/systm.h> 68 #ifndef __FreeBSD__ 69 #include <sys/device.h> 70 #endif 71 72 #include <machine/cpu.h> 73 #ifdef __FreeBSD__ 74 #include <machine/bus_pio.h> 75 #include <machine/bus_memio.h> 76 #endif 77 #include <machine/bus.h> 78 #ifdef __NetBSD__ 79 #include <machine/intr.h> 80 #endif 81 82 #ifdef __NetBSD__ 83 #include <dev/ic/am79c930reg.h> 84 #include <dev/ic/am79c930var.h> 85 #endif 86 #ifdef __FreeBSD__ 87 #include <dev/awi/am79c930reg.h> 88 #include <dev/awi/am79c930var.h> 89 #endif 90 91 #define AM930_DELAY(x) /*nothing*/ 92 93 void am79c930_regdump __P((struct am79c930_softc *sc)); 94 95 static void io_write_1 __P((struct am79c930_softc *, u_int32_t, u_int8_t)); 96 static void io_write_2 __P((struct am79c930_softc *, u_int32_t, u_int16_t)); 97 static void io_write_4 __P((struct am79c930_softc *, u_int32_t, u_int32_t)); 98 static void io_write_bytes __P((struct am79c930_softc *, u_int32_t, u_int8_t *, size_t)); 99 100 static u_int8_t io_read_1 __P((struct am79c930_softc *, u_int32_t)); 101 static u_int16_t io_read_2 __P((struct am79c930_softc *, u_int32_t)); 102 static u_int32_t io_read_4 __P((struct am79c930_softc *, u_int32_t)); 103 static void io_read_bytes __P((struct am79c930_softc *, u_int32_t, u_int8_t *, size_t)); 104 105 static void mem_write_1 __P((struct am79c930_softc *, u_int32_t, u_int8_t)); 106 static void mem_write_2 __P((struct am79c930_softc *, u_int32_t, u_int16_t)); 107 static void mem_write_4 __P((struct am79c930_softc *, u_int32_t, u_int32_t)); 108 static void mem_write_bytes __P((struct am79c930_softc *, u_int32_t, u_int8_t *, size_t)); 109 110 static u_int8_t mem_read_1 __P((struct am79c930_softc *, u_int32_t)); 111 static u_int16_t mem_read_2 __P((struct am79c930_softc *, u_int32_t)); 112 static u_int32_t mem_read_4 __P((struct am79c930_softc *, u_int32_t)); 113 static void mem_read_bytes __P((struct am79c930_softc *, u_int32_t, u_int8_t *, size_t)); 114 115 static struct am79c930_ops iospace_ops = { 116 io_write_1, 117 io_write_2, 118 io_write_4, 119 io_write_bytes, 120 io_read_1, 121 io_read_2, 122 io_read_4, 123 io_read_bytes 124 }; 125 126 struct am79c930_ops memspace_ops = { 127 mem_write_1, 128 mem_write_2, 129 mem_write_4, 130 mem_write_bytes, 131 mem_read_1, 132 mem_read_2, 133 mem_read_4, 134 mem_read_bytes 135 }; 136 137 static void io_write_1 (sc, off, val) 138 struct am79c930_softc *sc; 139 u_int32_t off; 140 u_int8_t val; 141 { 142 AM930_DELAY(1); 143 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_HI, 144 ((off>>8)& 0x7f)); 145 AM930_DELAY(1); 146 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_LO, (off&0xff)); 147 AM930_DELAY(1); 148 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_IODPA, val); 149 AM930_DELAY(1); 150 } 151 152 static void io_write_2 (sc, off, val) 153 struct am79c930_softc *sc; 154 u_int32_t off; 155 u_int16_t val; 156 { 157 AM930_DELAY(1); 158 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_HI, 159 ((off>>8)& 0x7f)); 160 AM930_DELAY(1); 161 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_LMA_LO, (off&0xff)); 162 AM930_DELAY(1); 163 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_IODPA, val & 0xff); 164 AM930_DELAY(1); 165 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_IODPA, (val>>8)&0xff); 166 AM930_DELAY(1); 167 } 168 169 static void io_write_4 (sc, off, val) 170 struct am79c930_softc *sc; 171 u_int32_t off; 172 u_int32_t val; 173 { 174 AM930_DELAY(1); 175 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_HI, 176 ((off>>8)& 0x7f)); 177 AM930_DELAY(1); 178 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_LMA_LO, (off&0xff)); 179 AM930_DELAY(1); 180 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_IODPA,val & 0xff); 181 AM930_DELAY(1); 182 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_IODPA,(val>>8)&0xff); 183 AM930_DELAY(1); 184 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_IODPA,(val>>16)&0xff); 185 AM930_DELAY(1); 186 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_IODPA,(val>>24)&0xff); 187 AM930_DELAY(1); 188 } 189 190 static void io_write_bytes (sc, off, ptr, len) 191 struct am79c930_softc *sc; 192 u_int32_t off; 193 u_int8_t *ptr; 194 size_t len; 195 { 196 int i; 197 198 AM930_DELAY(1); 199 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_HI, 200 ((off>>8)& 0x7f)); 201 AM930_DELAY(1); 202 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_LMA_LO, (off&0xff)); 203 AM930_DELAY(1); 204 for (i=0; i<len; i++) 205 bus_space_write_1(sc->sc_iot,sc->sc_ioh,AM79C930_IODPA,ptr[i]); 206 } 207 208 static u_int8_t io_read_1 (sc, off) 209 struct am79c930_softc *sc; 210 u_int32_t off; 211 { 212 u_int8_t val; 213 214 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_HI, 215 ((off>>8)& 0x7f)); 216 AM930_DELAY(1); 217 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_LO, (off&0xff)); 218 AM930_DELAY(1); 219 val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AM79C930_IODPA); 220 AM930_DELAY(1); 221 return val; 222 } 223 224 static u_int16_t io_read_2 (sc, off) 225 struct am79c930_softc *sc; 226 u_int32_t off; 227 { 228 u_int16_t val; 229 230 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_HI, 231 ((off>>8)& 0x7f)); 232 AM930_DELAY(1); 233 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_LO, (off&0xff)); 234 AM930_DELAY(1); 235 val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AM79C930_IODPA); 236 AM930_DELAY(1); 237 val |= bus_space_read_1(sc->sc_iot, sc->sc_ioh, AM79C930_IODPA) << 8; 238 AM930_DELAY(1); 239 return val; 240 } 241 242 static u_int32_t io_read_4 (sc, off) 243 struct am79c930_softc *sc; 244 u_int32_t off; 245 { 246 u_int32_t val; 247 248 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_HI, 249 ((off>>8)& 0x7f)); 250 AM930_DELAY(1); 251 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_LO, (off&0xff)); 252 AM930_DELAY(1); 253 val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AM79C930_IODPA); 254 AM930_DELAY(1); 255 val |= bus_space_read_1(sc->sc_iot, sc->sc_ioh, AM79C930_IODPA) << 8; 256 AM930_DELAY(1); 257 val |= bus_space_read_1(sc->sc_iot, sc->sc_ioh, AM79C930_IODPA) << 16; 258 AM930_DELAY(1); 259 val |= bus_space_read_1(sc->sc_iot, sc->sc_ioh, AM79C930_IODPA) << 24; 260 AM930_DELAY(1); 261 return val; 262 } 263 264 static void io_read_bytes (sc, off, ptr, len) 265 struct am79c930_softc *sc; 266 u_int32_t off; 267 u_int8_t *ptr; 268 size_t len; 269 { 270 int i; 271 272 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_HI, 273 ((off>>8)& 0x7f)); 274 AM930_DELAY(1); 275 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_LMA_LO, (off&0xff)); 276 AM930_DELAY(1); 277 for (i=0; i<len; i++) 278 ptr[i] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 279 AM79C930_IODPA); 280 } 281 282 static void mem_write_1 (sc, off, val) 283 struct am79c930_softc *sc; 284 u_int32_t off; 285 u_int8_t val; 286 { 287 bus_space_write_1(sc->sc_memt, sc->sc_memh, off, val); 288 } 289 290 static void mem_write_2 (sc, off, val) 291 struct am79c930_softc *sc; 292 u_int32_t off; 293 u_int16_t val; 294 { 295 bus_space_tag_t t = sc->sc_memt; 296 bus_space_handle_t h = sc->sc_memh; 297 298 /* could be unaligned */ 299 if ((off & 0x1) == 0) 300 bus_space_write_2(t, h, off, val); 301 else { 302 bus_space_write_1(t, h, off, val & 0xff); 303 bus_space_write_1(t, h, off+1, (val >> 8) & 0xff); 304 } 305 } 306 307 static void mem_write_4 (sc, off, val) 308 struct am79c930_softc *sc; 309 u_int32_t off; 310 u_int32_t val; 311 { 312 bus_space_tag_t t = sc->sc_memt; 313 bus_space_handle_t h = sc->sc_memh; 314 315 /* could be unaligned */ 316 if ((off & 0x3) == 0) 317 bus_space_write_4(t, h, off, val); 318 else { 319 bus_space_write_1(t, h, off, val & 0xff); 320 bus_space_write_1(t, h, off+1, (val >> 8) & 0xff); 321 bus_space_write_1(t, h, off+2, (val >> 16) & 0xff); 322 bus_space_write_1(t, h, off+3, (val >> 24) & 0xff); 323 } 324 } 325 326 static void mem_write_bytes (sc, off, ptr, len) 327 struct am79c930_softc *sc; 328 u_int32_t off; 329 u_int8_t *ptr; 330 size_t len; 331 { 332 bus_space_write_region_1 (sc->sc_memt, sc->sc_memh, off, ptr, len); 333 } 334 335 336 static u_int8_t mem_read_1 (sc, off) 337 struct am79c930_softc *sc; 338 u_int32_t off; 339 { 340 return bus_space_read_1(sc->sc_memt, sc->sc_memh, off); 341 } 342 343 static u_int16_t mem_read_2 (sc, off) 344 struct am79c930_softc *sc; 345 u_int32_t off; 346 { 347 /* could be unaligned */ 348 if ((off & 0x1) == 0) 349 return bus_space_read_2(sc->sc_memt, sc->sc_memh, off); 350 else 351 return 352 bus_space_read_1(sc->sc_memt, sc->sc_memh, off ) | 353 (bus_space_read_1(sc->sc_memt, sc->sc_memh, off+1) << 8); 354 } 355 356 static u_int32_t mem_read_4 (sc, off) 357 struct am79c930_softc *sc; 358 u_int32_t off; 359 { 360 /* could be unaligned */ 361 if ((off & 0x3) == 0) 362 return bus_space_read_4(sc->sc_memt, sc->sc_memh, off); 363 else 364 return 365 bus_space_read_1(sc->sc_memt, sc->sc_memh, off ) | 366 (bus_space_read_1(sc->sc_memt, sc->sc_memh, off+1) << 8) | 367 (bus_space_read_1(sc->sc_memt, sc->sc_memh, off+2) <<16) | 368 (bus_space_read_1(sc->sc_memt, sc->sc_memh, off+3) <<24); 369 } 370 371 372 373 static void mem_read_bytes (sc, off, ptr, len) 374 struct am79c930_softc *sc; 375 u_int32_t off; 376 u_int8_t *ptr; 377 size_t len; 378 { 379 bus_space_read_region_1 (sc->sc_memt, sc->sc_memh, off, ptr, len); 380 } 381 382 383 384 385 /* 386 * Set bits in GCR. 387 */ 388 389 void am79c930_gcr_setbits (sc, bits) 390 struct am79c930_softc *sc; 391 u_int8_t bits; 392 { 393 u_int8_t gcr = bus_space_read_1 (sc->sc_iot, sc->sc_ioh, AM79C930_GCR); 394 395 gcr |= bits; 396 397 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_GCR, gcr); 398 } 399 400 /* 401 * Clear bits in GCR. 402 */ 403 404 void am79c930_gcr_clearbits (sc, bits) 405 struct am79c930_softc *sc; 406 u_int8_t bits; 407 { 408 u_int8_t gcr = bus_space_read_1 (sc->sc_iot, sc->sc_ioh, AM79C930_GCR); 409 410 gcr &= ~bits; 411 412 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_GCR, gcr); 413 } 414 415 u_int8_t am79c930_gcr_read (sc) 416 struct am79c930_softc *sc; 417 { 418 return bus_space_read_1 (sc->sc_iot, sc->sc_ioh, AM79C930_GCR); 419 } 420 421 #if 0 422 void am79c930_regdump (sc) 423 struct am79c930_softc *sc; 424 { 425 u_int8_t buf[8]; 426 int i; 427 428 AM930_DELAY(5); 429 for (i=0; i<8; i++) { 430 buf[i] = bus_space_read_1 (sc->sc_iot, sc->sc_ioh, i); 431 AM930_DELAY(5); 432 } 433 printf("am79c930: regdump:"); 434 for (i=0; i<8; i++) { 435 printf(" %02x", buf[i]); 436 } 437 printf("\n"); 438 } 439 #endif 440 441 void am79c930_chip_init (sc, how) 442 struct am79c930_softc *sc; 443 { 444 /* zero the bank select register, and leave it that way.. */ 445 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AM79C930_BSS, 0); 446 if (how) 447 sc->sc_ops = &memspace_ops; 448 else 449 sc->sc_ops = &iospace_ops; 450 } 451 452 453