微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > s5pv210与stm32 spi通信

s5pv210与stm32 spi通信

时间:11-19 来源:互联网 点击:
\n");}if (__copy_from_user(g_uxfers, (void __user *)arg, tmp)) {kfree(g_uxfers);printk("g_uxfers copy failed\n");}/* copy into scratch area */ioc = kmalloc(tmp, GFP_KERNEL);if (!ioc) {retval = -ENOMEM;break;}if (__copy_from_user(ioc, (void __user *)arg, tmp)) {kfree(ioc);retval = -EFAULT;break;}/* translate to spi_message, execute */retval = spidev_message(spidev, ioc, n_ioc);kfree(ioc);break;}mutex_unlock(&spidev->buf_lock);spi_dev_put(spi);return retval;}static int spidev_open(struct inode *inode, struct file *filp){struct spidev_data *spidev;int status = -ENXIO;mutex_lock(&device_list_lock);gk_xfers = kcalloc(1, sizeof (*gk_xfers), GFP_KERNEL);if (gk_xfers == NULL)printk("alloc gk_xfers_failed\n");list_for_each_entry(spidev, &device_list, device_entry) {if (spidev->devt == inode->i_rdev) {status = 0;break;}}if (status == 0) {if (!spidev->buffer) {spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);if (!spidev->buffer) {dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");status = -ENOMEM;}}if (status == 0) {spidev->users++;filp->private_data = spidev;nonseekable_open(inode, filp);}} elsepr_debug("spidev: nothing for minor %d\n", iminor(inode));mutex_unlock(&device_list_lock);return status;}static int spidev_release(struct inode *inode, struct file *filp){struct spidev_data *spidev;int status = 0;mutex_lock(&device_list_lock);spidev = filp->private_data;filp->private_data = NULL;/* last close? */spidev->users--;if (!spidev->users) {int dofree;kfree(spidev->buffer);spidev->buffer = NULL;/* ... after we unbound from the underlying device? */spin_lock_irq(&spidev->spi_lock);dofree = (spidev->spi == NULL);spin_unlock_irq(&spidev->spi_lock);if (dofree)kfree(spidev);}//disable_irq_nosync(spidev->irq);kfree(gk_xfers);kfree(g_uxfers);mutex_unlock(&device_list_lock);return status;}static const struct file_operations spidev_fops = {.owner = THIS_MODULE,/* REVISIT switch to aio primitives, so that userspace* gets more complete API coverage. Itll simplify things* too, except for the locking.*/.write = spidev_write,.read = spidev_read,.unlocked_ioctl = spidev_ioctl,.open = spidev_open,.release = spidev_release,.poll =gzsd_poll,};/*-------------------------------------------------------------------------*//* The main reason to have this class is to make mdev/udev create the* /dev/spidevB.C character device nodes exposing our userspace API.* It also simplifies memory management.*/static struct class *spidev_class;/*-------------------------------------------------------------------------*/static int __devinit spidev_probe(struct spi_device *spi){struct spidev_data *spidev;int status;unsigned long minor;int err;/* Allocate driver data */spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);if (!spidev)return -ENOMEM;/* Initialize the driver data */spidev->spi = spi;spin_lock_init(&spidev->spi_lock);mutex_init(&spidev->buf_lock);INIT_LIST_HEAD(&spidev->device_entry);/* If we can allocate a minor number, hook up this device.* Reusing minors is fine so long as udev or mdev is working.*/mutex_lock(&device_list_lock);minor = find_first_zero_bit(minors, N_SPI_MINORS);if (minor < N_SPI_MINORS) {struct device *dev;spidev->devt = MKDEV(SPIDEV_MAJOR, minor);dev = device_create(spidev_class, &spi->dev, spidev->devt,spidev, "spidev%d.%d",spi->master->bus_num, spi->chip_select);status = IS_ERR(dev) ? PTR_ERR(dev) : 0;} else {dev_dbg(&spi->dev, "no minor number available!\n");status = -ENODEV;}if (status == 0) {set_bit(minor, minors);list_add(&spidev->device_entry, &device_list);}spidev->irq = SPI_IRQ;err = request_irq(spidev->irq, gzsd_spiread, IRQ_TYPE_EDGE_FALLING,"spi", spidev);if(err < 0) {dev_err(&spidev->spi->dev, "Unable to request spi IRQ.\n");}init_waitqueue_head(&spidev->rqueue);mutex_unlock(&device_list_lock);if (status == 0)spi_set_drvdata(spi, spidev);elsekfree(spidev);return status;}static int __devexit spidev_remove(struct spi_device *spi){struct spidev_data *spidev = spi_get_drvdata(spi);/* make sure ops on existing fds can abort cleanly */spin_lock_irq(&spidev->spi_lock);spidev->spi = NULL;spi_set_drvdata(spi, NULL);spin_unlock_irq(&spidev->spi_lock);/* prevent new opens */mutex_lock(&device_list_lock);list_del(&spidev->device_entry);device_destroy(spidev_class, spidev->devt);clear_bit(MINOR(spidev->devt), minors);if (spidev->users == 0)kfree(spidev);mutex_unlock(&device_list_lock);return 0;}static struct spi_driver spidev_spi_driver = {.driver = {.name = "spidev",.owner = THIS_MODULE,},.probe = spidev_probe,.remove = __devexit_p(spidev_remove),/* NOTE: suspend/resume methods are not necessary here.* We dont 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 spidev_init(void){int status;/* Claim our 256 reserved device numbers. Then register a class* that will key udev/mdev to add/remove /dev nodes. Last, register* the driver which manages those device numbers.*/BUILD_BUG_ON(N_SPI_MINORS > 256);status =

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top