summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authormartin <martin@NetBSD.org>2010-02-28 11:35:40 +0000
committermartin <martin@NetBSD.org>2010-02-28 11:35:40 +0000
commit5aa9335e6793afc2495a38ef628ad3575ebddd87 (patch)
treeab964ca3c5b9ee20dd951176f23ade57f734c0af /sys/dev
parent9d9a6889160ad879a32511ff3928eb84ea6576d3 (diff)
Supporting cast for i2c direct configuration on OF machines
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ofw/ofw_subr.c61
-rw-r--r--sys/dev/ofw/openfirm.h4
2 files changed, 62 insertions, 3 deletions
diff --git a/sys/dev/ofw/ofw_subr.c b/sys/dev/ofw/ofw_subr.c
index 6a23ed9df22..366004d876a 100644
--- a/sys/dev/ofw/ofw_subr.c
+++ b/sys/dev/ofw/ofw_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ofw_subr.c,v 1.16 2010/01/21 15:56:08 martin Exp $ */
+/* $NetBSD: ofw_subr.c,v 1.17 2010/02/28 11:35:40 martin Exp $ */
/*
* Copyright 1998
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ofw_subr.c,v 1.16 2010/01/21 15:56:08 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ofw_subr.c,v 1.17 2010/02/28 11:35:40 martin Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -325,3 +325,60 @@ of_get_mode_string(char *buffer, int len)
strncpy(buffer, pos + 2, len);
return buffer;
}
+
+/*
+ * Iterate over the subtree of a i2c controller node.
+ * Add all sub-devices into an array as part of the controller's
+ * device properties.
+ * This is used by the i2c bus attach code to do direct configuration.
+ */
+void
+of_enter_i2c_devs(prop_dictionary_t props, int ofnode)
+{
+ int node, len;
+ char name[32];
+ uint64_t r64;
+ uint64_t r32;
+ uint8_t smr[24];
+ prop_array_t array;
+ prop_dictionary_t dev;
+
+ array = prop_array_create();
+
+ for (node = OF_child(ofnode); node; node = OF_peer(node)) {
+ if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
+ continue;
+ len = OF_getproplen(node, "reg");
+ if (len == sizeof(r64)) {
+ if (OF_getprop(node, "reg", &r64, sizeof(r64))
+ != sizeof(r64))
+ continue;
+ r32 = r64;
+ } else if (len == sizeof(r32)) {
+ if (OF_getprop(node, "reg", &r32, sizeof(r32))
+ != sizeof(r32))
+ continue;
+ } else if (len == 24) {
+ if (OF_getprop(node, "reg", smr, sizeof(smr))
+ != sizeof(smr))
+ continue;
+ /* smbus reg property */
+ r32 = smr[7];
+ } else {
+ panic("unexpected \"reg\" size %d for \"%s\", "
+ "parent %x, node %x",
+ len, name, ofnode, node);
+ }
+
+ dev = prop_dictionary_create();
+ prop_dictionary_set_cstring(dev, "name", name);
+ prop_dictionary_set_uint32(dev, "addr", r32 >> 1);
+ prop_dictionary_set_uint64(dev, "cookie", node);
+ of_to_dataprop(dev, node, "compatible", "compatible");
+ prop_array_add(array, dev);
+ prop_object_release(dev);
+ }
+
+ prop_dictionary_set(props, "i2c-child-devices", array);
+ prop_object_release(array);
+}
diff --git a/sys/dev/ofw/openfirm.h b/sys/dev/ofw/openfirm.h
index dc0693ea0a0..4dd8c78c4b0 100644
--- a/sys/dev/ofw/openfirm.h
+++ b/sys/dev/ofw/openfirm.h
@@ -1,4 +1,4 @@
-/* $NetBSD: openfirm.h,v 1.27 2009/11/11 16:56:52 macallan Exp $ */
+/* $NetBSD: openfirm.h,v 1.28 2010/02/28 11:35:40 martin Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -115,4 +115,6 @@ boolean_t of_to_dataprop(prop_dictionary_t, int, const char *,
int *of_network_decode_media(int, int *, int *);
char *of_get_mode_string(char *, int);
+void of_enter_i2c_devs(prop_dictionary_t, int);
+
#endif /*_OPENFIRM_H_*/