Module Name:    src
Committed By:   thorpej
Date:           Sun Apr 25 23:19:16 UTC 2021

Modified Files:
        src/sys/arch/sandpoint/sandpoint [thorpej-i2c-spi-conf]: autoconf.c

Log Message:
Use a private devhandle to implement i2c device enumeration on the
Sandpoint-based NAS devices.


To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.29.6.1 src/sys/arch/sandpoint/sandpoint/autoconf.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/sandpoint/sandpoint/autoconf.c
diff -u src/sys/arch/sandpoint/sandpoint/autoconf.c:1.29 src/sys/arch/sandpoint/sandpoint/autoconf.c:1.29.6.1
--- src/sys/arch/sandpoint/sandpoint/autoconf.c:1.29	Thu Jul  9 05:12:09 2020
+++ src/sys/arch/sandpoint/sandpoint/autoconf.c	Sun Apr 25 23:19:16 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: autoconf.c,v 1.29 2020/07/09 05:12:09 nisimura Exp $	*/
+/*	$NetBSD: autoconf.c,v 1.29.6.1 2021/04/25 23:19:16 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.29 2020/07/09 05:12:09 nisimura Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.29.6.1 2021/04/25 23:19:16 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -44,6 +44,7 @@ __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v
 
 #include <dev/cons.h>
 #include <dev/pci/pcivar.h>
+#include <dev/i2c/i2cvar.h>
 
 #include <net/if.h>
 #include <net/if_ether.h>
@@ -57,31 +58,167 @@ static struct btinfo_net *bi_net;
 static struct btinfo_prodfamily *bi_pfam;
 static struct btinfo_model *bi_model;
 
-struct i2c_dev {
-	const char	*name;
-	unsigned	addr;
-	/* only attach when one of these bits in the model flags is set */
+struct sandpoint_i2cdev {
+	const char *	name;
+	const char *	compat;
 	uint32_t	model_mask;
+	i2c_addr_t	addr;
 };
 
