aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorRhyland Klein <rklein@nvidia.com>2013-12-09 06:36:09 -0500
committerLee Jones <lee.jones@linaro.org>2014-01-21 03:28:06 -0500
commit01e73c89cf03c020e586dc9e30d52a6e098853f6 (patch)
treedaef78c50110f4fed3218742bf8c6560e3645639 /drivers/mfd
parentdaf93d2287ff8eb4a2f28224275fb02d623df2ab (diff)
mfd: cros ec: spi: Add delay for raising CS
The EC has specific timing it requires. Add support for an optional delay after raising CS to fix timing issues. This is configurable based on a DT property "google,cros-ec-spi-msg-delay". If this property isn't set, then no delay will be added. However, if set it will cause a delay equal to the value passed to it to be inserted at the end of a transaction. Signed-off-by: Rhyland Klein <rklein@nvidia.com> Reviewed-by: Bernie Thompson <bhthompson@chromium.org> Reviewed-by: Andrew Bresticker <abrestic@chromium.org> Acked-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/cros_ec_spi.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 005403643539..84af8d7a4295 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -18,6 +18,7 @@
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/mfd/cros_ec.h> 19#include <linux/mfd/cros_ec.h>
20#include <linux/mfd/cros_ec_commands.h> 20#include <linux/mfd/cros_ec_commands.h>
21#include <linux/of.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/slab.h> 23#include <linux/slab.h>
23#include <linux/spi/spi.h> 24#include <linux/spi/spi.h>
@@ -62,10 +63,13 @@
62 * @spi: SPI device we are connected to 63 * @spi: SPI device we are connected to
63 * @last_transfer_ns: time that we last finished a transfer, or 0 if there 64 * @last_transfer_ns: time that we last finished a transfer, or 0 if there
64 * if no record 65 * if no record
66 * @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
67 * is sent when we want to turn off CS at the end of a transaction.
65 */ 68 */
66struct cros_ec_spi { 69struct cros_ec_spi {
67 struct spi_device *spi; 70 struct spi_device *spi;
68 s64 last_transfer_ns; 71 s64 last_transfer_ns;
72 unsigned int end_of_msg_delay;
69}; 73};
70 74
71static void debug_packet(struct device *dev, const char *name, u8 *ptr, 75static void debug_packet(struct device *dev, const char *name, u8 *ptr,
@@ -238,6 +242,17 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
238 242
239 /* turn off CS */ 243 /* turn off CS */
240 spi_message_init(&msg); 244 spi_message_init(&msg);
245
246 if (ec_spi->end_of_msg_delay) {
247 /*
248 * Add delay for last transaction, to ensure the rising edge
249 * doesn't come too soon after the end of the data.
250 */
251 memset(&trans, 0, sizeof(trans));
252 trans.delay_usecs = ec_spi->end_of_msg_delay;
253 spi_message_add_tail(&trans, &msg);
254 }
255
241 final_ret = spi_sync(ec_spi->spi, &msg); 256 final_ret = spi_sync(ec_spi->spi, &msg);
242 ktime_get_ts(&ts); 257 ktime_get_ts(&ts);
243 ec_spi->last_transfer_ns = timespec_to_ns(&ts); 258 ec_spi->last_transfer_ns = timespec_to_ns(&ts);
@@ -284,6 +299,17 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
284 return 0; 299 return 0;
285} 300}
286 301
302static void cros_ec_spi_dt_probe(struct cros_ec_spi *ec_spi, struct device *dev)
303{
304 struct device_node *np = dev->of_node;
305 u32 val;
306 int ret;
307
308 ret = of_property_read_u32(np, "google,cros-ec-spi-msg-delay", &val);
309 if (!ret)
310 ec_spi->end_of_msg_delay = val;
311}
312
287static int cros_ec_spi_probe(struct spi_device *spi) 313static int cros_ec_spi_probe(struct spi_device *spi)
288{ 314{
289 struct device *dev = &spi->dev; 315 struct device *dev = &spi->dev;
@@ -305,6 +331,9 @@ static int cros_ec_spi_probe(struct spi_device *spi)
305 if (!ec_dev) 331 if (!ec_dev)
306 return -ENOMEM; 332 return -ENOMEM;
307 333
334 /* Check for any DT properties */
335 cros_ec_spi_dt_probe(ec_spi, dev);
336
308 spi_set_drvdata(spi, ec_dev); 337 spi_set_drvdata(spi, ec_dev);
309 ec_dev->name = "SPI"; 338 ec_dev->name = "SPI";
310 ec_dev->dev = dev; 339 ec_dev->dev = dev;