i81342.c revision 278613
1/*- 2 * Copyright (c) 2006 Olivier Houchard 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/i81342.c 278613 2015-02-12 03:50:33Z ian $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/kernel.h> 34#include <sys/module.h> 35 36#define _ARM32_BUS_DMA_PRIVATE 37#include <machine/armreg.h> 38#include <machine/bus.h> 39#include <machine/intr.h> 40 41#include <arm/xscale/i8134x/i81342reg.h> 42#include <arm/xscale/i8134x/i81342var.h> 43 44#define WDTCR_ENABLE1 0x1e1e1e1e 45#define WDTCR_ENABLE2 0xe1e1e1e1 46 47static volatile int intr_enabled0; 48static volatile int intr_enabled1; 49static volatile int intr_enabled2; 50static volatile int intr_enabled3; 51 52struct bus_space i81342_bs_tag; 53 54/* Read the interrupt pending register */ 55 56static __inline 57uint32_t intpnd0_read(void) 58{ 59 uint32_t ret; 60 61 __asm __volatile("mrc p6, 0, %0, c0, c3, 0" 62 : "=r" (ret)); 63 return (ret); 64} 65 66static __inline 67uint32_t intpnd1_read(void) 68{ 69 uint32_t ret; 70 71 __asm __volatile("mrc p6, 0, %0, c1, c3, 0" 72 : "=r" (ret)); 73 return (ret); 74} 75 76static __inline 77uint32_t intpnd2_read(void) 78{ 79 uint32_t ret; 80 81 __asm __volatile("mrc p6, 0, %0, c2, c3, 0" 82 : "=r" (ret)); 83 return (ret); 84} 85 86static __inline 87uint32_t intpnd3_read(void) 88{ 89 uint32_t ret; 90 91 __asm __volatile("mrc p6, 0, %0, c3, c3, 0" 92 : "=r" (ret)); 93 return (ret); 94} 95 96/* Read the interrupt control register */ 97/* 0 masked, 1 unmasked */ 98static __inline 99uint32_t intctl0_read(void) 100{ 101 uint32_t ret; 102 103 __asm __volatile("mrc p6, 0, %0, c0, c4, 0" 104 : "=r" (ret)); 105 return (ret); 106} 107 108static __inline 109uint32_t intctl1_read(void) 110{ 111 uint32_t ret; 112 113 __asm __volatile("mrc p6, 0, %0, c1, c4, 0" 114 : "=r" (ret)); 115 return (ret); 116} 117 118static __inline 119uint32_t intctl2_read(void) 120{ 121 uint32_t ret; 122 123 __asm __volatile("mrc p6, 0, %0, c2, c4, 0" 124 : "=r" (ret)); 125 return (ret); 126} 127 128static __inline 129uint32_t intctl3_read(void) 130{ 131 uint32_t ret; 132 133 __asm __volatile("mrc p6, 0, %0, c3, c4, 0" 134 : "=r" (ret)); 135 return (ret); 136} 137 138/* Write the interrupt control register */ 139 140static __inline 141void intctl0_write(uint32_t val) 142{ 143 144 __asm __volatile("mcr p6, 0, %0, c0, c4, 0" 145 : : "r" (val)); 146} 147 148static __inline 149void intctl1_write(uint32_t val) 150{ 151 152 __asm __volatile("mcr p6, 0, %0, c1, c4, 0" 153 : : "r" (val)); 154} 155 156static __inline 157void intctl2_write(uint32_t val) 158{ 159 160 __asm __volatile("mcr p6, 0, %0, c2, c4, 0" 161 : : "r" (val)); 162} 163 164static __inline 165void intctl3_write(uint32_t val) 166{ 167 168 __asm __volatile("mcr p6, 0, %0, c3, c4, 0" 169 : : "r" (val)); 170} 171 172/* Read the interrupt steering register */ 173/* 0 IRQ 1 FIQ */ 174static __inline 175uint32_t intstr0_read(void) 176{ 177 uint32_t ret; 178 179 __asm __volatile("mrc p6, 0, %0, c0, c5, 0" 180 : "=r" (ret)); 181 return (ret); 182} 183 184static __inline 185uint32_t intstr1_read(void) 186{ 187 uint32_t ret; 188 189 __asm __volatile("mrc p6, 0, %0, c1, c5, 0" 190 : "=r" (ret)); 191 return (ret); 192} 193 194static __inline 195uint32_t intstr2_read(void) 196{ 197 uint32_t ret; 198 199 __asm __volatile("mrc p6, 0, %0, c2, c5, 0" 200 : "=r" (ret)); 201 return (ret); 202} 203 204static __inline 205uint32_t intstr3_read(void) 206{ 207 uint32_t ret; 208 209 __asm __volatile("mrc p6, 0, %0, c3, c5, 0" 210 : "=r" (ret)); 211 return (ret); 212} 213 214/* Write the interrupt steering register */ 215 216static __inline 217void intstr0_write(uint32_t val) 218{ 219 220 __asm __volatile("mcr p6, 0, %0, c0, c5, 0" 221 : : "r" (val)); 222} 223 224static __inline 225void intstr1_write(uint32_t val) 226{ 227 228 __asm __volatile("mcr p6, 0, %0, c1, c5, 0" 229 : : "r" (val)); 230} 231 232static __inline 233void intstr2_write(uint32_t val) 234{ 235 236 __asm __volatile("mcr p6, 0, %0, c2, c5, 0" 237 : : "r" (val)); 238} 239 240static __inline 241void intstr3_write(uint32_t val) 242{ 243 244 __asm __volatile("mcr p6, 0, %0, c3, c5, 0" 245 : : "r" (val)); 246} 247 248void 249cpu_reset(void) 250{ 251 252 disable_interrupts(PSR_I); 253 /* XXX: Use the watchdog to reset for now */ 254 __asm __volatile("mcr p6, 0, %0, c8, c9, 0\n" 255 "mcr p6, 0, %1, c7, c9, 0\n" 256 "mcr p6, 0, %2, c7, c9, 0\n" 257 : : "r" (1), "r" (WDTCR_ENABLE1), "r" (WDTCR_ENABLE2)); 258 while (1); 259} 260 261void 262arm_mask_irq(uintptr_t nb) 263{ 264 265 if (nb < 32) { 266 intr_enabled0 &= ~(1 << nb); 267 intctl0_write(intr_enabled0); 268 } else if (nb < 64) { 269 intr_enabled1 &= ~(1 << (nb - 32)); 270 intctl1_write(intr_enabled1); 271 } else if (nb < 96) { 272 intr_enabled2 &= ~(1 << (nb - 64)); 273 intctl2_write(intr_enabled2); 274 } else { 275 intr_enabled3 &= ~(1 << (nb - 96)); 276 intctl3_write(intr_enabled3); 277 } 278} 279 280void 281arm_unmask_irq(uintptr_t nb) 282{ 283 if (nb < 32) { 284 intr_enabled0 |= (1 << nb); 285 intctl0_write(intr_enabled0); 286 } else if (nb < 64) { 287 intr_enabled1 |= (1 << (nb - 32)); 288 intctl1_write(intr_enabled1); 289 } else if (nb < 96) { 290 intr_enabled2 |= (1 << (nb - 64)); 291 intctl2_write(intr_enabled2); 292 } else { 293 intr_enabled3 |= (1 << (nb - 96)); 294 intctl3_write(intr_enabled3); 295 } 296} 297 298int 299arm_get_next_irq(int last __unused) 300{ 301 uint32_t val; 302 val = intpnd0_read() & intr_enabled0; 303 if (val) 304 return (ffs(val) - 1); 305 val = intpnd1_read() & intr_enabled1; 306 if (val) 307 return (32 + ffs(val) - 1); 308 val = intpnd2_read() & intr_enabled2; 309 if (val) 310 return (64 + ffs(val) - 1); 311 val = intpnd3_read() & intr_enabled3; 312 if (val) 313 return (96 + ffs(val) - 1); 314 return (-1); 315} 316 317int 318bus_dma_get_range_nb(void) 319{ 320 return (0); 321} 322 323struct arm32_dma_range * 324bus_dma_get_range(void) 325{ 326 return (NULL); 327} 328 329static int 330i81342_probe(device_t dev) 331{ 332 unsigned int freq; 333 334 freq = *(volatile unsigned int *)(IOP34X_VADDR + IOP34X_PFR); 335 336 switch (freq & IOP34X_FREQ_MASK) { 337 case IOP34X_FREQ_600: 338 device_set_desc(dev, "Intel 81342 600MHz"); 339 break; 340 case IOP34X_FREQ_667: 341 device_set_desc(dev, "Intel 81342 667MHz"); 342 break; 343 case IOP34X_FREQ_800: 344 device_set_desc(dev, "Intel 81342 800MHz"); 345 break; 346 case IOP34X_FREQ_833: 347 device_set_desc(dev, "Intel 81342 833MHz"); 348 break; 349 case IOP34X_FREQ_1000: 350 device_set_desc(dev, "Intel 81342 1000MHz"); 351 break; 352 case IOP34X_FREQ_1200: 353 device_set_desc(dev, "Intel 81342 1200MHz"); 354 break; 355 default: 356 device_set_desc(dev, "Intel 81342 unknown frequency"); 357 break; 358 } 359 return (0); 360} 361 362static void 363i81342_identify(driver_t *driver, device_t parent) 364{ 365 366 BUS_ADD_CHILD(parent, 0, "iq", 0); 367} 368 369static int 370i81342_attach(device_t dev) 371{ 372 struct i81342_softc *sc = device_get_softc(dev); 373 uint32_t esstrsr; 374 375 i81342_bs_init(&i81342_bs_tag, sc); 376 sc->sc_st = &i81342_bs_tag; 377 sc->sc_sh = IOP34X_VADDR; 378 esstrsr = bus_space_read_4(sc->sc_st, sc->sc_sh, IOP34X_ESSTSR0); 379 sc->sc_atux_sh = IOP34X_ATUX_ADDR(esstrsr) - IOP34X_HWADDR + 380 IOP34X_VADDR; 381 sc->sc_atue_sh = IOP34X_ATUE_ADDR(esstrsr) - IOP34X_HWADDR + 382 IOP34X_VADDR; 383 /* Disable all interrupts. */ 384 intctl0_write(0); 385 intctl1_write(0); 386 intctl2_write(0); 387 intctl3_write(0); 388 /* Defaults to IRQ */ 389 intstr0_write(0); 390 intstr1_write(0); 391 intstr2_write(0); 392 intstr3_write(0); 393 sc->sc_irq_rman.rm_type = RMAN_ARRAY; 394 sc->sc_irq_rman.rm_descr = "i81342 IRQs"; 395 if (rman_init(&sc->sc_irq_rman) != 0 || 396 rman_manage_region(&sc->sc_irq_rman, 0, 127) != 0) 397 panic("i81342_attach: failed to set up IRQ rman"); 398 399 device_add_child(dev, "obio", 0); 400 device_add_child(dev, "itimer", 0); 401 device_add_child(dev, "iopwdog", 0); 402 device_add_child(dev, "pcib", 0); 403 device_add_child(dev, "pcib", 1); 404 device_add_child(dev, "iqseg", 0); 405 bus_generic_probe(dev); 406 bus_generic_attach(dev); 407 return (0); 408} 409 410static struct resource * 411i81342_alloc_resource(device_t dev, device_t child, int type, int *rid, 412 u_long start, u_long end, u_long count, u_int flags) 413{ 414 struct i81342_softc *sc = device_get_softc(dev); 415 struct resource *rv; 416 417 if (type == SYS_RES_IRQ) { 418 rv = rman_reserve_resource(&sc->sc_irq_rman, 419 start, end, count, flags, child); 420 if (rv != NULL) 421 rman_set_rid(rv, *rid); 422 return (rv); 423 } 424 425 return (NULL); 426} 427 428static int 429i81342_setup_intr(device_t dev, device_t child, struct resource *ires, 430 int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, 431 void **cookiep) 432{ 433 int error; 434 435 error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, 436 filt, intr, arg, cookiep); 437 if (error) 438 return (error); 439 return (0); 440} 441 442static int 443i81342_teardown_intr(device_t dev, device_t child, struct resource *res, 444 void *cookie) 445{ 446 return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); 447} 448 449static device_method_t i81342_methods[] = { 450 DEVMETHOD(device_probe, i81342_probe), 451 DEVMETHOD(device_attach, i81342_attach), 452 DEVMETHOD(device_identify, i81342_identify), 453 DEVMETHOD(bus_alloc_resource, i81342_alloc_resource), 454 DEVMETHOD(bus_setup_intr, i81342_setup_intr), 455 DEVMETHOD(bus_teardown_intr, i81342_teardown_intr), 456 {0, 0}, 457}; 458 459static driver_t i81342_driver = { 460 "iq", 461 i81342_methods, 462 sizeof(struct i81342_softc), 463}; 464static devclass_t i81342_devclass; 465 466DRIVER_MODULE(iq, nexus, i81342_driver, i81342_devclass, 0, 0); 467