summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Stanley <joel@jms.id.au>2020-07-28 04:55:27 +0200
committerJoel Stanley <joel@jms.id.au>2020-09-10 04:56:43 +0200
commit4a851d714eadeabd65c7e321a2e7830f77d945c4 (patch)
treec8c917f9c05ec83efd97474e0bb2b4307e6f5bab
parentfsi: aspeed: Add module param for bus divisor (diff)
downloadlinux-4a851d714eadeabd65c7e321a2e7830f77d945c4.tar.xz
linux-4a851d714eadeabd65c7e321a2e7830f77d945c4.zip
fsi: aspeed: Support CFAM reset GPIO
Systems have a line for restting the remote CFAM. This is not part of the FSI master, but is associated with it, so it makes sense to include it in the master driver. This exposes a sysfs interface to reset the cfam, abstracting away the direction and polarity of the GPIO, as well as the timing of the reset pulse. Userspace will be blocked until the reset pulse is finished. The reset is hard coded to be in the range of (900, 1000) us. It was observed with a scope to regularly be just over 1ms. If the device tree property is not preset the driver will silently continue. Reviewed-by: Andrew Jeffery <andrew@aj.id.au> Link: https://lore.kernel.org/r/20200728025527.174503-6-joel@jms.id.au Signed-off-by: Joel Stanley <joel@jms.id.au>
-rw-r--r--Documentation/ABI/testing/sysfs-bus-fsi8
-rw-r--r--drivers/fsi/fsi-master-aspeed.c43
2 files changed, 51 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-fsi b/Documentation/ABI/testing/sysfs-bus-fsi
index 320697bdf41d..d148214181a1 100644
--- a/Documentation/ABI/testing/sysfs-bus-fsi
+++ b/Documentation/ABI/testing/sysfs-bus-fsi
@@ -36,3 +36,11 @@ Contact: linux-fsi@lists.ozlabs.org
Description:
Provides a means of reading/writing a 32 bit value from/to a
specified FSI bus address.
+
+What: /sys/bus/platform/devices/../cfam_reset
+Date: Sept 2020
+KernelVersion: 5.10
+Contact: linux-fsi@lists.ozlabs.org
+Description:
+ Provides a means of resetting the cfam that is attached to the
+ FSI device.
diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
index 2531e826ba8b..c006ec008a1a 100644
--- a/drivers/fsi/fsi-master-aspeed.c
+++ b/drivers/fsi/fsi-master-aspeed.c
@@ -22,6 +22,7 @@ struct fsi_master_aspeed {
struct device *dev;
void __iomem *base;
struct clk *clk;
+ struct gpio_desc *cfam_reset_gpio;
};
#define to_fsi_master_aspeed(m) \
@@ -425,6 +426,43 @@ static int aspeed_master_init(struct fsi_master_aspeed *aspeed)
return 0;
}
+static ssize_t cfam_reset_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fsi_master_aspeed *aspeed = dev_get_drvdata(dev);
+
+ gpiod_set_value(aspeed->cfam_reset_gpio, 1);
+ usleep_range(900, 1000);
+ gpiod_set_value(aspeed->cfam_reset_gpio, 0);
+
+ return count;
+}
+
+static DEVICE_ATTR(cfam_reset, 0200, NULL, cfam_reset_store);
+
+static int setup_cfam_reset(struct fsi_master_aspeed *aspeed)
+{
+ struct device *dev = aspeed->dev;
+ struct gpio_desc *gpio;
+ int rc;
+
+ gpio = devm_gpiod_get_optional(dev, "cfam-reset", GPIOD_OUT_LOW);
+ if (IS_ERR(gpio))
+ return PTR_ERR(gpio);
+ if (!gpio)
+ return 0;
+
+ aspeed->cfam_reset_gpio = gpio;
+
+ rc = device_create_file(dev, &dev_attr_cfam_reset);
+ if (rc) {
+ devm_gpiod_put(dev, gpio);
+ return rc;
+ }
+
+ return 0;
+}
+
static int tacoma_cabled_fsi_fixup(struct device *dev)
{
struct gpio_desc *routing_gpio, *mux_gpio;
@@ -507,6 +545,11 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
return rc;
}
+ rc = setup_cfam_reset(aspeed);
+ if (rc) {
+ dev_err(&pdev->dev, "CFAM reset GPIO setup failed\n");
+ }
+
writel(0x1, aspeed->base + OPB_CLK_SYNC);
writel(OPB1_XFER_ACK_EN | OPB0_XFER_ACK_EN,
aspeed->base + OPB_IRQ_MASK);