svn commit: r327215 - head/sys/dev/extres/syscon

Kyle Evans kevans at FreeBSD.org
Tue Dec 26 16:38:05 UTC 2017


Author: kevans
Date: Tue Dec 26 16:38:04 2017
New Revision: 327215
URL: https://svnweb.freebsd.org/changeset/base/327215

Log:
  extres/syscon: Commit missing bits from r327106
  
  r327106 introduced kobj to syscon so it can be subclassed and fit in with
  the rest of the syscon framework. The diff for syscon.c was misapplied in a
  clean tree prior to commit, so bring it back to what was included in the
  review and tested. The entire file has basically been rewritten from what
  was present prior to the kobj work.
  
  Pointy hat to:	me

Modified:
  head/sys/dev/extres/syscon/syscon.c

Modified: head/sys/dev/extres/syscon/syscon.c
==============================================================================
--- head/sys/dev/extres/syscon/syscon.c	Tue Dec 26 16:33:55 2017	(r327214)
+++ head/sys/dev/extres/syscon/syscon.c	Tue Dec 26 16:38:04 2017	(r327215)
@@ -33,153 +33,223 @@
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
+#include "opt_platform.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/kernel.h>
+#include <sys/kobj.h>
+#include <sys/lock.h>
 #include <sys/module.h>
 #include <sys/rman.h>
+#include <sys/sx.h>
+#include <sys/queue.h>
 
 #include <machine/bus.h>
 
+#ifdef FDT
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
+#endif
 
 #include "syscon_if.h"
+#include "syscon.h"
 
-#define SYSCON_LOCK(_sc)		mtx_lock(&(_sc)->mtx)
-#define	SYSCON_UNLOCK(_sc)		mtx_unlock(&(_sc)->mtx)
-#define SYSCON_LOCK_INIT(_sc)		mtx_init(&(_sc)->mtx,		\
-	    device_get_nameunit((_sc)->dev), "syscon", MTX_DEF)
-#define SYSCON_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->mtx);
-#define SYSCON_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_OWNED);
-#define SYSCON_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_NOTOWNED);
+/*
+ * Syscon interface details
+ */
+typedef TAILQ_HEAD(syscon_list, syscon) syscon_list_t;
 
