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

Joel Stanley joel at jms.id.au
Thu Feb 9 16:55:08 AEDT 2017


On Sat, Feb 4, 2017 at 6:08 AM, Christopher Bostic
<cbostic at linux.vnet.ibm.com> wrote:
> 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>

In my testing I did not need this patch even after a long idle period.

This patch did help when I tried to read or write to an invalid FSI
address. I suspect we want to fix the root cause of those invalid
read/writes - perhaps by catching them before they turn into
transactions on the bus, or only doing the reset when the bus got into
a bad state.

Doing it on every read/write seems excessive and will slow down access
to the bus.

Cheers,

Joel

> ---
>  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