[PATCH linux dev-5.4 2/2] fsi: aspeed: Support cabled FSI

Joel Stanley joel at jms.id.au
Tue Mar 24 22:25:29 AEDT 2020


Some FSI development systems have internally routed 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 jumper is freed to allow other software to inspect it's
state.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/fsi/fsi-master-aspeed.c | 45 +++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
index f49742b310c2..3436805d590a 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"
 
@@ -419,6 +420,44 @@ 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 routed FSI cable.
+	 */
+	routing_gpio = devm_gpiod_get_optional(dev, "fsi-routing", GPIOD_IN);
+	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_IN);
+	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 0;
+
+	/* If the routing GPIO is low we should set the mux to low. */
+	if (gpio == 0) {
+		gpiod_set_value(mux_gpio, 0);
+		dev_info(dev, "FSI configured for external cable\n");
+	}
+
+	/* Free the cabled mux GPIO for other users to sample */
+	devm_gpiod_put(dev, routing_gpio);
+
+	return 0;
+}
+
+
 static int fsi_master_aspeed_probe(struct platform_device *pdev)
 {
 	struct fsi_master_aspeed *aspeed;
@@ -426,6 +465,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;
-- 
2.25.1



More information about the openbmc mailing list