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
This commit is contained in:
parent
223aefb522
commit
e8b77c6ef1
@ -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 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", A20_NMI},
|
||||
{"allwinner,sun6i-a31-sc-nmi", A31_NMI},
|
||||
|
||||
{"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 */
|
||||
|
Loading…
Reference in New Issue
Block a user