[PATCH linux dev-4.7] drivers/fsi: Clock slave prior to master command

Christopher Bostic cbostic at linux.vnet.ibm.com
Sat Feb 4 06:38:00 AEDT 2017


If the FSI bus has been idle for some period it is necessary to
wake up the slave so its ready for a new master initiated
commands. This is done by clocking out a series of 0's on the
SDA line immediately before any command.

Signed-off-by: Christopher Bostic <cbostic at linux.vnet.ibm.com>
---
 drivers/fsi/fsi-master-gpio.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
index 73d9985..49598c33 100644
--- a/drivers/fsi/fsi-master-gpio.c
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -59,6 +59,7 @@
 #define	FSI_GPIO_MSG_ID_SIZE		2
 #define	FSI_GPIO_MSG_RESPID_SIZE	2
 #define	FSI_GPIO_PRIME_SLAVE_CLOCKS	100
+#define	FSI_GPIO_WAKE_CLOCKS		32	/* >= 32 ok, 16 fails */
 
 static DEFINE_SPINLOCK(fsi_gpio_cmd_lock);	/* lock around fsi commands */
 
@@ -178,6 +179,16 @@ static void echo_delay(struct fsi_master_gpio *master)
 }
 
 /*
+ * Wake up the slave by clocking it a number of times prior to sending the next
+ * master command.  Needed when the bus has been idle for a while.
+ */
+static void wake_slave(struct fsi_master_gpio *master)
+{
+	set_sda_output(master, 1);
+	clock_toggle(master, FSI_GPIO_WAKE_CLOCKS);
+}
+
+/*
  * Used in bus error cases only.  Clears out any remaining data the slave
  * is attempting to send
  */
@@ -364,6 +375,7 @@ static int fsi_master_gpio_read(struct fsi_master *_master, int link,
 	build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
 
 	spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
+	wake_slave(master);
 	serial_out(master, &cmd);
 	echo_delay(master);
 	rc = poll_for_response(master, FSI_GPIO_RESP_ACKD, size, val);
@@ -386,6 +398,7 @@ static int fsi_master_gpio_write(struct fsi_master *_master, int link,
 	build_abs_ar_command(&cmd, FSI_GPIO_CMD_WRITE, slave, addr, size, val);
 
 	spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
+	wake_slave(master);
 	serial_out(master, &cmd);
 	echo_delay(master);
 	rc = poll_for_response(master, FSI_GPIO_RESP_ACK, size, NULL);
-- 
1.8.2.2



More information about the openbmc mailing list