Re: Multiple SPI MCP23S17s sharing a CS line

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



"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




[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux