1、针对s3c2410的spi控制器的配置信息(devs.c文件中):
static struct spi_board_info s3c2410_spi_board[] = {
[0] = {
.modalias = "spi-test",
.platform_data = NULL, // 设备的私有数据
//.irq = IRQ_EINT1,
.chip_select = 0, // 用于多个SPI选择,
.max_speed_hz = 500*1000,
},
};
static struct s3c2410_spi_info s3c2410_spi_platdata = {
.pin_cs = S3C2410_GPG2, // CS 片选
.board_info = s3c2410_spi_board,
.board_size = ARRAY_SIZE(s3c2410_spi_board),
};
/* end add */
static struct resource s3c_spi0_resource[] = {
[0] = {
.start = S3C24XX_PA_SPI,
.end = S3C24XX_PA_SPI + 0x1f,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_SPI0,
.end = IRQ_SPI0,
.flags = IORESOURCE_IRQ,
}
};
static u64 s3c_device_spi0_dmamask = 0xffffffffUL;
struct platform_device s3c_device_spi0 = {
.name = "s3c2410-spi",
.id = 0,
.num_resources = ARRAY_SIZE(s3c_spi0_resource),
.resource = s3c_spi0_resource,
.dev = {
.dma_mask = &s3c_device_spi0_dmamask,
.coherent_dma_mask = 0xffffffffUL,
.platform_data = &s3c2410_spi_platdata,
}
};
=================================================================
#include
#include
#include
#define TEST_REG 0x02
static int test_read_reg(struct spi_device *spi, int reg)
{
char buf[2];
buf[0] = reg << 2;
buf[1] = 0;
spi_write_then_read(spi, buf, 2, buf, 2);
return buf[1] << 8 | buf[0];
}
static int spi_test_probe(struct spi_device *spi)
{
printk("TEST_REG: 0x%02x\n", test_read_reg(spi, TEST_REG));
return 0;
}
static int spi_test_remove(struct spi_device *spi)
{
return 0;
}
static struct spi_driver spi_test_driver = {
.probe = spi_test_probe,
.remove = spi_test_remove,
.driver = {
.name = "testHW",
},
};
static int __init spi_test_init(void)
{
return spi_register_driver(&spi_test_driver);
}
static void __exit spi_test_exit(void)
{
spi_unregister_driver(&spi_test_driver);
}
module_init(spi_test_init);
module_exit(spi_test_exit);
MODULE_DESCRIPTION("spi device test");
MODULE_LICENSE("GPL");
在这个驱动中,你只需要用spi_register_driver向系统进行注册,就可以让系统用你指定的与 .name 相匹配的硬件交互代码
去执行你的读写请求。
几乎在所有与spi相关的函数中都会用到struct spi_device *spi这个指针,probe函数正好把这个指针传给你,保存好这个指针,你就可以在驱动的任何地方通过他去处理与spi设备相关的操作。
==================================================================================
在内核配置时候选择了 Samsung S3C24XX series SPI,按照论坛上以前帖子上的做法,然后在arch/arm/mach-s3c2410/的devs.c文件中加入下列信息:
/* add by jiarubin*/
static struct spi_board_info s3c2410_spi_board[] = {
[0] = {
.modalias = "spi_fpga",
.platform_data =NULL,
.chip_select = S3C2410_GPE7,
// ?????????????不理解
.max_speed_hz = 500*1000,
},
};
struct s3c2410_spi_info s3c2410_spi_platdata = {
.pin_cs = S3C2410_GPE7,
.board_info = s3c2410_spi_board,
.board_size = ARRAY_SIZE(s3c2410_spi_board),
};
/* end add */
struct platform_device s3c_device_spi0 = {
.name = "s3c2410-spi",
.id = 0,
.num_resources = ARRAY_SIZE(s3c_spi0_resource),
.resource = s3c_spi0_resource,
.dev = {
.dma_mask = &s3c_device_spi0_dmamask,
.coherent_dma_mask = 0xffffffffUL,
.platform_data =&s3c2410_spi_platdata/*add by jiarubin*/
}
};
最后将我自己编译出来的ko文件成功加载上以后,从/sys/下的bus/和devices/都能找到自己fpga设备和驱动,但是在应用程序中调用write()函数访问时报错,我的驱动代码如下,请高手帮我分析一下,谢谢!
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "spi_fpga.h"
struct spi_fpga{
struct spi_device *spi;
/* data buffers */
unsigned char *tx;
unsigned char *rx;
struct semaphore lock;
};
struct spi_device *new_device;
struct spi_fpga *fpga_dev;
unsigned char register_address=0;
void config_gpio(void)
{
s3c2410_gpio_cfgpin(SPI_FPGA_RST,S3C2410_GPIO_OUTPUT);
}
static int spi_fpga_probe(struct spi_device *spi)
{
struct spi_board_info *data;
struct spi_fpga *fpga;
data=kzalloc(sizeof(struct spi_board_info), SLAB_KERNEL);
if (!data)
return -ENOMEM;
data->platform_data = spi->dev.platform_data;
if (!data->platform_data) {
dev_dbg(&spi->dev, "no platform data?\n");
return -ENODEV;
}
fpga = kzalloc(sizeof(struct spi_fpga), SLAB_KERNEL);
if (!fpga)
return -ENOMEM;
fpga->spi = spi;
new_device=fpga->spi;
fpga_dev=fpga;
init_MUTEX(&fpga->lock);
dev_set_drvdata(&spi->dev, fpga);
fpga_dev=dev_get_drvdata(&spi->dev);
return 0;
}
static int spi_fpga_remove(struct spi_device *spi)
{
struct spi_fpga *pfpga = dev_get_drvdata(&spi->dev);
kfree(pfpga);
return 0;
}
static ssize_t spi_fpga_write(struct file *file, const char * buffer, size_t count, loff_t *ppos)
{
struct spi_transfer t[2];
struct spi_message m;
unsigned char *buf,ret;
//down(&fpga_write_sem);
buf=kmalloc(count,GFP_KERNEL);
if (buf== NULL)
return - ENOMEM;
memset(buf,0,count);
ret = copy_from_user(buf, buffer, count);
if(ret != 0)
{
kfree(buf);
return -EFAULT;
}
spi_message_init(&m);
memset(t, 0, (sizeof t));
t[0].tx_buf = ®ister_address;
t[0].len = sizeof(register_address);
spi_message_add_tail(&t[0], &m);
t[1].tx_buf = buf;
t[1].len = count;
spi_message_add_tail(&t[1], &m);
//up(&fpga_write_sem);
return spi_sync(new_device, &m);
}
static ssize_t spi_fpga_read(struct file * file, const char * buffer, size_t count, loff_t *ppos)
{
struct spi_transfer t[2];
struct spi_message m;
unsigned char *buf,ret;
//down(&fpga_read_sem);
buf=kmalloc(count,GFP_KERNEL);
if (buf== NULL)
return - ENOMEM;
memset(buf,0,count);
spi_message_init(&m);
memset(t, 0, (sizeof t));
t[0].tx_buf = ®ister_address;
t[0].len = sizeof(register_address);
spi_message_add_tail(&t[0], &m);
t[1].rx_buf = buf;
t[1].len = count;
spi_message_add_tail(&t[1], &m);
ret=copy_to_user(buffer, buf, count);
if(ret != 0)
{
kfree(buf);
return -EFAULT;
}
//up(&fpga_read_sem);
return spi_sync(new_device, &m);
}
static struct spi_driver spi_fpga_driver = {
.driver = {
.name = "spi_fpga",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = spi_fpga_probe,
.remove = __devexit_p(spi_fpga_remove),
};
static int spi_fpga_open(struct inode * inode, struct file * filp)
{
return 0;
}
static int spi_fpga_release(struct inode * inode, struct file * filp)
{
return 0;
}
static loff_t spi_fpga_llseek (struct file *filp, loff_t off, int whence)
{
switch(whence)
{
case SEEK_SET:
register_address= off;
break;
case SEEK_CUR:
register_address = register_address+ off;
break;
default: /* can't happen */
return -EINVAL;
}
return register_address;
}
void spi_fpga_highreset(void)
{
s3c2410_gpio_setpin(SPI_FPGA_RST, 1 );
msleep(10);
}
void spi_fpga_lowreset(void)
{
s3c2410_gpio_setpin(SPI_FPGA_RST, 0 );
msleep(10);
}
/*to user*/
static struct file_operations spi_fpga_fops = {
.owner = THIS_MODULE,
.open = spi_fpga_open,
.write = spi_fpga_write,
.read = spi_fpga_read,
.llseek = spi_fpga_llseek,
.release = spi_fpga_release,
};
static int __init spi_fpga_init(void)
{
unsigned int result;
result = register_chrdev(DS3_FPGA_MAJOR, DEVICE_NAME, &spi_fpga_fops);
if (result < 0)
{
printk(KERN_ERR DEVICE_NAME ": Unable to get major %d\n", DS3_FPGA_MAJOR);
return(result);
}
config_gpio();
spi_fpga_lowreset();
spi_fpga_highreset();
spi_fpga_lowreset();
printk(KERN_ERR DEVICE_NAME ": init OK\n");
return spi_register_driver(&spi_fpga_driver);
}
static void __exit spi_fpga_exit(void)
{
spi_unregister_driver(&spi_fpga_driver);
unregister_chrdev(DS3_FPGA_MAJOR, DEVICE_NAME);
}
module_init(spi_fpga_init);
module_exit(spi_fpga_exit);
MODULE_DESCRIPTION("spi fpga driver");
MODULE_LICENSE("GPL");
阅读(3602) | 评论(3) | 转发(0) |