和菜鸟一起学linux总线驱动之初识spi驱动数据传输流程
对于SPI的一些结构体都有所了解之后呢,那么再去瞧瞧SPI的那些长见的操作的函数了。
首先看一下本人画的比较挫的数据流了,仅供参考,如有不对,不吝赐教
接下来看看各个函数吧还是:
SPI write
/** * spi_write - SPI synchronous write * @spi: device to which data will be written * @buf: data buffer * @len: data buffer size * Context: can sleep * * This writes the buffer and returns zero or a negative error code. * Callable only from contexts that can sleep. */ static inline int spi_write(struct spi_device *spi, const void *buf, size_t len) { struct spi_transfer t = { .tx_buf = buf, .len = len, }; struct spi_message m; spi_message_init(&m); spi_message_add_tail(&t, &m); return spi_sync(spi, &m); }
SPI发送函数,数据放在buf中,然后把要发送的数据放在工作队列中
SPI read
/** * spi_read - SPI synchronous read * @spi: device from which data will be read * @buf: data buffer * @len: data buffer size * Context: can sleep * * This reads the buffer and returns zero or a negative error code. * Callable only from contexts that can sleep. */ static inline int spi_read(struct spi_device *spi, void *buf, size_t len) { struct spi_transfer t = { .rx_buf = buf, .len = len, }; struct spi_message m; spi_message_init(&m); spi_message_add_tail(&t, &m); return spi_sync(spi, &m); }
SPI接收函数,数据放在buf中,然后把要发送的数据放在工作队列中,发送出去
SPI write 8 bits read 8 bits
/* this copies txbuf and rxbuf data; for small transfers only! */ extern int spi_write_then_read(struct spi_device *spi, const void *txbuf, unsigned n_tx, void *rxbuf, unsigned n_rx); /** * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read * @spi: device with which data will be exchanged * @cmd: command to be written before data is read back * Context: can sleep * * This returns the (unsigned) eight bit number returned by the * device, or else a negative error code. Callable only from * contexts that can sleep. */ static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd) { ssize_t status; u8 result; status = spi_write_then_read(spi, &cmd, 1, &result, 1); /* return negative errno or unsigned value */ return (status < 0) ? status : result; }
SPI write 8 bit read 16 bits
/** * spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read * @spi: device with which data will be exchanged * @cmd: command to be written before data is read back * Context: can sleep * * This returns the (unsigned) sixteen bit number returned by the * device, or else a negative error code. Callable only from * contexts that can sleep. * * The number is returned in wire-order, which is at least sometimes * big-endian. */ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd) { ssize_t status; u16 result; status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2); /* return negative errno or unsigned value */ return (status < 0) ? status : result; }
int spi_write_then_read(struct spi_device *spi, const void *txbuf, unsigned n_tx, void *rxbuf, unsigned n_rx) { static DEFINE_MUTEX(lock); int status; struct spi_message message; struct spi_transfer x[2]; u8 *local_buf; /* Use preallocated DMA-safe buffer. We can't avoid copying here, * (as a pure convenience thing), but we can keep heap costs * out of the hot path ... */ if ((n_tx + n_rx) > SPI_BUFSIZ) return -EINVAL; spi_message_init(&message); memset(x, 0, sizeof x); if (n_tx) { x[0].len = n_tx; spi_message_add_tail(&x[0], &message); } if (n_rx) { x[1].len = n_rx; spi_message_add_tail(&x[1], &message); } /* ... unless someone else is using the pre-allocated buffer */ if (!mutex_trylock(&lock)) { local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); if (!local_buf) return -ENOMEM; } else local_buf = buf; memcpy(local_buf, txbuf, n_tx); x[0].tx_buf = local_buf; x[1].rx_buf = local_buf + n_tx; /* do the i/o */ status = spi_sync(spi, &message); if (status == 0) memcpy(rxbuf, x[1].rx_buf, n_rx); if (x[0].tx_buf == buf) mutex_unlock(&lock); else kfree(local_buf); return status; }
SPI sync
读写都会调用到spi_sync
int spi_sync(struct spi_device *spi, struct spi_message *message) { return __spi_sync(spi, message, 0); }
接着调用了__spi_sync
static int __spi_sync(struct spi_device *spi, struct spi_message *message, int bus_locked) { DECLARE_COMPLETION_ONSTACK(done); int status; struct spi_master *master = spi->master; message->complete = spi_complete; message->context = &done; if (!bus_locked) mutex_lock(&master->bus_lock_mutex); status = spi_async_locked(spi, message); if (!bus_locked) mutex_unlock(&master->bus_lock_mutex); if (status == 0) { wait_for_completion(&done); status = message->status; } message->context = NULL; return status; }
然后就是spi_async
int spi_async(struct spi_device *spi, struct spi_message *message) { struct spi_master *master = spi->master; int ret; unsigned long flags; spin_lock_irqsave(&master->bus_lock_spinlock, flags); if (master->bus_lock_flag) ret = -EBUSY; else ret = __spi_async(spi, message); spin_unlock_irqrestore(&master->bus_lock_spinlock, flags); return ret; }
最后调用__spi_async
static int __spi_async(struct spi_device *spi, struct spi_message *message) { struct spi_master *master = spi->master; /* Half-duplex links include original MicroWire, and ones with * only one data pin like SPI_3WIRE (switches direction) or where * either MOSI or MISO is missing. They can also be caused by * software limitations. */ if ((master->flags & SPI_MASTER_HALF_DUPLEX) || (spi->mode & SPI_3WIRE)) { struct spi_transfer *xfer; unsigned flags = master->flags; list_for_each_entry(xfer, &message->transfers, transfer_list) { if (xfer->rx_buf && xfer->tx_buf) return -EINVAL; if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf) return -EINVAL; if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf) return -EINVAL; } } message->spi = spi; message->status = -EINPROGRESS; return master->transfer(spi, message); }
返回了master->transfer(spi, message);那么就是控制器里去工作了。
我用的是gpio模拟的spi,所以那用gpio模拟的那个控制器去看控制器的处理了。
先还是看一下probe函数
static int __init spi_gpio_probe(struct platform_device *pdev) { int status; struct spi_master *master; struct spi_gpio *spi_gpio; struct spi_gpio_platform_data *pdata; u16 master_flags = 0; pdata = pdev->dev.platform_data; #ifdef GENERIC_BITBANG if (!pdata || !pdata->num_chipselect) return -ENODEV; #endif status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags); if (status < 0) return status; master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio); if (!master) { status = -ENOMEM; goto gpio_free; } spi_gpio = spi_master_get_devdata(master); platform_set_drvdata(pdev, spi_gpio); spi_gpio->pdev = pdev; if (pdata) spi_gpio->pdata = *pdata; master->flags = master_flags; master->bus_num = pdev->id; master->num_chipselect = SPI_N_CHIPSEL; master->setup = spi_gpio_setup; master->cleanup = spi_gpio_cleanup; spi_gpio->bitbang.master = spi_master_get(master); spi_gpio->bitbang.chipselect = spi_gpio_chipselect; if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) { spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; } else { spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0; spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1; spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2; spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3; } spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; spi_gpio->bitbang.flags = SPI_CS_HIGH; status = spi_bitbang_start(&spi_gpio->bitbang); if (status < 0) { spi_master_put(spi_gpio->bitbang.master); gpio_free: if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) gpio_free(SPI_MISO_GPIO); if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) gpio_free(SPI_MOSI_GPIO); gpio_free(SPI_SCK_GPIO); spi_master_put(master); } return status; }
主要看下下面三个函数
spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; status = spi_bitbang_start(&spi_gpio->bitbang);
spi_gpio_txrx_word_mode0;就是最后调用到的先放一边,spi_bitbang_start,看一下这个函数
int spi_bitbang_start(struct spi_bitbang *bitbang) { int status; if (!bitbang->master || !bitbang->chipselect) return -EINVAL; INIT_WORK(&bitbang->work, bitbang_work); spin_lock_init(&bitbang->lock); INIT_LIST_HEAD(&bitbang->queue); if (!bitbang->master->mode_bits) bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; if (!bitbang->master->transfer) bitbang->master->transfer = spi_bitbang_transfer; if (!bitbang->txrx_bufs) { bitbang->use_dma = 0; bitbang->txrx_bufs = spi_bitbang_bufs; if (!bitbang->master->setup) { if (!bitbang->setup_transfer) bitbang->setup_transfer = spi_bitbang_setup_transfer; bitbang->master->setup = spi_bitbang_setup; bitbang->master->cleanup = spi_bitbang_cleanup; } } else if (!bitbang->master->setup) return -EINVAL; if (bitbang->master->transfer == spi_bitbang_transfer && !bitbang->setup_transfer) return -EINVAL; /* this task is the only thing to touch the SPI bits */ bitbang->busy = 0; bitbang->workqueue = create_singlethread_workqueue( dev_name(bitbang->master->dev.parent)); if (bitbang->workqueue == NULL) { status = -EBUSY; goto err1; } /* driver may get busy before register() returns, especially * if someone registered boardinfo for devices */ status = spi_register_master(bitbang->master); if (status < 0) goto err2; return status; err2: destroy_workqueue(bitbang->workqueue); err1: return status; }
看到这个函数指针了吧:
if (!bitbang->master->transfer) bitbang->master->transfer = spi_bitbang_transfer;
那么设备驱动调用的master->transfer(spi, message);就是调用到了spi_bitbang_transfer了,
/** * spi_bitbang_transfer - default submit to transfer queue */ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) { struct spi_bitbang *bitbang; unsigned long flags; int status = 0; m->actual_length = 0; m->status = -EINPROGRESS; bitbang = spi_master_get_devdata(spi->master); spin_lock_irqsave(&bitbang->lock, flags); if (!spi->max_speed_hz) status = -ENETDOWN; else { list_add_tail(&m->queue, &bitbang->queue); queue_work(bitbang->workqueue, &bitbang->work); } spin_unlock_irqrestore(&bitbang->lock, flags); return status; }
这里是把信息加到了bitbang->workqueue,然后在bitbang->work里处理
再来看下bitbang->work做了什么
static void bitbang_work(struct work_struct *work) { struct spi_bitbang *bitbang = container_of(work, struct spi_bitbang, work); unsigned long flags; spin_lock_irqsave(&bitbang->lock, flags); bitbang->busy = 1; while (!list_empty(&bitbang->queue)) { struct spi_message *m; struct spi_device *spi; unsigned nsecs; struct spi_transfer *t = NULL; unsigned tmp; unsigned cs_change; int status; int do_setup = -1; m = container_of(bitbang->queue.next, struct spi_message, queue); list_del_init(&m->queue); spin_unlock_irqrestore(&bitbang->lock, flags); /* FIXME this is made-up ... the correct value is known to * word-at-a-time bitbang code, and presumably chipselect() * should enforce these requirements too? */ nsecs = 100; spi = m->spi; tmp = 0; cs_change = 1; status = 0; list_for_each_entry (t, &m->transfers, transfer_list) { /* override speed or wordsize? */ if (t->speed_hz || t->bits_per_word) do_setup = 1; /* init (-1) or override (1) transfer params */ if (do_setup != 0) { status = bitbang->setup_transfer(spi, t); if (status < 0) break; if (do_setup == -1) do_setup = 0; } /* set up default clock polarity, and activate chip; * this implicitly updates clock and spi modes as * previously recorded for this device via setup(). * (and also deselects any other chip that might be * selected ...) */ if (cs_change) { bitbang->chipselect(spi, BITBANG_CS_ACTIVE); ndelay(nsecs); } cs_change = t->cs_change; if (!t->tx_buf && !t->rx_buf && t->len) { status = -EINVAL; break; } /* transfer data. the lower level code handles any * new dma mappings it needs. our caller always gave * us dma-safe buffers. */ if (t->len) { /* REVISIT dma API still needs a designated * DMA_ADDR_INVALID; ~0 might be better. */ if (!m->is_dma_mapped) t->rx_dma = t->tx_dma = 0; status = bitbang->txrx_bufs(spi, t); } if (status > 0) m->actual_length += status; if (status != t->len) { /* always report some kind of error */ if (status >= 0) status = -EREMOTEIO; break; } status = 0; /* protocol tweaks before next transfer */ if (t->delay_usecs) udelay(t->delay_usecs); if (!cs_change) continue; if (t->transfer_list.next == &m->transfers) break; /* sometimes a short mid-message deselect of the chip * may be needed to terminate a mode or command */ ndelay(nsecs); bitbang->chipselect(spi, BITBANG_CS_INACTIVE); ndelay(nsecs); } m->status = status; m->complete(m->context); /* normally deactivate chipselect ... unless no error and * cs_change has hinted that the next message will probably * be for this chip too. */ if (!(status == 0 && cs_change)) { ndelay(nsecs); bitbang->chipselect(spi, BITBANG_CS_INACTIVE); ndelay(nsecs); } spin_lock_irqsave(&bitbang->lock, flags); } bitbang->busy = 0; spin_unlock_irqrestore(&bitbang->lock, flags); }
当队列非空的时候就一直去取队列的数据,然后会执行到
status = bitbang->setup_transfer(spi, t);
这个函数,因为在spi_bitbang_start中
if (!bitbang->txrx_bufs) { bitbang->use_dma = 0; bitbang->txrx_bufs = spi_bitbang_bufs; if (!bitbang->master->setup) { if (!bitbang->setup_transfer) bitbang->setup_transfer = spi_bitbang_setup_transfer; bitbang->master->setup = spi_bitbang_setup; bitbang->master->cleanup = spi_bitbang_cleanup; } }
所以就调用了spi_bitbang_setup_transfer;
int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { struct spi_bitbang_cs *cs = spi->controller_state; u8 bits_per_word; u32 hz; if (t) { bits_per_word = t->bits_per_word; hz = t->speed_hz; } else { bits_per_word = 0; hz = 0; } /* spi_transfer level calls that work per-word */ if (!bits_per_word) bits_per_word = spi->bits_per_word; if (bits_per_word <= 8) cs->txrx_bufs = bitbang_txrx_8; else if (bits_per_word <= 16) cs->txrx_bufs = bitbang_txrx_16; else if (bits_per_word <= 32) cs->txrx_bufs = bitbang_txrx_32; else return -EINVAL; /* nsecs = (clock period)/2 */ if (!hz) hz = spi->max_speed_hz; if (hz) { cs->nsecs = (1000000000/2) / hz; if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000)) return -EINVAL; } return 0; }
这里主要是根据bits_per_word选择传输的方式,分8、16,、32三种模式,ads7843touchscreen是用bits_per_word默认没有,选择bitbang_txrx_8的。
static unsigned bitbang_txrx_8( struct spi_device *spi, u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits), unsigned ns, struct spi_transfer *t ) { unsigned bits = t->bits_per_word ? : spi->bits_per_word; unsigned count = t->len; const u8 *tx = t->tx_buf; u8 *rx = t->rx_buf; while (likely(count > 0)) { u8 word = 0; if (tx) word = *tx++; word = txrx_word(spi, ns, word, bits); if (rx) *rx++ = word; count -= 1; } return t->len - count; }
这里word = txrx_word(spi, ns, word, bits);会调用到哪里呢?,首先看下这个函数的指针指向哪里。
在spi_bitbang_start中,bitbang->master->setup = spi_bitbang_setup;
然后在spi_bitbang_setup 中有
cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
所以,这个最终还是调用到了spi_gpio.c文件中的spi_gpio_spec_txrx_word_mode0
static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits) { unsigned flags = spi->master->flags; return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); }
然后这个函数就调用了bitbang_txrx_be_cpha0,这个函数在spi-bitbang-txrx.h中
static inline u32 bitbang_txrx_be_cpha0(struct spi_device *spi, unsigned nsecs, unsigned cpol, unsigned flags, u32 word, u8 bits) { /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ /* clock starts at inactive polarity */ for (word <<= (32 - bits); likely(bits); bits--) { /* setup MSB (to slave) on trailing edge */ if ((flags & SPI_MASTER_NO_TX) == 0) setmosi(spi, word & (1 << 31)); spidelay(nsecs); /* T(setup) */ setsck(spi, !cpol); spidelay(nsecs); /* sample MSB (from slave) on leading edge */ word <<= 1; if ((flags & SPI_MASTER_NO_RX) == 0) word |= getmiso(spi); setsck(spi, cpol); } return word; }
这里就是gpio模拟的spi总线的协议过程了。这样,从最上面设备程序调用到控制器的整个数据流就结束了。
注:这里有一个很恶心的东东,就是在bitbang_txrx_16,bitbang_txrx_32中的
const u8 *tx = t->tx_buf; u8 *rx = t->rx_buf;
这里是强制转换的,由于大小端的问题,可能导致数据相反,从而传输会出现问题的,如果是8bit的,那么就没有任何问题了。
一段小插曲,也是用逻辑分析仪抓到的数据才发现的,如果没有这玩意儿,估计现在还纠结着。
OK,至此,linux的SPI的数据传输就到这里了。