Module Name:    src
Committed By:   thorpej
Date:           Sat May  8 11:40:02 UTC 2021

Modified Files:
        src/sys/arch/macppc/dev [thorpej-i2c-spi-conf]: cuda.c videopll.c

Log Message:
Children of the "cuda" i2c controller don't appear in the OF device tree,
so we need to supply our own "i2c-enumerate-devices" method.


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.28.2.1 src/sys/arch/macppc/dev/cuda.c
cvs rdiff -u -r1.3 -r1.3.18.1 src/sys/arch/macppc/dev/videopll.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/macppc/dev/cuda.c
diff -u src/sys/arch/macppc/dev/cuda.c:1.28 src/sys/arch/macppc/dev/cuda.c:1.28.2.1
--- src/sys/arch/macppc/dev/cuda.c:1.28	Sat Apr 24 23:36:41 2021
+++ src/sys/arch/macppc/dev/cuda.c	Sat May  8 11:40:02 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: cuda.c,v 1.28 2021/04/24 23:36:41 thorpej Exp $ */
+/*	$NetBSD: cuda.c,v 1.28.2.1 2021/05/08 11:40:02 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2006 Michael Lorenz
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cuda.c,v 1.28 2021/04/24 23:36:41 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cuda.c,v 1.28.2.1 2021/05/08 11:40:02 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -72,6 +72,8 @@ typedef struct _cuda_handler {
 	void *cookie;
 } CudaHandler;
 
+#define	CUDA_MAX_I2C_DEVICES	2
+
 struct cuda_softc {
 	device_t sc_dev;
 	void *sc_ih;
@@ -81,6 +83,20 @@ struct cuda_softc {
 	struct i2c_controller sc_i2c;
 	bus_space_tag_t sc_memt;
 	bus_space_handle_t sc_memh;
+
+	/*
+	 * We provide our own i2c device enumeration method, so we
+	 * need to provide our own devhandle_impl.
+	 */
+	struct devhandle_impl sc_devhandle_impl;
+
+	struct {
+		const char *name;
+		const char *compatible;
+		i2c_addr_t addr;
+	} sc_i2c_devices[CUDA_MAX_I2C_DEVICES];
+	int sc_ni2c_devices;
+
 	int sc_node;
 	int sc_state;
 	int sc_waiting;
@@ -147,6 +163,65 @@ static	int cuda_adb_set_handler(void *, 
 static int cuda_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
 		    void *, size_t, int);
 
