svn commit: r366156 - in head/sys/dev: extres/syscon fdt

Michal Meloun mmel at FreeBSD.org
Fri Sep 25 13:52:32 UTC 2020


Author: mmel
Date: Fri Sep 25 13:52:31 2020
New Revision: 366156
URL: https://svnweb.freebsd.org/changeset/base/366156

Log:
  Correctly handle nodes compatible with "syscon", "simple-bus".
  Syscon can also have child nodes that share a registration file with it.
  To do this correctly, follow these steps:
  - subclass syscon from simplebus and expose it if the node is also
    "simple-bus" compatible.
  - block simplebus probe for this compatible string, so it's priority
   (bus pass) doesn't colide with syscon driver.
  
  While I'm in, also block "syscon", "simple-mfd" for the same reason.
  
  MFC after:	4 weeks

Modified:
  head/sys/dev/extres/syscon/syscon_generic.c
  head/sys/dev/extres/syscon/syscon_generic.h
  head/sys/dev/fdt/simplebus.c

Modified: head/sys/dev/extres/syscon/syscon_generic.c
==============================================================================
--- head/sys/dev/extres/syscon/syscon_generic.c	Fri Sep 25 13:28:57 2020	(r366155)
+++ head/sys/dev/extres/syscon/syscon_generic.c	Fri Sep 25 13:52:31 2020	(r366156)
@@ -60,7 +60,7 @@ static int syscon_generic_write_4(struct syscon *sysco
     uint32_t val);
 static int syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset,
     uint32_t clear_bits, uint32_t set_bits);
-
+static int syscon_generic_detach(device_t dev);
 /*
  * Generic syscon driver (FDT)
  */
@@ -152,7 +152,7 @@ static int
 syscon_generic_attach(device_t dev)
 {
 	struct syscon_generic_softc *sc;
-	int rid;
+	int rid, rv;
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
@@ -170,9 +170,20 @@ syscon_generic_attach(device_t dev)
 		ofw_bus_get_node(dev));
 	if (sc->syscon == NULL) {
 		device_printf(dev, "Failed to create/register syscon\n");
+		syscon_generic_detach(dev);
 		return (ENXIO);
 	}
-	return (0);
+	if (ofw_bus_is_compatible(dev, "simple-bus")) {
+		rv = simplebus_attach_impl(sc->dev);
+		if (rv != 0) {
+			device_printf(dev, "Failed to create simplebus\n");
+			syscon_generic_detach(dev);
+			return (ENXIO);
+		}
+		sc->simplebus_attached = true;
+	}
+
+	return (bus_generic_attach(dev));
 }
 
 static int
@@ -185,7 +196,8 @@ syscon_generic_detach(device_t dev)
 		syscon_unregister(sc->syscon);
 		free(sc->syscon, M_SYSCON);
 	}
-
+	if (sc->simplebus_attached)
+		simplebus_detach(dev);
 	SYSCON_LOCK_DESTROY(sc);
 
 	if (sc->mem_res != NULL)
@@ -202,8 +214,8 @@ static device_method_t syscon_generic_dmethods[] = {
 	DEVMETHOD_END
 };
 
-DEFINE_CLASS_0(syscon_generic, syscon_generic_driver, syscon_generic_dmethods,
-    sizeof(struct syscon_generic_softc));
+DEFINE_CLASS_1(syscon_generic_dev, syscon_generic_driver, syscon_generic_dmethods,
+    sizeof(struct syscon_generic_softc), simplebus_driver);
 static devclass_t syscon_generic_devclass;
 
 EARLY_DRIVER_MODULE(syscon_generic, simplebus, syscon_generic_driver,

Modified: head/sys/dev/extres/syscon/syscon_generic.h
==============================================================================
--- head/sys/dev/extres/syscon/syscon_generic.h	Fri Sep 25 13:28:57 2020	(r366155)
+++ head/sys/dev/extres/syscon/syscon_generic.h	Fri Sep 25 13:52:31 2020	(r366156)
@@ -29,11 +29,15 @@
 #ifndef DEV_SYSCON_GENERIC_H
 #define DEV_SYSCON_GENERIC_H
 
+#include <dev/fdt/simplebus.h>
+
 struct syscon_generic_softc {
+	struct simplebus_softc	simplebus;
 	device_t		dev;
 	struct syscon		*syscon;
 	struct resource		*mem_res;
 	struct mtx		mtx;
+	bool			simplebus_attached;
 };
 
 DECLARE_CLASS(syscon_generic_driver);

Modified: head/sys/dev/fdt/simplebus.c
==============================================================================
--- head/sys/dev/fdt/simplebus.c	Fri Sep 25 13:28:57 2020	(r366155)
+++ head/sys/dev/fdt/simplebus.c	Fri Sep 25 13:52:31 2020	(r366156)
@@ -116,6 +116,16 @@ simplebus_probe(device_t dev)
  
 	if (!ofw_bus_status_okay(dev))
 		return (ENXIO);
+	/*
+	 * XXX We should attach only to pure' compatible = "simple-bus"',
+	 * without any other compatible string.
+	 * For now, filter only know cases:
+	 * "syscon", "simple-bus"; is handled by fdt/syscon driver
+	 * "simple-mfd", "simple-bus"; is handled by fdt/simple-mfd driver
+	 */
+	if (ofw_bus_is_compatible(dev, "syscon") ||
+	    ofw_bus_is_compatible(dev, "simple-mfd"))
+		return (ENXIO);
 
 	/*
 	 * FDT data puts a "simple-bus" compatible string on many things that


More information about the svn-src-head mailing list