[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