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