Home | History | Annotate | Line # | Download | only in fdt
fdt_spi.c revision 1.12
      1 /* $NetBSD: fdt_spi.c,v 1.12 2025/09/14 00:28:43 thorpej Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2021, 2022 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 /*
     30  * Copyright (c) 2019 The NetBSD Foundation, Inc.
     31  * All rights reserved.
     32  *
     33  * This code is derived from software contributed to The NetBSD Foundation
     34  * by Tobias Nygren.
     35  *
     36  * Redistribution and use in source and binary forms, with or without
     37  * modification, are permitted provided that the following conditions
     38  * are met:
     39  * 1. Redistributions of source code must retain the above copyright
     40  *    notice, this list of conditions and the following disclaimer.
     41  * 2. Redistributions in binary form must reproduce the above copyright
     42  *    notice, this list of conditions and the following disclaimer in the
     43  *    documentation and/or other materials provided with the distribution.
     44  *
     45  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     46  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     47  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     48  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     49  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     50  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     51  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     52  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     53  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     54  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     55  * POSSIBILITY OF SUCH DAMAGE.
     56  */
     57 
     58 #include <sys/cdefs.h>
     59 __KERNEL_RCSID(0, "$NetBSD: fdt_spi.c,v 1.12 2025/09/14 00:28:43 thorpej Exp $");
     60 
     61 #include <sys/param.h>
     62 #include <sys/device.h>
     63 #include <sys/kmem.h>
     64 #include <sys/queue.h>
     65 
     66 #include <dev/fdt/fdtvar.h>
     67 
     68 #include <dev/ofw/openfirm.h>
     69 
     70 #include <dev/spi/spi_calls.h>
     71 
     72 struct fdtbus_spi_controller {
     73 	device_t spi_dev;
     74 	const struct spi_controller *spi_controller;
     75 	LIST_ENTRY(fdtbus_spi_controller) spi_next;
     76 };
     77 
     78 static LIST_HEAD(, fdtbus_spi_controller) fdtbus_spi_controllers =
     79     LIST_HEAD_INITIALIZER(fdtbus_spi_controllers);
     80 
     81 /* XXX Maybe garbage-collect this. */
     82 int
     83 fdtbus_register_spi_controller(device_t dev,
     84     const struct spi_controller *controller)
     85 {
     86 	struct fdtbus_spi_controller *spi;
     87 
     88 	spi = kmem_alloc(sizeof(*spi), KM_SLEEP);
     89 	spi->spi_dev = dev;
     90 	spi->spi_controller = controller;
     91 
     92 	LIST_INSERT_HEAD(&fdtbus_spi_controllers, spi, spi_next);
     93 
     94 	return 0;
     95 }
     96 
     97 #if 0
     98 static const struct spi_controller *
     99 fdtbus_get_spi_controller(int phandle)
    100 {
    101 	struct fdtbus_spi_controller *spi;
    102 
    103 	LIST_FOREACH(spi, &fdtbus_spi_controllers, spi_next) {
    104 		if (phandle ==
    105 		    devhandle_to_of(device_handle(spi->spi_dev))) {
    106 			return spi->spi_controller;
    107 		}
    108 	}
    109 	return NULL;
    110 }
    111 #endif
    112 
    113 static int
    114 fdtbus_spi_enumerate_devices(device_t dev, devhandle_t call_handle, void *v)
    115 {
    116 	struct spi_enumerate_devices_args *args = v;
    117 	int spi_node, node;
    118 	char name[32], compat_buf[32];
    119 	bus_addr_t chip_select;
    120 	char *clist;
    121 	int clist_size;
    122 	bool cbrv;
    123 
    124 	spi_node = devhandle_to_of(call_handle);
    125 
    126 	for (node = OF_child(spi_node); node != 0; node = OF_peer(node)) {
    127 		if (OF_getprop(node, "name", name, sizeof(name)) <= 0) {
    128 			continue;
    129 		}
    130 
    131 		if (fdtbus_get_reg(node, 0, &chip_select, NULL) != 0) {
    132 			continue;
    133 		}
    134 
    135 		/* Device Tree bindings specify a max chip select of 256. */
    136 		if (chip_select > 256) {
    137 			continue;
    138 		}
    139 
    140 		clist_size = OF_getproplen(node, "compatible");
    141 		if (clist_size <= 0) {
    142 			continue;
    143 		}
    144 
    145 		clist = kmem_tmpbuf_alloc(clist_size,
    146 		    compat_buf, sizeof(compat_buf), KM_SLEEP);
    147 		if (OF_getprop(node, "compatible", clist, clist_size) <
    148 		    clist_size) {
    149 			kmem_tmpbuf_free(clist, clist_size, compat_buf);
    150 			continue;
    151 		}
    152 
    153 		args->chip_select = (int)chip_select;
    154 		args->sa->sa_name = name;
    155 		args->sa->sa_clist = clist;
    156 		args->sa->sa_clist_size = clist_size;
    157 		args->sa->sa_devhandle = devhandle_from_of(call_handle, node);
    158 
    159 		cbrv = args->callback(dev, args);
    160 
    161 		kmem_tmpbuf_free(clist, clist_size, compat_buf);
    162 
    163 		if (!cbrv) {
    164 			break;
    165 		}
    166 	}
    167 
    168 	return 0;
    169 }
    170 OF_DEVICE_CALL_REGISTER(SPI_ENUMERATE_DEVICES_STR,
    171 			fdtbus_spi_enumerate_devices);
    172