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