Dynamically attach ampintc(4) and make it register itself as an interrupt
authorkettenis <kettenis@openbsd.org>
Thu, 4 Aug 2016 15:52:52 +0000 (15:52 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 4 Aug 2016 15:52:52 +0000 (15:52 +0000)
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
sys/arch/arm/cortex/files.cortex
sys/arch/armv7/conf/GENERIC
sys/arch/armv7/conf/RAMDISK
sys/arch/armv7/imx/if_fec.c
sys/arch/armv7/imx/imxahci.c
sys/arch/armv7/imx/imxehci.c
sys/arch/armv7/imx/imxesdhc.c
sys/arch/armv7/imx/imxiic.c
sys/arch/armv7/imx/imxuart.c

index 774b909..c6e9d99 100644 (file)
@@ -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 <drahn@openbsd.org>
  *
 #include <sys/malloc.h>
 #include <sys/device.h>
 #include <sys/evcount.h>
-#include <arm/cpufunc.h>
+
 #include <machine/bus.h>
-#include <arm/cortex/cortex.h>
+#include <machine/fdt.h>
 
-/* offset from periphbase */
-#define ICP_ADDR       0x100
-#define ICP_SIZE       0x100
-#define ICD_ADDR       0x1000
-#define ICD_SIZE       0x1000
+#include <arm/cpufunc.h>
+#include <arm/cortex/cortex.h>
 
-#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 <dev/ofw/fdt.h>
+#include <dev/ofw/openfirm.h>
 
 /* registers */
 #define        ICD_DCR                 0x000
 #define ICD_COMP_ID_2                  0xFEC
 #define ICD_COMP_ID_3                  0xFEC
 
-#define ICD_SIZE                       0x1000
-
 
 #define ICPICR                         0x00
 #define ICPIPMR                                0x04
 #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)
index cb4200a..630dabb 100644 (file)
@@ -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
index c3f0311..da2fbeb 100644 (file)
@@ -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?
index 4a3c53e..4b1c87c 100644 (file)
@@ -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?
index ad06d31..1e9be36 100644 (file)
@@ -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 <patrick@blueri.se>
  *
@@ -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);
index 9efa0c8..01d3272 100644 (file)
@@ -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 <patrick@blueri.se>
  *
@@ -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");
index eaa8bfc..29d1bf3 100644 (file)
@@ -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 <patrick@blueri.se>
  *
@@ -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");
index 3a5e16d..20ee004 100644 (file)
@@ -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 <drahn@openbsd.org>
  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -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,
index ae6d01a..c08261d 100644 (file)
@@ -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 <patrick@blueri.se>
  *
@@ -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
 
index 3fd81b0..abc5731 100644 (file)
@@ -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 <drahn@motorola.com>
  *
@@ -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;