基础知识:
第一点:硬件四线
第二点:重要结构体和函数
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)