1 /* Blackfin System Interrupt Controller (SIC) model. 2 3 Copyright (C) 2010-2023 Free Software Foundation, Inc. 4 Contributed by Analog Devices, Inc. 5 6 This file is part of simulators. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 /* This must come before any other includes. */ 22 #include "defs.h" 23 24 #include "sim-main.h" 25 #include "devices.h" 26 #include "dv-bfin_sic.h" 27 #include "dv-bfin_cec.h" 28 29 struct bfin_sic 30 { 31 /* We assume first element is the base. */ 32 bu32 base; 33 34 /* Order after here is important -- matches hardware MMR layout. */ 35 bu16 BFIN_MMR_16(swrst); 36 bu16 BFIN_MMR_16(syscr); 37 bu16 BFIN_MMR_16(rvect); /* XXX: BF59x has a 32bit AUX_REVID here. */ 38 union { 39 struct { 40 bu32 imask0; 41 bu32 iar0, iar1, iar2, iar3; 42 bu32 isr0, iwr0; 43 bu32 _pad0[9]; 44 bu32 imask1; 45 bu32 iar4, iar5, iar6, iar7; 46 bu32 isr1, iwr1; 47 } bf52x; 48 struct { 49 bu32 imask; 50 bu32 iar0, iar1, iar2, iar3; 51 bu32 isr, iwr; 52 } bf537; 53 struct { 54 bu32 imask0, imask1, imask2; 55 bu32 isr0, isr1, isr2; 56 bu32 iwr0, iwr1, iwr2; 57 bu32 iar0, iar1, iar2, iar3; 58 bu32 iar4, iar5, iar6, iar7; 59 bu32 iar8, iar9, iar10, iar11; 60 } bf54x; 61 struct { 62 bu32 imask0, imask1; 63 bu32 iar0, iar1, iar2, iar3; 64 bu32 iar4, iar5, iar6, iar7; 65 bu32 isr0, isr1; 66 bu32 iwr0, iwr1; 67 } bf561; 68 }; 69 }; 70 #define mmr_base() offsetof(struct bfin_sic, swrst) 71 #define mmr_offset(mmr) (offsetof(struct bfin_sic, mmr) - mmr_base()) 72 #define mmr_idx(mmr) (mmr_offset (mmr) / 4) 73 74 static const char * const bf52x_mmr_names[] = 75 { 76 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IAR0", "SIC_IAR1", 77 "SIC_IAR2", "SIC_IAR3", "SIC_ISR0", "SIC_IWR0", 78 [mmr_idx (bf52x.imask1)] = "SIC_IMASK1", "SIC_IAR4", "SIC_IAR5", 79 "SIC_IAR6", "SIC_IAR7", "SIC_ISR1", "SIC_IWR1", 80 }; 81 static const char * const bf537_mmr_names[] = 82 { 83 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK", "SIC_IAR0", "SIC_IAR1", 84 "SIC_IAR2", "SIC_IAR3", "SIC_ISR", "SIC_IWR", 85 }; 86 static const char * const bf54x_mmr_names[] = 87 { 88 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IMASK1", "SIC_IMASK2", 89 "SIC_ISR0", "SIC_ISR1", "SIC_ISR2", "SIC_IWR0", "SIC_IWR1", "SIC_IWR2", 90 "SIC_IAR0", "SIC_IAR1", "SIC_IAR2", "SIC_IAR3", 91 "SIC_IAR4", "SIC_IAR5", "SIC_IAR6", "SIC_IAR7", 92 "SIC_IAR8", "SIC_IAR9", "SIC_IAR10", "SIC_IAR11", 93 }; 94 static const char * const bf561_mmr_names[] = 95 { 96 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IMASK1", 97 "SIC_IAR0", "SIC_IAR1", "SIC_IAR2", "SIC_IAR3", 98 "SIC_IAR4", "SIC_IAR5", "SIC_IAR6", "SIC_IAR7", 99 "SIC_ISR0", "SIC_ISR1", "SIC_IWR0", "SIC_IWR1", 100 }; 101 static const char * const *mmr_names; 102 #define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>") 103 104 static void 105 bfin_sic_forward_interrupts (struct hw *me, bu32 *isr, bu32 *imask, bu32 *iar) 106 { 107 int my_port; 108 bu32 ipend; 109 110 /* Process pending and unmasked interrupts. */ 111 ipend = *isr & *imask; 112 113 /* Usually none are pending unmasked, so avoid bit twiddling. */ 114 if (!ipend) 115 return; 116 117 for (my_port = 0; my_port < 32; ++my_port) 118 { 119 bu32 iar_idx, iar_off, iar_val; 120 bu32 bit = (1 << my_port); 121 122 /* This bit isn't pending, so check next one. */ 123 if (!(ipend & bit)) 124 continue; 125 126 /* The IAR registers map the System input to the Core output. 127 Every 4 bits in the IAR are used to map to IVG{7..15}. */ 128 iar_idx = my_port / 8; 129 iar_off = (my_port % 8) * 4; 130 iar_val = (iar[iar_idx] & (0xf << iar_off)) >> iar_off; 131 HW_TRACE ((me, "forwarding int %i to CEC", IVG7 + iar_val)); 132 hw_port_event (me, IVG7 + iar_val, 1); 133 } 134 } 135 136 static void 137 bfin_sic_52x_forward_interrupts (struct hw *me, struct bfin_sic *sic) 138 { 139 bfin_sic_forward_interrupts (me, &sic->bf52x.isr0, &sic->bf52x.imask0, &sic->bf52x.iar0); 140 bfin_sic_forward_interrupts (me, &sic->bf52x.isr1, &sic->bf52x.imask1, &sic->bf52x.iar4); 141 } 142 143 static unsigned 144 bfin_sic_52x_io_write_buffer (struct hw *me, const void *source, int space, 145 address_word addr, unsigned nr_bytes) 146 { 147 struct bfin_sic *sic = hw_data (me); 148 bu32 mmr_off; 149 bu32 value; 150 bu16 *value16p; 151 bu32 *value32p; 152 void *valuep; 153 154 /* Invalid access mode is higher priority than missing register. */ 155 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true)) 156 return 0; 157 158 if (nr_bytes == 4) 159 value = dv_load_4 (source); 160 else 161 value = dv_load_2 (source); 162 163 mmr_off = addr - sic->base; 164 valuep = (void *)((uintptr_t)sic + mmr_base() + mmr_off); 165 value16p = valuep; 166 value32p = valuep; 167 168 HW_TRACE_WRITE (); 169 170 /* XXX: Discard all SIC writes for now. */ 171 switch (mmr_off) 172 { 173 case mmr_offset(swrst): 174 /* XXX: This should trigger a software reset ... */ 175 break; 176 case mmr_offset(syscr): 177 /* XXX: what to do ... */ 178 break; 179 case mmr_offset(bf52x.imask0): 180 case mmr_offset(bf52x.imask1): 181 bfin_sic_52x_forward_interrupts (me, sic); 182 *value32p = value; 183 break; 184 case mmr_offset(bf52x.iar0) ... mmr_offset(bf52x.iar3): 185 case mmr_offset(bf52x.iar4) ... mmr_offset(bf52x.iar7): 186 case mmr_offset(bf52x.iwr0): 187 case mmr_offset(bf52x.iwr1): 188 *value32p = value; 189 break; 190 case mmr_offset(bf52x.isr0): 191 case mmr_offset(bf52x.isr1): 192 /* ISR is read-only. */ 193 break; 194 default: 195 /* XXX: Should discard other writes. */ 196 ; 197 } 198 199 return nr_bytes; 200 } 201 202 static unsigned 203 bfin_sic_52x_io_read_buffer (struct hw *me, void *dest, int space, 204 address_word addr, unsigned nr_bytes) 205 { 206 struct bfin_sic *sic = hw_data (me); 207 bu32 mmr_off; 208 bu16 *value16p; 209 bu32 *value32p; 210 void *valuep; 211 212 /* Invalid access mode is higher priority than missing register. */ 213 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false)) 214 return 0; 215 216 mmr_off = addr - sic->base; 217 valuep = (void *)((uintptr_t)sic + mmr_base() + mmr_off); 218 value16p = valuep; 219 value32p = valuep; 220 221 HW_TRACE_READ (); 222 223 switch (mmr_off) 224 { 225 case mmr_offset(swrst): 226 case mmr_offset(syscr): 227 case mmr_offset(rvect): 228 dv_store_2 (dest, *value16p); 229 break; 230 case mmr_offset(bf52x.imask0): 231 case mmr_offset(bf52x.imask1): 232 case mmr_offset(bf52x.iar0) ... mmr_offset(bf52x.iar3): 233 case mmr_offset(bf52x.iar4) ... mmr_offset(bf52x.iar7): 234 case mmr_offset(bf52x.iwr0): 235 case mmr_offset(bf52x.iwr1): 236 case mmr_offset(bf52x.isr0): 237 case mmr_offset(bf52x.isr1): 238 dv_store_4 (dest, *value32p); 239 break; 240 default: 241 if (nr_bytes == 2) 242 dv_store_2 (dest, 0); 243 else 244 dv_store_4 (dest, 0); 245 break; 246 } 247 248 return nr_bytes; 249 } 250 251 static void 252 bfin_sic_537_forward_interrupts (struct hw *me, struct bfin_sic *sic) 253 { 254 bfin_sic_forward_interrupts (me, &sic->bf537.isr, &sic->bf537.imask, &sic->bf537.iar0); 255 } 256 257 static unsigned 258 bfin_sic_537_io_write_buffer (struct hw *me, const void *source, int space, 259 address_word addr, unsigned nr_bytes) 260 { 261 struct bfin_sic *sic = hw_data (me); 262 bu32 mmr_off; 263 bu32 value; 264 bu16 *value16p; 265 bu32 *value32p; 266 void *valuep; 267 268 /* Invalid access mode is higher priority than missing register. */ 269 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true)) 270 return 0; 271 272 if (nr_bytes == 4) 273 value = dv_load_4 (source); 274 else 275 value = dv_load_2 (source); 276 277 mmr_off = addr - sic->base; 278 valuep = (void *)((uintptr_t)sic + mmr_base() + mmr_off); 279 value16p = valuep; 280 value32p = valuep; 281 282 HW_TRACE_WRITE (); 283 284 /* XXX: Discard all SIC writes for now. */ 285 switch (mmr_off) 286 { 287 case mmr_offset(swrst): 288 /* XXX: This should trigger a software reset ... */ 289 break; 290 case mmr_offset(syscr): 291 /* XXX: what to do ... */ 292 break; 293 case mmr_offset(bf537.imask): 294 bfin_sic_537_forward_interrupts (me, sic); 295 *value32p = value; 296 break; 297 case mmr_offset(bf537.iar0): 298 case mmr_offset(bf537.iar1): 299 case mmr_offset(bf537.iar2): 300 case mmr_offset(bf537.iar3): 301 case mmr_offset(bf537.iwr): 302 *value32p = value; 303 break; 304 case mmr_offset(bf537.isr): 305 /* ISR is read-only. */ 306 break; 307 default: 308 /* XXX: Should discard other writes. */ 309 ; 310 } 311 312 return nr_bytes; 313 } 314 315 static unsigned 316 bfin_sic_537_io_read_buffer (struct hw *me, void *dest, int space, 317 address_word addr, unsigned nr_bytes) 318 { 319 struct bfin_sic *sic = hw_data (me); 320 bu32 mmr_off; 321 bu16 *value16p; 322 bu32 *value32p; 323 void *valuep; 324 325 /* Invalid access mode is higher priority than missing register. */ 326 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false)) 327 return 0; 328 329 mmr_off = addr - sic->base; 330 valuep = (void *)((uintptr_t)sic + mmr_base() + mmr_off); 331 value16p = valuep; 332 value32p = valuep; 333 334 HW_TRACE_READ (); 335 336 switch (mmr_off) 337 { 338 case mmr_offset(swrst): 339 case mmr_offset(syscr): 340 case mmr_offset(rvect): 341 dv_store_2 (dest, *value16p); 342 break; 343 case mmr_offset(bf537.imask): 344 case mmr_offset(bf537.iar0): 345 case mmr_offset(bf537.iar1): 346 case mmr_offset(bf537.iar2): 347 case mmr_offset(bf537.iar3): 348 case mmr_offset(bf537.isr): 349 case mmr_offset(bf537.iwr): 350 dv_store_4 (dest, *value32p); 351 break; 352 default: 353 if (nr_bytes == 2) 354 dv_store_2 (dest, 0); 355 else 356 dv_store_4 (dest, 0); 357 break; 358 } 359 360 return nr_bytes; 361 } 362 363 static void 364 bfin_sic_54x_forward_interrupts (struct hw *me, struct bfin_sic *sic) 365 { 366 bfin_sic_forward_interrupts (me, &sic->bf54x.isr0, &sic->bf54x.imask0, &sic->bf54x.iar0); 367 bfin_sic_forward_interrupts (me, &sic->bf54x.isr1, &sic->bf54x.imask1, &sic->bf54x.iar4); 368 bfin_sic_forward_interrupts (me, &sic->bf54x.isr2, &sic->bf54x.imask2, &sic->bf54x.iar8); 369 } 370 371 static unsigned 372 bfin_sic_54x_io_write_buffer (struct hw *me, const void *source, int space, 373 address_word addr, unsigned nr_bytes) 374 { 375 struct bfin_sic *sic = hw_data (me); 376 bu32 mmr_off; 377 bu32 value; 378 bu16 *value16p; 379 bu32 *value32p; 380 void *valuep; 381 382 /* Invalid access mode is higher priority than missing register. */ 383 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true)) 384 return 0; 385 386 if (nr_bytes == 4) 387 value = dv_load_4 (source); 388 else 389 value = dv_load_2 (source); 390 391 mmr_off = addr - sic->base; 392 valuep = (void *)((uintptr_t)sic + mmr_base() + mmr_off); 393 value16p = valuep; 394 value32p = valuep; 395 396 HW_TRACE_WRITE (); 397 398 /* XXX: Discard all SIC writes for now. */ 399 switch (mmr_off) 400 { 401 case mmr_offset(swrst): 402 /* XXX: This should trigger a software reset ... */ 403 break; 404 case mmr_offset(syscr): 405 /* XXX: what to do ... */ 406 break; 407 case mmr_offset(bf54x.imask0) ... mmr_offset(bf54x.imask2): 408 bfin_sic_54x_forward_interrupts (me, sic); 409 *value32p = value; 410 break; 411 case mmr_offset(bf54x.iar0) ... mmr_offset(bf54x.iar11): 412 case mmr_offset(bf54x.iwr0) ... mmr_offset(bf54x.iwr2): 413 *value32p = value; 414 break; 415 case mmr_offset(bf54x.isr0) ... mmr_offset(bf54x.isr2): 416 /* ISR is read-only. */ 417 break; 418 default: 419 /* XXX: Should discard other writes. */ 420 ; 421 } 422 423 return nr_bytes; 424 } 425 426 static unsigned 427 bfin_sic_54x_io_read_buffer (struct hw *me, void *dest, int space, 428 address_word addr, unsigned nr_bytes) 429 { 430 struct bfin_sic *sic = hw_data (me); 431 bu32 mmr_off; 432 bu16 *value16p; 433 bu32 *value32p; 434 void *valuep; 435 436 /* Invalid access mode is higher priority than missing register. */ 437 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false)) 438 return 0; 439 440 mmr_off = addr - sic->base; 441 valuep = (void *)((uintptr_t)sic + mmr_base() + mmr_off); 442 value16p = valuep; 443 value32p = valuep; 444 445 HW_TRACE_READ (); 446 447 switch (mmr_off) 448 { 449 case mmr_offset(swrst): 450 case mmr_offset(syscr): 451 case mmr_offset(rvect): 452 dv_store_2 (dest, *value16p); 453 break; 454 case mmr_offset(bf54x.imask0) ... mmr_offset(bf54x.imask2): 455 case mmr_offset(bf54x.iar0) ... mmr_offset(bf54x.iar11): 456 case mmr_offset(bf54x.iwr0) ... mmr_offset(bf54x.iwr2): 457 case mmr_offset(bf54x.isr0) ... mmr_offset(bf54x.isr2): 458 dv_store_4 (dest, *value32p); 459 break; 460 default: 461 if (nr_bytes == 2) 462 dv_store_2 (dest, 0); 463 else 464 dv_store_4 (dest, 0); 465 break; 466 } 467 468 return nr_bytes; 469 } 470 471 static void 472 bfin_sic_561_forward_interrupts (struct hw *me, struct bfin_sic *sic) 473 { 474 bfin_sic_forward_interrupts (me, &sic->bf561.isr0, &sic->bf561.imask0, &sic->bf561.iar0); 475 bfin_sic_forward_interrupts (me, &sic->bf561.isr1, &sic->bf561.imask1, &sic->bf561.iar4); 476 } 477 478 static unsigned 479 bfin_sic_561_io_write_buffer (struct hw *me, const void *source, int space, 480 address_word addr, unsigned nr_bytes) 481 { 482 struct bfin_sic *sic = hw_data (me); 483 bu32 mmr_off; 484 bu32 value; 485 bu16 *value16p; 486 bu32 *value32p; 487 void *valuep; 488 489 /* Invalid access mode is higher priority than missing register. */ 490 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true)) 491 return 0; 492 493 if (nr_bytes == 4) 494 value = dv_load_4 (source); 495 else 496 value = dv_load_2 (source); 497 498 mmr_off = addr - sic->base; 499 valuep = (void *)((uintptr_t)sic + mmr_base() + mmr_off); 500 value16p = valuep; 501 value32p = valuep; 502 503 HW_TRACE_WRITE (); 504 505 /* XXX: Discard all SIC writes for now. */ 506 switch (mmr_off) 507 { 508 case mmr_offset(swrst): 509 /* XXX: This should trigger a software reset ... */ 510 break; 511 case mmr_offset(syscr): 512 /* XXX: what to do ... */ 513 break; 514 case mmr_offset(bf561.imask0): 515 case mmr_offset(bf561.imask1): 516 bfin_sic_561_forward_interrupts (me, sic); 517 *value32p = value; 518 break; 519 case mmr_offset(bf561.iar0) ... mmr_offset(bf561.iar3): 520 case mmr_offset(bf561.iar4) ... mmr_offset(bf561.iar7): 521 case mmr_offset(bf561.iwr0): 522 case mmr_offset(bf561.iwr1): 523 *value32p = value; 524 break; 525 case mmr_offset(bf561.isr0): 526 case mmr_offset(bf561.isr1): 527 /* ISR is read-only. */ 528 break; 529 default: 530 /* XXX: Should discard other writes. */ 531 ; 532 } 533 534 return nr_bytes; 535 } 536 537 static unsigned 538 bfin_sic_561_io_read_buffer (struct hw *me, void *dest, int space, 539 address_word addr, unsigned nr_bytes) 540 { 541 struct bfin_sic *sic = hw_data (me); 542 bu32 mmr_off; 543 bu16 *value16p; 544 bu32 *value32p; 545 void *valuep; 546 547 /* Invalid access mode is higher priority than missing register. */ 548 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false)) 549 return 0; 550 551 mmr_off = addr - sic->base; 552 valuep = (void *)((uintptr_t)sic + mmr_base() + mmr_off); 553 value16p = valuep; 554 value32p = valuep; 555 556 HW_TRACE_READ (); 557 558 switch (mmr_off) 559 { 560 case mmr_offset(swrst): 561 case mmr_offset(syscr): 562 case mmr_offset(rvect): 563 dv_store_2 (dest, *value16p); 564 break; 565 case mmr_offset(bf561.imask0): 566 case mmr_offset(bf561.imask1): 567 case mmr_offset(bf561.iar0) ... mmr_offset(bf561.iar3): 568 case mmr_offset(bf561.iar4) ... mmr_offset(bf561.iar7): 569 case mmr_offset(bf561.iwr0): 570 case mmr_offset(bf561.iwr1): 571 case mmr_offset(bf561.isr0): 572 case mmr_offset(bf561.isr1): 573 dv_store_4 (dest, *value32p); 574 break; 575 default: 576 if (nr_bytes == 2) 577 dv_store_2 (dest, 0); 578 else 579 dv_store_4 (dest, 0); 580 break; 581 } 582 583 return nr_bytes; 584 } 585 586 /* Give each SIC its own base to make it easier to extract the pin at 587 runtime. The pin is used as its bit position in the SIC MMRs. */ 588 #define ENC(sic, pin) (((sic) << 8) + (pin)) 589 #define DEC_PIN(pin) ((pin) % 0x100) 590 #define DEC_SIC(pin) ((pin) >> 8) 591 592 /* It would be nice to declare just one set of input_ports, and then 593 have the device tree instantiate multiple SICs, but the MMR layout 594 on the BF54x/BF561 makes this pretty hard to pull off since their 595 regs are interwoven in the address space. */ 596 597 #define BFIN_SIC_TO_CEC_PORTS \ 598 { "ivg7", IVG7, 0, output_port, }, \ 599 { "ivg8", IVG8, 0, output_port, }, \ 600 { "ivg9", IVG9, 0, output_port, }, \ 601 { "ivg10", IVG10, 0, output_port, }, \ 602 { "ivg11", IVG11, 0, output_port, }, \ 603 { "ivg12", IVG12, 0, output_port, }, \ 604 { "ivg13", IVG13, 0, output_port, }, \ 605 { "ivg14", IVG14, 0, output_port, }, \ 606 { "ivg15", IVG15, 0, output_port, }, 607 608 #define SIC_PORTS(n) \ 609 { "int0@"#n, ENC(n, 0), 0, input_port, }, \ 610 { "int1@"#n, ENC(n, 1), 0, input_port, }, \ 611 { "int2@"#n, ENC(n, 2), 0, input_port, }, \ 612 { "int3@"#n, ENC(n, 3), 0, input_port, }, \ 613 { "int4@"#n, ENC(n, 4), 0, input_port, }, \ 614 { "int5@"#n, ENC(n, 5), 0, input_port, }, \ 615 { "int6@"#n, ENC(n, 6), 0, input_port, }, \ 616 { "int7@"#n, ENC(n, 7), 0, input_port, }, \ 617 { "int8@"#n, ENC(n, 8), 0, input_port, }, \ 618 { "int9@"#n, ENC(n, 9), 0, input_port, }, \ 619 { "int10@"#n, ENC(n, 10), 0, input_port, }, \ 620 { "int11@"#n, ENC(n, 11), 0, input_port, }, \ 621 { "int12@"#n, ENC(n, 12), 0, input_port, }, \ 622 { "int13@"#n, ENC(n, 13), 0, input_port, }, \ 623 { "int14@"#n, ENC(n, 14), 0, input_port, }, \ 624 { "int15@"#n, ENC(n, 15), 0, input_port, }, \ 625 { "int16@"#n, ENC(n, 16), 0, input_port, }, \ 626 { "int17@"#n, ENC(n, 17), 0, input_port, }, \ 627 { "int18@"#n, ENC(n, 18), 0, input_port, }, \ 628 { "int19@"#n, ENC(n, 19), 0, input_port, }, \ 629 { "int20@"#n, ENC(n, 20), 0, input_port, }, \ 630 { "int21@"#n, ENC(n, 21), 0, input_port, }, \ 631 { "int22@"#n, ENC(n, 22), 0, input_port, }, \ 632 { "int23@"#n, ENC(n, 23), 0, input_port, }, \ 633 { "int24@"#n, ENC(n, 24), 0, input_port, }, \ 634 { "int25@"#n, ENC(n, 25), 0, input_port, }, \ 635 { "int26@"#n, ENC(n, 26), 0, input_port, }, \ 636 { "int27@"#n, ENC(n, 27), 0, input_port, }, \ 637 { "int28@"#n, ENC(n, 28), 0, input_port, }, \ 638 { "int29@"#n, ENC(n, 29), 0, input_port, }, \ 639 { "int30@"#n, ENC(n, 30), 0, input_port, }, \ 640 { "int31@"#n, ENC(n, 31), 0, input_port, }, 641 642 static const struct hw_port_descriptor bfin_sic1_ports[] = 643 { 644 BFIN_SIC_TO_CEC_PORTS 645 SIC_PORTS(0) 646 { NULL, 0, 0, 0, }, 647 }; 648 649 static const struct hw_port_descriptor bfin_sic2_ports[] = 650 { 651 BFIN_SIC_TO_CEC_PORTS 652 SIC_PORTS(0) 653 SIC_PORTS(1) 654 { NULL, 0, 0, 0, }, 655 }; 656 657 static const struct hw_port_descriptor bfin_sic3_ports[] = 658 { 659 BFIN_SIC_TO_CEC_PORTS 660 SIC_PORTS(0) 661 SIC_PORTS(1) 662 SIC_PORTS(2) 663 { NULL, 0, 0, 0, }, 664 }; 665 666 static const struct hw_port_descriptor bfin_sic_561_ports[] = 667 { 668 { "sup_irq@0", 0, 0, output_port, }, 669 { "sup_irq@1", 1, 0, output_port, }, 670 BFIN_SIC_TO_CEC_PORTS 671 SIC_PORTS(0) 672 SIC_PORTS(1) 673 { NULL, 0, 0, 0, }, 674 }; 675 676 static void 677 bfin_sic_port_event (struct hw *me, bu32 *isr, bu32 bit, int level) 678 { 679 if (level) 680 *isr |= bit; 681 else 682 *isr &= ~bit; 683 } 684 685 static void 686 bfin_sic_52x_port_event (struct hw *me, int my_port, struct hw *source, 687 int source_port, int level) 688 { 689 struct bfin_sic *sic = hw_data (me); 690 bu32 idx = DEC_SIC (my_port); 691 bu32 pin = DEC_PIN (my_port); 692 bu32 bit = 1 << pin; 693 694 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)", 695 level, my_port, idx, pin)); 696 697 /* SIC only exists to forward interrupts from the system to the CEC. */ 698 switch (idx) 699 { 700 case 0: bfin_sic_port_event (me, &sic->bf52x.isr0, bit, level); break; 701 case 1: bfin_sic_port_event (me, &sic->bf52x.isr1, bit, level); break; 702 } 703 704 /* XXX: Handle SIC wakeup source ? 705 if (sic->bf52x.iwr0 & bit) 706 What to do ?; 707 if (sic->bf52x.iwr1 & bit) 708 What to do ?; 709 */ 710 711 bfin_sic_52x_forward_interrupts (me, sic); 712 } 713 714 static void 715 bfin_sic_537_port_event (struct hw *me, int my_port, struct hw *source, 716 int source_port, int level) 717 { 718 struct bfin_sic *sic = hw_data (me); 719 bu32 idx = DEC_SIC (my_port); 720 bu32 pin = DEC_PIN (my_port); 721 bu32 bit = 1 << pin; 722 723 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)", 724 level, my_port, idx, pin)); 725 726 /* SIC only exists to forward interrupts from the system to the CEC. */ 727 bfin_sic_port_event (me, &sic->bf537.isr, bit, level); 728 729 /* XXX: Handle SIC wakeup source ? 730 if (sic->bf537.iwr & bit) 731 What to do ?; 732 */ 733 734 bfin_sic_537_forward_interrupts (me, sic); 735 } 736 737 static void 738 bfin_sic_54x_port_event (struct hw *me, int my_port, struct hw *source, 739 int source_port, int level) 740 { 741 struct bfin_sic *sic = hw_data (me); 742 bu32 idx = DEC_SIC (my_port); 743 bu32 pin = DEC_PIN (my_port); 744 bu32 bit = 1 << pin; 745 746 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)", 747 level, my_port, idx, pin)); 748 749 /* SIC only exists to forward interrupts from the system to the CEC. */ 750 switch (idx) 751 { 752 case 0: bfin_sic_port_event (me, &sic->bf54x.isr0, bit, level); break; 753 case 1: bfin_sic_port_event (me, &sic->bf54x.isr0, bit, level); break; 754 case 2: bfin_sic_port_event (me, &sic->bf54x.isr0, bit, level); break; 755 } 756 757 /* XXX: Handle SIC wakeup source ? 758 if (sic->bf54x.iwr0 & bit) 759 What to do ?; 760 if (sic->bf54x.iwr1 & bit) 761 What to do ?; 762 if (sic->bf54x.iwr2 & bit) 763 What to do ?; 764 */ 765 766 bfin_sic_54x_forward_interrupts (me, sic); 767 } 768 769 static void 770 bfin_sic_561_port_event (struct hw *me, int my_port, struct hw *source, 771 int source_port, int level) 772 { 773 struct bfin_sic *sic = hw_data (me); 774 bu32 idx = DEC_SIC (my_port); 775 bu32 pin = DEC_PIN (my_port); 776 bu32 bit = 1 << pin; 777 778 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)", 779 level, my_port, idx, pin)); 780 781 /* SIC only exists to forward interrupts from the system to the CEC. */ 782 switch (idx) 783 { 784 case 0: bfin_sic_port_event (me, &sic->bf561.isr0, bit, level); break; 785 case 1: bfin_sic_port_event (me, &sic->bf561.isr1, bit, level); break; 786 } 787 788 /* XXX: Handle SIC wakeup source ? 789 if (sic->bf561.iwr0 & bit) 790 What to do ?; 791 if (sic->bf561.iwr1 & bit) 792 What to do ?; 793 */ 794 795 bfin_sic_561_forward_interrupts (me, sic); 796 } 797 798 static void 799 attach_bfin_sic_regs (struct hw *me, struct bfin_sic *sic) 800 { 801 address_word attach_address; 802 int attach_space; 803 unsigned attach_size; 804 reg_property_spec reg; 805 806 if (hw_find_property (me, "reg") == NULL) 807 hw_abort (me, "Missing \"reg\" property"); 808 809 if (!hw_find_reg_array_property (me, "reg", 0, ®)) 810 hw_abort (me, "\"reg\" property must contain three addr/size entries"); 811 812 hw_unit_address_to_attach_address (hw_parent (me), 813 ®.address, 814 &attach_space, &attach_address, me); 815 hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me); 816 817 if (attach_size != BFIN_MMR_SIC_SIZE) 818 hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_SIC_SIZE); 819 820 hw_attach_address (hw_parent (me), 821 0, attach_space, attach_address, attach_size, me); 822 823 sic->base = attach_address; 824 } 825 826 static void 827 bfin_sic_finish (struct hw *me) 828 { 829 struct bfin_sic *sic; 830 831 sic = HW_ZALLOC (me, struct bfin_sic); 832 833 set_hw_data (me, sic); 834 attach_bfin_sic_regs (me, sic); 835 836 switch (hw_find_integer_property (me, "type")) 837 { 838 case 500 ... 509: 839 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer); 840 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer); 841 set_hw_ports (me, bfin_sic2_ports); 842 set_hw_port_event (me, bfin_sic_52x_port_event); 843 mmr_names = bf52x_mmr_names; 844 845 /* Initialize the SIC. */ 846 sic->bf52x.imask0 = sic->bf52x.imask1 = 0; 847 sic->bf52x.isr0 = sic->bf52x.isr1 = 0; 848 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF; 849 sic->bf52x.iar0 = 0x00000000; 850 sic->bf52x.iar1 = 0x22111000; 851 sic->bf52x.iar2 = 0x33332222; 852 sic->bf52x.iar3 = 0x44444433; 853 sic->bf52x.iar4 = 0x55555555; 854 sic->bf52x.iar5 = 0x06666655; 855 sic->bf52x.iar6 = 0x33333003; 856 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */ 857 break; 858 case 510 ... 519: 859 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer); 860 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer); 861 set_hw_ports (me, bfin_sic2_ports); 862 set_hw_port_event (me, bfin_sic_52x_port_event); 863 mmr_names = bf52x_mmr_names; 864 865 /* Initialize the SIC. */ 866 sic->bf52x.imask0 = sic->bf52x.imask1 = 0; 867 sic->bf52x.isr0 = sic->bf52x.isr1 = 0; 868 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF; 869 sic->bf52x.iar0 = 0x00000000; 870 sic->bf52x.iar1 = 0x11000000; 871 sic->bf52x.iar2 = 0x33332222; 872 sic->bf52x.iar3 = 0x44444433; 873 sic->bf52x.iar4 = 0x55555555; 874 sic->bf52x.iar5 = 0x06666655; 875 sic->bf52x.iar6 = 0x33333000; 876 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */ 877 break; 878 case 522 ... 527: 879 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer); 880 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer); 881 set_hw_ports (me, bfin_sic2_ports); 882 set_hw_port_event (me, bfin_sic_52x_port_event); 883 mmr_names = bf52x_mmr_names; 884 885 /* Initialize the SIC. */ 886 sic->bf52x.imask0 = sic->bf52x.imask1 = 0; 887 sic->bf52x.isr0 = sic->bf52x.isr1 = 0; 888 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF; 889 sic->bf52x.iar0 = 0x00000000; 890 sic->bf52x.iar1 = 0x11000000; 891 sic->bf52x.iar2 = 0x33332222; 892 sic->bf52x.iar3 = 0x44444433; 893 sic->bf52x.iar4 = 0x55555555; 894 sic->bf52x.iar5 = 0x06666655; 895 sic->bf52x.iar6 = 0x33333000; 896 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */ 897 break; 898 case 531 ... 533: 899 set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer); 900 set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer); 901 set_hw_ports (me, bfin_sic1_ports); 902 set_hw_port_event (me, bfin_sic_537_port_event); 903 mmr_names = bf537_mmr_names; 904 905 /* Initialize the SIC. */ 906 sic->bf537.imask = 0; 907 sic->bf537.isr = 0; 908 sic->bf537.iwr = 0xFFFFFFFF; 909 sic->bf537.iar0 = 0x10000000; 910 sic->bf537.iar1 = 0x33322221; 911 sic->bf537.iar2 = 0x66655444; 912 sic->bf537.iar3 = 0; /* XXX: fix this */ 913 break; 914 case 534: 915 case 536: 916 case 537: 917 set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer); 918 set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer); 919 set_hw_ports (me, bfin_sic1_ports); 920 set_hw_port_event (me, bfin_sic_537_port_event); 921 mmr_names = bf537_mmr_names; 922 923 /* Initialize the SIC. */ 924 sic->bf537.imask = 0; 925 sic->bf537.isr = 0; 926 sic->bf537.iwr = 0xFFFFFFFF; 927 sic->bf537.iar0 = 0x22211000; 928 sic->bf537.iar1 = 0x43333332; 929 sic->bf537.iar2 = 0x55555444; 930 sic->bf537.iar3 = 0x66655555; 931 break; 932 case 538 ... 539: 933 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer); 934 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer); 935 set_hw_ports (me, bfin_sic2_ports); 936 set_hw_port_event (me, bfin_sic_52x_port_event); 937 mmr_names = bf52x_mmr_names; 938 939 /* Initialize the SIC. */ 940 sic->bf52x.imask0 = sic->bf52x.imask1 = 0; 941 sic->bf52x.isr0 = sic->bf52x.isr1 = 0; 942 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF; 943 sic->bf52x.iar0 = 0x10000000; 944 sic->bf52x.iar1 = 0x33322221; 945 sic->bf52x.iar2 = 0x66655444; 946 sic->bf52x.iar3 = 0x00000000; 947 sic->bf52x.iar4 = 0x32222220; 948 sic->bf52x.iar5 = 0x44433333; 949 sic->bf52x.iar6 = 0x00444664; 950 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */ 951 break; 952 case 540 ... 549: 953 set_hw_io_read_buffer (me, bfin_sic_54x_io_read_buffer); 954 set_hw_io_write_buffer (me, bfin_sic_54x_io_write_buffer); 955 set_hw_ports (me, bfin_sic3_ports); 956 set_hw_port_event (me, bfin_sic_54x_port_event); 957 mmr_names = bf54x_mmr_names; 958 959 /* Initialize the SIC. */ 960 sic->bf54x.imask0 = sic->bf54x.imask1 = sic->bf54x.imask2 = 0; 961 sic->bf54x.isr0 = sic->bf54x.isr1 = sic->bf54x.isr2 = 0; 962 sic->bf54x.iwr0 = sic->bf54x.iwr1 = sic->bf54x.iwr2 = 0xFFFFFFFF; 963 sic->bf54x.iar0 = 0x10000000; 964 sic->bf54x.iar1 = 0x33322221; 965 sic->bf54x.iar2 = 0x66655444; 966 sic->bf54x.iar3 = 0x00000000; 967 sic->bf54x.iar4 = 0x32222220; 968 sic->bf54x.iar5 = 0x44433333; 969 sic->bf54x.iar6 = 0x00444664; 970 sic->bf54x.iar7 = 0x00000000; 971 sic->bf54x.iar8 = 0x44111111; 972 sic->bf54x.iar9 = 0x44444444; 973 sic->bf54x.iar10 = 0x44444444; 974 sic->bf54x.iar11 = 0x55444444; 975 break; 976 case 561: 977 set_hw_io_read_buffer (me, bfin_sic_561_io_read_buffer); 978 set_hw_io_write_buffer (me, bfin_sic_561_io_write_buffer); 979 set_hw_ports (me, bfin_sic_561_ports); 980 set_hw_port_event (me, bfin_sic_561_port_event); 981 mmr_names = bf561_mmr_names; 982 983 /* Initialize the SIC. */ 984 sic->bf561.imask0 = sic->bf561.imask1 = 0; 985 sic->bf561.isr0 = sic->bf561.isr1 = 0; 986 sic->bf561.iwr0 = sic->bf561.iwr1 = 0xFFFFFFFF; 987 sic->bf561.iar0 = 0x00000000; 988 sic->bf561.iar1 = 0x11111000; 989 sic->bf561.iar2 = 0x21111111; 990 sic->bf561.iar3 = 0x22222222; 991 sic->bf561.iar4 = 0x33333222; 992 sic->bf561.iar5 = 0x43333333; 993 sic->bf561.iar6 = 0x21144444; 994 sic->bf561.iar7 = 0x00006552; 995 break; 996 case 590 ... 599: 997 set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer); 998 set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer); 999 set_hw_ports (me, bfin_sic1_ports); 1000 set_hw_port_event (me, bfin_sic_537_port_event); 1001 mmr_names = bf537_mmr_names; 1002 1003 /* Initialize the SIC. */ 1004 sic->bf537.imask = 0; 1005 sic->bf537.isr = 0; 1006 sic->bf537.iwr = 0xFFFFFFFF; 1007 sic->bf537.iar0 = 0x00000000; 1008 sic->bf537.iar1 = 0x33322221; 1009 sic->bf537.iar2 = 0x55444443; 1010 sic->bf537.iar3 = 0x66600005; 1011 break; 1012 default: 1013 hw_abort (me, "no support for SIC on this Blackfin model yet"); 1014 } 1015 } 1016 1017 const struct hw_descriptor dv_bfin_sic_descriptor[] = 1018 { 1019 {"bfin_sic", bfin_sic_finish,}, 1020 {NULL, NULL}, 1021 }; 1022