6410 spi设备驱动
来源:互联网 发布:js模仿select 编辑:程序博客网 时间:2024/06/05 06:51
可以参考这篇文章 mostmark linux设备模型之SPI子系统:http://blog.csdn.net/gdt_a20/article/details/6437941
重要的结构体:
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, unless * spi_message.is_dma_mapped reports a pre-existing mapping */const void*tx_buf;void*rx_buf;unsignedlen;dma_addr_ttx_dma;dma_addr_trx_dma;unsignedcs_change:1;u8bits_per_word;u16delay_usecs;u32speed_hz;struct list_head transfer_list;};struct spi_message {struct list_headtransfers;struct spi_device*spi;unsignedis_dma_mapped:1;/* REVISIT: we might want a flag affecting the behavior of the * last transfer ... allowing things like "read 16 bit length L" * immediately followed by "read L bytes". Basically imposing * a specific message scheduling algorithm. * * Some controller drivers (message-at-a-time queue processing) * could provide that as their default scheduling algorithm. But * others (with multi-message pipelines) could need a flag to * tell them about such special cases. *//* completion is reported through a callback */void(*complete)(void *context);void*context;unsignedactual_length;intstatus;/* for optional use by whatever driver currently owns the * spi_message ... between calls to spi_async and then later * complete(), that's the spi_master controller driver. */struct list_headqueue;void*state;};
分析设备写:
struct spi_transfer st[2];
struct spi_message msg;
spi_message_init( &msg );
spi_message_add_tail( &st[0], &msg );
spi_sync( flash->spi, &msg ); 函数的原型位于:drivers/spi/spi.c 中
int spi_sync(struct spi_device *spi, struct spi_message *message)
{
return __spi_sync(spi, message, 0);
}
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;
}
int spi_async_locked(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);
ret = __spi_async(spi, message);
spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
return ret;
}
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 调用的是 drivers/spi/spi_s3c64xx.c里的s3c64xx_spi_transfer函数。
接着查看 linux设备驱动剖析之SPI(三) 网址为:http://www.cnblogs.com/lknlfy/p/3265054.html
修改drivers/spi/spi_s3c64xx.c
static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
struct spi_transfer *xfer, int dma_mode)
{
struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
void __iomem *regs = sdd->regs;
unsigned long val;
int ms;
/* millisecs to xfer 'len' bytes @ 'cur_speed' */
ms = xfer->len * 8 * 1000 / sdd->cur_speed;
ms += 10; /* some tolerance */
if (dma_mode) {
val = msecs_to_jiffies(ms) + 10;
val = wait_for_completion_timeout(&sdd->xfer_completion, val);
} else {
u32 status;
val = msecs_to_loops(ms);
do {
status = readl(regs + S3C64XX_SPI_STATUS);
} while (RX_FIFO_LVL(status, sci) < xfer->len && --val);
}
if (!val)
return -EIO;
if (dma_mode) {
u32 status;
/*
* DmaTx returns after simply writing data in the FIFO,
* w/o waiting for real transmission on the bus to finish.
* DmaRx returns only after Dma read data from FIFO which
* needs bus transmission to finish, so we don't worry if
* Xfer involved Rx(with or without Tx).
*/
if (xfer->rx_buf == NULL) {
val = msecs_to_loops(10);
status = readl(regs + S3C64XX_SPI_STATUS);
while ((TX_FIFO_LVL(status, sci)
|| !S3C64XX_SPI_ST_TX_DONE(status, sci))
&& --val) {
cpu_relax();
status = readl(regs + S3C64XX_SPI_STATUS);
}
if (!val)
return -EIO;
}
} else {
/* If it was only Tx */
if (xfer->rx_buf == NULL) {
sdd->state &= ~TXBUSY;
return 0;
}
/*
switch (sdd->cur_bpw) {
case 32:
ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
xfer->rx_buf, xfer->len / 4);
break;
case 16:
ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
xfer->rx_buf, xfer->len / 2);
break;
default:
ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
xfer->rx_buf, xfer->len);
break;
}
*/
i = 0;
buf = xfer->rx_buf;
while (i < xfer->len)
while(ren);
buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA);
sdd->state &= ~RXBUSY;
}
return 0;
}
红色的内容替换蓝色的内容。
- 6410 spi设备驱动
- 6410 spi 设备驱动
- SPI设备的驱动
- SPI设备的驱动
- SPI设备的驱动
- SPI设备的驱动
- linux SPI 设备驱动
- Linux spi设备驱动
- SPI设备的驱动
- Linux spi 设备驱动
- spi设备驱动模型
- SPI驱动之SPI设备驱动程序
- SPI驱动之SPI设备驱动程序
- spi总线设备驱动分析
- SPI设备的驱动(Z
- SPI设备的驱动(Z
- SPI设备的驱动(Z
- 三、Linux spi 设备驱动
- linux操作系统之进程
- 最小费用最大流模板题
- VisualBox问题
- 李克用置酒三垂冈赋——刘翰(清)
- 2014/5/19/翻译
- 6410 spi设备驱动
- Create a Project with Eclipse
- 关于怎么得到一个UIView所在的控制器或者说关于第三方库UIViewAdditions
- <菜鸟学算法-A排序(分治的思想:归并排序)>
- android 使用Binder通信
- 老MacBook升级内存记
- 简单JAR包制作
- Thinking in Java 笔记(二)
- java学习笔记——泛型Generic