123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631 |
- #include <types.h>
- #include <lib.h>
- #include <cpu.h>
- #include <spinlock.h>
- #include <current.h>
- #include <lamebus/lamebus.h>
- #define CFGREG_VID 0
- #define CFGREG_DID 4
- #define CFGREG_DRL 8
- #define CTLREG_RAMSZ 0x200
- #define CTLREG_IRQS 0x204
- #define CTLREG_PWR 0x208
- #define CTLREG_IRQE 0x20c
- #define CTLREG_CPUS 0x210
- #define CTLREG_CPUE 0x214
- #define CTLREG_SELF 0x218
- #define CTLCPU_CIRQE 0x000
- #define CTLCPU_CIPI 0x004
- #define CTLCPU_CRAM 0x300
- static
- inline
- uint32_t
- read_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset)
- {
-
- offset += LB_CONFIG_SIZE*slot;
- return lamebus_read_register(lb, LB_CONTROLLER_SLOT, offset);
- }
- static
- inline
- void
- write_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset,
- uint32_t val)
- {
- offset += LB_CONFIG_SIZE*slot;
- lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
- }
- static
- inline
- uint32_t
- read_ctl_register(struct lamebus_softc *lb, uint32_t offset)
- {
-
- return read_cfg_register(lb, LB_CONTROLLER_SLOT, offset);
- }
- static
- inline
- void
- write_ctl_register(struct lamebus_softc *lb, uint32_t offset, uint32_t val)
- {
- write_cfg_register(lb, LB_CONTROLLER_SLOT, offset, val);
- }
- static
- inline
- void
- write_ctlcpu_register(struct lamebus_softc *lb, unsigned hw_cpunum,
- uint32_t offset, uint32_t val)
- {
- offset += LB_CTLCPU_OFFSET + hw_cpunum * LB_CTLCPU_SIZE;
- lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
- }
- void
- lamebus_find_cpus(struct lamebus_softc *lamebus)
- {
- uint32_t cpumask, self, bit, val;
- unsigned i, numcpus, bootcpu;
- unsigned hwnum[32];
- cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
- self = read_ctl_register(lamebus, CTLREG_SELF);
- numcpus = 0;
- bootcpu = 0;
- for (i=0; i<32; i++) {
- bit = (uint32_t)1 << i;
- if ((cpumask & bit) != 0) {
- if (self & bit) {
- bootcpu = numcpus;
- curcpu->c_hardware_number = i;
- }
- hwnum[numcpus] = i;
- numcpus++;
- }
- }
- for (i=0; i<numcpus; i++) {
- if (i != bootcpu) {
- cpu_create(hwnum[i]);
- }
- }
-
- for (i=0; i<numcpus; i++) {
- if (i != bootcpu) {
- val = 0;
- }
- else {
- val = 0xffffffff;
- }
- write_ctlcpu_register(lamebus, hwnum[i], CTLCPU_CIRQE, val);
- }
- }
- void
- lamebus_start_cpus(struct lamebus_softc *lamebus)
- {
- uint32_t cpumask, self, bit;
- uint32_t ctlcpuoffset;
- uint32_t *cram;
- unsigned i;
- unsigned cpunum;
- cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
- self = read_ctl_register(lamebus, CTLREG_SELF);
-
- cpunum = 1;
- for (i=0; i<32; i++) {
- bit = (uint32_t)1 << i;
- if ((cpumask & bit) != 0) {
- if (self & bit) {
- continue;
- }
- ctlcpuoffset = LB_CTLCPU_OFFSET + i * LB_CTLCPU_SIZE;
- cram = lamebus_map_area(lamebus,
- LB_CONTROLLER_SLOT,
- ctlcpuoffset + CTLCPU_CRAM);
- cram[0] = (uint32_t)cpu_start_secondary;
- cram[1] = cpunum++;
- }
- }
-
- write_ctl_register(lamebus, CTLREG_CPUE, cpumask);
- }
- int
- lamebus_probe(struct lamebus_softc *sc,
- uint32_t vendorid, uint32_t deviceid,
- uint32_t lowver, uint32_t highver)
- {
- int slot;
- uint32_t val;
-
- spinlock_acquire(&sc->ls_lock);
- for (slot=0; slot<LB_NSLOTS; slot++) {
- if (sc->ls_slotsinuse & (1<<slot)) {
-
- continue;
- }
- val = read_cfg_register(sc, slot, CFGREG_VID);
- if (val!=vendorid) {
-
- continue;
- }
- val = read_cfg_register(sc, slot, CFGREG_DID);
- if (val != deviceid) {
-
- continue;
- }
- val = read_cfg_register(sc, slot, CFGREG_DRL);
- if (val < lowver || val > highver) {
-
- continue;
- }
-
- spinlock_release(&sc->ls_lock);
- return slot;
- }
-
- spinlock_release(&sc->ls_lock);
- return -1;
- }
- void
- lamebus_mark(struct lamebus_softc *sc, int slot)
- {
- uint32_t mask = ((uint32_t)1) << slot;
- KASSERT(slot>=0 && slot < LB_NSLOTS);
- spinlock_acquire(&sc->ls_lock);
- if ((sc->ls_slotsinuse & mask)!=0) {
- panic("lamebus_mark: slot %d already in use\n", slot);
- }
- sc->ls_slotsinuse |= mask;
- spinlock_release(&sc->ls_lock);
- }
- void
- lamebus_unmark(struct lamebus_softc *sc, int slot)
- {
- uint32_t mask = ((uint32_t)1) << slot;
- KASSERT(slot>=0 && slot < LB_NSLOTS);
- spinlock_acquire(&sc->ls_lock);
- if ((sc->ls_slotsinuse & mask)==0) {
- panic("lamebus_mark: slot %d not marked in use\n", slot);
- }
- sc->ls_slotsinuse &= ~mask;
- spinlock_release(&sc->ls_lock);
- }
- void
- lamebus_attach_interrupt(struct lamebus_softc *sc, int slot,
- void *devdata,
- void (*irqfunc)(void *devdata))
- {
- uint32_t mask = ((uint32_t)1) << slot;
- KASSERT(slot>=0 && slot < LB_NSLOTS);
- spinlock_acquire(&sc->ls_lock);
- if ((sc->ls_slotsinuse & mask)==0) {
- panic("lamebus_attach_interrupt: slot %d not marked in use\n",
- slot);
- }
- KASSERT(sc->ls_devdata[slot]==NULL);
- KASSERT(sc->ls_irqfuncs[slot]==NULL);
- sc->ls_devdata[slot] = devdata;
- sc->ls_irqfuncs[slot] = irqfunc;
-
- spinlock_release(&sc->ls_lock);
- }
- void
- lamebus_detach_interrupt(struct lamebus_softc *sc, int slot)
- {
- uint32_t mask = ((uint32_t)1) << slot;
- KASSERT(slot>=0 && slot < LB_NSLOTS);
- spinlock_acquire(&sc->ls_lock);
- if ((sc->ls_slotsinuse & mask)==0) {
- panic("lamebus_detach_interrupt: slot %d not marked in use\n",
- slot);
- }
- KASSERT(sc->ls_irqfuncs[slot]!=NULL);
- sc->ls_devdata[slot] = NULL;
- sc->ls_irqfuncs[slot] = NULL;
-
- spinlock_release(&sc->ls_lock);
- }
- void
- lamebus_mask_interrupt(struct lamebus_softc *lamebus, int slot)
- {
- uint32_t bits, mask = ((uint32_t)1) << slot;
- KASSERT(slot >= 0 && slot < LB_NSLOTS);
- spinlock_acquire(&lamebus->ls_lock);
- bits = read_ctl_register(lamebus, CTLREG_IRQE);
- bits &= ~mask;
- write_ctl_register(lamebus, CTLREG_IRQE, bits);
- spinlock_release(&lamebus->ls_lock);
- }
- void
- lamebus_unmask_interrupt(struct lamebus_softc *lamebus, int slot)
- {
- uint32_t bits, mask = ((uint32_t)1) << slot;
- KASSERT(slot >= 0 && slot < LB_NSLOTS);
- spinlock_acquire(&lamebus->ls_lock);
- bits = read_ctl_register(lamebus, CTLREG_IRQE);
- bits |= mask;
- write_ctl_register(lamebus, CTLREG_IRQE, bits);
- spinlock_release(&lamebus->ls_lock);
- }
- void
- lamebus_interrupt(struct lamebus_softc *lamebus)
- {
-
- int slot;
- uint32_t mask;
- uint32_t irqs;
- void (*handler)(void *);
- void *data;
-
- static int duds = 0;
- int duds_this_time = 0;
-
- KASSERT(lamebus != NULL);
-
- spinlock_acquire(&lamebus->ls_lock);
-
- irqs = read_ctl_register(lamebus, CTLREG_IRQS);
- if (irqs == 0) {
-
- kprintf("lamebus: stray interrupt on cpu %u\n",
- curcpu->c_number);
- duds++;
- duds_this_time++;
-
- }
-
- for (mask=1, slot=0; slot<LB_NSLOTS; mask<<=1, slot++) {
- if ((irqs & mask) == 0) {
-
- continue;
- }
-
-
- if ((lamebus->ls_slotsinuse & mask)==0) {
-
- duds++;
- duds_this_time++;
- continue;
- }
- if (lamebus->ls_irqfuncs[slot]==NULL) {
-
- duds++;
- duds_this_time++;
- continue;
- }
-
- handler = lamebus->ls_irqfuncs[slot];
- data = lamebus->ls_devdata[slot];
- spinlock_release(&lamebus->ls_lock);
- handler(data);
- spinlock_acquire(&lamebus->ls_lock);
-
- irqs = read_ctl_register(lamebus, CTLREG_IRQS);
- }
-
- if (duds_this_time == 0 && duds > 0) {
- kprintf("lamebus: %d dud interrupts\n", duds);
- duds = 0;
- }
- if (duds > 10000) {
- panic("lamebus: too many (%d) dud interrupts\n", duds);
- }
-
- spinlock_release(&lamebus->ls_lock);
- }
- void
- lamebus_poweroff(struct lamebus_softc *lamebus)
- {
-
- cpu_irqoff();
- write_ctl_register(lamebus, CTLREG_PWR, 0);
-
- cpu_halt();
- }
- uint32_t
- lamebus_ramsize(void)
- {
-
- return read_ctl_register(NULL, CTLREG_RAMSZ);
- }
- void
- lamebus_assert_ipi(struct lamebus_softc *lamebus, struct cpu *target)
- {
- write_ctlcpu_register(lamebus, target->c_hardware_number,
- CTLCPU_CIPI, 1);
- }
- void
- lamebus_clear_ipi(struct lamebus_softc *lamebus, struct cpu *target)
- {
- write_ctlcpu_register(lamebus, target->c_hardware_number,
- CTLCPU_CIPI, 0);
- }
- struct lamebus_softc *
- lamebus_init(void)
- {
- struct lamebus_softc *lamebus;
- int i;
-
- lamebus = kmalloc(sizeof(struct lamebus_softc));
- if (lamebus==NULL) {
- panic("lamebus_init: Out of memory\n");
- }
- spinlock_init(&lamebus->ls_lock);
-
- lamebus->ls_slotsinuse = 1 << LB_CONTROLLER_SLOT;
- for (i=0; i<LB_NSLOTS; i++) {
- lamebus->ls_devdata[i] = NULL;
- lamebus->ls_irqfuncs[i] = NULL;
- }
- return lamebus;
- }
|