Index: sys/mips/broadcom/bcm_mipscore.c =================================================================== --- sys/mips/broadcom/bcm_mipscore.c +++ sys/mips/broadcom/bcm_mipscore.c @@ -46,6 +46,8 @@ #include #include +#include + #include "bcm_mipscore.h" static const struct resource_spec mipscore_rspec[MIPSCORE_MAX_RSPEC] = { @@ -56,6 +58,9 @@ #define MIPSCORE_DEV(_vendor, _core) \ BHND_DEVICE(_vendor, _core, NULL, NULL, BHND_DF_SOC) +#define BHND_MIPS74K_IRQN 5 +#define BHND_MIPS74K_IRQBASE 2 + struct bhnd_device mipscore_match[] = { MIPSCORE_DEV(BCM, MIPS), MIPSCORE_DEV(BCM, MIPS33), @@ -81,9 +86,13 @@ { struct mipscore_softc *sc; struct resource *res; - uint32_t intmask; + device_t *children; + uint32_t tmp; + uint32_t intmasks[BHND_MIPS74K_IRQN]; uint16_t devid; int error; + int offset, count; + int i, j; sc = device_get_softc(dev); devid = bhnd_get_device(dev); @@ -102,10 +111,55 @@ return (ENXIO); if (devid == BHND_COREID_MIPS74K) { - intmask = (1 << 31); + tmp = (1 << 31); + offset = offsetof(struct mipscore_regs, intmask[5]); /* Use intmask5 register to route the timer interrupt */ - bus_write_4(res, offsetof(struct mipscore_regs, intmask[5]), - intmask); + bus_write_4(res, offset, tmp); + /* Use intmask0-4 to identify mapping IRQ to cores */ + offset = offsetof(struct mipscore_regs, intmask[0]); + + /* scan IRQ masks of lines */ + for (i = 0; i < BHND_MIPS74K_IRQN; i++) { + intmasks[i] = bus_read_4(res, offset); + offset += sizeof(uint32_t); + } + + error = device_get_children(device_get_parent(dev), &children, + &count); + + if (error) { + BHND_ERROR_DEV(dev, "can't get list of BHND devices: %d", + error); + return (error); + } + + for (i = 0; i < count; i++) { + tmp = bhnd_read_config(children[i], + BCMA_DMP_OOBSELOUTA30, sizeof(uint32_t)); + if (tmp == 0) + continue; + + /* filter bits by LINE mask */ + tmp &= 0x1f; + /* calculate bitmask according to line number */ + tmp = (1 << tmp); + + /* try find line in IRQ bit masks */ + for (j = 0; j < BHND_MIPS74K_IRQN; j++) { + if ((intmasks[j] & tmp) == 0) + continue; + + BHND_INFO_DEV(dev, "%s: IRQ %d as rid 0", + bhnd_get_device_name(children[i]), + BHND_MIPS74K_IRQBASE + j); + + bus_set_resource(children[i], SYS_RES_IRQ, 0, + BHND_MIPS74K_IRQBASE + j, 1); + + break; + } + } + free(children, M_TEMP); } return (0);