diff options
author | Kyle Evans <kevans@FreeBSD.org> | 2017-11-19 03:14:10 +0000 |
---|---|---|
committer | Kyle Evans <kevans@FreeBSD.org> | 2017-11-19 03:14:10 +0000 |
commit | c4717ac049bd529976c0e4da0a7638972eb94278 (patch) | |
tree | 8d317ca4afefbfccb06330c6bf81d99b015c78b0 /sys/arm/allwinner/aw_nmi.c | |
parent | 6be8e27be013a67c96cbdda060a5f17b13a66eea (diff) | |
download | src-c4717ac049bd529976c0e4da0a7638972eb94278.tar.gz src-c4717ac049bd529976c0e4da0a7638972eb94278.zip |
aw_nmi: add support for a31/a83t's r_intc
We currently support the a83t's r_intc in a somewhat hack-ish way; our .dts
describes it as nmi_intc, and uses a subset of the actual register space to
make it line up with a20/a31 nmi offsets.
This breaks with the recent 4.14 update describing r_intc using the full
register space, so update aw_nmi to use the correct register offsets with
the right compat data in a way that doesn't break our current dts with
nmi_intc or upstream with r_intc described.
Reviewed by: manu
Approved by: emaste (mentor)
Differential Revision: https://reviews.freebsd.org/D13122
Notes
Notes:
svn path=/head/; revision=325991
Diffstat (limited to 'sys/arm/allwinner/aw_nmi.c')
-rw-r--r-- | sys/arm/allwinner/aw_nmi.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/sys/arm/allwinner/aw_nmi.c b/sys/arm/allwinner/aw_nmi.c index 86c122f5300a..73783c13cee4 100644 --- a/sys/arm/allwinner/aw_nmi.c +++ b/sys/arm/allwinner/aw_nmi.c @@ -57,6 +57,10 @@ __FBSDID("$FreeBSD$"); #define A31_NMI_IRQ_ENABLE_REG 0x34 #define NMI_IRQ_ENABLE (1U << 0) +#define R_NMI_IRQ_CTRL_REG 0x0c +#define R_NMI_IRQ_PENDING_REG 0x10 +#define R_NMI_IRQ_ENABLE_REG 0x40 + #define SC_NMI_READ(_sc, _reg) bus_read_4(_sc->res[0], _reg) #define SC_NMI_WRITE(_sc, _reg, _val) bus_write_4(_sc->res[0], _reg, _val) @@ -73,21 +77,43 @@ struct aw_nmi_intr { enum intr_trigger tri; }; +struct aw_nmi_reg_cfg { + uint8_t ctrl_reg; + uint8_t pending_reg; + uint8_t enable_reg; +}; + struct aw_nmi_softc { device_t dev; struct resource * res[2]; void * intrcookie; struct aw_nmi_intr intr; - uint8_t enable_reg; + struct aw_nmi_reg_cfg * cfg; }; -#define A20_NMI 1 -#define A31_NMI 2 +static struct aw_nmi_reg_cfg a20_nmi_cfg = { + .ctrl_reg = NMI_IRQ_CTRL_REG, + .pending_reg = NMI_IRQ_PENDING_REG, + .enable_reg = A20_NMI_IRQ_ENABLE_REG, +}; -static struct ofw_compat_data compat_data[] = { - {"allwinner,sun7i-a20-sc-nmi", A20_NMI}, - {"allwinner,sun6i-a31-sc-nmi", A31_NMI}, +static struct aw_nmi_reg_cfg a31_nmi_cfg = { + .ctrl_reg = NMI_IRQ_CTRL_REG, + .pending_reg = NMI_IRQ_PENDING_REG, + .enable_reg = A31_NMI_IRQ_ENABLE_REG, +}; +static struct aw_nmi_reg_cfg a83t_r_nmi_cfg = { + .ctrl_reg = R_NMI_IRQ_CTRL_REG, + .pending_reg = R_NMI_IRQ_PENDING_REG, + .enable_reg = R_NMI_IRQ_ENABLE_REG, +}; + +static struct ofw_compat_data compat_data[] = { + {"allwinner,sun7i-a20-sc-nmi", (uintptr_t)&a20_nmi_cfg}, + {"allwinner,sun6i-a31-sc-nmi", (uintptr_t)&a31_nmi_cfg}, + {"allwinner,sun6i-a31-r-intc", (uintptr_t)&a83t_r_nmi_cfg}, + {"allwinner,sun8i-a83t-r-intc", (uintptr_t)&a83t_r_nmi_cfg}, {NULL, 0}, }; @@ -98,13 +124,13 @@ aw_nmi_intr(void *arg) sc = arg; - if (SC_NMI_READ(sc, NMI_IRQ_PENDING_REG) == 0) { + if (SC_NMI_READ(sc, sc->cfg->pending_reg) == 0) { device_printf(sc->dev, "Spurious interrupt\n"); return (FILTER_HANDLED); } if (intr_isrc_dispatch(&sc->intr.isrc, curthread->td_intr_frame) != 0) { - SC_NMI_WRITE(sc, sc->enable_reg, !NMI_IRQ_ENABLE); + SC_NMI_WRITE(sc, sc->cfg->enable_reg, !NMI_IRQ_ENABLE); device_printf(sc->dev, "Stray interrupt, NMI disabled\n"); } @@ -118,7 +144,7 @@ aw_nmi_enable_intr(device_t dev, struct intr_irqsrc *isrc) sc = device_get_softc(dev); - SC_NMI_WRITE(sc, sc->enable_reg, NMI_IRQ_ENABLE); + SC_NMI_WRITE(sc, sc->cfg->enable_reg, NMI_IRQ_ENABLE); } static void @@ -128,7 +154,7 @@ aw_nmi_disable_intr(device_t dev, struct intr_irqsrc *isrc) sc = device_get_softc(dev); - SC_NMI_WRITE(sc, sc->enable_reg, !NMI_IRQ_ENABLE); + SC_NMI_WRITE(sc, sc->cfg->enable_reg, !NMI_IRQ_ENABLE); } static int @@ -254,7 +280,7 @@ aw_nmi_setup_intr(device_t dev, struct intr_irqsrc *isrc, icfg = NMI_IRQ_LOW_EDGE; } - SC_NMI_WRITE(sc, NMI_IRQ_CTRL_REG, icfg); + SC_NMI_WRITE(sc, sc->cfg->ctrl_reg, icfg); return (0); } @@ -271,7 +297,7 @@ aw_nmi_teardown_intr(device_t dev, struct intr_irqsrc *isrc, sc->intr.pol = INTR_POLARITY_CONFORM; sc->intr.tri = INTR_TRIGGER_CONFORM; - SC_NMI_WRITE(sc, sc->enable_reg, !NMI_IRQ_ENABLE); + SC_NMI_WRITE(sc, sc->cfg->enable_reg, !NMI_IRQ_ENABLE); } return (0); @@ -284,7 +310,7 @@ aw_nmi_pre_ithread(device_t dev, struct intr_irqsrc *isrc) sc = device_get_softc(dev); aw_nmi_disable_intr(dev, isrc); - SC_NMI_WRITE(sc, NMI_IRQ_PENDING_REG, NMI_IRQ_ACK); + SC_NMI_WRITE(sc, sc->cfg->pending_reg, NMI_IRQ_ACK); } static void @@ -303,7 +329,7 @@ aw_nmi_post_filter(device_t dev, struct intr_irqsrc *isrc) sc = device_get_softc(dev); arm_irq_memory_barrier(0); - SC_NMI_WRITE(sc, NMI_IRQ_PENDING_REG, NMI_IRQ_ACK); + SC_NMI_WRITE(sc, sc->cfg->pending_reg, NMI_IRQ_ACK); } static int @@ -327,6 +353,8 @@ aw_nmi_attach(device_t dev) sc = device_get_softc(dev); sc->dev = dev; + sc->cfg = (struct aw_nmi_reg_cfg *) + ofw_bus_search_compatible(dev, compat_data)->ocd_data; if (bus_alloc_resources(dev, aw_nmi_res_spec, sc->res) != 0) { device_printf(dev, "can't allocate device resources\n"); @@ -339,18 +367,9 @@ aw_nmi_attach(device_t dev) return (ENXIO); } - switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) { - case A20_NMI: - sc->enable_reg = A20_NMI_IRQ_ENABLE_REG; - break; - case A31_NMI: - sc->enable_reg = A31_NMI_IRQ_ENABLE_REG; - break; - } - /* Disable and clear interrupts */ - SC_NMI_WRITE(sc, sc->enable_reg, !NMI_IRQ_ENABLE); - SC_NMI_WRITE(sc, NMI_IRQ_PENDING_REG, NMI_IRQ_ACK); + SC_NMI_WRITE(sc, sc->cfg->enable_reg, !NMI_IRQ_ENABLE); + SC_NMI_WRITE(sc, sc->cfg->pending_reg, NMI_IRQ_ACK); xref = OF_xref_from_node(ofw_bus_get_node(dev)); /* Register our isrc */ |