diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h index 4cd26513d409..ce681aa03f49 100644 --- a/sys/arm/include/intr.h +++ b/sys/arm/include/intr.h @@ -55,7 +55,12 @@ #elif defined(CPU_ARM11) #define NIRQ 128 #elif defined(SOC_MV_ARMADAXP) -#define NIRQ 148 +#define MAIN_IRQ_NUM 116 +#define ERR_IRQ_NUM 32 +#define ERR_IRQ (MAIN_IRQ_NUM) +#define MSI_IRQ_NUM 32 +#define MSI_IRQ (ERR_IRQ + ERR_IRQ_NUM) +#define NIRQ (MAIN_IRQ_NUM + ERR_IRQ_NUM + MSI_IRQ_NUM) #else #define NIRQ 32 #endif diff --git a/sys/arm/mv/mpic.c b/sys/arm/mv/mpic.c index ba8dde0275e0..0a1be1dae5ed 100644 --- a/sys/arm/mv/mpic.c +++ b/sys/arm/mv/mpic.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2006 Benno Rice. * Copyright (C) 2007-2011 MARVELL INTERNATIONAL LTD. + * Copyright (c) 2012 Semihalf. * All rights reserved. * * Developed by Semihalf. @@ -46,23 +47,34 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include +#include -#define IRQ_ERR 4 -#define MAIN_IRQS 116 +#ifdef DEBUG +#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ + printf(fmt,##args); } while (0) +#else +#define debugf(fmt, args...) +#endif + +#define MPIC_INT_ERR 4 +#define MPIC_INT_MSI 96 #define IRQ_MASK 0x3ff #define MPIC_CTRL 0x0 #define MPIC_SOFT_INT 0x4 +#define MPIC_SOFT_INT_DRBL1 (1 << 5) #define MPIC_ERR_CAUSE 0x20 #define MPIC_ISE 0x30 #define MPIC_ICE 0x34 -#define MPIC_IN_DOORBELL 0x78 -#define MPIC_IN_DOORBELL_MASK 0x7c +#define MPIC_IN_DRBL 0x78 +#define MPIC_IN_DRBL_MASK 0x7c #define MPIC_CTP 0xb0 #define MPIC_CTP 0xb0 #define MPIC_IIACK 0xb4 @@ -71,16 +83,20 @@ __FBSDID("$FreeBSD$"); #define MPIC_ERR_MASK 0xec0 struct mv_mpic_softc { - struct resource * mpic_res[2]; + device_t sc_dev; + struct resource * mpic_res[3]; bus_space_tag_t mpic_bst; bus_space_handle_t mpic_bsh; bus_space_tag_t cpu_bst; bus_space_handle_t cpu_bsh; + bus_space_tag_t drbl_bst; + bus_space_handle_t drbl_bsh; }; static struct resource_spec mv_mpic_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { SYS_RES_MEMORY, 1, RF_ACTIVE }, + { SYS_RES_MEMORY, 2, RF_ACTIVE }, { -1, 0 } }; @@ -92,14 +108,21 @@ static int mv_mpic_probe(device_t); static int mv_mpic_attach(device_t); uint32_t mv_mpic_get_cause(void); uint32_t mv_mpic_get_cause_err(void); +uint32_t mv_mpic_get_msi(void); static void arm_mask_irq_err(uintptr_t); static void arm_unmask_irq_err(uintptr_t); +static void arm_unmask_msi(void); #define MPIC_CPU_WRITE(softc, reg, val) \ bus_space_write_4((softc)->cpu_bst, (softc)->cpu_bsh, (reg), (val)) #define MPIC_CPU_READ(softc, reg) \ bus_space_read_4((softc)->cpu_bst, (softc)->cpu_bsh, (reg)) +#define MPIC_DRBL_WRITE(softc, reg, val) \ + bus_space_write_4((softc)->drbl_bst, (softc)->drbl_bsh, (reg), (val)) +#define MPIC_DRBL_READ(softc, reg) \ + bus_space_read_4((softc)->drbl_bst, (softc)->drbl_bsh, (reg)) + static int mv_mpic_probe(device_t dev) { @@ -123,6 +146,8 @@ mv_mpic_attach(device_t dev) return (ENXIO); mv_mpic_sc = sc; + sc->sc_dev = dev; + error = bus_alloc_resources(dev, mv_mpic_spec, sc->mpic_res); if (error) { device_printf(dev, "could not allocate resources\n"); @@ -135,10 +160,15 @@ mv_mpic_attach(device_t dev) sc->cpu_bst = rman_get_bustag(sc->mpic_res[1]); sc->cpu_bsh = rman_get_bushandle(sc->mpic_res[1]); + sc->drbl_bst = rman_get_bustag(sc->mpic_res[2]); + sc->drbl_bsh = rman_get_bushandle(sc->mpic_res[2]); + bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh, MPIC_CTRL, 1); MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 0); + arm_unmask_msi(); + return (0); } @@ -167,8 +197,10 @@ arm_get_next_irq(int last) CTR2(KTR_INTR, "%s: irq:%#x", __func__, irq); if (irq != IRQ_MASK) { - if (irq == IRQ_ERR) + if (irq == MPIC_INT_ERR) irq = mv_mpic_get_cause_err(); + if (irq == MPIC_INT_MSI) + irq = mv_mpic_get_msi(); next = irq; } @@ -186,11 +218,11 @@ arm_mask_irq(uintptr_t nb) MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 1); - if (nb < MAIN_IRQS) { + if (nb < ERR_IRQ) { bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh, MPIC_ICE, nb); MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ISM, nb); - } else + } else if (nb < MSI_IRQ) arm_mask_irq_err(nb); } @@ -201,7 +233,7 @@ arm_mask_irq_err(uintptr_t nb) uint32_t mask; uint8_t bit_off; - bit_off = nb - MAIN_IRQS; + bit_off = nb - ERR_IRQ; mask = MPIC_CPU_READ(mv_mpic_sc, MPIC_ERR_MASK); mask &= ~(1 << bit_off); MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ERR_MASK, mask); @@ -213,15 +245,15 @@ arm_unmask_irq(uintptr_t nb) MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 0); - if (nb < MAIN_IRQS) { + if (nb < ERR_IRQ) { bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh, MPIC_ISE, nb); MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ICM, nb); - } else + } else if (nb < MSI_IRQ) arm_unmask_irq_err(nb); if (nb == 0) - MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DOORBELL_MASK, 0xffffffff); + MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DRBL_MASK, 0xffffffff); } void @@ -231,15 +263,22 @@ arm_unmask_irq_err(uintptr_t nb) uint8_t bit_off; bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh, - MPIC_ISE, IRQ_ERR); - MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ICM, IRQ_ERR); + MPIC_ISE, MPIC_INT_ERR); + MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ICM, MPIC_INT_ERR); - bit_off = nb - MAIN_IRQS; + bit_off = nb - ERR_IRQ; mask = MPIC_CPU_READ(mv_mpic_sc, MPIC_ERR_MASK); mask |= (1 << bit_off); MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ERR_MASK, mask); } +static void +arm_unmask_msi(void) +{ + + arm_unmask_irq(MPIC_INT_MSI); +} + uint32_t mv_mpic_get_cause(void) { @@ -260,7 +299,61 @@ mv_mpic_get_cause_err(void) bit_off = ffs(err_cause) - 1; else return (-1); - return (MAIN_IRQS + bit_off); + + debugf("%s: irq:%x cause:%x\n", __func__, bit_off, err_cause); + return (ERR_IRQ + bit_off); +} + +uint32_t +mv_mpic_get_msi(void) +{ + uint32_t cause; + uint8_t bit_off; + + cause = MPIC_DRBL_READ(mv_mpic_sc, 0); + + if (cause) + bit_off = ffs(cause) - 1; + else + return (-1); + + debugf("%s: irq:%x cause:%x\n", __func__, bit_off, cause); + + cause &= ~(1 << bit_off); + MPIC_DRBL_WRITE(mv_mpic_sc, 0, cause); + + return (MSI_IRQ + bit_off); +} + +int +mv_msi_data(int irq, uint64_t *addr, uint32_t *data) +{ + u_long phys, base, size; + phandle_t node; + int error; + + node = ofw_bus_get_node(mv_mpic_sc->sc_dev); + + /* Get physical addres of register space */ + error = fdt_get_range(OF_parent(node), 0, &phys, &size); + if (error) { + printf("%s: Cannot get register physical address, err:%d", + __func__, error); + return (error); + } + + /* Get offset of MPIC register space */ + error = fdt_regsize(node, &base, &size); + if (error) { + printf("%s: Cannot get MPIC register offset, err:%d", + __func__, error); + return (error); + } + + *addr = phys + base + MPIC_SOFT_INT; + *data = MPIC_SOFT_INT_DRBL1 | irq; + + return (0); } #if defined(SMP) @@ -283,7 +376,7 @@ pic_ipi_get(int i __unused) { uint32_t val; - val = MPIC_CPU_READ(mv_mpic_sc, MPIC_IN_DOORBELL); + val = MPIC_CPU_READ(mv_mpic_sc, MPIC_IN_DRBL); if (val) return (ffs(val) - 1); @@ -296,7 +389,7 @@ pic_ipi_clear(int ipi) uint32_t val; val = ~(1 << ipi); - MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DOORBELL, val); + MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DRBL, val); } #endif diff --git a/sys/arm/mv/mvvar.h b/sys/arm/mv/mvvar.h index 4a2c87ded051..002640cea161 100644 --- a/sys/arm/mv/mvvar.h +++ b/sys/arm/mv/mvvar.h @@ -134,4 +134,6 @@ uint32_t mv_drbl_get_cause(int dir, int unit); void mv_drbl_set_msg(uint32_t val, int mnr, int dir, int unit); uint32_t mv_drbl_get_msg(int mnr, int dir, int unit); +int mv_msi_data(int irq, uint64_t *addr, uint32_t *data); + #endif /* _MVVAR_H_ */ diff --git a/sys/boot/fdt/dts/db78460.dts b/sys/boot/fdt/dts/db78460.dts index 2db9a9917214..45a13c319e05 100644 --- a/sys/boot/fdt/dts/db78460.dts +++ b/sys/boot/fdt/dts/db78460.dts @@ -75,7 +75,7 @@ interrupt-controller; #address-cells = <0>; #interrupt-cells = <1>; - reg = <0x20a00 0x500 0x21000 0x800>; + reg = <0x20a00 0x500 0x21000 0x800 0x20400 0x100>; compatible = "mrvl,mpic"; };