Linux下SPI驱动简解

基础知识:
第一点:硬件四线
第二点:重要结构体和函数
struct spi_device 
{
struct device dev;
struct spi_master *master;
u32 max_speed_hz;
u8 chip_select;
u8 bits_per_word;
u16 mode;
#define SPI_CPHA 0x01 /* clock phase */
#define SPI_CPOL 0x02 /* clock polarity */
#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? */
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
#define SPI_3WIRE 0x10 /* SI/SO signals shared */
#define SPI_LOOP 0x20 /* loopback mode */
#define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */
#define SPI_READY 0x80 /* slave pulls low to pause */
#define SPI_TX_DUAL 0x100 /* transmit with 2 wires */
#define SPI_TX_QUAD 0x200 /* transmit with 4 wires */
#define SPI_RX_DUAL 0x400 /* receive with 2 wires */
#define SPI_RX_QUAD 0x800 /* receive with 4 wires */
int irq;
void *controller_state;
void *controller_data;
char modalias[SPI_NAME_SIZE];
int     cs_gpio;                     /* chip select gpio */
}
struct spi_message{
struct list_head transfers;
struct spi_device *spi;
unsigned is_dma_mapped:1;
void (*complete)(void *context);
void *context;
unsigned frame_length;
unsigned actual_length;
int     status;
struct list_head queue;
void *state;
}
struct spi_transfer{
const void *tx_buf;
void *rx_buf;
unsigned len;


dma_addr_t tx_dma;
dma_addr_t rx_dma;
struct sg_table tx_sg;
struct sg_table rx_sg;


unsigned cs_change:1;
unsigned tx_nbits:3;
unsigned rx_nbits:3;
#define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */
#define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
#define SPI_NBITS_QUAD 0x04 /* 4bits transfer */
u8 bits_per_word;
u16 delay_usecs;
u32 speed_hz;


struct list_head transfer_list;
}
int spi_async(struct spi_device *spi, struct spi_message *message)
{
struct spi_master *master = spi->master;
int ret;
unsigned long flags;


ret = __spi_validate(spi, message);
if (ret != 0)
return ret;


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;
}
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);
}




第三点:设备驱动编写步骤
/*在mach-xxxxx中添加这个设备 , 设备注册=内核挖土坑 ,形成新的zImage*/
struct spi_board_info xxxxx_spi_board_info
{
.modalias = "xxxxx",
.platform_data = NULL,
.max_speed_hz = 10*1000*1000,
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data = ,
};
#ifdef CONFIG_xxxxx
spi_register_board_info(xxxxx_spi_board_info, ARRAY_SIZE(xxxxx_spi_board_info));
#endif


/*注册驱动*/
static struct spi_driver xxxxx_spi_driver = {
.driver = {
.name  = "xxxxx",
.owner = THIS_MODULE,
},
.probe = xxxxx_probe,
.remove = __devexit_p(xxxxx_remove),
};
module_init(my_rc522_init)->spi_register_driver(&xxxxx_spi_driver)->xxxxx_probe->
GPIO_Init->misc_register(&xxxxx_dev)->fops->read/write->


/*读写实现*/
struct spi_device *my_spi; //
/*read*/
int status;
unsigned char rx_buf; //rx_buf存放被读的东西,前提要先写入地址
struct spi_transfer t = {
.rx_buf = &rx_buf,
.len = count,
};
struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&t, &m);
status = spi_async(my_spi,&m);


/*wirte*/
int status;
unsigned char tx_buf; //tx_buf存放想写的东西,前提是要先写入地址
struct spi_transfer t = {
.tx_buf = tx_buf,
.len = count,
};
struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&t, &m);

status = spi_async(my_spi,&m);




/*卸载*/
spi_unregister_driver(&xxxxx_spi_driver)

你可能感兴趣的:(Linux下SPI驱动简解)