Skip to content

Commit

Permalink
fsi: aspeed: Support cabled FSI
Browse files Browse the repository at this point in the history
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.

Reviewed-by: Andrew Jeffery <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Joel Stanley <[email protected]>
  • Loading branch information
shenki committed Sep 10, 2020
1 parent 4d4905f commit f369a29
Showing 1 changed file with 46 additions and 0 deletions.
46 changes: 46 additions & 0 deletions drivers/fsi/fsi-master-aspeed.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -417,13 +418,58 @@ 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;
struct resource *res;
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;
Expand Down

0 comments on commit f369a29

Please sign in to comment.