Hi,

based on the other changes this diff is a draft to make ampintc, the
generic interrupt controller code, FDT aware.

It basically only needs to see if the compatible string matches and
then read out two rows of regs/addresses.

Still, it needs to take care of the address- and size-cell sizes, as
the address and size values can be either of size 32-bit or 64-bit.

To make extraction of memory addresses easier I had implemented
fdt_get_memory_address().  As we want to use the OF_* API, would it make
sense to expose and implement that function as OF_* function, or should
I just do it manually like in this diff?

The code will probably be duplicated in every driver.  Most only need
one "reg" row though, which shortens the code a bit.

Patrick

diff --git sys/arch/arm/cortex/ampintc.c sys/arch/arm/cortex/ampintc.c
index 774b909..84294c4 100644
--- sys/arch/arm/cortex/ampintc.c
+++ sys/arch/arm/cortex/ampintc.c
@@ -29,6 +29,9 @@
 #include <arm/cpufunc.h>
 #include <machine/bus.h>
 #include <arm/cortex/cortex.h>
+#include <arm/fdt.h>
+
+#include <dev/ofw/openfirm.h>
 
 /* offset from periphbase */
 #define ICP_ADDR       0x100
@@ -166,7 +169,10 @@ struct intrq {
 
 
 int             ampintc_match(struct device *, void *, void *);
+int             ampintc_match_fdt(struct device *, void *, void *);
 void            ampintc_attach(struct device *, struct device *, void *);
+void            ampintc_attach_cortex(struct device *, struct device *, void 
*);
+void            ampintc_attach_fdt(struct device *, struct device *, void *);
 int             ampintc_spllower(int);
 void            ampintc_splx(int);
 int             ampintc_splraise(int);
@@ -187,36 +193,63 @@ void               ampintc_intr_disable(int);
 void            ampintc_route(int, int , int);
 
 struct cfattach        ampintc_ca = {
-       sizeof (struct ampintc_softc), ampintc_match, ampintc_attach
+       sizeof (struct ampintc_softc), ampintc_match, ampintc_attach_cortex
+};
+
+struct cfattach        ampintc_fdt_ca = {
+       sizeof (struct ampintc_softc), ampintc_match_fdt, ampintc_attach_fdt
 };
 
 struct cfdriver ampintc_cd = {
        NULL, "ampintc", DV_DULL
 };
 
+static char *ampintc_compatibles[] = {
+       "arm,gic",
+       "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);
 }
 
+int
+ampintc_match_fdt(struct device *parent, void *cfdata, void *aux)
+{
+       struct fdt_attach_args *fa = (struct fdt_attach_args *)aux;
+       char buffer[128];
+       int i;
+
+       if (fa->fa_node == 0)
+               return (0);
+
+       if (!OF_getprop(fa->fa_node, "compatible", buffer,
+           sizeof(buffer)))
+               return (0);
+
+       for (i = 0; ampintc_compatibles[i]; i++)
+               if (!strcmp(buffer, 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_cortex(struct device *parent, struct device *self,
+    void *args)
 {
        struct ampintc_softc *sc = (struct ampintc_softc *)self;
        struct cortex_attach_args *ia = args;
-       int i, nintr;
-       bus_space_tag_t         iot;
-       bus_space_handle_t      d_ioh, p_ioh;
-       uint32_t                icp, icpsize, icd, icdsize;
+       uint32_t icp, icpsize, icd, icdsize;
 
-       ampintc = sc;
-
-       arm_init_smask();
-
-       iot = ia->ca_iot;
+       sc->sc_iot = ia->ca_iot;
        icp = ia->ca_periphbase + ICP_ADDR;
        icpsize = ICP_SIZE;
        icd = ia->ca_periphbase + ICD_ADDR;
@@ -241,15 +274,104 @@ ampintc_attach(struct device *parent, struct device 
*self, void *args)
        if (gic_dist_size)
                icdsize = gic_dist_size;
 
-       if (bus_space_map(iot, icp, icpsize, 0, &p_ioh))
+       if (bus_space_map(sc->sc_iot, icp, icpsize, 0, &sc->sc_p_ioh))
                panic("ampintc_attach: ICP bus_space_map failed!");
 
-       if (bus_space_map(iot, icd, icdsize, 0, &d_ioh))
+       if (bus_space_map(sc->sc_iot, icd, icdsize, 0, &sc->sc_d_ioh))
                panic("ampintc_attach: ICD bus_space_map failed!");
 
-       sc->sc_iot = iot;
-       sc->sc_d_ioh = d_ioh;
-       sc->sc_p_ioh = p_ioh;
+       ampintc_attach(parent, self, args);
+}
+
+void
+ampintc_attach_fdt(struct device *parent, struct device *self,
+    void *args)
+{
+       struct ampintc_softc *sc = (struct ampintc_softc *)self;
+       struct fdt_attach_args *fa = args;
+       uint32_t icp, icpsize, icd, icdsize;
+       int nac, nsc, inlen, pnode, off;
+       uint32_t buffer[8];
+
+       sc->sc_iot = fa->fa_iot;
+
+       if ((pnode = OF_parent(fa->fa_node)) == 0)
+               panic("ampintc_attach: cannot get device tree parent");
+
+       inlen = OF_getprop(pnode, "#address-cells", buffer,
+           sizeof(buffer));
+       if (inlen != sizeof(uint32_t))
+               panic("ampintc_attach: cannot get address cells");
+       nac = betoh32(buffer[0]);
+
+       inlen = OF_getprop(pnode, "#size-cells", buffer,
+           sizeof(buffer));
+       if (inlen != sizeof(uint32_t))
+               panic("ampintc_attach: cannot get size cells");
+       nsc = betoh32(buffer[0]);
+
+       inlen = OF_getprop(fa->fa_node, "reg", buffer,
+           sizeof(buffer));
+       if (inlen < 2 * (nac+nsc) * sizeof(uint32_t))
+               panic("ampintc_attach: cannot extract both rows");
+
+       /* XXX: try to cope with 64-byte bus addresses */
+       /* First row: ICD */
+       off = 0;
+       if (nac == 1)
+               icd = betoh32(buffer[off]);
+       else if (nac == 2)
+               icd = betoh32(buffer[off + 1]);
+       else
+               panic("ampintc_attach: invalid address cells");
+
+       if (nsc == 1)
+               icdsize = betoh32(buffer[off + nac]);
+       else if (nsc == 2)
+               icdsize = betoh32(buffer[off + nac + 1]);
+       else
+               panic("ampintc_attach: invalid size cells");
+
+       /* Second row: ICP */
+       off = nac + nsc;
+       if (nac == 1)
+               icp = betoh32(buffer[off]);
+       else if (nac == 2)
+               icp = betoh32(buffer[off + 1]);
+       else
+               panic("ampintc_attach: invalid address cells");
+
+       if (nsc == 1)
+               icpsize = betoh32(buffer[off + nac]);
+       else if (nsc == 2)
+               icpsize = betoh32(buffer[off + nac + 1]);
+       else
+               panic("ampintc_attach: invalid size cells");
+
+       if (bus_space_map(sc->sc_iot, icp, icpsize, 0, &sc->sc_p_ioh))
+               panic("ampintc_attach: ICP bus_space_map failed!");
+
+       if (bus_space_map(sc->sc_iot, icd, icdsize, 0, &sc->sc_d_ioh))
+               panic("ampintc_attach: ICD bus_space_map failed!");
+
+       ampintc_attach(parent, self, args);
+}
+
+void
+ampintc_attach(struct device *parent, struct device *self, void *args)
+{
+       struct ampintc_softc *sc = (struct ampintc_softc *)self;
+       int i, nintr;
+       bus_space_tag_t         iot;
+       bus_space_handle_t      d_ioh, p_ioh;
+
+       ampintc = sc;
+
+       iot = sc->sc_iot;
+       d_ioh = sc->sc_d_ioh;
+       p_ioh = sc->sc_p_ioh;
+
+       arm_init_smask();
 
        evcount_attach(&sc->sc_spur, "irq1023/spur", NULL);
 
diff --git sys/arch/arm/cortex/files.cortex sys/arch/arm/cortex/files.cortex
index 052acfd..12273ef 100644
--- sys/arch/arm/cortex/files.cortex
+++ sys/arch/arm/cortex/files.cortex
@@ -7,7 +7,8 @@ file    arch/arm/cortex/cortex.c                cortex
 
 device ampintc
 attach ampintc at cortex
-file   arch/arm/cortex/ampintc.c               ampintc
+attach ampintc at fdt with ampintc_fdt
+file   arch/arm/cortex/ampintc.c               ampintc | ampintc_fdt
 
 device amptimer
 attach amptimer at cortex
diff --git sys/arch/armv7/conf/GENERIC sys/arch/armv7/conf/GENERIC
index 019c0ef..ee972fb 100644
--- sys/arch/armv7/conf/GENERIC
+++ sys/arch/armv7/conf/GENERIC
@@ -34,6 +34,7 @@ cpu0          at mainbus?
 # Cortex-A9
 cortex0                at mainbus?
 ampintc*       at cortex?
+ampintc*       at fdt?
 amptimer*      at cortex?
 agtimer*       at cortex?
 armliicc*      at cortex?
diff --git sys/arch/armv7/conf/RAMDISK sys/arch/armv7/conf/RAMDISK
index 9c1b1b8..310c6c6 100644
--- sys/arch/armv7/conf/RAMDISK
+++ sys/arch/armv7/conf/RAMDISK
@@ -33,6 +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?

Reply via email to