Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/spi spi: prepare for fdt direct attachment of spi sl...
details: https://anonhg.NetBSD.org/src/rev/ee5745526703
branches: trunk
changeset: 964712:ee5745526703
user: tnn <tnn%NetBSD.org@localhost>
date: Tue Aug 13 16:37:15 2019 +0000
description:
spi: prepare for fdt direct attachment of spi slaves
Introduce sba_child_devices array in spibus_attach_args. If the parent has
populated sba_child_devices then attach them first. Then do any devices
devices the user has wired in the kernel config, if any.
diffstat:
sys/dev/spi/spi.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++--
sys/dev/spi/spivar.h | 12 ++++-
2 files changed, 128 insertions(+), 8 deletions(-)
diffs (204 lines):
diff -r 53371ba96d8c -r ee5745526703 sys/dev/spi/spi.c
--- a/sys/dev/spi/spi.c Tue Aug 13 13:22:16 2019 +0000
+++ b/sys/dev/spi/spi.c Tue Aug 13 16:37:15 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: spi.c,v 1.11 2019/03/09 07:53:12 mlelstv Exp $ */
+/* $NetBSD: spi.c,v 1.12 2019/08/13 16:37:15 tnn Exp $ */
/*-
* Copyright (c) 2006 Urbana-Champaign Independent Media Center.
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.11 2019/03/09 07:53:12 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.12 2019/08/13 16:37:15 tnn Exp $");
#include "locators.h"
@@ -102,6 +102,8 @@
int sh_slave;
int sh_mode;
int sh_speed;
+ int sh_flags;
+#define SPIH_ATTACHED 1
};
#define SPI_MAXDATA 4096
@@ -151,15 +153,123 @@
return -1;
}
+ memset(&sa, 0, sizeof sa);
sa.sa_handle = &sc->sc_slaves[addr];
+ if (ISSET(sa.sa_handle->sh_flags, SPIH_ATTACHED))
+ return -1;
- if (config_match(parent, cf, &sa) > 0)
+ if (config_match(parent, cf, &sa) > 0) {
+ SET(sa.sa_handle->sh_flags, SPIH_ATTACHED);
config_attach(parent, cf, &sa, spi_print);
+ }
return 0;
}
/*
+ * XXX this is the same as i2c_fill_compat. It could be refactored into a
+ * common fill_compat function with pointers to compat & ncompat instead
+ * of attach_args as the first parameter.
+ */
+static void
+spi_fill_compat(struct spi_attach_args *sa, const char *compat, size_t len,
+ char **buffer)
+{
+ int count, i;
+ const char *c, *start, **ptr;
+
+ *buffer = NULL;
+ for (i = count = 0, c = compat; i < len; i++, c++)
+ if (*c == 0)
+ count++;
+ count += 2;
+ ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK);
+ if (!ptr)
+ return;
+
+ for (i = count = 0, start = c = compat; i < len; i++, c++) {
+ if (*c == 0) {
+ ptr[count++] = start;
+ start = c + 1;
+ }
+ }
+ if (start < compat + len) {
+ /* last string not 0 terminated */
+ size_t l = c - start;
+ *buffer = malloc(l + 1, M_TEMP, M_WAITOK);
+ memcpy(*buffer, start, l);
+ (*buffer)[l] = 0;
+ ptr[count++] = *buffer;
+ }
+ ptr[count] = NULL;
+
+ sa->sa_compat = ptr;
+ sa->sa_ncompat = count;
+}
+
+static void
+spi_direct_attach_child_devices(device_t parent, struct spi_softc *sc,
+ prop_array_t child_devices)
+{
+ unsigned int count;
+ prop_dictionary_t child;
+ prop_data_t cdata;
+ uint32_t slave;
+ uint64_t cookie;
+ struct spi_attach_args sa;
+ int loc[SPICF_NLOCS];
+ char *buf;
+ int i;
+
+ memset(loc, 0, sizeof loc);
+ count = prop_array_count(child_devices);
+ for (i = 0; i < count; i++) {
+ child = prop_array_get(child_devices, i);
+ if (!child)
+ continue;
+ if (!prop_dictionary_get_uint32(child, "slave", &slave))
+ continue;
+ if(slave >= sc->sc_controller.sct_nslaves)
+ continue;
+ if (!prop_dictionary_get_uint64(child, "cookie", &cookie))
+ continue;
+ if (!(cdata = prop_dictionary_get(child, "compatible")))
+ continue;
+ loc[SPICF_SLAVE] = slave;
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_handle = &sc->sc_slaves[i];
+ if (ISSET(sa.sa_handle->sh_flags, SPIH_ATTACHED))
+ continue;
+ SET(sa.sa_handle->sh_flags, SPIH_ATTACHED);
+
+ buf = NULL;
+ spi_fill_compat(&sa,
+ prop_data_data_nocopy(cdata),
+ prop_data_size(cdata), &buf);
+ (void) config_found_sm_loc(parent, "spi",
+ loc, &sa, spi_print,
+ NULL);
+
+ if (sa.sa_compat)
+ free(sa.sa_compat, M_TEMP);
+ if (buf)
+ free(buf, M_TEMP);
+ }
+}
+
+int
+spi_compatible_match(const struct spi_attach_args *sa, const cfdata_t cf,
+ const struct device_compatible_entry *compats)
+{
+ if (sa->sa_ncompat > 0)
+ return device_compatible_match(sa->sa_compat, sa->sa_ncompat,
+ compats, NULL);
+
+ return 1;
+}
+
+/*
* API for device drivers.
*
* We provide wrapper routines to decouple the ABI for the SPI
@@ -197,9 +307,11 @@
sc->sc_slaves[i].sh_controller = &sc->sc_controller;
}
- /*
- * Locate and attach child devices
- */
+ /* First attach devices known to be present via fdt */
+ if (sba->sba_child_devices) {
+ spi_direct_attach_child_devices(self, sc, sba->sba_child_devices);
+ }
+ /* Then do any other devices the user may have manually wired */
config_search_ia(spi_search, self, "spi", NULL);
}
diff -r 53371ba96d8c -r ee5745526703 sys/dev/spi/spivar.h
--- a/sys/dev/spi/spivar.h Tue Aug 13 13:22:16 2019 +0000
+++ b/sys/dev/spi/spivar.h Tue Aug 13 16:37:15 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: spivar.h,v 1.7 2019/02/23 10:43:25 mlelstv Exp $ */
+/* $NetBSD: spivar.h,v 1.8 2019/08/13 16:37:15 tnn Exp $ */
/*-
* Copyright (c) 2006 Urbana-Champaign Independent Media Center.
@@ -77,10 +77,16 @@
/* one per chip select */
struct spibus_attach_args {
struct spi_controller *sba_controller;
+ prop_array_t sba_child_devices;
};
struct spi_attach_args {
struct spi_handle *sa_handle;
+ /* only set if using direct config */
+ int sa_ncompat; /* number of pointers in the
+ ia_compat array */
+ const char ** sa_compat; /* chip names */
+ prop_dictionary_t sa_prop; /* dictionary for this device */
};
/*
@@ -132,7 +138,9 @@
#define SPI_F_DONE 0x0001
#define SPI_F_ERROR 0x0002
-int spi_configure(struct spi_handle *, int mode, int speed);
+int spi_compatible_match(const struct spi_attach_args *, const cfdata_t,
+ const struct device_compatible_entry *);
+int spi_configure(struct spi_handle *, int, int);
int spi_transfer(struct spi_handle *, struct spi_transfer *);
void spi_transfer_init(struct spi_transfer *);
void spi_chunk_init(struct spi_chunk *, int, const uint8_t *, uint8_t *);
Home |
Main Index |
Thread Index |
Old Index