346 lines
10 KiB
C
346 lines
10 KiB
C
#ifndef __SPI_H__
|
||
#define __SPI_H__
|
||
|
||
|
||
#include "typedef.h"
|
||
#include "generic/ioctl.h"
|
||
|
||
#define SPI_MAX_SIZE (0x7FFFFFFF - 1)//(2^31 - 1)//由于该宏可能赋值给有符合变量,因此使用2^31 - 1
|
||
|
||
/*enum spi_mode {
|
||
SPI_2WIRE_MODE,
|
||
SPI_STD_MODE,
|
||
SPI_DUAL_MODE,
|
||
SPI_QUAD_MODE,
|
||
};*/
|
||
|
||
#define SPI_MODE_SLAVE BIT(0)
|
||
|
||
#define SPI_UPDATE_SAMPLE_SAME BIT(1)
|
||
#define SPI_SCLK_H_UPH_SMPL BIT(2)//CLK空闲H,上升沿更新数据,下降沿采样数据
|
||
#define SPI_SCLK_H_UPL_SMPH BIT(3)//CLK空闲H,下降沿更新数据,上升沿采样数据
|
||
#define SPI_SCLK_H_UPH_SMPH BIT(4)//CLK空闲H,上升沿更新数据,上升沿采样数据
|
||
#define SPI_SCLK_H_UPL_SMPL BIT(5)//CLK空闲H,下降沿更新数据,下降沿采样数据
|
||
#define SPI_SCLK_L_UPH_SMPL BIT(6)//CLK空闲L,上升沿更新数据,下降沿采样数据
|
||
#define SPI_SCLK_L_UPL_SMPH BIT(7)//CLK空闲L,下降沿更新数据,上升沿采样数据
|
||
#define SPI_SCLK_L_UPH_SMPH BIT(8)//CLK空闲L,上升沿更新数据,上升沿采样数据
|
||
#define SPI_SCLK_L_UPL_SMPL BIT(9)//CLK空闲L,下降沿更新数据,下降沿采样数据
|
||
|
||
#define SPI_UNIDIR_MODE BIT(10) //单向:只用SPI_DO一根线数据传输(一般只用于作为从机接收数据)
|
||
#define SPI_BIDIR_MODE BIT(11) //双向:用SPI_DO/DI两根线数据传输
|
||
#define SPI_SCLK_PORT_HD BIT(13) //SPI CLK时钟开启强电流强驱
|
||
|
||
#define IOCTL_SPI_SET_CS _IOW('S', 1, u8)
|
||
#define IOCTL_SPI_SEND_BYTE _IOW('S', 2, u8)
|
||
#define IOCTL_SPI_SEND_CMD_2BIT_MODE _IOW('S', 3, u32)
|
||
#define IOCTL_SPI_GET_BIT_MODE _IOW('S', 4, u32)
|
||
#define IOCTL_SPI_READ_BYTE _IOW('S', 5, u8)
|
||
#define IOCTL_SPI_SET_CRC _IOW('S', 6, u16)
|
||
#define IOCTL_SPI_READ_CRC _IOR('S', 7, u16)
|
||
|
||
#define IOCTL_SFC_SEND_ADDR _IOW('S', 8, u32)
|
||
#define IOCTL_SFC_SWITCH_TO_SPI _IOW('S', 9, u32)
|
||
#define IOCTL_SFC_DATA_UPDATE _IOW('S', 10, u32)
|
||
#define IOCTL_SFC_DATA_ERASE _IOW('S', 11, u32)
|
||
|
||
#define IOCTL_SPI_SET_IRQ_CPU_ID _IOW('S', 12, u32)
|
||
#define IOCTL_SPI_SET_USER_INFO _IOW('S', 13, u32)
|
||
#define IOCTL_SPI_READ_DATA _IOR('S', 13, u32)
|
||
#define IOCTL_SPI_FREE_DATA _IOW('S', 14, u32)
|
||
#define IOCTL_SPI_SET_CB _IOW('S', 15, u32)
|
||
#define IOCTL_SPI_SET_USE_SEM _IOW('S', 16, u32)
|
||
#define IOCTL_SPI_SET_IRQ_FUNC _IOW('S', 17, u32)
|
||
|
||
#define IOCTL_SPI_SET_BIT_MODE _IOW('S', 18, u32)
|
||
//SPI同一组多ABC口同时使用时切换口命令,使用示例:ioctl(spi_hdl, IOCTL_SPI_SET_PORT, 0);
|
||
#define IOCTL_SPI_SET_PORT _IOW('S', 19, u32)
|
||
//非阻塞方式发包
|
||
#define IOCTL_SPI_NON_BLOCK _IOW('S', 20, u32)
|
||
//休眠前需要调用这个当使用非阻塞方式发包时候
|
||
#define IOCTL_SPI_WRITE_NON_BLOCK_FLUSH _IOW('S', 21, u32)
|
||
//获取spi配置是否阻塞发送
|
||
#define IOCTL_SPI_GET_NON_BLOCK _IOR('S', 22, u32)
|
||
#define IOCTL_SPI_SET_THRESHOLD_SEM_WAIT _IOW('S', 23, u32)
|
||
|
||
struct spi_io {
|
||
u8 cs_pin;
|
||
u8 di_pin;
|
||
u8 do_pin;
|
||
u8 clk_pin;
|
||
u8 d2_pin;
|
||
u8 d3_pin;
|
||
};
|
||
|
||
struct spi_2bit_data {
|
||
u32 len;
|
||
u8 *buf;
|
||
};
|
||
|
||
struct spi_user {
|
||
u8 *buf;
|
||
u32 buf_size;
|
||
u32 dma_max_cnt;
|
||
u32 first_dma_size;
|
||
u32 block_size;
|
||
};
|
||
|
||
struct spi_cb {
|
||
int (*cb_func)(void *priv, u8 **data, u32 *len);
|
||
void *cb_priv;
|
||
};
|
||
|
||
struct spi_block {
|
||
volatile u8 *buf;
|
||
volatile u32 buf_size;
|
||
volatile u32 block_num;
|
||
volatile u32 dma_max_cnt;
|
||
volatile u32 first_dma_size;
|
||
volatile u32 block_size;
|
||
volatile u32 dma_size;
|
||
volatile u32 wblock;
|
||
volatile u32 rblock;
|
||
volatile u32 free_size;
|
||
volatile u8 start;
|
||
};
|
||
|
||
struct spi_regs {
|
||
volatile u32 con;
|
||
volatile u8 baud;
|
||
volatile u8 reg1[3];
|
||
volatile u8 buf;
|
||
volatile u8 reg2[3];
|
||
volatile u32 adr;
|
||
volatile u32 cnt;
|
||
};
|
||
|
||
struct sfc_regs {
|
||
volatile u32 con;
|
||
volatile u16 baud;
|
||
volatile u32 reserved0;
|
||
volatile u32 base_addr;
|
||
volatile u32 reserved1;
|
||
volatile u32 econ;
|
||
};
|
||
|
||
struct spi_platform_data {
|
||
u8 port;
|
||
u8 mode;
|
||
u8 irq;
|
||
u32 attr;
|
||
u32 clk;
|
||
const struct spi_io *io;
|
||
volatile struct spi_regs *reg;
|
||
void (*init)(const struct spi_platform_data *);
|
||
};
|
||
|
||
struct sfc_spi_platform_data {
|
||
u8 mode;
|
||
u8 ro_mode;
|
||
u32 clk;
|
||
const struct spi_io *io;
|
||
volatile struct spi_regs *spi_reg;
|
||
volatile struct sfc_regs *sfc_reg;
|
||
};
|
||
|
||
struct sfc_spi_data {
|
||
u32 addr;
|
||
u32 len;
|
||
};
|
||
|
||
#define SPI0_PLATFORM_DATA_BEGIN(spi0_data) \
|
||
static const struct spi_io spi0_data##_io[] = { \
|
||
{ \
|
||
.cs_pin = IO_PORTD_00, \
|
||
.di_pin = IO_PORTD_01, \
|
||
.do_pin = IO_PORTD_05, \
|
||
.clk_pin = IO_PORTD_04, \
|
||
.d2_pin = IO_PORTD_02, \
|
||
.d3_pin = IO_PORTD_03, \
|
||
}, \
|
||
{ \
|
||
.cs_pin = IO_PORTC_05, \
|
||
.di_pin = IO_PORTC_00, \
|
||
.do_pin = IO_PORTC_04, \
|
||
.clk_pin = IO_PORTC_03, \
|
||
.d2_pin = IO_PORTC_01, \
|
||
.d3_pin = IO_PORTC_02, \
|
||
}, \
|
||
}; \
|
||
static void spi0_data##_iomc_init(const struct spi_platform_data *pd) \
|
||
{ \
|
||
JL_IOMAP->CON1 &= ~BIT(1); \
|
||
if (pd->port == 'A') { \
|
||
JL_IOMAP->CON0 &= ~BIT(5); \
|
||
} else { \
|
||
JL_IOMAP->CON0 |= BIT(5); \
|
||
} \
|
||
}\
|
||
static const struct spi_platform_data spi0_data = { \
|
||
.irq = IRQ_SPI0_IDX, \
|
||
.io = spi0_data##_io, \
|
||
.init = spi0_data##_iomc_init, \
|
||
|
||
|
||
#define SPI0_PLATFORM_DATA_END() \
|
||
.reg = (volatile struct spi_regs *)&JL_SPI0->CON, \
|
||
};
|
||
|
||
|
||
#define SFC_SPI_PLATFORM_DATA_BEGIN(sfc_spi0_data) \
|
||
static const struct spi_io sfc_spi0_io = { \
|
||
.cs_pin = IO_PORTD_00, \
|
||
.di_pin = IO_PORTD_01, \
|
||
.do_pin = IO_PORTD_05, \
|
||
.clk_pin = IO_PORTD_04, \
|
||
.d2_pin = IO_PORTD_02, \
|
||
.d3_pin = IO_PORTD_03, \
|
||
}; \
|
||
static const struct sfc_spi_platform_data sfc_spi0_data = { \
|
||
|
||
|
||
#define SFC_SPI_PLATFORM_DATA_END() \
|
||
.io = &sfc_spi0_io, \
|
||
.spi_reg = (volatile struct spi_regs *)&JL_SPI0->CON, \
|
||
.sfc_reg = (volatile struct sfc_regs *)&JL_SFC->CON, \
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
#define SPI1_PLATFORM_DATA_BEGIN(spi1_data) \
|
||
static const struct spi_io spi1_data##_io[] = { \
|
||
{ \
|
||
.cs_pin = -1, \
|
||
.di_pin = IO_PORTB_05, \
|
||
.do_pin = IO_PORTB_07, \
|
||
.clk_pin = IO_PORTB_06, \
|
||
.d2_pin = -1, \
|
||
.d3_pin = -1, \
|
||
}, \
|
||
{ \
|
||
.cs_pin = -1, \
|
||
.di_pin = IO_PORTC_08, \
|
||
.do_pin = IO_PORTC_10, \
|
||
.clk_pin = IO_PORTC_09, \
|
||
.d2_pin = -1, \
|
||
.d3_pin = -1, \
|
||
}, \
|
||
}; \
|
||
static void spi1_data##_iomc_init(const struct spi_platform_data *pd) \
|
||
{ \
|
||
if (pd->port == 'A') { \
|
||
JL_IOMAP->CON1 &= ~BIT(4); \
|
||
} else { \
|
||
JL_IOMAP->CON1 |= BIT(4); \
|
||
} \
|
||
}\
|
||
static const struct spi_platform_data spi1_data = { \
|
||
.irq = IRQ_SPI1_IDX, \
|
||
.io = spi1_data##_io, \
|
||
.init = spi1_data##_iomc_init, \
|
||
|
||
|
||
#define SPI1_PLATFORM_DATA_END() \
|
||
.reg = (volatile struct spi_regs *)&JL_SPI1->CON, \
|
||
};
|
||
|
||
|
||
|
||
#define SPI2_PLATFORM_DATA_BEGIN(spi2_data) \
|
||
static const struct spi_io spi2_data##_io[] = { \
|
||
{ \
|
||
.cs_pin = -1, \
|
||
.di_pin = IO_PORTH_02, \
|
||
.do_pin = IO_PORTH_01, \
|
||
.clk_pin = IO_PORTH_00, \
|
||
.d2_pin = -1, \
|
||
.d3_pin = -1, \
|
||
}, \
|
||
{ \
|
||
.cs_pin = -1, \
|
||
.di_pin = IO_PORTG_15, \
|
||
.do_pin = IO_PORT_USB_DMA, \
|
||
.clk_pin = IO_PORT_USB_DPA, \
|
||
.d2_pin = -1, \
|
||
.d3_pin = -1, \
|
||
}, \
|
||
{ \
|
||
.cs_pin = -1, \
|
||
.di_pin = IO_PORTA_02, \
|
||
.do_pin = IO_PORTA_04, \
|
||
.clk_pin = IO_PORTA_03, \
|
||
.d2_pin = -1, \
|
||
.d3_pin = -1, \
|
||
}, \
|
||
}; \
|
||
static void spi2_data##_iomc_init(const struct spi_platform_data *pd) \
|
||
{ \
|
||
JL_IOMAP->CON1 &= ~(BIT(16) | BIT(17)); \
|
||
if (pd->port == 'B') { \
|
||
JL_IOMAP->CON1 |= BIT(16); \
|
||
} else if (pd->port == 'C') { \
|
||
JL_IOMAP->CON1 |= BIT(17); \
|
||
} \
|
||
}\
|
||
static const struct spi_platform_data spi2_data = { \
|
||
.irq = IRQ_SPI2_IDX, \
|
||
.io = spi2_data##_io, \
|
||
.init = spi2_data##_iomc_init, \
|
||
|
||
|
||
#define SPI2_PLATFORM_DATA_END() \
|
||
.reg = (volatile struct spi_regs *)&JL_SPI2->CON, \
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
#define SPI3_PLATFORM_DATA_BEGIN(spi3_data) \
|
||
static const struct spi_io spi3_data##_io[] = { \
|
||
{ \
|
||
.cs_pin = IO_PORTG_04, \
|
||
.di_pin = IO_PORTG_05, \
|
||
.do_pin = IO_PORTG_07, \
|
||
.clk_pin = IO_PORTG_03, \
|
||
.d2_pin = IO_PORTG_06, \
|
||
.d3_pin = IO_PORTG_02, \
|
||
}, \
|
||
{ \
|
||
.cs_pin = IO_PORTG_11, \
|
||
.di_pin = IO_PORTG_12, \
|
||
.do_pin = IO_PORTG_14, \
|
||
.clk_pin = IO_PORTG_10, \
|
||
.d2_pin = IO_PORTG_13, \
|
||
.d3_pin = IO_PORTG_09, \
|
||
}, \
|
||
}; \
|
||
static void spi3_data##_iomc_init(const struct spi_platform_data *pd) \
|
||
{ \
|
||
if (pd->port == 'A') { \
|
||
JL_IOMAP->CON0 &= ~BIT(15); \
|
||
} else { \
|
||
JL_IOMAP->CON0 |= BIT(15); \
|
||
} \
|
||
}\
|
||
static const struct spi_platform_data spi3_data = { \
|
||
.irq = IRQ_SPI3_IDX, \
|
||
.io = spi3_data##_io, \
|
||
.init = spi3_data##_iomc_init, \
|
||
|
||
|
||
#define SPI3_PLATFORM_DATA_END() \
|
||
.reg = (volatile struct spi_regs *)&JL_SPI3->CON, \
|
||
};
|
||
|
||
|
||
|
||
|
||
extern const struct device_operations spi_dev_ops;
|
||
extern const struct device_operations sfc_spi_dev_ops;
|
||
|
||
|
||
#endif
|
||
|