00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <types.h>
00035 #include <lib.h>
00036 #include <cpu.h>
00037 #include <spinlock.h>
00038 #include <current.h>
00039 #include <lamebus/lamebus.h>
00040
00041
00042 #define CFGREG_VID 0
00043 #define CFGREG_DID 4
00044 #define CFGREG_DRL 8
00045
00046
00047 #define CTLREG_RAMSZ 0x200
00048 #define CTLREG_IRQS 0x204
00049 #define CTLREG_PWR 0x208
00050 #define CTLREG_IRQE 0x20c
00051 #define CTLREG_CPUS 0x210
00052 #define CTLREG_CPUE 0x214
00053 #define CTLREG_SELF 0x218
00054
00055
00056 #define CTLCPU_CIRQE 0x000
00057 #define CTLCPU_CIPI 0x004
00058 #define CTLCPU_CRAM 0x300
00059
00060
00061
00062
00063
00064 static
00065 inline
00066 uint32_t
00067 read_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset)
00068 {
00069
00070 offset += LB_CONFIG_SIZE*slot;
00071 return lamebus_read_register(lb, LB_CONTROLLER_SLOT, offset);
00072 }
00073
00074
00075
00076
00077 static
00078 inline
00079 void
00080 write_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset,
00081 uint32_t val)
00082 {
00083 offset += LB_CONFIG_SIZE*slot;
00084 lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
00085 }
00086
00087
00088
00089
00090 static
00091 inline
00092 uint32_t
00093 read_ctl_register(struct lamebus_softc *lb, uint32_t offset)
00094 {
00095
00096 return read_cfg_register(lb, LB_CONTROLLER_SLOT, offset);
00097 }
00098
00099
00100
00101
00102 static
00103 inline
00104 void
00105 write_ctl_register(struct lamebus_softc *lb, uint32_t offset, uint32_t val)
00106 {
00107 write_cfg_register(lb, LB_CONTROLLER_SLOT, offset, val);
00108 }
00109
00110
00111
00112
00113 static
00114 inline
00115 void
00116 write_ctlcpu_register(struct lamebus_softc *lb, unsigned hw_cpunum,
00117 uint32_t offset, uint32_t val)
00118 {
00119 offset += LB_CTLCPU_OFFSET + hw_cpunum * LB_CTLCPU_SIZE;
00120 lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
00121 }
00122
00123
00124
00125
00126 void
00127 lamebus_find_cpus(struct lamebus_softc *lamebus)
00128 {
00129 uint32_t cpumask, self, bit, val;
00130 unsigned i, numcpus, bootcpu;
00131 unsigned hwnum[32];
00132
00133 cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
00134 self = read_ctl_register(lamebus, CTLREG_SELF);
00135
00136 numcpus = 0;
00137 bootcpu = 0;
00138 for (i=0; i<32; i++) {
00139 bit = (uint32_t)1 << i;
00140 if ((cpumask & bit) != 0) {
00141 if (self & bit) {
00142 bootcpu = numcpus;
00143 curcpu->c_hardware_number = i;
00144 }
00145 hwnum[numcpus] = i;
00146 numcpus++;
00147 }
00148 }
00149
00150 for (i=0; i<numcpus; i++) {
00151 if (i != bootcpu) {
00152 cpu_create(hwnum[i]);
00153 }
00154 }
00155
00156
00157
00158
00159
00160
00161
00162 for (i=0; i<numcpus; i++) {
00163 if (i != bootcpu) {
00164 val = 0;
00165 }
00166 else {
00167 val = 0xffffffff;
00168 }
00169 write_ctlcpu_register(lamebus, hwnum[i], CTLCPU_CIRQE, val);
00170 }
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 void
00184 lamebus_start_cpus(struct lamebus_softc *lamebus)
00185 {
00186 uint32_t cpumask, self, bit;
00187 uint32_t ctlcpuoffset;
00188 uint32_t *cram;
00189 unsigned i;
00190 unsigned cpunum;
00191
00192 cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
00193 self = read_ctl_register(lamebus, CTLREG_SELF);
00194
00195
00196 cpunum = 1;
00197 for (i=0; i<32; i++) {
00198 bit = (uint32_t)1 << i;
00199 if ((cpumask & bit) != 0) {
00200 if (self & bit) {
00201 continue;
00202 }
00203 ctlcpuoffset = LB_CTLCPU_OFFSET + i * LB_CTLCPU_SIZE;
00204 cram = lamebus_map_area(lamebus,
00205 LB_CONTROLLER_SLOT,
00206 ctlcpuoffset + CTLCPU_CRAM);
00207 cram[0] = (uint32_t)cpu_start_secondary;
00208 cram[1] = cpunum++;
00209 }
00210 }
00211
00212
00213 write_ctl_register(lamebus, CTLREG_CPUE, cpumask);
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 int
00228 lamebus_probe(struct lamebus_softc *sc,
00229 uint32_t vendorid, uint32_t deviceid,
00230 uint32_t lowver, uint32_t highver)
00231 {
00232 int slot;
00233 uint32_t val;
00234
00235
00236
00237
00238
00239
00240 spinlock_acquire(&sc->ls_lock);
00241
00242 for (slot=0; slot<LB_NSLOTS; slot++) {
00243 if (sc->ls_slotsinuse & (1<<slot)) {
00244
00245 continue;
00246 }
00247
00248 val = read_cfg_register(sc, slot, CFGREG_VID);
00249 if (val!=vendorid) {
00250
00251 continue;
00252 }
00253
00254 val = read_cfg_register(sc, slot, CFGREG_DID);
00255 if (val != deviceid) {
00256
00257 continue;
00258 }
00259
00260 val = read_cfg_register(sc, slot, CFGREG_DRL);
00261 if (val < lowver || val > highver) {
00262
00263 continue;
00264 }
00265
00266
00267
00268 spinlock_release(&sc->ls_lock);
00269 return slot;
00270 }
00271
00272
00273
00274 spinlock_release(&sc->ls_lock);
00275 return -1;
00276 }
00277
00278
00279
00280
00281
00282
00283 void
00284 lamebus_mark(struct lamebus_softc *sc, int slot)
00285 {
00286 uint32_t mask = ((uint32_t)1) << slot;
00287 KASSERT(slot>=0 && slot < LB_NSLOTS);
00288
00289 spinlock_acquire(&sc->ls_lock);
00290
00291 if ((sc->ls_slotsinuse & mask)!=0) {
00292 panic("lamebus_mark: slot %d already in use\n", slot);
00293 }
00294
00295 sc->ls_slotsinuse |= mask;
00296
00297 spinlock_release(&sc->ls_lock);
00298 }
00299
00300
00301
00302
00303 void
00304 lamebus_unmark(struct lamebus_softc *sc, int slot)
00305 {
00306 uint32_t mask = ((uint32_t)1) << slot;
00307 KASSERT(slot>=0 && slot < LB_NSLOTS);
00308
00309 spinlock_acquire(&sc->ls_lock);
00310
00311 if ((sc->ls_slotsinuse & mask)==0) {
00312 panic("lamebus_mark: slot %d not marked in use\n", slot);
00313 }
00314
00315 sc->ls_slotsinuse &= ~mask;
00316
00317 spinlock_release(&sc->ls_lock);
00318 }
00319
00320
00321
00322
00323
00324 void
00325 lamebus_attach_interrupt(struct lamebus_softc *sc, int slot,
00326 void *devdata,
00327 void (*irqfunc)(void *devdata))
00328 {
00329 uint32_t mask = ((uint32_t)1) << slot;
00330 KASSERT(slot>=0 && slot < LB_NSLOTS);
00331
00332 spinlock_acquire(&sc->ls_lock);
00333
00334 if ((sc->ls_slotsinuse & mask)==0) {
00335 panic("lamebus_attach_interrupt: slot %d not marked in use\n",
00336 slot);
00337 }
00338
00339 KASSERT(sc->ls_devdata[slot]==NULL);
00340 KASSERT(sc->ls_irqfuncs[slot]==NULL);
00341
00342 sc->ls_devdata[slot] = devdata;
00343 sc->ls_irqfuncs[slot] = irqfunc;
00344
00345 spinlock_release(&sc->ls_lock);
00346 }
00347
00348
00349
00350
00351
00352 void
00353 lamebus_detach_interrupt(struct lamebus_softc *sc, int slot)
00354 {
00355 uint32_t mask = ((uint32_t)1) << slot;
00356 KASSERT(slot>=0 && slot < LB_NSLOTS);
00357
00358 spinlock_acquire(&sc->ls_lock);
00359
00360 if ((sc->ls_slotsinuse & mask)==0) {
00361 panic("lamebus_detach_interrupt: slot %d not marked in use\n",
00362 slot);
00363 }
00364
00365 KASSERT(sc->ls_irqfuncs[slot]!=NULL);
00366
00367 sc->ls_devdata[slot] = NULL;
00368 sc->ls_irqfuncs[slot] = NULL;
00369
00370 spinlock_release(&sc->ls_lock);
00371 }
00372
00373
00374
00375
00376 void
00377 lamebus_mask_interrupt(struct lamebus_softc *lamebus, int slot)
00378 {
00379 uint32_t bits, mask = ((uint32_t)1) << slot;
00380 KASSERT(slot >= 0 && slot < LB_NSLOTS);
00381
00382 spinlock_acquire(&lamebus->ls_lock);
00383 bits = read_ctl_register(lamebus, CTLREG_IRQE);
00384 bits &= ~mask;
00385 write_ctl_register(lamebus, CTLREG_IRQE, bits);
00386 spinlock_release(&lamebus->ls_lock);
00387 }
00388
00389 void
00390 lamebus_unmask_interrupt(struct lamebus_softc *lamebus, int slot)
00391 {
00392 uint32_t bits, mask = ((uint32_t)1) << slot;
00393 KASSERT(slot >= 0 && slot < LB_NSLOTS);
00394
00395 spinlock_acquire(&lamebus->ls_lock);
00396 bits = read_ctl_register(lamebus, CTLREG_IRQE);
00397 bits |= mask;
00398 write_ctl_register(lamebus, CTLREG_IRQE, bits);
00399 spinlock_release(&lamebus->ls_lock);
00400 }
00401
00402
00403
00404
00405
00406 void
00407 lamebus_interrupt(struct lamebus_softc *lamebus)
00408 {
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 int slot;
00421 uint32_t mask;
00422 uint32_t irqs;
00423 void (*handler)(void *);
00424 void *data;
00425
00426
00427 static int duds = 0;
00428 int duds_this_time = 0;
00429
00430
00431 KASSERT(lamebus != NULL);
00432
00433
00434 spinlock_acquire(&lamebus->ls_lock);
00435
00436
00437
00438
00439
00440 irqs = read_ctl_register(lamebus, CTLREG_IRQS);
00441
00442 if (irqs == 0) {
00443
00444
00445
00446 kprintf("lamebus: stray interrupt on cpu %u\n",
00447 curcpu->c_number);
00448 duds++;
00449 duds_this_time++;
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 }
00463
00464
00465
00466
00467
00468
00469 for (mask=1, slot=0; slot<LB_NSLOTS; mask<<=1, slot++) {
00470 if ((irqs & mask) == 0) {
00471
00472 continue;
00473 }
00474
00475
00476
00477
00478
00479 if ((lamebus->ls_slotsinuse & mask)==0) {
00480
00481
00482
00483 duds++;
00484 duds_this_time++;
00485 continue;
00486 }
00487
00488 if (lamebus->ls_irqfuncs[slot]==NULL) {
00489
00490
00491
00492
00493 duds++;
00494 duds_this_time++;
00495 continue;
00496 }
00497
00498
00499
00500
00501
00502
00503 handler = lamebus->ls_irqfuncs[slot];
00504 data = lamebus->ls_devdata[slot];
00505 spinlock_release(&lamebus->ls_lock);
00506
00507 handler(data);
00508
00509 spinlock_acquire(&lamebus->ls_lock);
00510
00511
00512
00513
00514
00515
00516
00517 irqs = read_ctl_register(lamebus, CTLREG_IRQS);
00518 }
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 if (duds_this_time == 0 && duds > 0) {
00540 kprintf("lamebus: %d dud interrupts\n", duds);
00541 duds = 0;
00542 }
00543
00544 if (duds > 10000) {
00545 panic("lamebus: too many (%d) dud interrupts\n", duds);
00546 }
00547
00548
00549 spinlock_release(&lamebus->ls_lock);
00550 }
00551
00552
00553
00554
00555 void
00556 lamebus_poweroff(struct lamebus_softc *lamebus)
00557 {
00558
00559
00560
00561
00562 cpu_irqoff();
00563 write_ctl_register(lamebus, CTLREG_PWR, 0);
00564
00565
00566 cpu_halt();
00567 }
00568
00569
00570
00571
00572 uint32_t
00573 lamebus_ramsize(void)
00574 {
00575
00576
00577
00578
00579
00580
00581
00582 return read_ctl_register(NULL, CTLREG_RAMSZ);
00583 }
00584
00585
00586
00587
00588 void
00589 lamebus_assert_ipi(struct lamebus_softc *lamebus, struct cpu *target)
00590 {
00591 write_ctlcpu_register(lamebus, target->c_hardware_number,
00592 CTLCPU_CIPI, 1);
00593 }
00594
00595 void
00596 lamebus_clear_ipi(struct lamebus_softc *lamebus, struct cpu *target)
00597 {
00598 write_ctlcpu_register(lamebus, target->c_hardware_number,
00599 CTLCPU_CIPI, 0);
00600 }
00601
00602
00603
00604
00605
00606 struct lamebus_softc *
00607 lamebus_init(void)
00608 {
00609 struct lamebus_softc *lamebus;
00610 int i;
00611
00612
00613 lamebus = kmalloc(sizeof(struct lamebus_softc));
00614 if (lamebus==NULL) {
00615 panic("lamebus_init: Out of memory\n");
00616 }
00617
00618 spinlock_init(&lamebus->ls_lock);
00619
00620
00621
00622
00623 lamebus->ls_slotsinuse = 1 << LB_CONTROLLER_SLOT;
00624
00625 for (i=0; i<LB_NSLOTS; i++) {
00626 lamebus->ls_devdata[i] = NULL;
00627 lamebus->ls_irqfuncs[i] = NULL;
00628 }
00629
00630 return lamebus;
00631 }