-#define MAXI2CDEVS	4
-struct model_i2c {
-	const char	*family;
-	struct i2c_dev	i2c_devs[MAXI2CDEVS];
-};
-
-static struct model_i2c model_i2c_list[] = {
-	{ "dlink",	{	{ "strtc",	0x68, 0 } } },
-	{ "iomega",	{	{ "dsrtc",	0x68, 0 } } },
-	{ "kurobox",	{	{ "rs5c372rtc", 0x32, 0 } } },
-	{ "kurot4",	{	{ "rs5c372rtc", 0x32, 0 } } },
-	{ "nhnas",	{	{ "pcf8563rtc", 0x51, 0 } } },
-	{ "qnap",	{	{ "s390rtc",    0x30, 0 } } },
-	{ "synology",	{	{ "rs5c372rtc", 0x32, 0 },
-				{ "lmtemp",	0x48, BI_MODEL_THERMAL } } },
+static const struct sandpoint_i2cdev dlink_i2cdevs[] = {
+[0] =	{
+		.name = "strtc",
+		.compat = "st,m41t80",
+		.addr = 0x68,
+	},
+[1] =	{
+		.name = NULL
+	}
+};
+
+static const struct sandpoint_i2cdev iomega_i2cdevs[] = {
+[0] =	{
+		.name = "dsrtc",
+		.compat = "dallas,ds1307",
+		.addr = 0x68,
+	},
+[1] =	{
+		.name = NULL
+	}
+};
+
+static const struct sandpoint_i2cdev kurobox_i2cdevs[] = {
+[0] =	{
+		.name = "rs5c372rtc",
+		.compat = "ricoh,rs5c372a",
+		.addr = 0x32,
+	},
+[1] =	{
+		.name = NULL
+	}
+};
+
+static const struct sandpoint_i2cdev nhnas_i2cdevs[] = {
+[0] =	{
+		.name = "pcf8563rtc",
+		.compat = "nxp,pcf8563",
+		.addr = 0x51,
+	},
+[1] =	{
+		.name = NULL
+	}
+};
+
+static const struct sandpoint_i2cdev qnap_i2cdevs[] = {
+[0] =	{
+		.name = "s390rtc",
+		.compat = "sii,s35390a",
+		.addr = 0x30,
+	},
+[1] =	{
+		.name = NULL
+	}
+};
+
+static const struct sandpoint_i2cdev synology_i2cdevs[] = {
+[0] =	{
+		.name = "rs5c372rtc",
+		.compat = "ricoh,rs5c372a",
+		.addr = 0x32,
+	},
+[1] =	{
+		.name = "lmtemp",
+		.compat = "national,lm75",
+		.addr = 0x48,
+		.model_mask = BI_MODEL_THERMAL,
+	},
+[2] =	{
+		.name = NULL
+	}
 };
 
-static void add_i2c_child_devices(device_t, const char *);
+static const struct device_compatible_entry sandpoint_i2c_compat[] = {
+	{ .compat = "dlink",		.data = &dlink_i2cdevs },
+	{ .compat = "iomega",		.data = &iomega_i2cdevs },
+	{ .compat = "kurobox",		.data = &kurobox_i2cdevs },
+	/* kurot4 has same i2c devices as kurobox */
+	{ .compat = "kurot4",		.data = &kurobox_i2cdevs },
+	{ .compat = "nhnas",		.data = &nhnas_i2cdevs },
+	{ .compat = "qnap",		.data = &qnap_i2cdevs },
+	{ .compat = "synology",		.data = &synology_i2cdevs },
+	DEVICE_COMPAT_EOL
+};
+
+/*
+ * We provide a device handle implementation for i2c device enumeration.
+ */
+static int
+sandpoint_i2c_enumerate_devices(device_t dev, devhandle_t call_handle, void *v)
+{
+	struct i2c_enumerate_devices_args *args = v;
+	const struct device_compatible_entry *dce;
+	const struct sandpoint_i2cdev *i2cdev;
+	prop_dictionary_t props;
+	bool cbrv;
+
+	KASSERT(bi_pfam != NULL);
+
+	const char *fam_name = bi_pfam->name;
+	dce = device_compatible_lookup(&fam_name, 1, sandpoint_i2c_compat);
+	if (dce == NULL) {
+		/* no i2c devices for this model. */
+		return 0;
+	}
+	i2cdev = dce->data;
+	KASSERT(i2cdev != NULL);
+
+	for (; i2cdev->name != NULL; i2cdev++) {
+		if (i2cdev->model_mask != 0) {
+			KASSERT(bi_model != NULL);
+			if ((i2cdev->model_mask & bi_model->flags) == 0) {
+				/* skip this device. */
+				continue;
+			}
+		}
+
+		props = prop_dictionary_create();
+
+		args->ia->ia_addr = i2cdev->addr;
+		args->ia->ia_name = i2cdev->name;
+		args->ia->ia_clist = i2cdev->compat;
+		args->ia->ia_clist_size = strlen(i2cdev->compat) + 1;
+		args->ia->ia_prop = props;
+		/* no devhandle for child devices. */
+		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;
+		}
+	}
+
+	return 0;
+}
+
+static device_call_t
+sandpoint_i2c_devhandle_lookup_device_call(devhandle_t handle, const char *name,
+    devhandle_t *call_handlep)
+{
+	if (strcmp(name, "i2c-enumerate-devices") == 0) {
+		return sandpoint_i2c_enumerate_devices;
+	}
+	return NULL;
+}
+
+static const struct devhandle_impl sandpoint_i2c_devhandle_impl = {
+	.type = DEVHANDLE_TYPE_PRIVATE,
+	.lookup_device_call = sandpoint_i2c_devhandle_lookup_device_call,
+};
 
 /*
  * Determine i/o configuration for a machine.
@@ -170,45 +307,10 @@ device_register(device_t dev, void *aux)
 		booted_partition = bi_rdev->cookie & 0xff;
 	}
 	else if (device_is_a(dev, "ociic") && bi_pfam != NULL) {
-		add_i2c_child_devices(dev, bi_pfam->name);
+		/* For i2c device enumeration. */
+		devhandle_t devhandle = {
+			.impl = &sandpoint_i2c_devhandle_impl,
+		};
+		device_set_handle(dev, devhandle);
 	}
 }
-
-static void
-add_i2c_child_devices(device_t self, const char *family)
-{
-	struct i2c_dev *model_i2c_devs;
-	prop_dictionary_t pd;
-	prop_array_t pa;
-	int i;
-
-	for (i = 0;
-	    i < (int)(sizeof(model_i2c_list) / sizeof(model_i2c_list[0]));
-	    i++) {
-		if (strcmp(family, model_i2c_list[i].family) == 0) {
-			model_i2c_devs = model_i2c_list[i].i2c_devs;
-			goto found;
-		}
-	}
-	return;
-
- found:
-	/* make an i2c-child-devices property list with for direct config. */
-	pa = prop_array_create();
-
-	for (i = 0; i < MAXI2CDEVS && model_i2c_devs[i].name != NULL; i++) {
-		if (model_i2c_devs[i].model_mask != 0 &&
-		    !(bi_model->flags & model_i2c_devs[i].model_mask))
-			continue;
-		pd = prop_dictionary_create();
-		prop_dictionary_set_string_nocopy(pd, "name",
-		    model_i2c_devs[i].name);
-		prop_dictionary_set_uint32(pd, "addr",
-		    model_i2c_devs[i].addr);
-		prop_array_add(pa, pd);
-		prop_object_release(pd);
-	}
-
-	prop_dictionary_set(device_properties(self), "i2c-child-devices", pa);
-	prop_object_release(pa);
-}

Reply via email to