SPI总线由Motorola公司推出的同步串行总线,全双工工作模式,用于CPU与各种外围器件进行全双工、同步串行通讯。硬件由SCLK,MOSI,MISO及SS/CS(Slave Select/Chip Select,主机发出,拉低有效)组成,简略图如下:
SPI总线工作方式有四种,由时钟信号的极性及相位组合而成,
CPOL: 时钟极性选择,为0时SPI总线空闲为低电平,为1时SPI总线空闲为高电平。
CPHA:时钟相位选择,为0时在SCK第一个跳变沿采样,为1时在SCK第二个跳变沿采样。
MTK平台SPI的数据传输模式有:
1. FIFO,支持一次传输32bytes。
2. DMA,一次最多支持1024B,支持多次传输(length=loop*1024,1≤loop≤256)。
3. SPI控制器只有一个片选信号,故只支持一个从设备。
MTK SPI代码架构与MTK-I2C类似,不做进一步介绍。
下面是驱动代码的示例:
/*****************************************************************************
Copyright(c) 2012 NMI Inc. All Rights Reserved
File name : my-spi.h
Description : NM326 host interface
History :
----------------------------------------------------------------------
2015/02/02 dlj initial
*******************************************************************************/
#ifndef __my_SPI_H__
#define __my_SPI_H__
#ifdef __cplusplus
extern "C" {
#endif
#define my_SPI_DEBUG
#ifdef my_SPI_DEBUG
#define my_spi_dbg(fmt...) printk(fmt)
#else
#define my_spi_dbg(fmt, ...)
#endif
#define my_spi_err(fmt, ...) printk(fmt)
#define xxxx_DEV_MAJOR 227
#define xxxx_DEV_MINOR 0
#define xxxx_DEV_NAME "ttySPI"
#define SPI_FIFO_BATYE_PER_TIMES 32
typedef enum
{
SPI_SEND = 0,
SPI_RECV = 1,
}SPI_MODE;
typedef enum
{
NO_RESPONE = 0x00,
OP_RIGHT = 0x01,
OP_WRONG = 0x02,
}SPI_RESPONE;
extern void mt_eint_mask(unsigned int eint_num);
extern void mt_eint_unmask(unsigned int eint_num);
extern void mt_eint_set_hw_debounce(unsigned int eint_num, unsigned int ms);
extern void mt_eint_set_polarity(unsigned int eint_num, unsigned int pol);
extern unsigned int mt_eint_set_sens(unsigned int eint_num, unsigned int sens);
extern void mt_eint_registration(unsigned int eint_num, unsigned int flow, void (EINT_FUNC_PTR)(void), unsigned int is_auto_umask);
size_t RFReceivePacket(unsigned char **recv_buf, size_t pktLen);
#endif // __NMI_HW_H__
/*****************************************************************************
Copyright(c) 2012 my Inc. All Rights Reserved
File name : my-spi.c
Description : NM326 host interface
History :
----------------------------------------------------------------------
2015/02/02 dlj initial
*******************************************************************************/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/stat.h>
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/vmalloc.h>
#include <linux/io.h>
#include <mach/board.h>
#include <linux/gpio.h>
#include "mach/mt_gpio.h"
#include <mach/mt_gpt.h>
#include <mach/mt_pm_ldo.h>
#include <mach/mt_typedefs.h>
#include <mach/upmu_common.h>
#include <mach/upmu_hw.h>
#include <mach/mt_spi.h>
#include <net/sock.h>
#include <net/netlink.h>
#include <cust_eint.h>
#include <cust_eint_md1.h>
#include <linux/spi/spi.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include "cust_gpio_usage.h"
#include "my-spi.h"
static unsigned char yyyy_spibuff_head[5] = {0x55,0xaa,0x00,0x00,0x00};
static size_t pkt_len = 0;
static unsigned char respone_flag = NO_RESPONE;
static DEFINE_MUTEX(my_spi_lock);
static unsigned char recv_tmp_buf[SPI_FIFO_BATYE_PER_TIMES] = {0};
static struct spi_device *xxxx_spi;
static struct class *xxxx_class;
static int sleep_time = HZ;
static int conn_state_flag = 0;
struct task_struct *xxxx_thread = NULL;
static DECLARE_WAIT_QUEUE_HEAD(interrupt_waiter);
static int xxxx_interrupt_flag = 0;
static DECLARE_WAIT_QUEUE_HEAD(read_waiter);
static int xxxx_read_flag = 0;
static DECLARE_WAIT_QUEUE_HEAD(write_waiter);
static int xxxx_write_flag = 0;
struct semaphore xxxx_sem;
static struct mt_chip_conf spi_xxxx_conf = {
.setuptime = 10000,
.holdtime = 0,
.high_time = 50,//165,//40,//335, //10--6m 15--4m 20--3m 30--2m [ 60--1m 120--0.5