我在做一个s3c2410+linux-2.6.18平台上通过spi总线方式接入的fpga芯片驱动时遇到问题,有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 = 1, .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");
谢谢各位关注,问题已经解决.简单说一下,之前贴的加在devs.c里的板极信息
struct spi_board_info s3c2410_spi_board[] = { [0] = { .modalias = "spi_fpga", //.bus_num =0, .chip_select = S3C2410_GPE7, .max_speed_hz = 1*1000*1000, }, };
这里最重要的是modalias,务必和设备驱动的设备名一致.因为在下面已经把platform_data =&s3c2410_spi_platdata分给spi0,这里的bus_num就没必要赋了.
struct s3c2410_spi_info s3c2410_spi_platdata = { .pin_cs = S3C2410_GPE7, .board_info = s3c2410_spi_board, .board_size = ARRAY_SIZE(s3c2410_spi_board), };
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 } };
文章选项: |
(old hand) 08-07-29 11:44
|
Re: [求助]SPI设备驱动问题? [] |
| |
有浅在风险啊,改一下,牢靠一些
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;
}
|
|