嵌入式linux之spi驱动

驱动:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/compat.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>
#include <asm/uaccess.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>

struct spi_device *my_spi;

#define RC522_RESET_PIN	EXYNOS4_GPK1(0)
void my_rc522_reset()
{
	//printk("************************ %s\n", __FUNCTION__);
	if(gpio_request_one(RC522_RESET_PIN, GPIOF_OUT_INIT_HIGH, "RC522_RESET"))
                pr_err("failed to request GPK1_0 for RC522 reset control\n");

        s3c_gpio_setpull(RC522_RESET_PIN, S3C_GPIO_PULL_UP);
        gpio_set_value(RC522_RESET_PIN, 0);

        mdelay(5);

        gpio_set_value(RC522_RESET_PIN, 1);
        gpio_free(RC522_RESET_PIN);
}

//static ssize_t rc522_write(unsigned char *buffer, int len)
static ssize_t rc522_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	int status;
	unsigned char tx_buf[2];
	
	status = copy_from_user(tx_buf,buf,count);
	
	struct spi_transfer	t = {
		.tx_buf		= tx_buf,
		.len		= count,
	};
	struct spi_message	m;
	spi_message_init(&m);
	spi_message_add_tail(&t, &m);
	DECLARE_COMPLETION_ONSTACK(done);
	m.complete = complete;
	m.context = &done;
	
	printk("spi_async send begin!\n");
	status = spi_async(my_spi,&m);
	if(status == 0){
		wait_for_completion(&done);
		status = m.status;
		if (status == 0)
			status = m.actual_length;
	}
	return status;
}

/*//另一种写法
static int spi_write_bytes(struct spi_device *spi, unsigned char *txbuf, int txlen)
{
    int ret = 0;
    struct spi_message msg;
    struct spi_transfer xfer = {
        .len  = txlen,
        .tx_buf  = txbuf,
        .delay_usecs = 5,
        .bits_per_word = 8,
    };
    spi_message_init(&msg);
    spi_message_add_tail(&xfer, &msg);
    ret = spi_sync(spi, &msg);
    if (ret < 0)
        printk(KERN_ERR "spi send error\n");
}
*/


//static ssize_t rc522_read(unsigned char *buffer, int len)
static ssize_t rc522_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	int status;
	unsigned char *rx_buf;
	
	struct spi_transfer	t = {
		.rx_buf		= &rx_buf,
		.len		= count,
	};
	struct spi_message	m;
	spi_message_init(&m);
	spi_message_add_tail(&t, &m);
	DECLARE_COMPLETION_ONSTACK(done);
	m.complete = complete;
	m.context = &done;
	
	printk("spi_async read begin!\n");
	status = spi_async(my_spi,&m);
	if(status == 0){
		wait_for_completion(&done);
		status = m.status;
		if (status == 0)
			status = m.actual_length;
	}
	
	status = copy_to_user(buf,&rx_buf,status);
	
	return status;
}
/*//另一种方法,实际没差别
static int spi_read(struct spi_device *spi, unsigned char addr,\
        unsigned int length, unsigned char *data)
{
    int ret = 0;
    unsigned char buf[1];
    struct spi_message  msg;
    struct spi_transfer     xfer[] = { 
        {
            .tx_buf     = buf,
            .bits_per_word  = 8,
            .len        = sizeof(buf),
        },
        {
            .rx_buf     = data,
            .bits_per_word  = 8,
            .len        = length,
        }
    };  

    buf[0] = (addr | 0x80); 

    if (!spi || !data) {
        ret = -EINVAL;
        return ret;
    }   

    spi_message_init(&msg);

    spi_message_add_tail(&xfer[0], &msg);
    spi_message_add_tail(&xfer[1], &msg);

    return spi_sync(spi, &msg);
}
*/

int rc522_open(struct inode *inode,struct file *filp)
{
	return 0;
}



static struct file_operations rc522_ops = {
	.owner 	= THIS_MODULE,
	.open 	= rc522_open,
	.read	= rc522_read,
	.write 	= rc522_write,
};

static struct miscdevice rc522_dev = {
	.minor	= MISC_DYNAMIC_MINOR,
	.fops	= &rc522_ops,
	.name	= "rc522",
};

static int __devinit my_rc522_probe(struct spi_device *spi)
{
	
	printk("my_rc522_probe!\n");
	
	/* reset */
	my_rc522_reset();
	my_spi = spi;
	
	misc_register(&rc522_dev);
	
	return 0;
}

static int __devexit my_rc522_remove(struct spi_device *spi)
{
	printk("my_rc522_remove!\n");
	misc_deregister(&rc522_dev);	
	return 0;
}

static struct spi_driver my_rc522_spi_driver = {
	.driver = {
		.name  = "my_rc522",
		.owner = THIS_MODULE,
	},
	.probe =	my_rc522_probe,
	.remove = __devexit_p(my_rc522_remove),

	/* NOTE:  suspend/resume methods are not necessary here.
	 * We don't do anything except pass the requests to/from
	 * the underlying controller.  The refrigerator handles
	 * most issues; the controller driver handles the rest.
	 */
};


static int __init my_rc522_init(void)
{
	spi_register_driver(&my_rc522_spi_driver);
	return 0;
}

static void __exit my_rc522_exit(void)
{
	spi_unregister_driver(&my_rc522_spi_driver);
}

module_exit(my_rc522_exit);
module_init(my_rc522_init);


MODULE_AUTHOR("topeet: rty");
MODULE_LICENSE("GPL");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值