Module Name: src Committed By: thorpej Date: Sun Apr 25 22:16:05 UTC 2021
Modified Files: src/sys/dev/ofw [thorpej-i2c-spi-conf]: ofw_i2c_subr.c openfirm.h Log Message: Implement "i2c-enumerate-devices" for OFW / FDT. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.1.6.1 src/sys/dev/ofw/ofw_i2c_subr.c cvs rdiff -u -r1.47 -r1.47.2.1 src/sys/dev/ofw/openfirm.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ofw/ofw_i2c_subr.c diff -u src/sys/dev/ofw/ofw_i2c_subr.c:1.1 src/sys/dev/ofw/ofw_i2c_subr.c:1.1.6.1 --- src/sys/dev/ofw/ofw_i2c_subr.c:1.1 Thu Feb 4 20:19:09 2021 +++ src/sys/dev/ofw/ofw_i2c_subr.c Sun Apr 25 22:16:05 2021 @@ -1,4 +1,30 @@ -/* $NetBSD: ofw_i2c_subr.c,v 1.1 2021/02/04 20:19:09 thorpej Exp $ */ +/* $NetBSD: ofw_i2c_subr.c,v 1.1.6.1 2021/04/25 22:16:05 thorpej Exp $ */ + +/* + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ /* * Copyright 1998 @@ -34,7 +60,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ofw_i2c_subr.c,v 1.1 2021/02/04 20:19:09 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ofw_i2c_subr.c,v 1.1.6.1 2021/04/25 22:16:05 thorpej Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -44,66 +70,81 @@ __KERNEL_RCSID(0, "$NetBSD: ofw_i2c_subr #include <dev/i2c/i2cvar.h> /* - * 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. + * Standard routine for fetching an i2c device address, according + * to the standard OpenFirmware / Device Tree bindings. */ -void -of_enter_i2c_devs(prop_dictionary_t props, int ofnode, size_t cell_size, - int addr_shift) +static bool +of_i2c_get_address(int node, uint32_t *addrp) +{ + uint32_t reg; + + if (of_getprop_uint32(node, "reg", ®) == -1) { + return false; + } + + *addrp = reg; + return true; +} + +static int +of_i2c_enumerate_devices(device_t dev, devhandle_t call_handle, void *v) { - int node, len; - char name[32]; - uint64_t reg64; - uint32_t reg32; - uint64_t addr; - prop_array_t array = NULL; - prop_dictionary_t dev; + return of_i2c_enumerate_devices_ext(dev, call_handle, v, + of_i2c_get_address); +} +OF_DEVICE_CALL_REGISTER("i2c-enumerate-devices", of_i2c_enumerate_devices); - for (node = OF_child(ofnode); node; node = OF_peer(node)) { - if (OF_getprop(node, "name", name, sizeof(name)) <= 0) +int +of_i2c_enumerate_devices_ext(device_t dev, devhandle_t call_handle, void *v, + bool (*get_address)(int, uint32_t *)) +{ + struct i2c_enumerate_devices_args *args = v; + int i2c_node, node; + char name[32], compat_buf[32]; + prop_dictionary_t props; + uint32_t addr; + char *clist; + int clist_size; + bool cbrv; + + i2c_node = devhandle_to_of(call_handle); + + for (node = OF_child(i2c_node); node != 0; node = OF_peer(node)) { + if (OF_getprop(node, "name", name, sizeof(name)) <= 0) { continue; - len = OF_getproplen(node, "reg"); - addr = 0; - if (cell_size == 8 && len >= sizeof(reg64)) { - if (OF_getprop(node, "reg", ®64, sizeof(reg64)) - < sizeof(reg64)) - continue; - addr = be64toh(reg64); - /* - * The i2c bus number (0 or 1) is encoded in bit 33 - * of the register, but we encode it in bit 8 of - * i2c_addr_t. - */ - if (addr & 0x100000000) - addr = (addr & 0xff) | 0x100; - } else if (cell_size == 4 && len >= sizeof(reg32)) { - if (OF_getprop(node, "reg", ®32, sizeof(reg32)) - < sizeof(reg32)) - continue; - addr = be32toh(reg32); - } else { + } + if (!get_address(node, &addr)) { continue; } - addr >>= addr_shift; - if (addr == 0) continue; - if (array == NULL) - array = prop_array_create(); + clist_size = OF_getproplen(node, "compatible"); + clist = kmem_tmpbuf_alloc(clist_size, + compat_buf, sizeof(compat_buf), KM_SLEEP); + if (OF_getprop(node, "compatible", clist, clist_size) < + clist_size) { + kmem_tmpbuf_free(clist, clist_size, compat_buf); + continue; + } + props = prop_dictionary_create(); - dev = prop_dictionary_create(); - prop_dictionary_set_string(dev, "name", name); - prop_dictionary_set_uint32(dev, "addr", addr); - prop_dictionary_set_uint64(dev, "cookie", node); - prop_dictionary_set_uint32(dev, "cookietype", I2C_COOKIE_OF); - of_to_dataprop(dev, node, "compatible", "compatible"); - prop_array_add(array, dev); - prop_object_release(dev); - } + args->ia->ia_addr = (i2c_addr_t)addr; + args->ia->ia_name = name; + args->ia->ia_clist = clist; + args->ia->ia_clist_size = clist_size; + args->ia->ia_prop = props; + args->ia->ia_devhandle = devhandle_from_of(node); + args->ia->ia_cookie = node; /* XXX */ + args->ia->ia_cookietype = I2C_COOKIE_OF; /* XXX */ + + cbrv = args->callback(dev, args); + + prop_object_release(props); + kmem_tmpbuf_free(clist, clist_size, compat_buf); - if (array != NULL) { - prop_dictionary_set(props, "i2c-child-devices", array); - prop_object_release(array); + if (!cbrv) { + break; + } } + + return 0; } Index: src/sys/dev/ofw/openfirm.h diff -u src/sys/dev/ofw/openfirm.h:1.47 src/sys/dev/ofw/openfirm.h:1.47.2.1 --- src/sys/dev/ofw/openfirm.h:1.47 Sat Apr 24 23:36:57 2021 +++ src/sys/dev/ofw/openfirm.h Sun Apr 25 22:16:05 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: openfirm.h,v 1.47 2021/04/24 23:36:57 thorpej Exp $ */ +/* $NetBSD: openfirm.h,v 1.47.2.1 2021/04/25 22:16:05 thorpej Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -129,7 +129,8 @@ device_t of_device_from_phandle(int); int *of_network_decode_media(int, int *, int *); char *of_get_mode_string(char *, int); -void of_enter_i2c_devs(prop_dictionary_t, int, size_t, int); +int of_i2c_enumerate_devices_ext(device_t, devhandle_t, void *, + bool (*)(int, uint32_t *)); void of_enter_spi_devs(prop_dictionary_t, int, size_t); #endif /* _KERNEL */