Module Name:    src
Committed By:   thorpej
Date:           Wed May 19 12:35:28 UTC 2021

Modified Files:
        src/sys/dev/spi [thorpej-i2c-spi-conf]: mcp23s17.c

Log Message:
The MCP23S17 can multiplex multiple chips on the same chip select.
This driver has traditionally used cf_flags (from the kernel config
file) to get the chip address.

For direct configuration, we need to consult the platform device tree.
Add support for this, and implement for the Device Tree bindings for
this device (consulting the "microchip,spi-present-mask" property).

XXX The "microchip,spi-present-mask" property can encode for multiple
chips at the same device tree node; we do not currently support this
in the driver.


To generate a diff of this commit:
cvs rdiff -u -r1.2.2.2 -r1.2.2.3 src/sys/dev/spi/mcp23s17.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/dev/spi/mcp23s17.c
diff -u src/sys/dev/spi/mcp23s17.c:1.2.2.2 src/sys/dev/spi/mcp23s17.c:1.2.2.3
--- src/sys/dev/spi/mcp23s17.c:1.2.2.2	Wed May 19 03:46:26 2021
+++ src/sys/dev/spi/mcp23s17.c	Wed May 19 12:35:28 2021
@@ -1,4 +1,4 @@
-/*      $NetBSD: mcp23s17.c,v 1.2.2.2 2021/05/19 03:46:26 thorpej Exp $ */
+/*      $NetBSD: mcp23s17.c,v 1.2.2.3 2021/05/19 12:35:28 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mcp23s17.c,v 1.2.2.2 2021/05/19 03:46:26 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mcp23s17.c,v 1.2.2.3 2021/05/19 12:35:28 thorpej Exp $");
 
 /* 
  * Driver for Microchip MCP23S17 GPIO
@@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: mcp23s17.c,v
  */
 
 #include "gpio.h"
+#include "opt_fdt.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -51,9 +52,12 @@ __KERNEL_RCSID(0, "$NetBSD: mcp23s17.c,v
 #include <dev/gpio/gpiovar.h>
 
 #include <dev/spi/spivar.h>
-
 #include <dev/spi/mcp23s17.h>
 
+#ifdef FDT
+#include <dev/ofw/openfirm.h>
+#endif /* FDT */
+
 /* #define MCP23S17_DEBUG */
 #ifdef MCP23S17_DEBUG
 int mcp23S17debug = 3;
@@ -109,6 +113,60 @@ mcp23s17gpio_match(device_t parent, cfda
 	return spi_compatible_match(sa, cf, compat_data);
 }
 
+#ifdef FDT
+static bool
+mcp23s17gpio_ha_fdt(struct mcp23s17gpio_softc *sc)
+{
+	devhandle_t devhandle = device_handle(sc->sc_dev);
+	int phandle = devhandle_to_of(devhandle);
+	uint32_t mask;
+	int count;
+
+	/*
+	 * The number of devices sharing this chip select,
+	 * along with their assigned addresses, is encoded
+	 * in the "microchip,spi-present-mask" property.
+	 *
+	 * N.B. we also check for "mcp,spi-present-mask" if
+	 * the first one isn't present (it's a deprecated
+	 * property that may be present in older device trees).
+	 */
+	if (of_getprop_uint32(phandle, "microchip,spi-present-mask",
+			      &mask) != 0 ||
+	    of_getprop_uint32(phandle, "mcp,spi-present-mask",
+			      &mask) != 0) {
+		aprint_error(
+		    ": missing \"microchip,spi-present-mask\" property\n");
+		return false;
+	}
+
+	/*
+	 * If we ever support the mcp23s08, then only bits 0-3 are valid
+	 * on that device.
+	 */
+	if (mask == 0 || mask > __BITS(0,7)) {
+		aprint_error(
+		    ": invalid \"microchip,spi-present-mask\" property\n");
+		return false;
+	}
+
+	count = popcount32(mask);
+	if (count > 1) {
+		/*
+		 * XXX We only support a single chip on this chip
+		 * select for now.
+		 */
+		aprint_error(": unsupported %d-chip configuration\n", count);
+		return false;
+	}
+
+	sc->sc_ha = ffs(mask) - 1;
+	KASSERT(sc->sc_ha >= 0 && sc->sc_ha <= 7);
+
+	return true;
+}
+#endif /* FDT */
+
 static void
 mcp23s17gpio_attach(device_t parent, device_t self, void *aux)
 {
@@ -127,6 +185,34 @@ mcp23s17gpio_attach(device_t parent, dev
 	sc->sc_bank = 0;
 
 	/*
+	 * The MCP23S17 can multiplex multiple chips on the same
+	 * chip select.
+	 *
+	 * If we got here using indirect configuration, our kernel
+	 * config file directive has our address.  Otherwise, we need
+	 * to consult the device tree used for direct configuration.
+	 */
+	if (sa->sa_name == NULL) {
+		sc->sc_ha = device_cfdata(sc->sc_dev)->cf_flags & 0x7;
+	} else {
+		devhandle_t devhandle = device_handle(self);
+
+		switch (devhandle_type(devhandle)) {
+#ifdef FDT
+		case DEVHANDLE_TYPE_OF:
+			if (! mcp23s17gpio_ha_fdt(sc)) {
+				/* Error alredy displayed. */
+				return;
+			}
+			return;
+#endif /* FDT */
+		default:
+			aprint_error(": unsupported device handle type\n");
+			return;
+		}
+	}
+
+	/*
 	 * XXX Initialize sc_ha from microchip,spi-present-mask
 	 * XXX property for FDT.  Only consult cf_flags for indirect.
 	 */

Reply via email to