-struct syscon_softc {
-	device_t		dev;
-	struct resource		*mem_res;
-	struct mtx		mtx;
+/*
+ * Declarations
+ */
+static int syscon_method_init(struct syscon *syscon);
+static int syscon_method_uninit(struct syscon *syscon);
+
+MALLOC_DEFINE(M_SYSCON, "syscon", "Syscon driver");
+
+static syscon_list_t syscon_list = TAILQ_HEAD_INITIALIZER(syscon_list);
+static struct sx		syscon_topo_lock;
+SX_SYSINIT(syscon_topology, &syscon_topo_lock, "Syscon topology lock");
+
+/*
+ * Syscon methods.
+ */
+static syscon_method_t syscon_methods[] = {
+	SYSCONMETHOD(syscon_init,	syscon_method_init),
+	SYSCONMETHOD(syscon_uninit,	syscon_method_uninit),
+
+	SYSCONMETHOD_END
 };
+DEFINE_CLASS_0(syscon, syscon_class, syscon_methods, 0);
 
-static struct ofw_compat_data compat_data[] = {
-	{"syscon",	1},
-	{NULL,		0}
+#define SYSCON_TOPO_SLOCK()	sx_slock(&syscon_topo_lock)
+#define SYSCON_TOPO_XLOCK()	sx_xlock(&syscon_topo_lock)
+#define SYSCON_TOPO_UNLOCK()	sx_unlock(&syscon_topo_lock)
+#define SYSCON_TOPO_ASSERT()	sx_assert(&syscon_topo_lock, SA_LOCKED)
+#define SYSCON_TOPO_XASSERT()	sx_assert(&syscon_topo_lock, SA_XLOCKED)
+
+/*
+ * Default syscon methods for base class.
+ */
+static int
+syscon_method_init(struct syscon *syscon)
+{
+
+	return (0);
 };
 
-static uint32_t
-syscon_read_4(device_t dev, device_t consumer, bus_size_t offset)
+static int
+syscon_method_uninit(struct syscon *syscon)
 {
-	struct syscon_softc *sc;
-	uint32_t val;
 
-	sc = device_get_softc(dev);
+	return (0);
+};
 
-	SYSCON_LOCK(sc);
-	val = bus_read_4(sc->mem_res, offset);
-	SYSCON_UNLOCK(sc);
-	return (val);
-}
+void *
+syscon_get_softc(struct syscon *syscon)
+{
 
-static void
-syscon_write_4(device_t dev, device_t consumer, bus_size_t offset, uint32_t val)
+	return (syscon->softc);
+};
+
+/*
+ * Create and initialize syscon object, but do not register it.
+ */
+struct syscon *
+syscon_create(device_t pdev, syscon_class_t syscon_class)
 {
-	struct syscon_softc *sc;
+	struct syscon *syscon;
 
-	sc = device_get_softc(dev);
+	/* Create object and initialize it. */
+	syscon = malloc(sizeof(struct syscon), M_SYSCON,
+	    M_WAITOK | M_ZERO);
+	kobj_init((kobj_t)syscon, (kobj_class_t)syscon_class);
 
-	SYSCON_LOCK(sc);
-	bus_write_4(sc->mem_res, offset, val);
-	SYSCON_UNLOCK(sc);
+	/* Allocate softc if required. */
+	if (syscon_class->size > 0)
+		syscon->softc = malloc(syscon_class->size, M_SYSCON,
+		    M_WAITOK | M_ZERO);
+
+	/* Rest of init. */
+	syscon->pdev = pdev;
+	return (syscon);
 }
 
-static void
-syscon_modify_4(device_t dev,  device_t consumer, bus_size_t offset,
-    uint32_t clear_bits, uint32_t set_bits)
+/* Register syscon object. */
+struct syscon *
+syscon_register(struct syscon *syscon)
 {
-	struct syscon_softc *sc;
-	uint32_t val;
+	int rv;
 
-	sc = device_get_softc(dev);
+#ifdef FDT
+	if (syscon->ofw_node <= 0)
+		syscon->ofw_node = ofw_bus_get_node(syscon->pdev);
+	if (syscon->ofw_node <= 0)
+		return (NULL);
+#endif
 
-	SYSCON_LOCK(sc);
-	val = bus_read_4(sc->mem_res, offset);
-	val &= ~clear_bits;
-	val |= set_bits;
-	bus_write_4(sc->mem_res, offset, val);
-	SYSCON_UNLOCK(sc);
+	rv = SYSCON_INIT(syscon);
+	if (rv != 0) {
+		printf("SYSCON_INIT failed: %d\n", rv);
+		return (NULL);
+	}
+
+#ifdef FDT
+	OF_device_register_xref(OF_xref_from_node(syscon->ofw_node),
+	    syscon->pdev);
+#endif
+	SYSCON_TOPO_XLOCK();
+	TAILQ_INSERT_TAIL(&syscon_list, syscon, syscon_link);
+	SYSCON_TOPO_UNLOCK();
+	return (syscon);
 }
 
-static int
-syscon_probe(device_t dev)
+int
+syscon_unregister(struct syscon *syscon)
 {
 
-	if (!ofw_bus_status_okay(dev))
-		return (ENXIO);
-	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
-		return (ENXIO);
-
-	device_set_desc(dev, "syscon");
-	return (BUS_PROBE_GENERIC);
+	SYSCON_TOPO_XLOCK();
+	TAILQ_REMOVE(&syscon_list, syscon, syscon_link);
+	SYSCON_TOPO_UNLOCK();
+#ifdef FDT
+	OF_device_register_xref(OF_xref_from_node(syscon->ofw_node), NULL);
+#endif
+	return (SYSCON_UNINIT(syscon));
 }
 
-static int
-syscon_attach(device_t dev)
+/**
+ * Provider methods
+ */
+#ifdef FDT
+static struct syscon *
+syscon_find_by_ofw_node(phandle_t node)
 {
-	struct syscon_softc *sc;
-	int rid;
-	phandle_t node;
+	struct syscon *entry;
 
-	sc = device_get_softc(dev);
-	sc->dev = dev;
-	node = ofw_bus_get_node(sc->dev);
+	SYSCON_TOPO_ASSERT();
 
-	SYSCON_LOCK_INIT(sc);
-
-	rid = 0;
-	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
-	    RF_ACTIVE);
-	if (sc->mem_res == NULL) {
-		device_printf(dev, "Cannot allocate memory resource\n");
-		return (ENXIO);
+	TAILQ_FOREACH(entry, &syscon_list, syscon_link) {
+		if (entry->ofw_node == node)
+			return (entry);
 	}
 
-	OF_device_register_xref(OF_xref_from_node(node), dev);
-
-	return (0);
+	return (NULL);
 }
 
-static int
-syscon_detach(device_t dev)
+struct syscon *
+syscon_create_ofw_node(device_t pdev, syscon_class_t syscon_class,
+    phandle_t node)
 {
-	struct syscon_softc *sc;
+	struct syscon *syscon;
 
-	sc = device_get_softc(dev);
+	syscon = syscon_create(pdev, syscon_class);
+	if (syscon == NULL)
+		return (NULL);
+	syscon->ofw_node = node;
+	if (syscon_register(syscon) == NULL)
+		return (NULL);
+	return (syscon);
+}
 
-	OF_device_register_xref(OF_xref_from_device(dev), NULL);
+phandle_t
+syscon_get_ofw_node(struct syscon *syscon)
+{
 
-	SYSCON_LOCK_DESTROY(sc);
-	if (sc->mem_res != NULL)
-		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
-	return (0);
+	return (syscon->ofw_node);
 }
 
-static device_method_t syscon_methods[] = {
-	/* Device interface */
-	DEVMETHOD(device_probe,		syscon_probe),
-	DEVMETHOD(device_attach,	syscon_attach),
-	DEVMETHOD(device_detach,	syscon_detach),
+int
+syscon_get_by_ofw_property(device_t cdev, phandle_t cnode, char *name,
+    struct syscon **syscon)
+{
+	pcell_t *cells;
+	int ncells;
 
-	/* Syscon interface */
-	DEVMETHOD(syscon_read_4,	syscon_read_4),
-	DEVMETHOD(syscon_write_4,	syscon_write_4),
-	DEVMETHOD(syscon_modify_4,	syscon_modify_4),
+	if (cnode <= 0)
+		cnode = ofw_bus_get_node(cdev);
+	if (cnode <= 0) {
+		device_printf(cdev,
+		    "%s called on not ofw based device\n", __func__);
+		return (ENXIO);
+	}
+	ncells = OF_getencprop_alloc(cnode, name, sizeof(pcell_t),
+	    (void **)&cells);
+	if (ncells < 1)
+		return (ENXIO);
 
-	DEVMETHOD_END
-};
-
-DEFINE_CLASS_0(syscon, syscon_driver, syscon_methods,
-    sizeof(struct syscon_softc));
-static devclass_t syscon_devclass;
-EARLY_DRIVER_MODULE(syscon, simplebus, syscon_driver, syscon_devclass, 0, 0,
-    BUS_PASS_BUS + BUS_PASS_ORDER_LATE);
-MODULE_VERSION(syscon, 1);
+	/* Translate to syscon node. */
+	SYSCON_TOPO_SLOCK();
+	*syscon = syscon_find_by_ofw_node(OF_node_from_xref(cells[0]));
+	if (*syscon == NULL) {
+		SYSCON_TOPO_UNLOCK();
+		device_printf(cdev, "Failed to find syscon node\n");
+		OF_prop_free(cells);
+		return (ENODEV);
+	}
+	SYSCON_TOPO_UNLOCK();
+	OF_prop_free(cells);
+	return (0);
+}
+#endif


More information about the svn-src-all mailing list