2017-11-14 14:44:36

by Jon Hunter

[permalink] [raw]
Subject: [PATCH V2 1/2] mfd: cros ec: spi: Don't send first message too soon

On the Tegra124 Nyan-Big chromebook the very first SPI message sent to
the EC is failing.

The Tegra SPI driver configures the SPI chip-selects to be active-high
by default (and always has for many years). The EC SPI requires an
active-low chip-select and so the Tegra chip-select is reconfigured to
be active-low when the EC SPI driver calls spi_setup(). The problem is
that if the first SPI message to the EC is sent too soon after
reconfiguring the SPI chip-select, it fails.

The EC SPI driver prevents back-to-back SPI messages being sent too
soon by keeping track of the time the last transfer was sent via the
variable 'last_transfer_ns'. To prevent the very first transfer being
sent too soon, initialise the 'last_transfer_ns' variable after calling
spi_setup() and before sending the first SPI message.

Cc: <[email protected]>

Signed-off-by: Jon Hunter <[email protected]>
Reviewed-by: Brian Norris <[email protected]>
---
Changes since V1:
- Added stable-tag and Brian's reviewed-by.

Looks like this issue has been around for several Linux releases now
and it just depends on timing if this issue is seen or not and so there
is no specific commit this fixes. However, would be good to include for
v4.15.

drivers/mfd/cros_ec_spi.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index c9714072e224..a14196e95e9b 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -667,6 +667,7 @@ static int cros_ec_spi_probe(struct spi_device *spi)
sizeof(struct ec_response_get_protocol_info);
ec_dev->dout_size = sizeof(struct ec_host_request);

+ ec_spi->last_transfer_ns = ktime_get_ns();

err = cros_ec_register(ec_dev);
if (err) {
--
2.7.4


From 1585231705083927708@xxx Mon Nov 27 14:59:22 +0000 2017
X-GM-THRID: 1584781837431730783
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread


2017-11-14 15:53:51

by Jon Hunter

[permalink] [raw]
Subject: [PATCH V2 2/2] mfd: cros ec: spi: Simplify delay handling between SPI messages

The EC SPI driver prevents SPI transfers being to rapidly by keeping
track of the time the last transfer was issued via the
'last_transfer_ns' variable. Previously, if the 'last_transfer_ns'
variable was zero, this indicated that no previous transfer had been
sent and that no delay was needed. However, the EC SPI driver has
been updated to always initialise the 'last_transfer_ns' variable
during probe and therefore, it is no longer necessary to test if it
is zero. Remove the code that checks if this variable is zero.

Signed-off-by: Jon Hunter <[email protected]>
Reviewed-by: Brian Norris <[email protected]>
---
Changes since V1:
- Added Brian's reviewed-by.

drivers/mfd/cros_ec_spi.c | 25 +++++++++----------------
1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index a14196e95e9b..7849d781c6bb 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -72,8 +72,7 @@
* struct cros_ec_spi - information about a SPI-connected EC
*
* @spi: SPI device we are connected to
- * @last_transfer_ns: time that we last finished a transfer, or 0 if there
- * if no record
+ * @last_transfer_ns: time that we last finished a transfer.
* @start_of_msg_delay: used to set the delay_usecs on the spi_transfer that
* is sent when we want to turn on CS at the start of a transaction.
* @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
@@ -378,18 +377,15 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev,
u8 *rx_buf;
u8 sum;
int ret = 0, final_ret;
+ unsigned long delay;

len = cros_ec_prepare_tx(ec_dev, ec_msg);
dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);

/* If it's too soon to do another transaction, wait */
- if (ec_spi->last_transfer_ns) {
- unsigned long delay; /* The delay completed so far */
-
- delay = ktime_get_ns() - ec_spi->last_transfer_ns;
- if (delay < EC_SPI_RECOVERY_TIME_NS)
- ndelay(EC_SPI_RECOVERY_TIME_NS - delay);
- }
+ delay = ktime_get_ns() - ec_spi->last_transfer_ns;
+ if (delay < EC_SPI_RECOVERY_TIME_NS)
+ ndelay(EC_SPI_RECOVERY_TIME_NS - delay);

rx_buf = kzalloc(len, GFP_KERNEL);
if (!rx_buf)
@@ -510,18 +506,15 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
u8 *rx_buf;
int sum;
int ret = 0, final_ret;
+ unsigned long delay;

len = cros_ec_prepare_tx(ec_dev, ec_msg);
dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);

/* If it's too soon to do another transaction, wait */
- if (ec_spi->last_transfer_ns) {
- unsigned long delay; /* The delay completed so far */
-
- delay = ktime_get_ns() - ec_spi->last_transfer_ns;
- if (delay < EC_SPI_RECOVERY_TIME_NS)
- ndelay(EC_SPI_RECOVERY_TIME_NS - delay);
- }
+ delay = ktime_get_ns() - ec_spi->last_transfer_ns;
+ if (delay < EC_SPI_RECOVERY_TIME_NS)
+ ndelay(EC_SPI_RECOVERY_TIME_NS - delay);

rx_buf = kzalloc(len, GFP_KERNEL);
if (!rx_buf)
--
2.7.4


From 1583611795653589674@xxx Thu Nov 09 17:51:36 +0000 2017
X-GM-THRID: 1583611795653589674
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread