diff options
Diffstat (limited to 'drivers/spi/spidev.c')
| -rw-r--r-- | drivers/spi/spidev.c | 64 | 
1 files changed, 48 insertions, 16 deletions
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 4e6245e6799..e3bc23bb588 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -1,5 +1,5 @@  /* - * spidev.c -- simple synchronous userspace interface to SPI devices + * Simple synchronous userspace interface to SPI devices   *   * Copyright (C) 2006 SWAPP   *	Andrea Paterniani <a.paterniani@swapp-eng.it> @@ -30,15 +30,18 @@  #include <linux/errno.h>  #include <linux/mutex.h>  #include <linux/slab.h> +#include <linux/compat.h> +#include <linux/of.h> +#include <linux/of_device.h>  #include <linux/spi/spi.h>  #include <linux/spi/spidev.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h>  /* - * This supports acccess to SPI devices using normal userspace I/O calls. + * This supports access to SPI devices using normal userspace I/O calls.   * Note that while traditional UNIX/POSIX I/O semantics are half duplex,   * and often mask message boundaries, full SPI support requires full duplex   * transfers.  There are several kinds of internal message boundaries to @@ -70,7 +73,8 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS);   */  #define SPI_MODE_MASK		(SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \  				| SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ -				| SPI_NO_CS | SPI_READY) +				| SPI_NO_CS | SPI_READY | SPI_TX_DUAL \ +				| SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)  struct spidev_data {  	dev_t			devt; @@ -203,9 +207,9 @@ spidev_write(struct file *filp, const char __user *buf,  	mutex_lock(&spidev->buf_lock);  	missing = copy_from_user(spidev->buffer, buf, count); -	if (missing == 0) { +	if (missing == 0)  		status = spidev_sync_write(spidev, count); -	} else +	else  		status = -EFAULT;  	mutex_unlock(&spidev->buf_lock); @@ -262,6 +266,8 @@ static int spidev_message(struct spidev_data *spidev,  		buf += k_tmp->len;  		k_tmp->cs_change = !!u_tmp->cs_change; +		k_tmp->tx_nbits = u_tmp->tx_nbits; +		k_tmp->rx_nbits = u_tmp->rx_nbits;  		k_tmp->bits_per_word = u_tmp->bits_per_word;  		k_tmp->delay_usecs = u_tmp->delay_usecs;  		k_tmp->speed_hz = u_tmp->speed_hz; @@ -356,6 +362,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		retval = __put_user(spi->mode & SPI_MODE_MASK,  					(__u8 __user *)arg);  		break; +	case SPI_IOC_RD_MODE32: +		retval = __put_user(spi->mode & SPI_MODE_MASK, +					(__u32 __user *)arg); +		break;  	case SPI_IOC_RD_LSB_FIRST:  		retval = __put_user((spi->mode & SPI_LSB_FIRST) ?  1 : 0,  					(__u8 __user *)arg); @@ -369,9 +379,13 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  	/* write requests */  	case SPI_IOC_WR_MODE: -		retval = __get_user(tmp, (u8 __user *)arg); +	case SPI_IOC_WR_MODE32: +		if (cmd == SPI_IOC_WR_MODE) +			retval = __get_user(tmp, (u8 __user *)arg); +		else +			retval = __get_user(tmp, (u32 __user *)arg);  		if (retval == 0) { -			u8	save = spi->mode; +			u32	save = spi->mode;  			if (tmp & ~SPI_MODE_MASK) {  				retval = -EINVAL; @@ -379,18 +393,18 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  			}  			tmp |= spi->mode & ~SPI_MODE_MASK; -			spi->mode = (u8)tmp; +			spi->mode = (u16)tmp;  			retval = spi_setup(spi);  			if (retval < 0)  				spi->mode = save;  			else -				dev_dbg(&spi->dev, "spi mode %02x\n", tmp); +				dev_dbg(&spi->dev, "spi mode %x\n", tmp);  		}  		break;  	case SPI_IOC_WR_LSB_FIRST:  		retval = __get_user(tmp, (__u8 __user *)arg);  		if (retval == 0) { -			u8	save = spi->mode; +			u32	save = spi->mode;  			if (tmp)  				spi->mode |= SPI_LSB_FIRST; @@ -471,6 +485,16 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  	return retval;  } +#ifdef CONFIG_COMPAT +static long +spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ +	return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#else +#define spidev_compat_ioctl NULL +#endif /* CONFIG_COMPAT */ +  static int spidev_open(struct inode *inode, struct file *filp)  {  	struct spidev_data	*spidev; @@ -543,6 +567,7 @@ static const struct file_operations spidev_fops = {  	.write =	spidev_write,  	.read =		spidev_read,  	.unlocked_ioctl = spidev_ioctl, +	.compat_ioctl = spidev_compat_ioctl,  	.open =		spidev_open,  	.release =	spidev_release,  	.llseek =	no_llseek, @@ -559,7 +584,7 @@ static struct class *spidev_class;  /*-------------------------------------------------------------------------*/ -static int __devinit spidev_probe(struct spi_device *spi) +static int spidev_probe(struct spi_device *spi)  {  	struct spidev_data	*spidev;  	int			status; @@ -589,7 +614,7 @@ static int __devinit spidev_probe(struct spi_device *spi)  		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; +		status = PTR_ERR_OR_ZERO(dev);  	} else {  		dev_dbg(&spi->dev, "no minor number available!\n");  		status = -ENODEV; @@ -608,14 +633,13 @@ static int __devinit spidev_probe(struct spi_device *spi)  	return status;  } -static int __devexit spidev_remove(struct spi_device *spi) +static int 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 */ @@ -630,13 +654,21 @@ static int __devexit spidev_remove(struct spi_device *spi)  	return 0;  } +static const struct of_device_id spidev_dt_ids[] = { +	{ .compatible = "rohm,dh2228fv" }, +	{}, +}; + +MODULE_DEVICE_TABLE(of, spidev_dt_ids); +  static struct spi_driver spidev_spi_driver = {  	.driver = {  		.name =		"spidev",  		.owner =	THIS_MODULE, +		.of_match_table = of_match_ptr(spidev_dt_ids),  	},  	.probe =	spidev_probe, -	.remove =	__devexit_p(spidev_remove), +	.remove =	spidev_remove,  	/* NOTE:  suspend/resume methods are not necessary here.  	 * We don't do anything except pass the requests to/from  | 