+static void
+cuda_add_i2c_device(struct cuda_softc *sc, const char *name,
+    const char *compatible, i2c_addr_t addr)
+{
+	KASSERT(sc->sc_ni2c_devices < CUDA_MAX_I2C_DEVICES);
+	sc->sc_i2c_devices[sc->sc_ni2c_devices].name = name;
+	sc->sc_i2c_devices[sc->sc_ni2c_devices].compatible = compatible;
+	sc->sc_i2c_devices[sc->sc_ni2c_devices].addr = addr;
+	sc->sc_ni2c_devices++;
+}
+
+static int
+cuda_i2c_enumerate_devices(device_t dev, devhandle_t call_handle, void *v)
+{
+	struct i2c_enumerate_devices_args *args = v;
+	prop_dictionary_t props;
+	int i;
+	bool cbrv;
+
+	/* dev is the "iicbus" instance.  Cuda softc is in args. */
+	struct cuda_softc *sc = args->ia->ia_tag->ic_cookie;
+
+	for (i = 0; i < sc->sc_ni2c_devices; i++) {
+		props = prop_dictionary_create();
+
+		args->ia->ia_addr = sc->sc_i2c_devices[i].addr;
+		args->ia->ia_name = sc->sc_i2c_devices[i].name;
+		args->ia->ia_clist = sc->sc_i2c_devices[i].compatible;
+		args->ia->ia_clist_size = strlen(args->ia->ia_clist) + 1;
+		args->ia->ia_prop = props;
+		/* Child gets no handle. */
+		devhandle_invalidate(&args->ia->ia_devhandle);
+		args->ia->ia_cookie = 0;			/* XXX */
+		args->ia->ia_cookietype = I2C_COOKIE_NONE;	/* XXX */
+
+		cbrv = args->callback(dev, args);
+
+		prop_object_release(props);
+
+		if (!cbrv) {
+			break;	/* callback decides if we continue */
+		}
+	}
+
+	return 0;
+}
+
+static device_call_t
+cuda_devhandle_lookup_device_call(devhandle_t handle, const char *name,
+    devhandle_t *call_handlep)
+{
+	if (strcmp(name, "i2c-enumerate-devices") == 0) {
+		return cuda_i2c_enumerate_devices;
+	}
+
+	/* Defer everything else to the "super". */
+	return NULL;
+}
+
 static int
 cuda_match(device_t parent, struct cfdata *cf, void *aux)
 {
@@ -172,9 +247,6 @@ cuda_attach(device_t parent, device_t se
 	struct cuda_softc *sc = device_private(self);
 	struct i2cbus_attach_args iba;
 	static struct cuda_attach_args caa;
-	prop_dictionary_t dict = device_properties(self);
-	prop_dictionary_t dev;
-	prop_array_t cfg;
 	int irq = ca->ca_intr[0];
 	int node, i, child;
 	char name[32];
@@ -252,37 +324,41 @@ cuda_attach(device_t parent, device_t se
 #if notyet
 	config_found(self, &caa, cuda_print, CFARG_EOL);
 #endif
-	cfg = prop_array_create();
-	prop_dictionary_set(dict, "i2c-child-devices", cfg);
-	prop_object_release(cfg);
-
 	/* we don't have OF nodes for i2c devices so we have to make our own */
-
 	node = OF_finddevice("/valkyrie");
 	if (node != -1) {
-		dev = prop_dictionary_create();
-		prop_dictionary_set_string(dev, "name", "videopll");
-		prop_dictionary_set_uint32(dev, "addr", 0x50);
-		prop_array_add(cfg, dev);
-		prop_object_release(dev);
+		/* XXX a real "compatible" string would be nice... */
+		cuda_add_i2c_device(sc, "videopll",
+		    "aapl,valkyrie-videopll", 0x50);
 	}
 
 	node = OF_finddevice("/perch");
 	if (node != -1) {
-		dev = prop_dictionary_create();
-		prop_dictionary_set_string(dev, "name", "sgsmix");
-		prop_dictionary_set_uint32(dev, "addr", 0x8a);
-		prop_array_add(cfg, dev);
-		prop_object_release(dev);
+		cuda_add_i2c_device(sc, "sgsmix", "st,tda7433", 0x8a);
 	}
 
-	memset(&iba, 0, sizeof(iba));
-	iba.iba_tag = &sc->sc_i2c;
+	/*
+	 * Normally the i2c bus instance would automatically inherit
+	 * our devhandle, but we provide our own i2c device enumeration
+	 * method, so we need to supply the bus instance with our own
+	 * device handle implementation, using the one we got from
+	 * OpenFirmware as the "super".
+	 */
+	devhandle_t devhandle = devhandle_from_of(sc->sc_node);
+	devhandle_impl_inherit(&sc->sc_devhandle_impl, devhandle.impl);
+	sc->sc_devhandle_impl.lookup_device_call =
+	    cuda_devhandle_lookup_device_call;
+	devhandle.impl = &sc->sc_devhandle_impl;
+
 	iic_tag_init(&sc->sc_i2c);
 	sc->sc_i2c.ic_cookie = sc;
 	sc->sc_i2c.ic_exec = cuda_i2c_exec;
+
+	memset(&iba, 0, sizeof(iba));
+	iba.iba_tag = &sc->sc_i2c;
 	config_found(self, &iba, iicbus_print,
 	    CFARG_IATTR, "i2cbus",
+	    CFARG_DEVHANDLE, devhandle,
 	    CFARG_EOL);
 
 	if (cuda0 == NULL)

Index: src/sys/arch/macppc/dev/videopll.c
diff -u src/sys/arch/macppc/dev/videopll.c:1.3 src/sys/arch/macppc/dev/videopll.c:1.3.18.1
--- src/sys/arch/macppc/dev/videopll.c:1.3	Sat Jun 16 21:22:13 2018
+++ src/sys/arch/macppc/dev/videopll.c	Sat May  8 11:40:02 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: videopll.c,v 1.3 2018/06/16 21:22:13 thorpej Exp $	*/
+/*	$NetBSD: videopll.c,v 1.3.18.1 2021/05/08 11:40:02 thorpej Exp $	*/
 
 /*
  * Copyright (c) 2012 Michael Lorenz
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: videopll.c,v 1.3 2018/06/16 21:22:13 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: videopll.c,v 1.3.18.1 2021/05/08 11:40:02 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -66,13 +66,19 @@ CFATTACH_DECL_NEW(videopll, sizeof(struc
 
 static void *glob = NULL;
 
+static const struct device_compatible_entry compat_data[] = {
+	/* XXX a real "compatible" string would be nice... */
+	{ .compat = "aapl,valkyrie-videopll" },
+	DEVICE_COMPAT_EOL
+};
+
 static int
 videopll_match(device_t parent, cfdata_t cfdata, void *aux)
 {
 	struct i2c_attach_args *ia = aux;
 	int match_result;
 
-	if (iic_use_direct_match(ia, cfdata, NULL, &match_result))
+	if (iic_use_direct_match(ia, cfdata, compat_data, &match_result))
 		return match_result;
 	
 	/* This driver is direct-config only. */

Reply via email to