u8 mode;
#define SPI_CPHA 0x01 /* clock phase */
#define SPI_CPOL 0x02 /* clock polarity */
-#define SPI_MODE_0 (0|0)
-#define SPI_MODE_1 (0|SPI_CPHA) /* (original MicroWire) */
+#define SPI_MODE_0 (0|0) /* (original MicroWire) */
+#define SPI_MODE_1 (0|SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
#define SPI_CS_HIGH 0x04 /* chipselect active high? */
void (*cleanup)(const struct spi_device *spi);
};
+static inline void *spi_master_get_devdata(struct spi_master *master)
+{
+ return class_get_devdata(&master->cdev);
+}
+
+static inline void spi_master_set_devdata(struct spi_master *master, void *data)
+{
+ class_set_devdata(&master->cdev, data);
+}
+
+static inline struct spi_master *spi_master_get(struct spi_master *master)
+{
+ if (!master || !class_device_get(&master->cdev))
+ return NULL;
+ return master;
+}
+
+static inline void spi_master_put(struct spi_master *master)
+{
+ if (master)
+ class_device_put(&master->cdev);
+}
+
+
/* the spi driver core manages memory for the spi_master classdev */
extern struct spi_master *
spi_alloc_master(struct device *host, unsigned size);
/**
* struct spi_transfer - a read/write buffer pair
- * @tx_buf: data to be written (dma-safe address), or NULL
- * @rx_buf: data to be read (dma-safe address), or NULL
- * @tx_dma: DMA address of buffer, if spi_message.is_dma_mapped
- * @rx_dma: DMA address of buffer, if spi_message.is_dma_mapped
+ * @tx_buf: data to be written (dma-safe memory), or NULL
+ * @rx_buf: data to be read (dma-safe memory), or NULL
+ * @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped
+ * @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped
* @len: size of rx and tx buffers (in bytes)
* @cs_change: affects chipselect after this transfer completes
* @delay_usecs: microseconds to delay after this transfer before
* (optionally) changing the chipselect status, then starting
* the next transfer or completing this spi_message.
+ * @transfer_list: transfers are sequenced through spi_message.transfers
*
* SPI transfers always write the same number of bytes as they read.
* Protocol drivers should always provide rx_buf and/or tx_buf.
* the data being transferred; that may reduce overhead, when the
* underlying driver uses dma.
*
- * All SPI transfers start with the relevant chipselect active. Drivers
- * can change behavior of the chipselect after the transfer finishes
- * (including any mandatory delay). The normal behavior is to leave it
- * selected, except for the last transfer in a message. Setting cs_change
- * allows two additional behavior options:
+ * If the transmit buffer is null, undefined data will be shifted out
+ * while filling rx_buf. If the receive buffer is null, the data
+ * shifted in will be discarded. Only "len" bytes shift out (or in).
+ * It's an error to try to shift out a partial word. (For example, by
+ * shifting out three bytes with word size of sixteen or twenty bits;
+ * the former uses two bytes per word, the latter uses four bytes.)
+ *
+ * All SPI transfers start with the relevant chipselect active. Normally
+ * it stays selected until after the last transfer in a message. Drivers
+ * can affect the chipselect signal using cs_change:
*
* (i) If the transfer isn't the last one in the message, this flag is
* used to make the chipselect briefly go inactive in the middle of the
* stay selected until the next transfer. This is purely a performance
* hint; the controller driver may need to select a different device
* for the next message.
+ *
+ * The code that submits an spi_message (and its spi_transfers)
+ * to the lower layers is responsible for managing its memory.
+ * Zero-initialize every field you don't set up explicitly, to
+ * insulate against future API updates. After you submit a message
+ * and its transfers, ignore them until its completion callback.
*/
struct spi_transfer {
/* it's ok if tx_buf == rx_buf (right?)
* for MicroWire, one buffer must be null
- * buffers must work with dma_*map_single() calls
+ * buffers must work with dma_*map_single() calls, unless
+ * spi_message.is_dma_mapped reports a pre-existing mapping
*/
const void *tx_buf;
void *rx_buf;
unsigned cs_change:1;
u16 delay_usecs;
+
+ struct list_head transfer_list;
};
/**
* struct spi_message - one multi-segment SPI transaction
- * @transfers: the segements of the transaction
- * @n_transfer: how many segments
+ * @transfers: list of transfer segments in this transaction
* @spi: SPI device to which the transaction is queued
* @is_dma_mapped: if true, the caller provided both dma and cpu virtual
* addresses for each transfer buffer
* @status: zero for success, else negative errno
* @queue: for use by whichever driver currently owns the message
* @state: for use by whichever driver currently owns the message
+ *
+ * An spi_message is used to execute an atomic sequence of data transfers,
+ * each represented by a struct spi_transfer. The sequence is "atomic"
+ * in the sense that no other spi_message may use that SPI bus until that
+ * sequence completes. On some systems, many such sequences can execute as
+ * as single programmed DMA transfer. On all systems, these messages are
+ * queued, and might complete after transactions to other devices. Messages
+ * sent to a given spi_device are alway executed in FIFO order.
+ *
+ * The code that submits an spi_message (and its spi_transfers)
+ * to the lower layers is responsible for managing its memory.
+ * Zero-initialize every field you don't set up explicitly, to
+ * insulate against future API updates. After you submit a message
+ * and its transfers, ignore them until its completion callback.
*/
struct spi_message {
- struct spi_transfer *transfers;
- unsigned n_transfer;
+ struct list_head transfers;
struct spi_device *spi;
*/
/* completion is reported through a callback */
- void FASTCALL((*complete)(void *context));
+ void (*complete)(void *context);
void *context;
unsigned actual_length;
int status;
void *state;
};
+static inline void spi_message_init(struct spi_message *m)
+{
+ memset(m, 0, sizeof *m);
+ INIT_LIST_HEAD(&m->transfers);
+}
+
+static inline void
+spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
+{
+ list_add_tail(&t->transfer_list, &m->transfers);
+}
+
+static inline void
+spi_transfer_del(struct spi_transfer *t)
+{
+ list_del(&t->transfer_list);
+}
+
+/* It's fine to embed message and transaction structures in other data
+ * structures so long as you don't free them while they're in use.
+ */
+
+static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags)
+{
+ struct spi_message *m;
+
+ m = kzalloc(sizeof(struct spi_message)
+ + ntrans * sizeof(struct spi_transfer),
+ flags);
+ if (m) {
+ int i;
+ struct spi_transfer *t = (struct spi_transfer *)(m + 1);
+
+ INIT_LIST_HEAD(&m->transfers);
+ for (i = 0; i < ntrans; i++, t++)
+ spi_message_add_tail(t, m);
+ }
+ return m;
+}
+
+static inline void spi_message_free(struct spi_message *m)
+{
+ kfree(m);
+}
+
/**
* spi_setup -- setup SPI mode and clock rate
* @spi: the device whose settings are being modified
* device doesn't work with the mode 0 default. They may likewise need
* to update clock rates or word sizes from initial values. This function
* changes those settings, and must be called from a context that can sleep.
+ * The changes take effect the next time the device is selected and data
+ * is transferred to or from it.
*/
static inline int
spi_setup(struct spi_device *spi)
* The completion callback is invoked in a context which can't sleep.
* Before that invocation, the value of message->status is undefined.
* When the callback is issued, message->status holds either zero (to
- * indicate complete success) or a negative error code.
+ * indicate complete success) or a negative error code. After that
+ * callback returns, the driver which issued the transfer request may
+ * deallocate the associated memory; it's no longer in use by any SPI
+ * core or controller driver code.
*
* Note that although all messages to a spi_device are handled in
* FIFO order, messages may go to different devices in other orders.
{
struct spi_transfer t = {
.tx_buf = buf,
- .rx_buf = NULL,
.len = len,
- .cs_change = 0,
- };
- struct spi_message m = {
- .transfers = &t,
- .n_transfer = 1,
};
+ struct spi_message m;
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
return spi_sync(spi, &m);
}
spi_read(struct spi_device *spi, u8 *buf, size_t len)
{
struct spi_transfer t = {
- .tx_buf = NULL,
.rx_buf = buf,
.len = len,
- .cs_change = 0,
- };
- struct spi_message m = {
- .transfers = &t,
- .n_transfer = 1,
};
+ struct spi_message m;
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
return spi_sync(spi, &m);
}
+/* this copies txbuf and rxbuf data; for small transfers only! */
extern int spi_write_then_read(struct spi_device *spi,
const u8 *txbuf, unsigned n_tx,
u8 *rxbuf, unsigned n_rx);
/* If you're hotplugging an adapter with devices (parport, usb, etc)
- * use spi_new_device() to describe each device. You would then call
- * spi_unregister_device() to start making that device vanish.
+ * use spi_new_device() to describe each device. You can also call
+ * spi_unregister_device() to start making that device vanish, but
+ * normally that would be handled by spi_unregister_master().
*/
extern struct spi_device *
spi_new_device(struct spi_master *, struct spi_board_info *);