"Linux does not support multiple child devices "within" one SPI slave.
If there was proper support for this, this patch would be superfluous."
This is not a real limitation, we can have children inside SPI devices,
no problem at all. The driver can just parse them with something like
for_each_available_child_of_node(parent, child) from
<linux/of.h>.
It is possible for the driver to create proper subdevices for each
node or just create (I think) the different gpio_chip:s with
a reference to the unique DT node for each chip and then the
.xlate function will figure out the GPIO translation.
Hi,
I agree that an approach with "subnodes" is probably the best solution; I
like that.
When you have a patch, I'll be happy to test it :). I had no idea that you
can put multiple "client" devices such as gpiochips behind a single parent
device (itself a SPI client). I suspect that various fixes for making sure
that no duplicate data are present in, say, debugfs for pintrl and regmap
and gpio /sys/kernel/debug subtrees, will still be needed, but I think that
most of them are in place already.
For reference, this is how I've been using these chips:
gpio_spi_chips: gpio@1 {
compatible = "microchip,mcp23s17";
reg = <1>;
interrupt-parent = <&gpio1>;
interrupts = <22 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
microchip,spi-present-mask = <0x06>; /* extra addresses 1
and 2 */
microchip,irq-mirror;
drive-open-drain;
spi-max-frequency = <10000000>;
gpio-bank@1 {
address = <1>;
gpio-line-names =
"EDFA1_RESET",
"EDFA2_RESET",
"PMB_ALERT",
"EXP_GPIO2",
"WSS_SC",
"WSS_RST",
"I2C_XOR_RDY",
"OCM_HS_OUT",
"EDFA1_OUT_REFLECT_A",
"EDFA1_PUMP_CURRENT_A",
"EDFA1_ST1_IN_LOS_A",
"EDFA1_ST2_IN_LOS_A",
"EDFA1_ST2_OUT_GAIN_A",
"EDFA1_CASE_TEMP_A",
"EDFA1_ST1_OUT_GAIN_A",
"EDFA1_PUMP_TEMP_A";
};
gpio-bank@2 {
address = <2>;
gpio-line-names =
/* these are all grounded */
"GND",
"GND",
"GND",
"GND",
"GND",
"GND",
"GND",
"GND",
"EDFA2_OUT_REFLECT_A",
"EDFA2_PUMP_CURRENT_A",
"EDFA2_ST1_IN_LOS_A",
"EDFA2_ST2_IN_LOS_A",
"EDFA2_ST2_OUT_GAIN_A",
"EDFA2_CASE_TEMP_A",
"EDFA2_ST1_OUT_GAIN_A",
"EDFA2_PUMP_TEMP_A";
};
// FIXME: this hogs both .1 and .2 chips' #6 pin...
i2c_xor_ready {
gpio-hog;
gpios = <6 GPIO_ACTIVE_HIGH>;
input;
line-name = "I2C XOR ready";
};
};
Note that FIXME, though. I think that requesting GPIOs by name from
userspace works correctly (or perhaps only by chance? Cannot check atm, I
don't have the board + scope on this desk), but a gpio-hog from kernel
(which uses a GPIO offset within a chip as far as I can tell) appears to be
slightly wonky as wittnessed by /sys/kernel/debug/gpio on this system:
gpiochip4: GPIOs 464-479, parent: spi/spi1.1, mcp23s17.2, can sleep:
gpio-464 (GND )
gpio-465 (GND )
gpio-466 (GND )
gpio-467 (GND )
gpio-468 (GND )
gpio-469 (GND )
gpio-470 (GND |I2C XOR ready ) in lo
gpio-471 (GND )
gpio-472 (EDFA2_OUT_REFLECT_A )
gpio-473 (EDFA2_PUMP_CURRENT_A)
gpio-474 (EDFA2_ST1_IN_LOS_A )
gpio-475 (EDFA2_ST2_IN_LOS_A )
gpio-476 (EDFA2_ST2_OUT_GAIN_A)
gpio-477 (EDFA2_CASE_TEMP_A )
gpio-478 (EDFA2_ST1_OUT_GAIN_A)
gpio-479 (EDFA2_PUMP_TEMP_A )
gpiochip3: GPIOs 480-495, parent: spi/spi1.1, mcp23s17.1, can sleep:
gpio-480 (EDFA1_RESET |EDFA reset ) out hi
gpio-481 (EDFA2_RESET )
gpio-482 (PMB_ALERT )
gpio-483 (EXP_GPIO2 )
gpio-484 (WSS_SC )
gpio-485 (WSS_RST )
gpio-486 (I2C_XOR_RDY |I2C XOR ready ) in lo
gpio-487 (OCM_HS_OUT |OCM HS_OUT ) in hi IRQ
gpio-488 (EDFA1_OUT_REFLECT_A )
gpio-489 (EDFA1_PUMP_CURRENT_A)
gpio-490 (EDFA1_ST1_IN_LOS_A )
gpio-491 (EDFA1_ST2_IN_LOS_A )
gpio-492 (EDFA1_ST2_OUT_GAIN_A)
gpio-493 (EDFA1_CASE_TEMP_A )
gpio-494 (EDFA1_ST1_OUT_GAIN_A)
gpio-495 (EDFA1_PUMP_TEMP_A )
I think this is more or less the same thing as Phil Elwell wrote in his
initial message. But I think that
https://patchwork.ozlabs.org/patch/1052925/ at least makes it possible to
request the GPIOs from userspace.
Hope this helps,
Jan