linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Jan Kundrát" <jan.kundrat@cesnet.cz>
To: Linus Walleij <linus.walleij@linaro.org>
Cc: Phil Reid <preid@electromag.com.au>,
	Phil Elwell <phil@raspberrypi.org>,
	Jason Kridner <jkridner@gmail.com>,
	Sebastian Reichel <sre@kernel.org>,
	Bartosz Golaszewski <bgolaszewski@baylibre.com>,
	"open list:GPIO SUBSYSTEM" <linux-gpio@vger.kernel.org>
Subject: Re: Multiple SPI MCP23S17s sharing a CS line
Date: Thu, 28 Nov 2019 14:44:04 +0100	[thread overview]
Message-ID: <3ddc0c46-a5da-4617-b6b2-129ba062a9ec@cesnet.cz> (raw)
In-Reply-To: <CACRpkdZ23ncXQE+aqEDeZoppToXmWV+TpnJHjVvK3nxnN78+rA@mail.gmail.com>

> "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

  reply	other threads:[~2019-11-28 13:50 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-27 11:20 Multiple SPI MCP23S17s sharing a CS line Phil Elwell
2019-11-27 12:36 ` Linus Walleij
2019-11-28  4:11   ` Phil Reid
2019-11-28  9:17     ` Linus Walleij
2019-11-28 13:44       ` Jan Kundrát [this message]
2019-11-28  9:25   ` Phil Elwell
2019-11-28 12:24     ` Linus Walleij

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3ddc0c46-a5da-4617-b6b2-129ba062a9ec@cesnet.cz \
    --to=jan.kundrat@cesnet.cz \
    --cc=bgolaszewski@baylibre.com \
    --cc=jkridner@gmail.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=phil@raspberrypi.org \
    --cc=preid@electromag.com.au \
    --cc=sre@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).