Message ID | 20200728025527.174503-3-joel@jms.id.au |
---|---|
State | Accepted |
Commit | f369a29bdde9f14040e9f0cc4ac610cdb216e93c |
Headers | show |
Series | fsi: Support extra functions on ASPEED master | expand |
On Tue, 28 Jul 2020, at 12:25, Joel Stanley wrote: > Some FSI capable systems have internal FSI signals, and some have > external cabled FSI. Software can detect which machine this is by > reading a jumper GPIO, and also control which pins the signals are > routed to through a mux GPIO. > > This attempts to find the GPIOs at probe time. If they are not present > in the device tree the driver will not error and continue as before. > > The mux GPIO is owned by the FSI driver to ensure it is not modified at > runtime. The routing jumper obtained as non-exclusive to allow other > software to inspect it's state. > > Signed-off-by: Joel Stanley <joel@jms.id.au> > --- > drivers/fsi/fsi-master-aspeed.c | 46 +++++++++++++++++++++++++++++++++ > 1 file changed, 46 insertions(+) > > diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c > index 2b8ca72baeb5..c282de76e6e7 100644 > --- a/drivers/fsi/fsi-master-aspeed.c > +++ b/drivers/fsi/fsi-master-aspeed.c > @@ -13,6 +13,7 @@ > #include <linux/regmap.h> > #include <linux/slab.h> > #include <linux/iopoll.h> > +#include <linux/gpio/consumer.h> > > #include "fsi-master.h" > > @@ -417,6 +418,45 @@ static int aspeed_master_init(struct > fsi_master_aspeed *aspeed) > return 0; > } > > +static int tacoma_cabled_fsi_fixup(struct device *dev) > +{ > + struct gpio_desc *routing_gpio, *mux_gpio; > + int gpio; > + > + /* > + * The routing GPIO is a jumper indicating we should mux for the > + * externally connected FSI cable. > + */ > + routing_gpio = devm_gpiod_get_optional(dev, "fsi-routing", > + GPIOD_IN | GPIOD_FLAGS_BIT_NONEXCLUSIVE); > + if (IS_ERR(routing_gpio)) > + return PTR_ERR(routing_gpio); > + if (!routing_gpio) > + return 0; > + > + mux_gpio = devm_gpiod_get_optional(dev, "fsi-mux", GPIOD_ASIS); > + if (IS_ERR(mux_gpio)) > + return PTR_ERR(mux_gpio); > + if (!mux_gpio) > + return 0; > + > + gpio = gpiod_get_value(routing_gpio); > + if (gpio < 0) > + return gpio; > + > + /* If the routing GPIO is high we should set the mux to low. */ > + if (gpio) { > + gpiod_direction_output(mux_gpio, 0); > + dev_info(dev, "FSI configured for external cable\n"); > + } else { > + gpiod_direction_output(mux_gpio, 1); > + } I haven't checked this logic against the hardware but the rest of the patch looks okay. Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c index 2b8ca72baeb5..c282de76e6e7 100644 --- a/drivers/fsi/fsi-master-aspeed.c +++ b/drivers/fsi/fsi-master-aspeed.c @@ -13,6 +13,7 @@ #include <linux/regmap.h> #include <linux/slab.h> #include <linux/iopoll.h> +#include <linux/gpio/consumer.h> #include "fsi-master.h" @@ -417,6 +418,45 @@ static int aspeed_master_init(struct fsi_master_aspeed *aspeed) return 0; } +static int tacoma_cabled_fsi_fixup(struct device *dev) +{ + struct gpio_desc *routing_gpio, *mux_gpio; + int gpio; + + /* + * The routing GPIO is a jumper indicating we should mux for the + * externally connected FSI cable. + */ + routing_gpio = devm_gpiod_get_optional(dev, "fsi-routing", + GPIOD_IN | GPIOD_FLAGS_BIT_NONEXCLUSIVE); + if (IS_ERR(routing_gpio)) + return PTR_ERR(routing_gpio); + if (!routing_gpio) + return 0; + + mux_gpio = devm_gpiod_get_optional(dev, "fsi-mux", GPIOD_ASIS); + if (IS_ERR(mux_gpio)) + return PTR_ERR(mux_gpio); + if (!mux_gpio) + return 0; + + gpio = gpiod_get_value(routing_gpio); + if (gpio < 0) + return gpio; + + /* If the routing GPIO is high we should set the mux to low. */ + if (gpio) { + gpiod_direction_output(mux_gpio, 0); + dev_info(dev, "FSI configured for external cable\n"); + } else { + gpiod_direction_output(mux_gpio, 1); + } + + devm_gpiod_put(dev, routing_gpio); + + return 0; +} + static int fsi_master_aspeed_probe(struct platform_device *pdev) { struct fsi_master_aspeed *aspeed; @@ -424,6 +464,12 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev) int rc, links, reg; __be32 raw; + rc = tacoma_cabled_fsi_fixup(&pdev->dev); + if (rc) { + dev_err(&pdev->dev, "Tacoma FSI cable fixup failed\n"); + return rc; + } + aspeed = devm_kzalloc(&pdev->dev, sizeof(*aspeed), GFP_KERNEL); if (!aspeed) return -ENOMEM;
Some FSI capable systems have internal FSI signals, and some have external cabled FSI. Software can detect which machine this is by reading a jumper GPIO, and also control which pins the signals are routed to through a mux GPIO. This attempts to find the GPIOs at probe time. If they are not present in the device tree the driver will not error and continue as before. The mux GPIO is owned by the FSI driver to ensure it is not modified at runtime. The routing jumper obtained as non-exclusive to allow other software to inspect it's state. Signed-off-by: Joel Stanley <joel@jms.id.au> --- drivers/fsi/fsi-master-aspeed.c | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) -- 2.27.0