aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-10-05 06:50:40 -0400
committerMark Brown <broonie@linaro.org>2013-10-11 15:09:50 -0400
commitb158935f70b9c156903338053216dd0adf7ce31c (patch)
tree8fc35f89210cf56eb647c64f92a814c2ede84505
parent6bb9c0e34185717f5b0df4ad468476f64f0d73fb (diff)
spi: Provide common spi_message processing loop
The loops which SPI controller drivers use to process the list of transfers in a spi_message are typically very similar and have some error prone areas such as the handling of /CS. Help simplify drivers by factoring this code out into the core - if drivers provide a transfer_one() function instead of a transfer_one_message() function the core will handle processing at the message level. /CS can be controlled by either setting cs_gpio or providing a set_cs function. If this is not possible for hardware reasons then both can be omitted and the driver should continue to implement manual /CS handling. This is a first step in refactoring and it is expected that there will be further enhancements, for example factoring out of the mapping of transfers for DMA and the initiation and completion of interrupt driven transfers. Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--drivers/spi/spi.c92
-rw-r--r--include/linux/spi/spi.h21
-rw-r--r--include/trace/events/spi.h42
3 files changed, 153 insertions, 2 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 8a30c6b66a64..85c18d8a86b3 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -526,6 +526,95 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n)
526 526
527/*-------------------------------------------------------------------------*/ 527/*-------------------------------------------------------------------------*/
528 528
529static void spi_set_cs(struct spi_device *spi, bool enable)
530{
531 if (spi->mode & SPI_CS_HIGH)
532 enable = !enable;
533
534 if (spi->cs_gpio >= 0)
535 gpio_set_value(spi->cs_gpio, !enable);
536 else if (spi->master->set_cs)
537 spi->master->set_cs(spi, !enable);
538}
539
540/*
541 * spi_transfer_one_message - Default implementation of transfer_one_message()
542 *
543 * This is a standard implementation of transfer_one_message() for
544 * drivers which impelment a transfer_one() operation. It provides
545 * standard handling of delays and chip select management.
546 */
547static int spi_transfer_one_message(struct spi_master *master,
548 struct spi_message *msg)
549{
550 struct spi_transfer *xfer;
551 bool cur_cs = true;
552 bool keep_cs = false;
553 int ret = 0;
554
555 spi_set_cs(msg->spi, true);
556
557 list_for_each_entry(xfer, &msg->transfers, transfer_list) {
558 trace_spi_transfer_start(msg, xfer);
559
560 INIT_COMPLETION(master->xfer_completion);
561
562 ret = master->transfer_one(master, msg->spi, xfer);
563 if (ret < 0) {
564 dev_err(&msg->spi->dev,
565 "SPI transfer failed: %d\n", ret);
566 goto out;
567 }
568
569 if (ret > 0)
570 wait_for_completion(&master->xfer_completion);
571
572 trace_spi_transfer_stop(msg, xfer);
573
574 if (msg->status != -EINPROGRESS)
575 goto out;
576
577 if (xfer->delay_usecs)
578 udelay(xfer->delay_usecs);
579
580 if (xfer->cs_change) {
581 if (list_is_last(&xfer->transfer_list,
582 &msg->transfers)) {
583 keep_cs = true;
584 } else {
585 cur_cs = !cur_cs;
586 spi_set_cs(msg->spi, cur_cs);
587 }
588 }
589
590 msg->actual_length += xfer->len;
591 }
592
593out:
594 if (ret != 0 || !keep_cs)
595 spi_set_cs(msg->spi, false);
596
597 if (msg->status == -EINPROGRESS)
598 msg->status = ret;
599
600 spi_finalize_current_message(master);
601
602 return ret;
603}
604
605/**
606 * spi_finalize_current_transfer - report completion of a transfer
607 *
608 * Called by SPI drivers using the core transfer_one_message()
609 * implementation to notify it that the current interrupt driven
610 * transfer has finised and the next one may be scheduled.
611 */
612void spi_finalize_current_transfer(struct spi_master *master)
613{
614 complete(&master->xfer_completion);
615}
616EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
617
529/** 618/**
530 * spi_pump_messages - kthread work function which processes spi message queue 619 * spi_pump_messages - kthread work function which processes spi message queue
531 * @work: pointer to kthread work struct contained in the master struct 620 * @work: pointer to kthread work struct contained in the master struct
@@ -836,6 +925,8 @@ static int spi_master_initialize_queue(struct spi_master *master)
836 925
837 master->queued = true; 926 master->queued = true;
838 master->transfer = spi_queued_transfer; 927 master->transfer = spi_queued_transfer;
928 if (!master->transfer_one_message)
929 master->transfer_one_message = spi_transfer_one_message;
839 930
840 /* Initialize and start queue */ 931 /* Initialize and start queue */
841 ret = spi_init_queue(master); 932 ret = spi_init_queue(master);
@@ -1242,6 +1333,7 @@ int spi_register_master(struct spi_master *master)
1242 spin_lock_init(&master->bus_lock_spinlock); 1333 spin_lock_init(&master->bus_lock_spinlock);
1243 mutex_init(&master->bus_lock_mutex); 1334 mutex_init(&master->bus_lock_mutex);
1244 master->bus_lock_flag = 0; 1335 master->bus_lock_flag = 0;
1336 init_completion(&master->xfer_completion);
1245 1337
1246 /* register the device, then userspace will see it. 1338 /* register the device, then userspace will see it.
1247 * registration fails if the bus ID is in use. 1339 * registration fails if the bus ID is in use.
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 000b50bee6c0..da371ab5ebeb 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -23,6 +23,7 @@
23#include <linux/mod_devicetable.h> 23#include <linux/mod_devicetable.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/kthread.h> 25#include <linux/kthread.h>
26#include <linux/completion.h>
26 27
27/* 28/*
28 * INTERFACES between SPI master-side drivers and SPI infrastructure. 29 * INTERFACES between SPI master-side drivers and SPI infrastructure.
@@ -150,8 +151,7 @@ static inline void *spi_get_drvdata(struct spi_device *spi)
150} 151}
151 152
152struct spi_message; 153struct spi_message;
153 154struct spi_transfer;
154
155 155
156/** 156/**
157 * struct spi_driver - Host side "protocol" driver 157 * struct spi_driver - Host side "protocol" driver
@@ -259,6 +259,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
259 * @cur_msg: the currently in-flight message 259 * @cur_msg: the currently in-flight message
260 * @cur_msg_prepared: spi_prepare_message was called for the currently 260 * @cur_msg_prepared: spi_prepare_message was called for the currently
261 * in-flight message 261 * in-flight message
262 * @xfer_completion: used by core tranfer_one_message()
262 * @busy: message pump is busy 263 * @busy: message pump is busy
263 * @running: message pump is running 264 * @running: message pump is running
264 * @rt: whether this queue is set to run as a realtime task 265 * @rt: whether this queue is set to run as a realtime task
@@ -276,9 +277,15 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
276 * @unprepare_transfer_hardware: there are currently no more messages on the 277 * @unprepare_transfer_hardware: there are currently no more messages on the
277 * queue so the subsystem notifies the driver that it may relax the 278 * queue so the subsystem notifies the driver that it may relax the
278 * hardware by issuing this call 279 * hardware by issuing this call
280 * @set_cs: assert or deassert chip select, true to assert. May be called
281 * from interrupt context.
279 * @prepare_message: set up the controller to transfer a single message, 282 * @prepare_message: set up the controller to transfer a single message,
280 * for example doing DMA mapping. Called from threaded 283 * for example doing DMA mapping. Called from threaded
281 * context. 284 * context.
285 * @transfer_one: transfer a single spi_transfer. When the
286 * driver is finished with this transfer it must call
287 * spi_finalize_current_transfer() so the subsystem can issue
288 * the next transfer
282 * @unprepare_message: undo any work done by prepare_message(). 289 * @unprepare_message: undo any work done by prepare_message().
283 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS 290 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
284 * number. Any individual value may be -ENOENT for CS lines that 291 * number. Any individual value may be -ENOENT for CS lines that
@@ -395,6 +402,7 @@ struct spi_master {
395 bool rt; 402 bool rt;
396 bool auto_runtime_pm; 403 bool auto_runtime_pm;
397 bool cur_msg_prepared; 404 bool cur_msg_prepared;
405 struct completion xfer_completion;
398 406
399 int (*prepare_transfer_hardware)(struct spi_master *master); 407 int (*prepare_transfer_hardware)(struct spi_master *master);
400 int (*transfer_one_message)(struct spi_master *master, 408 int (*transfer_one_message)(struct spi_master *master,
@@ -405,6 +413,14 @@ struct spi_master {
405 int (*unprepare_message)(struct spi_master *master, 413 int (*unprepare_message)(struct spi_master *master,
406 struct spi_message *message); 414 struct spi_message *message);
407 415
416 /*
417 * These hooks are for drivers that use a generic implementation
418 * of transfer_one_message() provied by the core.
419 */
420 void (*set_cs)(struct spi_device *spi, bool enable);
421 int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
422 struct spi_transfer *transfer);
423
408 /* gpio chip select */ 424 /* gpio chip select */
409 int *cs_gpios; 425 int *cs_gpios;
410}; 426};
@@ -439,6 +455,7 @@ extern int spi_master_resume(struct spi_master *master);
439/* Calls the driver make to interact with the message queue */ 455/* Calls the driver make to interact with the message queue */
440extern struct spi_message *spi_get_next_queued_message(struct spi_master *master); 456extern struct spi_message *spi_get_next_queued_message(struct spi_master *master);
441extern void spi_finalize_current_message(struct spi_master *master); 457extern void spi_finalize_current_message(struct spi_master *master);
458extern void spi_finalize_current_transfer(struct spi_master *master);
442 459
443/* the spi driver core manages memory for the spi_master classdev */ 460/* the spi driver core manages memory for the spi_master classdev */
444extern struct spi_master * 461extern struct spi_master *
diff --git a/include/trace/events/spi.h b/include/trace/events/spi.h
index 5e77e21f885a..7e02c983bbe2 100644
--- a/include/trace/events/spi.h
+++ b/include/trace/events/spi.h
@@ -108,6 +108,48 @@ TRACE_EVENT(spi_message_done,
108 (unsigned)__entry->actual, (unsigned)__entry->frame) 108 (unsigned)__entry->actual, (unsigned)__entry->frame)
109); 109);
110 110
111DECLARE_EVENT_CLASS(spi_transfer,
112
113 TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer),
114
115 TP_ARGS(msg, xfer),
116
117 TP_STRUCT__entry(
118 __field( int, bus_num )
119 __field( int, chip_select )
120 __field( struct spi_transfer *, xfer )
121 __field( int, len )
122 ),
123
124 TP_fast_assign(
125 __entry->bus_num = msg->spi->master->bus_num;
126 __entry->chip_select = msg->spi->chip_select;
127 __entry->xfer = xfer;
128 __entry->len = xfer->len;
129 ),
130
131 TP_printk("spi%d.%d %p len=%d", (int)__entry->bus_num,
132 (int)__entry->chip_select,
133 (struct spi_message *)__entry->xfer,
134 (int)__entry->len)
135);
136
137DEFINE_EVENT(spi_transfer, spi_transfer_start,
138
139 TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer),
140
141 TP_ARGS(msg, xfer)
142
143);
144
145DEFINE_EVENT(spi_transfer, spi_transfer_stop,
146
147 TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer),
148
149 TP_ARGS(msg, xfer)
150
151);
152
111#endif /* _TRACE_POWER_H */ 153#endif /* _TRACE_POWER_H */
112 154
113/* This part must be outside protection */ 155/* This part must be outside protection */