On Fri, Apr 08, 2016 at 02:00:54PM +0200, Patrick Wildt wrote:
> Hi,
> 
> this diff replaces the ARM mainbus with a new implementation.  This
> implementation works like the old version if there's no device tree.
> 
> But if there is a device tree, this tree will be used to enumerate
> and attach all device drivers.
> 
> Currently drivers kind of depend on each other.  This means one
> driver might expect the GPIO driver to already be attached.  Until
> there are proper ways to establish interrupts, establish and set GPIOs,
> set pinmuxes and attach clocks, we need to keep this attachment order.
> 
> To cope with that this code goes through the list of drivers on mainbus,
> and for every driver looks through the whole device tree and calls
> the driver's match function per node.  So that we don't attach nodes
> multiple times, we need to keep a list of nodes that we already
> attached.
> 
> For now we need to manually attach the cpu and cortex bus.  Soon I hope
> that the cortex bus will not be needed for FDT, so that the devices
> can attach directly to mainbus and don't need this extra step.
> 
> Thoughts? ok?
> 
> Patrick
> 
> diff --git sys/arch/arm/conf/files.arm sys/arch/arm/conf/files.arm
> index cb11960..3436e8e 100644
> --- sys/arch/arm/conf/files.arm
> +++ sys/arch/arm/conf/files.arm
> @@ -21,6 +21,9 @@ device      mainbus {}
>  attach       mainbus at root
>  file arch/arm/mainbus/mainbus.c              mainbus
>  
> +# FDT support
> +file dev/ofw/fdt.c
> +
>  include "arch/arm/cortex/files.cortex"
>  
>  device       cpu {}
> diff --git sys/arch/arm/cortex/cortex.c sys/arch/arm/cortex/cortex.c
> index 73aa315..db878b7 100644
> --- sys/arch/arm/cortex/cortex.c
> +++ sys/arch/arm/cortex/cortex.c
> @@ -51,6 +51,7 @@
>  #include <arm/cpufunc.h>
>  #include <arm/armv7/armv7var.h>
>  #include <arm/cortex/cortex.h>
> +#include <arm/mainbus/mainbus.h>
>  
>  struct arm32_bus_dma_tag cortex_bus_dma_tag = {
>       0,
> @@ -94,10 +95,15 @@ struct cfdriver cortex_cd = {
>   */
>  
>  int
> -cortexmatch(struct device *parent, void *cf, void *aux)
> +cortexmatch(struct device *parent, void *cfdata, void *aux)
>  {
> +     struct mainbus_attach_args *ma = aux;
> +     struct cfdata *cf = (struct cfdata *)cfdata;
>       int cputype = cpufunc_id();
>  
> +     if (strcmp(cf->cf_driver->cd_name, ma->ma_name) != 0)
> +             return (0);
> +
>       if ((cputype & CPU_ID_CORTEX_A7_MASK) == CPU_ID_CORTEX_A7 ||
>           (cputype & CPU_ID_CORTEX_A9_MASK) == CPU_ID_CORTEX_A9 ||
>           (cputype & CPU_ID_CORTEX_A15_MASK) == CPU_ID_CORTEX_A15 ||
> diff --git sys/arch/arm/mainbus/mainbus.c sys/arch/arm/mainbus/mainbus.c
> index 6ad3e8f..02062a6 100644
> --- sys/arch/arm/mainbus/mainbus.c
> +++ sys/arch/arm/mainbus/mainbus.c
> @@ -1,124 +1,255 @@
> -/*   $OpenBSD: mainbus.c,v 1.7 2013/05/30 16:15:01 deraadt Exp $     */
> -/* $NetBSD: mainbus.c,v 1.3 2001/06/13 17:52:43 nathanw Exp $ */
> -
> +/* $OpenBSD$ */
>  /*
> - * Copyright (c) 1994,1995 Mark Brinicombe.
> - * Copyright (c) 1994 Brini.
> - * All rights reserved.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - * 1. Redistributions of source code must retain the above copyright
> - *    notice, this list of conditions and the following disclaimer.
> - * 2. Redistributions in binary form must reproduce the above copyright
> - *    notice, this list of conditions and the following disclaimer in the
> - *    documentation and/or other materials provided with the distribution.
> - * 3. All advertising materials mentioning features or use of this software
> - *    must display the following acknowledgement:
> - *   This product includes software developed by Brini.
> - * 4. The name of the company nor the name of the author may be used to
> - *    endorse or promote products derived from this software without specific
> - *    prior written permission.
> - *
> - * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
> - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> - * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
> - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> - * SUCH DAMAGE.
> - *
> - * RiscBSD kernel project
> + * Copyright (c) 2014-2016 Patrick Wildt <patr...@blueri.se>
>   *
> - * mainbus.c
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
>   *
> - * mainbus configuration
> - *
> - * Created      : 15/12/94
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>   */
>  
>  #include <sys/param.h>
>  #include <sys/systm.h>
> -#include <sys/kernel.h>
> -#include <sys/device.h>
> +#include <sys/malloc.h>
> +#include <sys/queue.h>
> +
> +#include <dev/ofw/fdt.h>
>  
>  #include <arm/mainbus/mainbus.h>
>  
> -/* Prototypes for functions provided */
> +int mainbus_match(struct device *, void *, void *);
> +void mainbus_attach(struct device *, struct device *, void *);
> +
> +struct device *mainbus_is_attached(void *);
> +void mainbus_dev_list_insert(void *, struct device *);
> +
> +void mainbus_find_match(struct device *, void *);
> +void mainbus_iterate(struct device *, struct device *, void *);
> +void mainbus_attach_node(struct device *, void *, void *);
> +
> +int mainbus_legacy_search(struct device *, void *, void *);
> +void mainbus_legacy_found(struct device *, char *);
> +
> +struct mainbus_softc {
> +     struct device            sc_dev;
> +     bus_space_tag_t          sc_iot;
> +     bus_dma_tag_t            sc_dmat;
> +};
> +
> +/*
> + * We need to look through the tree at least twice.  To make sure we
> + * do not attach node multiple times, keep a list of nodes that are
> + * already handled by any kind of driver.
> + */
> +SLIST_HEAD(, mainbus_entry) mainbus_dev_list = 
> SLIST_HEAD_INITIALIZER(mainbus_dev_list);
> +struct mainbus_entry {
> +     SLIST_ENTRY(mainbus_entry)       me_list;
> +     void                            *me_node;
> +     struct device                   *me_dev;
> +};
> +
> +struct device *
> +mainbus_is_attached(void *node)
> +{
> +     struct mainbus_entry *me;
> +
> +     SLIST_FOREACH(me, &mainbus_dev_list, me_list)
> +             if (me->me_node == node)
> +                     return me->me_dev;
> +
> +     return NULL;
> +}
> +
> +void
> +mainbus_dev_list_insert(void *node, struct device *child)
> +{
> +     struct mainbus_entry *me;
> +
> +     if (child == NULL)
> +             return;
>  
> -int  mainbusmatch(struct device *, void *, void *);
> -void mainbusattach(struct device *, struct device *, void *);
> -int  mainbusprint(void *aux, const char *mainbus);
> -int mainbussearch(struct device *,  void *, void *);
> +     me = malloc(sizeof(*me), M_DEVBUF, M_NOWAIT|M_ZERO);
> +     if (me == NULL)
> +             panic("%s: cannot allocate memory", __func__);
>  
> -/* attach and device structures for the device */
> +     me->me_node = node;
> +     me->me_dev = child;
> +     SLIST_INSERT_HEAD(&mainbus_dev_list, me, me_list);
> +}
>  
>  struct cfattach mainbus_ca = {
> -     sizeof(struct device), mainbusmatch, mainbusattach
> +     sizeof(struct mainbus_softc), mainbus_match, mainbus_attach, NULL,
> +     config_activate_children
>  };
>  
>  struct cfdriver mainbus_cd = {
>       NULL, "mainbus", DV_DULL
>  };
>  
> +struct arm32_bus_dma_tag mainbus_dma_tag = {
> +     0,
> +     0,
> +     NULL,
> +     _bus_dmamap_create,
> +     _bus_dmamap_destroy,
> +     _bus_dmamap_load,
> +     _bus_dmamap_load_mbuf,
> +     _bus_dmamap_load_uio,
> +     _bus_dmamap_load_raw,
> +     _bus_dmamap_unload,
> +     _bus_dmamap_sync,
> +     _bus_dmamem_alloc,
> +     _bus_dmamem_free,
> +     _bus_dmamem_map,
> +     _bus_dmamem_unmap,
> +     _bus_dmamem_mmap,
> +};
> +
>  /*
> - * int mainbusmatch(struct device *parent, struct cfdata *cf, void *aux)
> + * Mainbus takes care of FDT and non-FDT machines, so we
> + * always attach.
>   */
> -
>  int
> -mainbusmatch(struct device *parent, void *cf, void *aux)
> +mainbus_match(struct device *parent, void *cfdata, void *aux)
>  {
>       return (1);
>  }
>  
> +void
> +mainbus_attach(struct device *parent, struct device *self, void *aux)
> +{
> +     struct mainbus_softc *sc = (struct mainbus_softc *)self;
> +     char *compatible;
> +     void *node;
> +
> +     if ((node = fdt_next_node(0)) == NULL) {
> +             printf(": running without device tree\n");
> +             config_search(mainbus_legacy_search, self, aux);
> +             return;
> +     }
> +
> +#ifdef CPU_ARMv7
> +     extern struct bus_space armv7_bs_tag;
> +     sc->sc_iot = &armv7_bs_tag;
> +#endif
> +     sc->sc_dmat = &mainbus_dma_tag;
> +
> +     if (fdt_node_property(node, "compatible", &compatible))
> +             printf(": %s compatible\n", compatible);
> +     else
> +             printf(": unknown\n");
> +
> +     /* Attach CPU first. */
> +     mainbus_legacy_found(self, "cpu");
> +
> +     /* TODO: Cortex clients should connect to FDT. */
> +     mainbus_legacy_found(self, "cortex");
> +
> +     /* TODO: Scan for interrupt controllers and attach them first? */
> +
> +     /* Scan the whole tree. */
> +     config_scan(mainbus_find_match, self);
> +}
> +
>  /*
> - * void mainbusattach(struct device *parent, struct device *self, void *aux)
> + * Usually you should be able to attach devices in the order
> + * specified in the device tree.  Due to how a few drivers
> + * are written we need to make sure we attach them in the
> + * order stated in files.xxx.
>   *
> - * probe and attach all children
> + * This means for every driver enabled, we go through the
> + * FDT and look for compatible nodes.
>   */
> +void
> +mainbus_find_match(struct device *self, void *match)
> +{
> +     mainbus_iterate(self, match, fdt_next_node(0));
> +}
> +
> +void
> +mainbus_iterate(struct device *self, struct device *match, void *node)
> +{
> +     for (;
> +         node != NULL;
> +         node = fdt_next_node(node))
> +     {
> +             /* skip nodes that are already handled by some driver */
> +             if (!mainbus_is_attached(node))
> +                     mainbus_attach_node(self, match, node);
> +
> +             mainbus_iterate(self, match, fdt_child_node(node));
> +     }
> +}
>  
> +/*
> + * Try to attach a node to a known driver.
> + */
>  void
> -mainbusattach(struct device *parent, struct device *self, void *aux)
> +mainbus_attach_node(struct device *self, void *match, void *node)
>  {
> -     printf("\n");
> +     struct mainbus_softc    *sc = (struct mainbus_softc *)self;
> +     struct mainbus_attach_args ma;
> +     struct cfdata           *cf = match;
> +     struct device           *child;
> +     char                    *status;
> +
> +     if (!fdt_node_property(node, "compatible", NULL))
> +             return;
> +
> +     if (fdt_node_property(node, "status", &status))
> +             if (!strcmp(status, "disabled"))
> +                     return;
> +
> +     memset(&ma, 0, sizeof(ma));
> +     ma.ma_name = "";
> +     ma.ma_node = node;
> +     ma.ma_iot = sc->sc_iot;
> +     ma.ma_dmat = sc->sc_dmat;
>  
> -     config_search(mainbussearch, self, aux);
> +     /* allow for devices to be disabled in UKC */
> +     if ((*cf->cf_attach->ca_match)(self, cf, &ma) == 0)
> +             return;
> +
> +     /* TODO: attach the device's clocks first? */
> +
> +     child = config_attach(self, cf, &ma, NULL);
> +     mainbus_dev_list_insert(node, child);
>  }
>  
> +/*
> + * Legacy support for SoCs that do not use FDT.
> + */
>  int
> -mainbussearch(struct device *parent, void *vcf, void *aux)
> +mainbus_legacy_search(struct device *parent, void *match, void *aux)
>  {
>       struct mainbus_attach_args ma;
> -     struct cfdata *cf = vcf;
> +     struct cfdata           *cf = match;
>  
> +     memset(&ma, 0, sizeof(ma));
>       ma.ma_name = cf->cf_driver->cd_name;
>  
>       /* allow for devices to be disabled in UKC */
>       if ((*cf->cf_attach->ca_match)(parent, cf, &ma) == 0)
>               return 0;
>  
> -     config_attach(parent, cf, &ma, mainbusprint);
> +     config_attach(parent, cf, &ma, NULL);
>       return 1;
>  }
>  
> -/*
> - * int mainbusprint(void *aux, const char *mainbus)
> - *
> - * print routine used during config of children
> - */
> -
> -int
> -mainbusprint(void *aux, const char *mainbus)
> +void
> +mainbus_legacy_found(struct device *self, char *name)
>  {
> -     struct mainbus_attach_args *ma = aux;
> +     struct mainbus_attach_args ma;
>  
> -     if (mainbus != NULL)
> -             printf("%s at %s", ma->ma_name, mainbus);
> +     memset(&ma, 0, sizeof(ma));
> +     ma.ma_name = name;
>  
> -     return (UNCONF);
> +     config_found(self, &ma, NULL);
>  }
> diff --git sys/arch/arm/mainbus/mainbus.h sys/arch/arm/mainbus/mainbus.h
> index 3e17996..188bc5a 100644
> --- sys/arch/arm/mainbus/mainbus.h
> +++ sys/arch/arm/mainbus/mainbus.h
> @@ -1,51 +1,32 @@
> -/*   $OpenBSD: mainbus.h,v 1.2 2011/09/22 17:45:59 miod Exp $        */
> -/* $NetBSD: mainbus.h,v 1.1 2001/02/24 19:38:02 reinoud Exp $ */
> -
> +/* $OpenBSD$ */
>  /*
> - * Copyright (c) 1994,1995 Mark Brinicombe.
> - * Copyright (c) 1994 Brini.
> - * All rights reserved.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - * 1. Redistributions of source code must retain the above copyright
> - *    notice, this list of conditions and the following disclaimer.
> - * 2. Redistributions in binary form must reproduce the above copyright
> - *    notice, this list of conditions and the following disclaimer in the
> - *    documentation and/or other materials provided with the distribution.
> - * 3. All advertising materials mentioning features or use of this software
> - *    must display the following acknowledgement:
> - *   This product includes software developed by Brini.
> - * 4. The name of the company nor the name of the author may be used to
> - *    endorse or promote products derived from this software without specific
> - *    prior written permission.
> - *
> - * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
> - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> - * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
> - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> - * SUCH DAMAGE.
> - *
> - * RiscBSD kernel project
> - *
> - * mainbus.h
> + * Copyright (c) 2016 Patrick Wildt <patr...@blueri.se>
>   *
> - * mainbus configuration
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
>   *
> - * Created      : 15/12/94
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>   */
>  
> -/*
> - * mainbus driver attach arguments
> - */
> +#ifndef __MAINBUS_H__
> +#define __MAINBUS_H__
>  
> +#define _ARM32_BUS_DMA_PRIVATE
> +#include <machine/bus.h>
> +
> +/* Passed as third arg to attach functions. */
>  struct mainbus_attach_args {
> -     const char      *ma_name;
> +     const char              *ma_name;
> +     void                    *ma_node;
> +     bus_space_tag_t          ma_iot;
> +     bus_dma_tag_t            ma_dmat;
>  };
> +
> +#endif /* __MAINBUS_H__ */
> diff --git sys/arch/armv7/conf/files.armv7 sys/arch/armv7/conf/files.armv7
> index c5d022c..ae40f36 100644
> --- sys/arch/armv7/conf/files.armv7
> +++ sys/arch/armv7/conf/files.armv7
> @@ -10,7 +10,6 @@ major       {rd = 18}
>  
>  define       fdt {}
>  file arch/armv7/fdt/fdt_machdep.c    fdt     needs-flag
> -file dev/ofw/fdt.c
>  
>  file arch/arm/arm/conf.c
>  
> diff --git sys/dev/ofw/fdt.c sys/dev/ofw/fdt.c
> index cdb588b..4cf7248 100644
> --- sys/dev/ofw/fdt.c
> +++ sys/dev/ofw/fdt.c
> @@ -160,6 +160,7 @@ skip_node_name(u_int32_t *ptr)
>  /*
>   * Retrieves node property, the returned pointer is inside the fdt tree,
>   * so we should not modify content pointed by it directly.
> + * A NULL out parameter will cause this function to only return the size.
>   */
>  int
>  fdt_node_property(void *node, char *name, char **out)
> @@ -182,7 +183,8 @@ fdt_node_property(void *node, char *name, char **out)
>               nameid = betoh32(*(ptr + 2)); /* id of name in strings table */
>               tmp = fdt_get_str(nameid);
>               if (!strcmp(name, tmp)) {
> -                     *out = (char *)(ptr + 3); /* beginning of the value */
> +                     if (out != NULL)
> +                             *out = (char *)(ptr + 3); /* beginning of the 
> value */
>                       return betoh32(*(ptr + 1)); /* size of value */
>               }
>               ptr = skip_property(ptr);
> 

After some feedback and discussion with mpi@ I have modified this code
to use the OF_* API instead.

diff --git sys/arch/arm/conf/files.arm sys/arch/arm/conf/files.arm
index cb11960..3436e8e 100644
--- sys/arch/arm/conf/files.arm
+++ sys/arch/arm/conf/files.arm
@@ -21,6 +21,9 @@ device        mainbus {}
 attach mainbus at root
 file   arch/arm/mainbus/mainbus.c              mainbus
 
+# FDT support
+file   dev/ofw/fdt.c
+
 include "arch/arm/cortex/files.cortex"
 
 device cpu {}
diff --git sys/arch/arm/mainbus/mainbus.c sys/arch/arm/mainbus/mainbus.c
index 6ad3e8f..614ab15 100644
--- sys/arch/arm/mainbus/mainbus.c
+++ sys/arch/arm/mainbus/mainbus.c
@@ -1,124 +1,255 @@
-/*     $OpenBSD: mainbus.c,v 1.7 2013/05/30 16:15:01 deraadt Exp $     */
-/* $NetBSD: mainbus.c,v 1.3 2001/06/13 17:52:43 nathanw Exp $ */
-
+/* $OpenBSD$ */
 /*
- * Copyright (c) 1994,1995 Mark Brinicombe.
- * Copyright (c) 1994 Brini.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by Brini.
- * 4. The name of the company nor the name of the author may be used to
- *    endorse or promote products derived from this software without specific
- *    prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * RiscBSD kernel project
+ * Copyright (c) 2014-2016 Patrick Wildt <patr...@blueri.se>
  *
- * mainbus.c
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
  *
- * mainbus configuration
- *
- * Created      : 15/12/94
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+
+#include <dev/ofw/openfirm.h>
 
 #include <arm/mainbus/mainbus.h>
 
-/* Prototypes for functions provided */
+int mainbus_match(struct device *, void *, void *);
+void mainbus_attach(struct device *, struct device *, void *);
+
+struct device *mainbus_is_attached(int);
+void mainbus_dev_list_insert(int, struct device *);
+
+void mainbus_find_match(struct device *, void *);
+void mainbus_iterate(struct device *, struct device *, int);
+void mainbus_attach_node(struct device *, void *, int);
+
+int mainbus_legacy_search(struct device *, void *, void *);
+void mainbus_legacy_found(struct device *, char *);
+
+struct mainbus_softc {
+       struct device            sc_dev;
+       bus_space_tag_t          sc_iot;
+       bus_dma_tag_t            sc_dmat;
+};
+
+/*
+ * We need to look through the tree at least twice.  To make sure we
+ * do not attach node multiple times, keep a list of nodes that are
+ * already handled by any kind of driver.
+ */
+SLIST_HEAD(, mainbus_entry) mainbus_dev_list = 
SLIST_HEAD_INITIALIZER(mainbus_dev_list);
+struct mainbus_entry {
+       SLIST_ENTRY(mainbus_entry)       me_list;
+       int                              me_node;
+       struct device                   *me_dev;
+};
+
+struct device *
+mainbus_is_attached(int node)
+{
+       struct mainbus_entry *me;
+
+       SLIST_FOREACH(me, &mainbus_dev_list, me_list)
+               if (me->me_node == node)
+                       return me->me_dev;
+
+       return NULL;
+}
+
+void
+mainbus_dev_list_insert(int node, struct device *child)
+{
+       struct mainbus_entry *me;
+
+       if (child == NULL)
+               return;
 
-int  mainbusmatch(struct device *, void *, void *);
-void mainbusattach(struct device *, struct device *, void *);
-int  mainbusprint(void *aux, const char *mainbus);
-int mainbussearch(struct device *,  void *, void *);
+       me = malloc(sizeof(*me), M_DEVBUF, M_NOWAIT|M_ZERO);
+       if (me == NULL)
+               panic("%s: cannot allocate memory", __func__);
 
-/* attach and device structures for the device */
+       me->me_node = node;
+       me->me_dev = child;
+       SLIST_INSERT_HEAD(&mainbus_dev_list, me, me_list);
+}
 
 struct cfattach mainbus_ca = {
-       sizeof(struct device), mainbusmatch, mainbusattach
+       sizeof(struct mainbus_softc), mainbus_match, mainbus_attach, NULL,
+       config_activate_children
 };
 
 struct cfdriver mainbus_cd = {
        NULL, "mainbus", DV_DULL
 };
 
+struct arm32_bus_dma_tag mainbus_dma_tag = {
+       0,
+       0,
+       NULL,
+       _bus_dmamap_create,
+       _bus_dmamap_destroy,
+       _bus_dmamap_load,
+       _bus_dmamap_load_mbuf,
+       _bus_dmamap_load_uio,
+       _bus_dmamap_load_raw,
+       _bus_dmamap_unload,
+       _bus_dmamap_sync,
+       _bus_dmamem_alloc,
+       _bus_dmamem_free,
+       _bus_dmamem_map,
+       _bus_dmamem_unmap,
+       _bus_dmamem_mmap,
+};
+
 /*
- * int mainbusmatch(struct device *parent, struct cfdata *cf, void *aux)
+ * Mainbus takes care of FDT and non-FDT machines, so we
+ * always attach.
  */
-
 int
-mainbusmatch(struct device *parent, void *cf, void *aux)
+mainbus_match(struct device *parent, void *cfdata, void *aux)
 {
        return (1);
 }
 
+void
+mainbus_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct mainbus_softc *sc = (struct mainbus_softc *)self;
+       char buffer[128];
+       int node;
+
+       if ((node = OF_peer(0)) == 0) {
+               printf(": running without device tree\n");
+               config_search(mainbus_legacy_search, self, aux);
+               return;
+       }
+
+#ifdef CPU_ARMv7
+       extern struct bus_space armv7_bs_tag;
+       sc->sc_iot = &armv7_bs_tag;
+#endif
+       sc->sc_dmat = &mainbus_dma_tag;
+
+       if (OF_getprop(node, "compatible", buffer, sizeof(buffer)))
+               printf(": %s compatible\n", buffer);
+       else
+               printf(": unknown\n");
+
+       /* Attach CPU first. */
+       mainbus_legacy_found(self, "cpu");
+
+       /* TODO: Cortex clients should connect to FDT. */
+       mainbus_legacy_found(self, "cortex");
+
+       /* TODO: Scan for interrupt controllers and attach them first? */
+
+       /* Scan the whole tree. */
+       config_scan(mainbus_find_match, self);
+}
+
 /*
- * void mainbusattach(struct device *parent, struct device *self, void *aux)
+ * Usually you should be able to attach devices in the order
+ * specified in the device tree.  Due to how a few drivers
+ * are written we need to make sure we attach them in the
+ * order stated in files.xxx.
  *
- * probe and attach all children
+ * This means for every driver enabled, we go through the
+ * FDT and look for compatible nodes.
  */
+void
+mainbus_find_match(struct device *self, void *match)
+{
+       mainbus_iterate(self, match, OF_peer(0));
+}
+
+void
+mainbus_iterate(struct device *self, struct device *match, int node)
+{
+       for (;
+           node != 0;
+           node = OF_peer(node))
+       {
+               /* skip nodes that are already handled by some driver */
+               if (!mainbus_is_attached(node))
+                       mainbus_attach_node(self, match, node);
+
+               mainbus_iterate(self, match, OF_child(node));
+       }
+}
 
+/*
+ * Try to attach a node to a known driver.
+ */
 void
-mainbusattach(struct device *parent, struct device *self, void *aux)
+mainbus_attach_node(struct device *self, void *match, int node)
 {
-       printf("\n");
+       struct mainbus_softc    *sc = (struct mainbus_softc *)self;
+       struct mainbus_attach_args ma;
+       struct cfdata           *cf = match;
+       struct device           *child;
+       char                     buffer[128];
+
+       if (!OF_getprop(node, "compatible", NULL, 0))
+               return;
+
+       if (OF_getprop(node, "status", buffer, sizeof(buffer)))
+               if (!strcmp(buffer, "disabled"))
+                       return;
+
+       memset(&ma, 0, sizeof(ma));
+       ma.ma_name = "";
+       ma.ma_node = node;
+       ma.ma_iot = sc->sc_iot;
+       ma.ma_dmat = sc->sc_dmat;
 
-       config_search(mainbussearch, self, aux);
+       /* allow for devices to be disabled in UKC */
+       if ((*cf->cf_attach->ca_match)(self, cf, &ma) == 0)
+               return;
+
+       /* TODO: attach the device's clocks first? */
+
+       child = config_attach(self, cf, &ma, NULL);
+       mainbus_dev_list_insert(node, child);
 }
 
+/*
+ * Legacy support for SoCs that do not use FDT.
+ */
 int
-mainbussearch(struct device *parent, void *vcf, void *aux)
+mainbus_legacy_search(struct device *parent, void *match, void *aux)
 {
        struct mainbus_attach_args ma;
-       struct cfdata *cf = vcf;
+       struct cfdata           *cf = match;
 
+       memset(&ma, 0, sizeof(ma));
        ma.ma_name = cf->cf_driver->cd_name;
 
        /* allow for devices to be disabled in UKC */
        if ((*cf->cf_attach->ca_match)(parent, cf, &ma) == 0)
                return 0;
 
-       config_attach(parent, cf, &ma, mainbusprint);
+       config_attach(parent, cf, &ma, NULL);
        return 1;
 }
 
-/*
- * int mainbusprint(void *aux, const char *mainbus)
- *
- * print routine used during config of children
- */
-
-int
-mainbusprint(void *aux, const char *mainbus)
+void
+mainbus_legacy_found(struct device *self, char *name)
 {
-       struct mainbus_attach_args *ma = aux;
+       struct mainbus_attach_args ma;
 
-       if (mainbus != NULL)
-               printf("%s at %s", ma->ma_name, mainbus);
+       memset(&ma, 0, sizeof(ma));
+       ma.ma_name = name;
 
-       return (UNCONF);
+       config_found(self, &ma, NULL);
 }
diff --git sys/arch/arm/mainbus/mainbus.h sys/arch/arm/mainbus/mainbus.h
index 3e17996..b2dfbcc 100644
--- sys/arch/arm/mainbus/mainbus.h
+++ sys/arch/arm/mainbus/mainbus.h
@@ -1,51 +1,32 @@
-/*     $OpenBSD: mainbus.h,v 1.2 2011/09/22 17:45:59 miod Exp $        */
-/* $NetBSD: mainbus.h,v 1.1 2001/02/24 19:38:02 reinoud Exp $ */
-
+/* $OpenBSD$ */
 /*
- * Copyright (c) 1994,1995 Mark Brinicombe.
- * Copyright (c) 1994 Brini.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by Brini.
- * 4. The name of the company nor the name of the author may be used to
- *    endorse or promote products derived from this software without specific
- *    prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * RiscBSD kernel project
- *
- * mainbus.h
+ * Copyright (c) 2016 Patrick Wildt <patr...@blueri.se>
  *
- * mainbus configuration
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
  *
- * Created      : 15/12/94
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * mainbus driver attach arguments
- */
+#ifndef __MAINBUS_H__
+#define __MAINBUS_H__
 
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+/* Passed as third arg to attach functions. */
 struct mainbus_attach_args {
-       const char      *ma_name;
+       const char              *ma_name;
+       int                      ma_node;
+       bus_space_tag_t          ma_iot;
+       bus_dma_tag_t            ma_dmat;
 };
+
+#endif /* __MAINBUS_H__ */
diff --git sys/arch/armv7/conf/files.armv7 sys/arch/armv7/conf/files.armv7
index c5d022c..ae40f36 100644
--- sys/arch/armv7/conf/files.armv7
+++ sys/arch/armv7/conf/files.armv7
@@ -10,7 +10,6 @@ major {rd = 18}
 
 define fdt {}
 file   arch/armv7/fdt/fdt_machdep.c    fdt     needs-flag
-file   dev/ofw/fdt.c
 
 file   arch/arm/arm/conf.c
 

Reply via email to