Chinaunix首页 | 论坛 | 博客
  • 博客访问: 319133
  • 博文数量: 68
  • 博客积分: 1501
  • 博客等级: 上尉
  • 技术积分: 1010
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-30 09:52
文章分类

全部博文(68)

文章存档

2010年(1)

2009年(67)

我的朋友

分类:

2009-01-21 15:47:44

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");

 
 
 
阅读(3609) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-11-30 20:54:26

你好!我也在调用spidev的spidev_write函数时出错,返回值既然为-1,请问楼主找到原先write写出错的原因了吗?谢谢!

chinaunix网友2009-02-07 14:51:01

谢谢了

chinaunix网友2009-02-02 22:27:55

我在devs.c中添加了你说的那些代码 !但编译的时候.pin_cs = S3C2410_GPG2, .board_info = s3c2410_spi_board, .board_size = ARRAY_SIZE(s3c2410_spi_board), 这几个老是抱错啊 !这几个应该在哪声明阿!谢谢