From 6fc522b170aec3f74aa118c9c88b931d30a95f59 Mon Sep 17 00:00:00 2001 From: kettenis Date: Thu, 4 Aug 2016 15:52:52 +0000 Subject: [PATCH] Dynamically attach ampintc(4) and make it register itself as an interrupt controller. Switch all i.MX6 devices over to the new FDT-aware interrupt establish API and enable imxgpc(4). This may break other platforms that use ampintc(4) as their interrupt controller. We will fix this as soon as possible by switching them over to the new interrupt establish API as well. This also removes the hack in fec(4) to avoid the gpio-based interrupt workaround. This commit is an essential step on the road to fix that issue properly. ok patrick@, jsg@ --- sys/arch/arm/cortex/ampintc.c | 140 ++++++++++++++++--------------- sys/arch/arm/cortex/files.cortex | 4 +- sys/arch/armv7/conf/GENERIC | 5 +- sys/arch/armv7/conf/RAMDISK | 5 +- sys/arch/armv7/imx/if_fec.c | 9 +- sys/arch/armv7/imx/imxahci.c | 6 +- sys/arch/armv7/imx/imxehci.c | 6 +- sys/arch/armv7/imx/imxesdhc.c | 6 +- sys/arch/armv7/imx/imxiic.c | 4 +- sys/arch/armv7/imx/imxuart.c | 6 +- 10 files changed, 98 insertions(+), 93 deletions(-) diff --git a/sys/arch/arm/cortex/ampintc.c b/sys/arch/arm/cortex/ampintc.c index 774b909b537..c6e9d9954f7 100644 --- a/sys/arch/arm/cortex/ampintc.c +++ b/sys/arch/arm/cortex/ampintc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ampintc.c,v 1.9 2016/01/31 00:14:50 jsg Exp $ */ +/* $OpenBSD: ampintc.c,v 1.10 2016/08/04 15:52:52 kettenis Exp $ */ /* * Copyright (c) 2007,2009,2011 Dale Rahn * @@ -26,20 +26,15 @@ #include #include #include -#include + #include -#include +#include -/* offset from periphbase */ -#define ICP_ADDR 0x100 -#define ICP_SIZE 0x100 -#define ICD_ADDR 0x1000 -#define ICD_SIZE 0x1000 +#include +#include -#define ICD_A7_A15_ADDR 0x1000 -#define ICD_A7_A15_SIZE 0x1000 -#define ICP_A7_A15_ADDR 0x2000 -#define ICP_A7_A15_SIZE 0x1000 +#include +#include /* registers */ #define ICD_DCR 0x000 @@ -107,8 +102,6 @@ #define ICD_COMP_ID_2 0xFEC #define ICD_COMP_ID_3 0xFEC -#define ICD_SIZE 0x1000 - #define ICPICR 0x00 #define ICPIPMR 0x04 @@ -125,14 +118,11 @@ #define ICPPRP 0x14 #define ICPHPIR 0x18 #define ICPIIR 0xFC -#define ICP_SIZE 0x100 + /* * what about periph_id and component_id */ -#define AMPAMPINTC_SIZE 0x1000 - - #define IRQ_ENABLE 1 #define IRQ_DISABLE 0 @@ -143,6 +133,7 @@ struct ampintc_softc { bus_space_tag_t sc_iot; bus_space_handle_t sc_d_ioh, sc_p_ioh; struct evcount sc_spur; + struct interrupt_controller sc_ic; }; struct ampintc_softc *ampintc; @@ -176,6 +167,8 @@ void *ampintc_intr_establish(int, int, int (*)(void *), void *, char *); void *ampintc_intr_establish_ext(int, int, int (*)(void *), void *, char *); +void *ampintc_intr_establish_fdt(void *, int *, int, + int (*)(void *), void *, char *); void ampintc_intr_disestablish(void *); void ampintc_irq_handler(void *); const char *ampintc_intr_string(void *); @@ -194,85 +187,75 @@ struct cfdriver ampintc_cd = { NULL, "ampintc", DV_DULL }; +static char *ampintc_compatibles[] = { + "arm,cortex-a7-gic", + "arm,cortex-a9-gic", + "arm,cortex-a15-gic", + NULL +}; + int ampintc_match(struct device *parent, void *cfdata, void *aux) { - return (1); + struct fdt_attach_args *faa = aux; + int i; + + for (i = 0; ampintc_compatibles[i]; i++) + if (OF_is_compatible(faa->fa_node, ampintc_compatibles[i])) + return (1); + + return (0); } paddr_t gic_dist_base, gic_cpu_base, gic_dist_size, gic_cpu_size; void -ampintc_attach(struct device *parent, struct device *self, void *args) +ampintc_attach(struct device *parent, struct device *self, void *aux) { struct ampintc_softc *sc = (struct ampintc_softc *)self; - struct cortex_attach_args *ia = args; + struct fdt_attach_args *faa = aux; int i, nintr; - bus_space_tag_t iot; - bus_space_handle_t d_ioh, p_ioh; - uint32_t icp, icpsize, icd, icdsize; ampintc = sc; arm_init_smask(); - iot = ia->ca_iot; - icp = ia->ca_periphbase + ICP_ADDR; - icpsize = ICP_SIZE; - icd = ia->ca_periphbase + ICD_ADDR; - icdsize = ICD_SIZE; - - if ((cputype & CPU_ID_CORTEX_A7_MASK) == CPU_ID_CORTEX_A7 || - (cputype & CPU_ID_CORTEX_A15_MASK) == CPU_ID_CORTEX_A15 || - (cputype & CPU_ID_CORTEX_A17_MASK) == CPU_ID_CORTEX_A17) { - icp = ia->ca_periphbase + ICP_A7_A15_ADDR; - icpsize = ICP_A7_A15_SIZE; - icd = ia->ca_periphbase + ICD_A7_A15_ADDR; - icdsize = ICD_A7_A15_SIZE; - } - - /* exynos gic isn't at the expected offsets from periphbase */ - if (gic_cpu_base) - icp = gic_cpu_base; - if (gic_cpu_size) - icpsize = gic_cpu_size; - if (gic_dist_base) - icd = gic_dist_base; - if (gic_dist_size) - icdsize = gic_dist_size; - - if (bus_space_map(iot, icp, icpsize, 0, &p_ioh)) - panic("ampintc_attach: ICP bus_space_map failed!"); + sc->sc_iot = faa->fa_iot; - if (bus_space_map(iot, icd, icdsize, 0, &d_ioh)) - panic("ampintc_attach: ICD bus_space_map failed!"); + /* First row: ICD */ + if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, + faa->fa_reg[0].size, 0, &sc->sc_d_ioh)) + panic("%s: ICD bus_space_map failed!", __func__); - sc->sc_iot = iot; - sc->sc_d_ioh = d_ioh; - sc->sc_p_ioh = p_ioh; + /* Second row: ICP */ + if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr, + faa->fa_reg[1].size, 0, &sc->sc_p_ioh)) + panic("%s: ICP bus_space_map failed!", __func__); evcount_attach(&sc->sc_spur, "irq1023/spur", NULL); - nintr = 32 * (bus_space_read_4(iot, d_ioh, ICD_ICTR) & ICD_ICTR_ITL_M); + nintr = 32 * (bus_space_read_4(sc->sc_iot, sc->sc_d_ioh, + ICD_ICTR) & ICD_ICTR_ITL_M); nintr += 32; /* ICD_ICTR + 1, irq 0-31 is SGI, 32+ is PPI */ sc->sc_nintr = nintr; printf(" nirq %d\n", nintr); - /* Disable all interrupts, clear all pending */ for (i = 0; i < nintr/32; i++) { - bus_space_write_4(iot, d_ioh, ICD_ICERn(i*32), ~0); - bus_space_write_4(iot, d_ioh, ICD_ICPRn(i*32), ~0); + bus_space_write_4(sc->sc_iot, sc->sc_d_ioh, + ICD_ICERn(i*32), ~0); + bus_space_write_4(sc->sc_iot, sc->sc_d_ioh, + ICD_ICPRn(i*32), ~0); } for (i = 0; i < nintr; i++) { /* lowest priority ?? */ - bus_space_write_1(iot, d_ioh, ICD_IPRn(i), 0xff); + bus_space_write_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPRn(i), 0xff); /* target no cpus */ - bus_space_write_1(iot, d_ioh, ICD_IPTRn(i), 0); + bus_space_write_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(i), 0); } for (i = 2; i < nintr/16; i++) { /* irq 32 - N */ - bus_space_write_4(iot, d_ioh, ICD_ICRn(i*16), 0); + bus_space_write_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICRn(i*16), 0); } /* software reset of the part? */ @@ -280,7 +263,6 @@ ampintc_attach(struct device *parent, struct device *self, void *args) /* XXX - check power saving bit */ - sc->sc_ampintc_handler = mallocarray(nintr, sizeof(*sc->sc_ampintc_handler), M_DEVBUF, M_ZERO | M_NOWAIT); for (i = 0; i < nintr; i++) { @@ -296,9 +278,14 @@ ampintc_attach(struct device *parent, struct device *self, void *args) ampintc_intr_disestablish, ampintc_intr_string, ampintc_irq_handler); /* enable interrupts */ - bus_space_write_4(iot, d_ioh, ICD_DCR, 3); - bus_space_write_4(iot, p_ioh, ICPICR, 1); + bus_space_write_4(sc->sc_iot, sc->sc_d_ioh, ICD_DCR, 3); + bus_space_write_4(sc->sc_iot, sc->sc_p_ioh, ICPICR, 1); enable_interrupts(PSR_I); + + sc->sc_ic.ic_node = faa->fa_node; + sc->sc_ic.ic_cookie = self; + sc->sc_ic.ic_establish = ampintc_intr_establish_fdt; + arm_intr_register_fdt(&sc->sc_ic); } void @@ -532,6 +519,27 @@ ampintc_intr_establish_ext(int irqno, int level, int (*func)(void *), return ampintc_intr_establish(irqno+32, level, func, arg, name); } +void * +ampintc_intr_establish_fdt(void *cookie, int *cell, int level, + int (*func)(void *), void *arg, char *name) +{ + struct ampintc_softc *sc = (struct ampintc_softc *)cookie; + int irq; + + /* 2nd cell contains the interrupt number */ + irq = cell[1]; + + /* 1st cell contains type: 0 SPI (32-X), 1 PPI (16-31) */ + if (cell[0] == 0) + irq += 32; + else if (cell[0] == 1) + irq += 16; + else + panic("%s: bogus interrupt type", sc->sc_dev.dv_xname); + + return ampintc_intr_establish(irq, level, func, arg, name); +} + void * ampintc_intr_establish(int irqno, int level, int (*func)(void *), void *arg, char *name) diff --git a/sys/arch/arm/cortex/files.cortex b/sys/arch/arm/cortex/files.cortex index cb4200a091d..630dabb248c 100644 --- a/sys/arch/arm/cortex/files.cortex +++ b/sys/arch/arm/cortex/files.cortex @@ -1,4 +1,4 @@ -# $OpenBSD: files.cortex,v 1.4 2016/05/02 08:15:55 patrick Exp $ +# $OpenBSD: files.cortex,v 1.5 2016/08/04 15:52:52 kettenis Exp $ # ARM core device cortex {} @@ -6,7 +6,7 @@ attach cortex at fdt file arch/arm/cortex/cortex.c cortex device ampintc -attach ampintc at cortex +attach ampintc at fdt file arch/arm/cortex/ampintc.c ampintc device amptimer diff --git a/sys/arch/armv7/conf/GENERIC b/sys/arch/armv7/conf/GENERIC index c3f031123c9..da2fbeb3a51 100644 --- a/sys/arch/armv7/conf/GENERIC +++ b/sys/arch/armv7/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.31 2016/07/12 19:17:49 kettenis Exp $ +# $OpenBSD: GENERIC,v 1.32 2016/08/04 15:52:52 kettenis Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -33,7 +33,7 @@ cpu0 at mainbus? # Cortex-A9 cortex0 at mainbus? -ampintc* at cortex? +ampintc* at fdt? amptimer* at cortex? agtimer* at cortex? armliicc* at cortex? @@ -42,6 +42,7 @@ armliicc* at cortex? imx0 at mainbus? # iMX SoC imxccm* at imx? # clock control module imxiomuxc* at imx? # iomux controller +imxgpc* at fdt? # power controller imxdog* at fdt? # watchdog timer imxocotp* at imx? # on-chip otp controller imxgpio* at fdt? # user-visible GPIO pins? diff --git a/sys/arch/armv7/conf/RAMDISK b/sys/arch/armv7/conf/RAMDISK index 4a3c53eb478..4b1c87c873b 100644 --- a/sys/arch/armv7/conf/RAMDISK +++ b/sys/arch/armv7/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.28 2016/07/12 19:17:49 kettenis Exp $ +# $OpenBSD: RAMDISK,v 1.29 2016/08/04 15:52:52 kettenis Exp $ machine armv7 arm @@ -32,7 +32,7 @@ cpu0 at mainbus? # Cortex-A9 cortex0 at mainbus? -ampintc* at cortex? +ampintc* at fdt? amptimer* at cortex? agtimer* at cortex? armliicc* at cortex? @@ -41,6 +41,7 @@ armliicc* at cortex? imx0 at mainbus? # iMX SoC imxccm* at imx? # clock control module imxiomuxc* at imx? # iomux controller +imxgpc* at fdt? # power controller imxdog* at fdt? # watchdog timer imxocotp* at imx? # on-chip otp controller imxgpio* at fdt? # user-visible GPIO pins? diff --git a/sys/arch/armv7/imx/if_fec.c b/sys/arch/armv7/imx/if_fec.c index ad06d3162f3..1e9be366b2d 100644 --- a/sys/arch/armv7/imx/if_fec.c +++ b/sys/arch/armv7/imx/if_fec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_fec.c,v 1.12 2016/08/04 14:14:05 kettenis Exp $ */ +/* $OpenBSD: if_fec.c,v 1.13 2016/08/04 15:52:52 kettenis Exp $ */ /* * Copyright (c) 2012-2013 Patrick Wildt * @@ -295,17 +295,12 @@ fec_attach(struct device *parent, struct device *self, void *aux) struct mii_softc *child; struct ifnet *ifp; int tsize, rsize, tbsize, rbsize, s; - uint32_t intr[8]; uint32_t phy_reset_gpio[3]; uint32_t phy_reset_duration; if (faa->fa_nreg < 1) return; - if (OF_getpropintarray(faa->fa_node, "interrupts-extended", - intr, sizeof(intr)) < sizeof(intr)) - intr[2] = 0x76; - sc->sc_node = faa->fa_node; sc->sc_iot = faa->fa_iot; if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, @@ -356,7 +351,7 @@ fec_attach(struct device *parent, struct device *self, void *aux) HWRITE4(sc, ENET_EIMR, 0); HWRITE4(sc, ENET_EIR, 0xffffffff); - sc->sc_ih = arm_intr_establish(intr[2], IPL_NET, + sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_NET, fec_intr, sc, sc->sc_dev.dv_xname); tsize = ENET_MAX_TXD * sizeof(struct fec_buf_desc); diff --git a/sys/arch/armv7/imx/imxahci.c b/sys/arch/armv7/imx/imxahci.c index 9efa0c8fafb..01d32720603 100644 --- a/sys/arch/armv7/imx/imxahci.c +++ b/sys/arch/armv7/imx/imxahci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imxahci.c,v 1.6 2016/07/27 11:45:02 patrick Exp $ */ +/* $OpenBSD: imxahci.c,v 1.7 2016/08/04 15:52:52 kettenis Exp $ */ /* * Copyright (c) 2013 Patrick Wildt * @@ -115,7 +115,7 @@ imxahci_attach(struct device *parent, struct device *self, void *aux) struct fdt_attach_args *faa = aux; uint32_t timeout = 0x100000; - if (faa->fa_nreg < 1 || faa->fa_nintr < 3) + if (faa->fa_nreg < 1) return; sc->sc_iot = faa->fa_iot; @@ -126,7 +126,7 @@ imxahci_attach(struct device *parent, struct device *self, void *aux) faa->fa_reg[0].size, 0, &sc->sc_ioh)) panic("imxahci_attach: bus_space_map failed!"); - sc->sc_ih = arm_intr_establish(faa->fa_intr[1], IPL_BIO, + sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_BIO, ahci_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": unable to establish interrupt\n"); diff --git a/sys/arch/armv7/imx/imxehci.c b/sys/arch/armv7/imx/imxehci.c index eaa8bfc0ad9..29d1bf3e2db 100644 --- a/sys/arch/armv7/imx/imxehci.c +++ b/sys/arch/armv7/imx/imxehci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imxehci.c,v 1.14 2016/07/27 11:45:02 patrick Exp $ */ +/* $OpenBSD: imxehci.c,v 1.15 2016/08/04 15:52:52 kettenis Exp $ */ /* * Copyright (c) 2012-2013 Patrick Wildt * @@ -115,7 +115,7 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) uint32_t vbus; int node; - if (faa->fa_nreg < 1 || faa->fa_nintr < 3) + if (faa->fa_nreg < 1) return; if (OF_getpropintarray(faa->fa_node, "fsl,usbphy", @@ -255,7 +255,7 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) EOWRITE4(&sc->sc, EHCI_PORTSC(1), EOREAD4(&sc->sc, EHCI_PORTSC(1)) & ~EHCI_PS_PTS_UTMI_MASK); - sc->sc_ih = arm_intr_establish(faa->fa_intr[1], IPL_USB, + sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_USB, ehci_intr, &sc->sc, devname); if (sc->sc_ih == NULL) { printf(": unable to establish interrupt\n"); diff --git a/sys/arch/armv7/imx/imxesdhc.c b/sys/arch/armv7/imx/imxesdhc.c index 3a5e16d6693..20ee004055b 100644 --- a/sys/arch/armv7/imx/imxesdhc.c +++ b/sys/arch/armv7/imx/imxesdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imxesdhc.c,v 1.26 2016/07/27 11:45:02 patrick Exp $ */ +/* $OpenBSD: imxesdhc.c,v 1.27 2016/08/04 15:52:52 kettenis Exp $ */ /* * Copyright (c) 2009 Dale Rahn * Copyright (c) 2006 Uwe Stuehler @@ -297,7 +297,7 @@ imxesdhc_attach(struct device *parent, struct device *self, void *aux) uint32_t caps; uint32_t width; - if (faa->fa_nreg < 1 || faa->fa_nintr < 3) + if (faa->fa_nreg < 1) return; sc->unit = (faa->fa_reg[0].addr & 0xc000) >> 14; @@ -312,7 +312,7 @@ imxesdhc_attach(struct device *parent, struct device *self, void *aux) imxiomuxc_pinctrlbyname(faa->fa_node, "default"); - sc->sc_ih = arm_intr_establish(faa->fa_intr[1], IPL_SDMMC, + sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_SDMMC, imxesdhc_intr, sc, sc->sc_dev.dv_xname); OF_getpropintarray(sc->sc_node, "cd-gpios", sc->sc_gpio, diff --git a/sys/arch/armv7/imx/imxiic.c b/sys/arch/armv7/imx/imxiic.c index ae6d01adcf0..c08261d6b4c 100644 --- a/sys/arch/armv7/imx/imxiic.c +++ b/sys/arch/armv7/imx/imxiic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imxiic.c,v 1.9 2016/07/27 11:45:02 patrick Exp $ */ +/* $OpenBSD: imxiic.c,v 1.10 2016/08/04 15:52:52 kettenis Exp $ */ /* * Copyright (c) 2013 Patrick Wildt * @@ -128,7 +128,7 @@ imxiic_attach(struct device *parent, struct device *self, void *aux) panic("imxiic_attach: bus_space_map failed!"); #if 0 - sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_BIO, + sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_BIO, imxiic_intr, sc, sc->sc_dev.dv_xname); #endif diff --git a/sys/arch/armv7/imx/imxuart.c b/sys/arch/armv7/imx/imxuart.c index 3fd81b016b9..abc57318ed6 100644 --- a/sys/arch/armv7/imx/imxuart.c +++ b/sys/arch/armv7/imx/imxuart.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imxuart.c,v 1.10 2016/07/27 11:45:02 patrick Exp $ */ +/* $OpenBSD: imxuart.c,v 1.11 2016/08/04 15:52:52 kettenis Exp $ */ /* * Copyright (c) 2005 Dale Rahn * @@ -164,12 +164,12 @@ imxuart_attach(struct device *parent, struct device *self, void *aux) struct fdt_attach_args *faa = aux; int maj; - if (faa->fa_nreg < 1 || faa->fa_nintr < 3) + if (faa->fa_nreg < 1) return; imxiomuxc_pinctrlbyname(faa->fa_node, "default"); - sc->sc_irq = arm_intr_establish(faa->fa_intr[1], IPL_TTY, + sc->sc_irq = arm_intr_establish_fdt(faa->fa_node, IPL_TTY, imxuart_intr, sc, sc->sc_dev.dv_xname); sc->sc_iot = faa->fa_iot; -- 2.20.1