|
Rk3288的SPI从模式驱动应该怎么写?
发表于 2020-2-25 09:37:37
浏览:7162
|
回复:0
打印
只看该作者
[复制链接]
楼主
我按照Rk3288的寄存器来配置的,打印的RXDR寄存器和SR寄存器的值都是为0,不知道是我配置错了还是哪里的问题,请各位帮忙解决下。
代码:
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/ioctl.h>//
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/poll.h>
#include <linux/uaccess.h>
#include <linux/ioport.h>
//设置SPI的设备名与主设备号,注意避开那些已经使用的主设备号
#define DEVICE_NAME "spi0_slave" //设备名
#define SPI_MAJOR 237 //主设备号
#define SPI_MINOR 0 //次设备号
//指定SPI寄存器的基地址 ---- SPI0
#define RK3288_SPI_BASE (0xFF110000)
// SPI0的GPIO基地址 --- SPI0的GPIO复用
#define RK3288_GRF_BASE (0xFF780000)
/**********************************************************************************/
// 定义SPI寄存器偏移地址
#define SPI_CTRLR0 0x0000
#define SPI_CTRLR1 0x0004
#define SPI_ENR 0x0008
#define SPI_SER 0x000C
#define SPI_BAUDR 0x0010
#define SPI_TXFTLR 0x0014
#define SPI_RXFTLR 0x0018
#define SPI_TXFLR 0x001C
#define SPI_RXFLR 0x0020
#define SPI_SR 0x0024
#define SPI_IPR 0x0028
#define SPI_IMR 0x002C
#define SPI_ISR 0x0030
#define SPI_RISR 0x0034
#define SPI_ICR 0x0038
#define SPI_DMACR 0x003C
#define SPI_DMATDLR 0x0040
#define SPI_DMARDLR 0x0044
#define SPI_TXDR 0x0400 // 0x0400~0x07fc
#define SPI_RXDR 0x0800 // 0x0800~0x0bfc
/* SPI_CTRLR0 ----- Offset:0x0000 */
#define CR0_OPM_SLAVE (01 << 20) // Operation MODE : Slave Mode
#define CR0_XFM_RECVONLY (02 << 18) // Transfer MODE : receive only
#define CR0_BHT_8BIT (01 << 13) // ……
#define CR0_FBM_MSBFIRST (00 << 12) // First Bit MODE : MSB First
#define CR0_FBM_LSBFIRST (01 << 12) // First Bit MODE : LSB First
#define CR0_EM_LITTLE (00 << 11) // Endian Mode : Little Endian
#define CR0_EM_BIG (01 << 11) // Endian Mode : Big Endian
#define CR0_SCPOL_LOW (00 << 07) // CPOL : IDLE is LOW
#define CR0_SCPH_FIRST (00 << 06) // CPHA : First edge
#define CR0_DFS_8BIT (01 << 00) // Frame Size : 8bit
/* SPI_ENR ------ Offset:0x0008*/
#define ENR_SPI_DISABLE (00 << 00) // Disable SPI
#define ENR_SPI_ENABLE (01 << 00) // Enable SPI
/* SPI_SR ----- Offset:0x0024 */
#define SR_RF_FULL (01 << 04) // Receive FIFO Full
#define SR_RF_EMPTY (01 << 03) // Receive FIFO Empty
#define SR_SPI_BUSY (01 << 00) // SPI is BUSY
/* SPI_DMACR ----- Offset:0x003C*/
#define DMACR_RECV_ENABLE (01 << 00) // DMA Recvive Enable
#define DMACR_RECV_DISABLE (00 << 00) // DMA Recvive Disable
/**********************************************************************************/
#define MEMSIZE 0x1000
#define MYPRINT(format, ...) printk(format, ##__VA_ARGS__)
static void __iomem *pstSpiReg = NULL;
static void __iomem *TMP = NULL;
static dev_t stSpiDevNum;
//static struct class *pstSpi_class = NULL;
//static struct device *pstSpi_device = NULL;
//static struct resource *pstSpi_res = NULL;
// 定义一个cdev
static struct cdev Rk3288_spi_cdev;
static char s_cRecvData;
// 关闭spi
static int Rk3288_spi_close(struct inode *inode, struct file *filp)
{
MYPRINT("Rk3288 spi closed.\n");
return 0;
}
// 打开spi
static int Rk3288_spi_open(struct inode *inode, struct file *filp)
{
/* Config SPI -->
Slave Mode、RecvOnly Mode、MSB First Mode、
Big Endian、CPOL=CPHA=0 、Data Frame Size = 8bits
*/
TMP = pstSpiReg + SPI_CTRLR0;
*(unsigned int *)(TMP) = ( CR0_OPM_SLAVE | CR0_XFM_RECVONLY | CR0_FBM_MSBFIRST | CR0_BHT_8BIT |
CR0_EM_LITTLE | CR0_SCPOL_LOW | CR0_SCPH_FIRST | CR0_DFS_8BIT );
TMP = pstSpiReg + SPI_CTRLR1;
*(unsigned int *)(TMP) = (0x03ff) << 0;
/* Enable SPI */
TMP = pstSpiReg + SPI_ENR;
*(unsigned int *)(TMP) = ENR_SPI_ENABLE;
MYPRINT("Rk3288 open spi successfully\n");
return 0;
}
// spi读读操作
static ssize_t Rk3288_spi_read(struct file *filp, char __user *buf, size_t count, loff_t *f_ops)
{
int nRet = 0;
TMP = pstSpiReg + SPI_SR;
// get the SPI Status,wait the Recv FIFO FULL
//while ( !(*(unsigned int *)TMP & SR_RF_FULL) );
for (nRet = 0; nRet < 10; nRet++)
{
MYPRINT("SR reg : %#x\n", *(unsigned int *)TMP);
}
TMP = pstSpiReg + SPI_RXDR;
s_cRecvData = *(unsigned int *)TMP & 0x0F;
nRet = copy_to_user(buf, &s_cRecvData, count);
if (0 != nRet)
{
MYPRINT("Rk3288 read SPI data error\n");
return nRet;
}
return count;
}
// 填充file_operation结构体
static struct file_operations stRk3288_spi_fops =
{
.owner = THIS_MODULE,
.open = Rk3288_spi_open,
.read = Rk3288_spi_read,
.release = Rk3288_spi_close,
};
// 初始化设备
static int __init Rk3288_dev_init(void)
{
int nRet = 0;
//struct resource *pstGPIO_res = NULL;
void __iomem *GPIO_GRF_BASE = NULL;
void __iomem *GPIO5B_IOMUX = NULL;
// 申请或注册设备号
if (SPI_MAJOR == 0)
{
nRet = alloc_chrdev_region(&stSpiDevNum, SPI_MINOR, 1, DEVICE_NAME);
}
else
{
stSpiDevNum = MKDEV(SPI_MAJOR, SPI_MINOR);
nRet = register_chrdev_region(stSpiDevNum, 1, DEVICE_NAME);
}
if (nRet < 0)
{
MYPRINT("Rk3288 can not get device number\n");
return nRet;
}
// 初始化cdev
cdev_init(&Rk3288_spi_cdev, &stRk3288_spi_fops);
// 将cdev加入内核
nRet = cdev_add(&Rk3288_spi_cdev, stSpiDevNum, 1);
if (nRet < 0)
{
MYPRINT("Rk3288 add cdev error\n");
goto cdev_add_error;
}
// 创建class
#if 0
pstSpi_class = class_create(THIS_MODULE, "rk3288_spi_class");
if (pstSpi_class == NULL)
{
MYPRINT("Rk3288 class create error\n");
nRet = -EBUSY;
goto class_create_error;
}
// 创建device
pstSpi_device = device_create(pstSpi_class, NULL, stSpiDevNum, NULL, "rk3288_spi_drv");
if (pstSpi_device == NULL)
{
MYPRINT("Rk3288 device create error\n");
nRet = -EBUSY;
goto device_create_error;
}
// 申请物理内存区作为一个资源,申请了其他人就不能用了(不是必须的)----spi
pstSpi_res = request_mem_region(RK3288_SPI_BASE, MEMSIZE, "Rk3288_spi2");
if (pstSpi_res == NULL)
{
MYPRINT("Rk3288 request mem error\n");
nRet = -EBUSY;
goto request_mem_error;
}
// GPIO初始化
/****************************************************************************************/
pstGPIO_res = request_mem_region(RK3288_GRF_BASE, MEMSIZE, "Rk3288_GRF");
if (pstGPIO_res == NULL)
{
MYPRINT("Rk3288 GRF request mem error\n");
nRet = -EBUSY;
goto request_mem_error;
}
#endif
GPIO_GRF_BASE = ioremap(RK3288_GRF_BASE, MEMSIZE);
if (GPIO_GRF_BASE == NULL)
{
MYPRINT("Rk3288 GRF ioremap error\n");
nRet = -EFAULT;
goto GRF_ioremap_error;
}
GPIO5B_IOMUX = GPIO_GRF_BASE + 0x0050;
// spi2_clk-----GRF_GPIO8A_IOMUX[13:12]=01
// spi2_csn0----GRF_GPIO8A_IOMUX[15:14]=01
// spi2_rx------GRF_GPIO8B_IOMUX[ 1: 0]=01
// spi2_tx------GRF_GPIO8B_IOMUX[ 3: 2]=01
// GPIO5B_IOMUX[16:31] = bit15~0 write enable;
*(unsigned int *)GPIO5B_IOMUX &= ~((0x11 << 8) | (0x11 << 10) | (0x11 << 12) | (0x11 << 14));
*(unsigned int *)GPIO5B_IOMUX |= (1 << 8) | (1 << 10) | (1 << 12) | (1 << 14);
//MYPRINT("GPIO5B_IOMUX=%#x\n", *(unsigned int *)GPIO5B_IOMUX);
// 释放资源,解除映射---GRF
//release_mem_region(RK3288_GRF_BASE, MEMSIZE);
iounmap(GPIO_GRF_BASE);
/***************************************************************************************/
//IO内存动态映射,由物理地址得到虚拟地址----spi
pstSpiReg = ioremap(RK3288_SPI_BASE, MEMSIZE);
if (pstSpiReg == NULL)
{
MYPRINT("Rk3288 ioremap error\n");
nRet = -EFAULT;
goto spi_ioremap_error;
}
MYPRINT("Rk3288 spi slave driver init\n");
return 0;
// goto select:
/*----------------------------------------------*/
GRF_ioremap_error:
release_mem_region(RK3288_GRF_BASE, MEMSIZE);
spi_ioremap_error:
//release_mem_region(RK3288_SPI_BASE, MEMSIZE);
//request_mem_error:
//device_destroy(pstSpi_class, stSpiDevNum);
//device_create_error:
//class_destroy(pstSpi_class);
//class_create_error:
//cdev_del(&Rk3288_spi_cdev);
cdev_add_error:
unregister_chrdev_region(stSpiDevNum, 1);
/*----------------------------------------------*/
return nRet;
}
//module的出口函数---驱动程序的卸载函数
static void __exit Rk3288_dev_exit(void)
{
unregister_chrdev_region(stSpiDevNum, 1);
cdev_del(&Rk3288_spi_cdev);
//device_destroy(pstSpi_class, stSpiDevNum);
//class_destroy(pstSpi_class);
//release_mem_region(RK3288_SPI_BASE, MEMSIZE);
iounmap(pstSpiReg);
MYPRINT("Rk3288 spi driver exit\n");
}
//module的入口和出口
module_init(Rk3288_dev_init);
module_exit(Rk3288_dev_exit);
//module的描述
MODULE_AUTHOR("huangchengtian");
MODULE_DESCRIPTION("Rk3288 SPI SLAVE Device Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("V1.0");
|
|