diff mbox series

[linux,dev-5.4,1/3] fsi: aspeed: Support CFAM reset GPIO

Message ID 20200724023036.354310-2-joel@jms.id.au
State New
Headers show
Series fsi: aspeed: CFAM reset support | expand

Commit Message

Joel Stanley July 24, 2020, 2:30 a.m. UTC
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.

Signed-off-by: Joel Stanley <joel@jms.id.au>
---
v2: Releasing the reset should set it to 0
---
 drivers/fsi/fsi-master-aspeed.c | 43 +++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

Comments

Andrew Jeffery July 24, 2020, 2:39 a.m. UTC | #1
On Fri, 24 Jul 2020, at 12:00, Joel Stanley wrote:
> 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.
> 
> Signed-off-by: Joel Stanley <joel@jms.id.au>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
diff mbox series

Patch

diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
index b44f71f1f0a8..ef21362095f8 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) \
@@ -429,6 +430,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;
@@ -511,6 +549,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);