summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig45
-rw-r--r--drivers/spi/Makefile6
-rw-r--r--drivers/spi/at25.c7
-rw-r--r--drivers/spi/atmel_spi.c185
-rw-r--r--drivers/spi/au1550_spi.c9
-rw-r--r--drivers/spi/mpc52xx_psc_spi.c9
-rw-r--r--drivers/spi/omap_uwire.c9
-rw-r--r--drivers/spi/pxa2xx_spi.c9
-rw-r--r--drivers/spi/spi.c59
-rw-r--r--drivers/spi/spi_bfin5xx.c3
-rw-r--r--drivers/spi/spi_bitbang.c8
-rw-r--r--drivers/spi/spi_imx.c26
-rw-r--r--drivers/spi/spi_mpc83xx.c102
-rw-r--r--drivers/spi/spi_s3c24xx.c11
-rw-r--r--drivers/spi/spi_s3c24xx_gpio.c2
-rw-r--r--drivers/spi/spidev.c23
16 files changed, 402 insertions, 111 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index f767e2afb060..e6a0ea49c420 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -107,6 +107,15 @@ config SPI_IMX
This enables using the Freescale iMX SPI controller in master
mode.
+config SPI_LM70_LLP
+ tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
+ depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This driver supports the NS LM70 LLP Evaluation Board,
+ which interfaces to an LM70 temperature sensor using
+ a parallel port.
+
config SPI_MPC52xx_PSC
tristate "Freescale MPC52xx PSC SPI controller"
depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
@@ -133,6 +142,12 @@ config SPI_OMAP_UWIRE
help
This hooks up to the MicroWire controller on OMAP1 chips.
+config SPI_OMAP24XX
+ tristate "McSPI driver for OMAP24xx"
+ depends on SPI_MASTER && ARCH_OMAP24XX
+ help
+ SPI master controller for OMAP24xx Multichannel SPI
+ (McSPI) modules.
config SPI_PXA2XX
tristate "PXA2xx SSP SPI master"
@@ -145,18 +160,36 @@ config SPI_PXA2XX
config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI"
depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+ select SPI_BITBANG
help
SPI driver for Samsung S3C24XX series ARM SoCs
config SPI_S3C24XX_GPIO
tristate "Samsung S3C24XX series SPI by GPIO"
- depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL
+ depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+ select SPI_BITBANG
help
SPI driver for Samsung S3C24XX series ARM SoCs using
GPIO lines to provide the SPI bus. This can be used where
the inbuilt hardware cannot provide the transfer mode, or
where the board is using non hardware connected pins.
+config SPI_TXX9
+ tristate "Toshiba TXx9 SPI controller"
+ depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
+ help
+ SPI driver for Toshiba TXx9 MIPS SoCs
+
+config SPI_XILINX
+ tristate "Xilinx SPI controller"
+ depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This exposes the SPI controller IP from the Xilinx EDK.
+
+ See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
+ Product Specification document (DS464) for hardware details.
+
config SPI_MXC
tristate "MXC CSPI controller as SPI Master"
depends on ARCH_MXC && SPI_MASTER
@@ -183,7 +216,6 @@ config SPI_MXC_SELECT3
bool "CSPI3"
depends on SPI_MXC && (ARCH_MX3 || ARCH_MX27)
default n
-
#
# Add new SPI master controllers in alphabetical order above this line
#
@@ -215,6 +247,15 @@ config SPI_SPIDEV
Note that this application programming interface is EXPERIMENTAL
and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes.
+config SPI_TLE62X0
+ tristate "Infineon TLE62X0 (for power switching)"
+ depends on SPI_MASTER && SYSFS
+ help
+ SPI driver for Infineon TLE62X0 series line driver chips,
+ such as the TLE6220, TLE6230 and TLE6240. This provides a
+ sysfs interface, with each line presented as a kind of GPIO
+ exposing both switch control and diagnostic feedback.
+
#
# Add new SPI protocol masters in alphabetical order above this line
#
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index f535ddd2ffdb..9b24023202c3 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,19 +17,23 @@ obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
obj-$(CONFIG_SPI_IMX) += spi_imx.o
+obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
+obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o
obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
+obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
+obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
obj-$(CONFIG_SPI_MXC) += mxc_spi.o
-
# ... add above this line ...
# SPI protocol drivers (device/link on bus)
obj-$(CONFIG_SPI_AT25) += at25.o
obj-$(CONFIG_SPI_SPIDEV) += spidev.o
+obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o
# ... add above this line ...
# SPI slave controller drivers (upstream link)
diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c
index 8efa07e8b8c2..e007833cca59 100644
--- a/drivers/spi/at25.c
+++ b/drivers/spi/at25.c
@@ -111,7 +111,8 @@ at25_ee_read(
}
static ssize_t
-at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct device *dev;
struct at25_data *at25;
@@ -236,7 +237,8 @@ at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count)
}
static ssize_t
-at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct device *dev;
struct at25_data *at25;
@@ -314,7 +316,6 @@ static int at25_probe(struct spi_device *spi)
*/
at25->bin.attr.name = "eeprom";
at25->bin.attr.mode = S_IRUSR;
- at25->bin.attr.owner = THIS_MODULE;
at25->bin.read = at25_bin_read;
at25->bin.size = at25->chip.byte_len;
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 8b2601de3630..b0469749310a 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -46,6 +46,7 @@ struct atmel_spi {
struct clk *clk;
struct platform_device *pdev;
unsigned new_1:1;
+ struct spi_device *stay;
u8 stopping;
struct list_head queue;
@@ -62,29 +63,62 @@ struct atmel_spi {
/*
* Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
* they assume that spi slave device state will not change on deselect, so
- * that automagic deselection is OK. Not so! Workaround uses nCSx pins
- * as GPIOs; or newer controllers have CSAAT and friends.
+ * that automagic deselection is OK. ("NPCSx rises if no data is to be
+ * transmitted") Not so! Workaround uses nCSx pins as GPIOs; or newer
+ * controllers have CSAAT and friends.
*
- * Since the CSAAT functionality is a bit weird on newer controllers
- * as well, we use GPIO to control nCSx pins on all controllers.
+ * Since the CSAAT functionality is a bit weird on newer controllers as
+ * well, we use GPIO to control nCSx pins on all controllers, updating
+ * MR.PCS to avoid confusing the controller. Using GPIOs also lets us
+ * support active-high chipselects despite the controller's belief that
+ * only active-low devices/systems exists.
+ *
+ * However, at91rm9200 has a second erratum whereby nCS0 doesn't work
+ * right when driven with GPIO. ("Mode Fault does not allow more than one
+ * Master on Chip Select 0.") No workaround exists for that ... so for
+ * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
+ * and (c) will trigger that first erratum in some cases.
*/
-static inline void cs_activate(struct spi_device *spi)
+static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
{
unsigned gpio = (unsigned) spi->controller_data;
unsigned active = spi->mode & SPI_CS_HIGH;
+ u32 mr;
+
+ mr = spi_readl(as, MR);
+ mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
- dev_dbg(&spi->dev, "activate %u%s\n", gpio, active ? " (high)" : "");
- gpio_set_value(gpio, active);
+ dev_dbg(&spi->dev, "activate %u%s, mr %08x\n",
+ gpio, active ? " (high)" : "",
+ mr);
+
+ if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
+ gpio_set_value(gpio, active);
+ spi_writel(as, MR, mr);
}
-static inline void cs_deactivate(struct spi_device *spi)
+static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
{
unsigned gpio = (unsigned) spi->controller_data;
unsigned active = spi->mode & SPI_CS_HIGH;
+ u32 mr;
- dev_dbg(&spi->dev, "DEactivate %u%s\n", gpio, active ? " (low)" : "");
- gpio_set_value(gpio, !active);
+ /* only deactivate *this* device; sometimes transfers to
+ * another device may be active when this routine is called.
+ */
+ mr = spi_readl(as, MR);
+ if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) {
+ mr = SPI_BFINS(PCS, 0xf, mr);
+ spi_writel(as, MR, mr);
+ }
+
+ dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n",
+ gpio, active ? " (low)" : "",
+ mr);
+
+ if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
+ gpio_set_value(gpio, !active);
}
/*
@@ -140,6 +174,7 @@ static void atmel_spi_next_xfer(struct spi_master *master,
/* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer"
* mechanism might help avoid the IRQ latency between transfers
+ * (and improve the nCS0 errata handling on at91rm9200 chips)
*
* We're also waiting for ENDRX before we start the next
* transfer because we need to handle some difficult timing
@@ -169,33 +204,62 @@ static void atmel_spi_next_message(struct spi_master *master)
{
struct atmel_spi *as = spi_master_get_devdata(master);
struct spi_message *msg;
- u32 mr;
+ struct spi_device *spi;
BUG_ON(as->current_transfer);
msg = list_entry(as->queue.next, struct spi_message, queue);
+ spi = msg->spi;
- /* Select the chip */
- mr = spi_readl(as, MR);
- mr = SPI_BFINS(PCS, ~(1 << msg->spi->chip_select), mr);
- spi_writel(as, MR, mr);
- cs_activate(msg->spi);
+ dev_dbg(master->cdev.dev, "start message %p for %s\n",
+ msg, spi->dev.bus_id);
+
+ /* select chip if it's not still active */
+ if (as->stay) {
+ if (as->stay != spi) {
+ cs_deactivate(as, as->stay);
+ cs_activate(as, spi);
+ }
+ as->stay = NULL;
+ } else
+ cs_activate(as, spi);
atmel_spi_next_xfer(master, msg);
}
-static void
+/*
+ * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
+ * - The buffer is either valid for CPU access, else NULL
+ * - If the buffer is valid, so is its DMA addresss
+ *
+ * This driver manages the dma addresss unless message->is_dma_mapped.
+ */
+static int
atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
{
+ struct device *dev = &as->pdev->dev;
+
xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
- if (xfer->tx_buf)
- xfer->tx_dma = dma_map_single(&as->pdev->dev,
+ if (xfer->tx_buf) {
+ xfer->tx_dma = dma_map_single(dev,
(void *) xfer->tx_buf, xfer->len,
DMA_TO_DEVICE);
- if (xfer->rx_buf)
- xfer->rx_dma = dma_map_single(&as->pdev->dev,
+ if (dma_mapping_error(xfer->tx_dma))
+ return -ENOMEM;
+ }
+ if (xfer->rx_buf) {
+ xfer->rx_dma = dma_map_single(dev,
xfer->rx_buf, xfer->len,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(xfer->rx_dma)) {
+ if (xfer->tx_buf)
+ dma_unmap_single(dev,
+ xfer->tx_dma, xfer->len,
+ DMA_TO_DEVICE);
+ return -ENOMEM;
+ }
+ }
+ return 0;
}
static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
@@ -211,9 +275,13 @@ static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
static void
atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
- struct spi_message *msg, int status)
+ struct spi_message *msg, int status, int stay)
{
- cs_deactivate(msg->spi);
+ if (!stay || status < 0)
+ cs_deactivate(as, msg->spi);
+ else
+ as->stay = msg->spi;
+
list_del(&msg->queue);
msg->status = status;
@@ -303,7 +371,7 @@ atmel_spi_interrupt(int irq, void *dev_id)
/* Clear any overrun happening while cleaning up */
spi_readl(as, SR);
- atmel_spi_msg_done(master, as, msg, -EIO);
+ atmel_spi_msg_done(master, as, msg, -EIO, 0);
} else if (pending & SPI_BIT(ENDRX)) {
ret = IRQ_HANDLED;
@@ -321,12 +389,13 @@ atmel_spi_interrupt(int irq, void *dev_id)
if (msg->transfers.prev == &xfer->transfer_list) {
/* report completed message */
- atmel_spi_msg_done(master, as, msg, 0);
+ atmel_spi_msg_done(master, as, msg, 0,
+ xfer->cs_change);
} else {
if (xfer->cs_change) {
- cs_deactivate(msg->spi);
+ cs_deactivate(as, msg->spi);
udelay(1);
- cs_activate(msg->spi);
+ cs_activate(as, msg->spi);
}
/*
@@ -350,6 +419,7 @@ atmel_spi_interrupt(int irq, void *dev_id)
return ret;
}
+/* the spi->mode bits understood by this driver: */
#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
static int atmel_spi_setup(struct spi_device *spi)
@@ -388,6 +458,14 @@ static int atmel_spi_setup(struct spi_device *spi)
return -EINVAL;
}
+ /* see notes above re chipselect */
+ if (cpu_is_at91rm9200()
+ && spi->chip_select == 0
+ && (spi->mode & SPI_CS_HIGH)) {
+ dev_dbg(&spi->dev, "setup: can't be active-high\n");
+ return -EINVAL;
+ }
+
/* speed zero convention is used by some upper layers */
bus_hz = clk_get_rate(as->clk);
if (spi->max_speed_hz) {
@@ -397,8 +475,9 @@ static int atmel_spi_setup(struct spi_device *spi)
scbr = ((bus_hz + spi->max_speed_hz - 1)
/ spi->max_speed_hz);
if (scbr >= (1 << SPI_SCBR_SIZE)) {
- dev_dbg(&spi->dev, "setup: %d Hz too slow, scbr %u\n",
- spi->max_speed_hz, scbr);
+ dev_dbg(&spi->dev,
+ "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
+ spi->max_speed_hz, scbr, bus_hz/255);
return -EINVAL;
}
} else
@@ -423,6 +502,14 @@ static int atmel_spi_setup(struct spi_device *spi)
return ret;
spi->controller_state = (void *)npcs_pin;
gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
+ } else {
+ unsigned long flags;
+
+ spin_lock_irqsave(&as->lock, flags);
+ if (as->stay == spi)
+ as->stay = NULL;
+ cs_deactivate(as, spi);
+ spin_unlock_irqrestore(&as->lock, flags);
}
dev_dbg(&spi->dev,
@@ -464,14 +551,22 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
dev_dbg(&spi->dev, "no protocol options yet\n");
return -ENOPROTOOPT;
}
- }
- /* scrub dcache "early" */
- if (!msg->is_dma_mapped) {
- list_for_each_entry(xfer, &msg->transfers, transfer_list)
- atmel_spi_dma_map_xfer(as, xfer);
+ /*
+ * DMA map early, for performance (empties dcache ASAP) and
+ * better fault reporting. This is a DMA-only driver.
+ *
+ * NOTE that if dma_unmap_single() ever starts to do work on
+ * platforms supported by this driver, we would need to clean
+ * up mappings for previously-mapped transfers.
+ */
+ if (!msg->is_dma_mapped) {
+ if (atmel_spi_dma_map_xfer(as, xfer) < 0)
+ return -ENOMEM;
+ }
}
+#ifdef VERBOSE
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
dev_dbg(controller,
" xfer %p: len %u tx %p/%08x rx %p/%08x\n",
@@ -479,6 +574,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
xfer->tx_buf, xfer->tx_dma,
xfer->rx_buf, xfer->rx_dma);
}
+#endif
msg->status = -EINPROGRESS;
msg->actual_length = 0;
@@ -494,8 +590,21 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
static void atmel_spi_cleanup(struct spi_device *spi)
{
- if (spi->controller_state)
- gpio_free((unsigned int)spi->controller_data);
+ struct atmel_spi *as = spi_master_get_devdata(spi->master);
+ unsigned gpio = (unsigned) spi->controller_data;
+ unsigned long flags;
+
+ if (!spi->controller_state)
+ return;
+
+ spin_lock_irqsave(&as->lock, flags);
+ if (as->stay == spi) {
+ as->stay = NULL;
+ cs_deactivate(as, spi);
+ }
+ spin_unlock_irqrestore(&as->lock, flags);
+
+ gpio_free(gpio);
}
/*-------------------------------------------------------------------------*/
@@ -536,6 +645,10 @@ static int __init atmel_spi_probe(struct platform_device *pdev)
as = spi_master_get_devdata(master);
+ /*
+ * Scratch buffer is used for throwaway rx and tx data.
+ * It's coherent to minimize dcache pollution.
+ */
as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE,
&as->buffer_dma, GFP_KERNEL);
if (!as->buffer)
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
index ae2b1af0dba4..c47a650183a1 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/au1550_spi.c
@@ -280,6 +280,9 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
return 0;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST)
+
static int au1550_spi_setup(struct spi_device *spi)
{
struct au1550_spi *hw = spi_master_get_devdata(spi->master);
@@ -292,6 +295,12 @@ static int au1550_spi_setup(struct spi_device *spi)
return -EINVAL;
}
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
if (spi->max_speed_hz == 0)
spi->max_speed_hz = hw->freq_max;
if (spi->max_speed_hz > hw->freq_max
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 11f36bef3057..d2a4b2bdb07b 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -270,6 +270,9 @@ static void mpc52xx_psc_spi_work(struct work_struct *work)
spin_unlock_irq(&mps->lock);
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST)
+
static int mpc52xx_psc_spi_setup(struct spi_device *spi)
{
struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
@@ -279,6 +282,12 @@ static int mpc52xx_psc_spi_setup(struct spi_device *spi)
if (spi->bits_per_word%8)
return -EINVAL;
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
if (!cs) {
cs = kzalloc(sizeof *cs, GFP_KERNEL);
if (!cs)
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
index 95183e1df525..d275c615a73e 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/omap_uwire.c
@@ -445,10 +445,19 @@ done:
return status;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
static int uwire_setup(struct spi_device *spi)
{
struct uwire_state *ust = spi->controller_state;
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
if (ust == NULL) {
ust = kzalloc(sizeof(*ust), GFP_KERNEL);
if (ust == NULL)
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 9f2c887ffa04..e51311b2da0b 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1067,6 +1067,9 @@ static int transfer(struct spi_device *spi, struct spi_message *msg)
return 0;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA)
+
static int setup(struct spi_device *spi)
{
struct pxa2xx_spi_chip *chip_info = NULL;
@@ -1093,6 +1096,12 @@ static int setup(struct spi_device *spi)
return -EINVAL;
}
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
if (!chip) {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 4831edbae2d5..e84d21597943 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -23,6 +23,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/cache.h>
+#include <linux/mutex.h>
#include <linux/spi/spi.h>
@@ -185,7 +186,7 @@ struct boardinfo {
};
static LIST_HEAD(board_list);
-static DECLARE_MUTEX(board_lock);
+static DEFINE_MUTEX(board_lock);
/**
@@ -199,6 +200,8 @@ static DECLARE_MUTEX(board_lock);
* platforms may not be able to use spi_register_board_info though, and
* this is exported so that for example a USB or parport based adapter
* driver could add devices (which it would learn about out-of-band).
+ *
+ * Returns the new device, or NULL.
*/
struct spi_device *spi_new_device(struct spi_master *master,
struct spi_board_info *chip)
@@ -207,7 +210,20 @@ struct spi_device *spi_new_device(struct spi_master *master,
struct device *dev = master->cdev.dev;
int status;
- /* NOTE: caller did any chip->bus_num checks necessary */
+ /* NOTE: caller did any chip->bus_num checks necessary.
+ *
+ * Also, unless we change the return value convention to use
+ * error-or-pointer (not NULL-or-pointer), troubleshootability
+ * suggests syslogged diagnostics are best here (ugh).
+ */
+
+ /* Chipselects are numbered 0..max; validate. */
+ if (chip->chip_select >= master->num_chipselect) {
+ dev_err(dev, "cs%d > max %d\n",
+ chip->chip_select,
+ master->num_chipselect);
+ return NULL;
+ }
if (!spi_master_get(master))
return NULL;
@@ -235,10 +251,10 @@ struct spi_device *spi_new_device(struct spi_master *master,
proxy->controller_state = NULL;
proxy->dev.release = spidev_release;
- /* drivers may modify this default i/o setup */
+ /* drivers may modify this initial i/o setup */
status = master->setup(proxy);
if (status < 0) {
- dev_dbg(dev, "can't %s %s, status %d\n",
+ dev_err(dev, "can't %s %s, status %d\n",
"setup", proxy->dev.bus_id, status);
goto fail;
}
@@ -248,7 +264,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
*/
status = device_register(&proxy->dev);
if (status < 0) {
- dev_dbg(dev, "can't %s %s, status %d\n",
+ dev_err(dev, "can't %s %s, status %d\n",
"add", proxy->dev.bus_id, status);
goto fail;
}
@@ -292,9 +308,9 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
bi->n_board_info = n;
memcpy(bi->board_info, info, n * sizeof *info);
- down(&board_lock);
+ mutex_lock(&board_lock);
list_add_tail(&bi->list, &board_list);
- up(&board_lock);
+ mutex_unlock(&board_lock);
return 0;
}
@@ -302,13 +318,11 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
* creates board info from kernel command lines
*/
-static void __init_or_module
-scan_boardinfo(struct spi_master *master)
+static void scan_boardinfo(struct spi_master *master)
{
struct boardinfo *bi;
- struct device *dev = master->cdev.dev;
- down(&board_lock);
+ mutex_lock(&board_lock);
list_for_each_entry(bi, &board_list, list) {
struct spi_board_info *chip = bi->board_info;
unsigned n;
@@ -316,21 +330,13 @@ scan_boardinfo(struct spi_master *master)
for (n = bi->n_board_info; n > 0; n--, chip++) {
if (chip->bus_num != master->bus_num)
continue;
- /* some controllers only have one chip, so they
- * might not use chipselects. otherwise, the
- * chipselects are numbered 0..max.
+ /* NOTE: this relies on spi_new_device to
+ * issue diagnostics when given bogus inputs
*/
- if (chip->chip_select >= master->num_chipselect
- && master->num_chipselect) {
- dev_dbg(dev, "cs%d > max %d\n",
- chip->chip_select,
- master->num_chipselect);
- continue;
- }
(void) spi_new_device(master, chip);
}
}
- up(&board_lock);
+ mutex_unlock(&board_lock);
}
/*-------------------------------------------------------------------------*/
@@ -419,8 +425,17 @@ int spi_register_master(struct spi_master *master)
if (!dev)
return -ENODEV;
+ /* even if it's just one always-selected device, there must
+ * be at least one chipselect
+ */
+ if (master->num_chipselect == 0)
+ return -EINVAL;
+
/* convention: dynamically assigned bus IDs count down from the max */
if (master->bus_num < 0) {
+ /* FIXME switch to an IDR based scheme, something like
+ * I2C now uses, so we can't run out of "dynamic" IDs
+ */
master->bus_num = atomic_dec_return(&dyn_bus_id);
dynamic = 1;
}
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 48587c27050d..f540ed77a102 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1303,8 +1303,9 @@ static int bfin5xx_spi_resume(struct platform_device *pdev)
#define bfin5xx_spi_resume NULL
#endif /* CONFIG_PM */
+MODULE_ALIAS("bfin-spi-master"); /* for platform bus hotplug */
static struct platform_driver bfin5xx_spi_driver = {
- .driver = {
+ .driver = {
.name = "bfin-spi-master",
.owner = THIS_MODULE,
},
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 88425e1af4d3..0c85c984ccb4 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -187,12 +187,10 @@ int spi_bitbang_setup(struct spi_device *spi)
bitbang = spi_master_get_devdata(spi->master);
- /* REVISIT: some systems will want to support devices using lsb-first
- * bit encodings on the wire. In pure software that would be trivial,
- * just bitbang_txrx_le_cphaX() routines shifting the other way, and
- * some hardware controllers also have this support.
+ /* Bitbangers can support SPI_CS_HIGH, SPI_3WIRE, and so on;
+ * add those to master->flags, and provide the other support.
*/
- if ((spi->mode & SPI_LSB_FIRST) != 0)
+ if ((spi->mode & ~(SPI_CPOL|SPI_CPHA|bitbang->flags)) != 0)
return -EINVAL;
if (!cs) {
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 656be4a5094a..bd9177f51de9 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -1163,6 +1163,9 @@ msg_rejected:
return -EINVAL;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
/* On first setup bad values must free chip_data memory since will cause
spi_new_device to fail. Bad value setup from protocol driver are simply not
applied and notified to the calling driver. */
@@ -1174,6 +1177,12 @@ static int setup(struct spi_device *spi)
u32 tmp;
int status = 0;
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
/* Get controller data */
chip_info = spi->controller_data;
@@ -1245,21 +1254,6 @@ static int setup(struct spi_device *spi)
/* SPI mode */
tmp = spi->mode;
- if (tmp & SPI_LSB_FIRST) {
- status = -EINVAL;
- if (first_setup) {
- dev_err(&spi->dev,
- "setup - "
- "HW doesn't support LSB first transfer\n");
- goto err_first_setup;
- } else {
- dev_err(&spi->dev,
- "setup - "
- "HW doesn't support LSB first transfer, "
- "default to MSB first\n");
- spi->mode &= ~SPI_LSB_FIRST;
- }
- }
if (tmp & SPI_CS_HIGH) {
u32_EDIT(chip->control,
SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH);
@@ -1741,7 +1735,7 @@ static int spi_imx_resume(struct platform_device *pdev)
static struct platform_driver driver = {
.driver = {
- .name = "imx-spi",
+ .name = "spi_imx",
.bus = &platform_bus_type,
.owner = THIS_MODULE,
},
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index e9798bf7b8c6..32cda77b31cd 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -39,6 +39,7 @@ struct mpc83xx_spi_reg {
};
/* SPI Controller mode register definitions */
+#define SPMODE_LOOP (1 << 30)
#define SPMODE_CI_INACTIVEHIGH (1 << 29)
#define SPMODE_CP_BEGIN_EDGECLK (1 << 28)
#define SPMODE_DIV16 (1 << 27)
@@ -47,6 +48,7 @@ struct mpc83xx_spi_reg {
#define SPMODE_ENABLE (1 << 24)
#define SPMODE_LEN(x) ((x) << 20)
#define SPMODE_PM(x) ((x) << 16)
+#define SPMODE_OP (1 << 14)
/*
* Default for SPI Mode:
@@ -84,7 +86,12 @@ struct mpc83xx_spi {
unsigned nsecs; /* (clock cycle time)/2 */
- u32 sysclk;
+ u32 spibrg; /* SPIBRG input clock */
+ u32 rx_shift; /* RX data reg shift when in qe mode */
+ u32 tx_shift; /* TX data reg shift when in qe mode */
+
+ bool qe_mode;
+
void (*activate_cs) (u8 cs, u8 polarity);
void (*deactivate_cs) (u8 cs, u8 polarity);
};
@@ -103,7 +110,7 @@ static inline u32 mpc83xx_spi_read_reg(__be32 __iomem * reg)
void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \
{ \
type * rx = mpc83xx_spi->rx; \
- *rx++ = (type)data; \
+ *rx++ = (type)(data >> mpc83xx_spi->rx_shift); \
mpc83xx_spi->rx = rx; \
}
@@ -114,7 +121,7 @@ u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \
const type * tx = mpc83xx_spi->tx; \
if (!tx) \
return 0; \
- data = *tx++; \
+ data = *tx++ << mpc83xx_spi->tx_shift; \
mpc83xx_spi->tx = tx; \
return data; \
}
@@ -141,29 +148,48 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value)
if (value == BITBANG_CS_ACTIVE) {
u32 regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
u32 len = spi->bits_per_word;
+ u8 pm;
+
if (len == 32)
len = 0;
else
len = len - 1;
/* mask out bits we are going to set */
- regval &= ~0x38ff0000;
+ regval &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
+ | SPMODE_LEN(0xF) | SPMODE_DIV16
+ | SPMODE_PM(0xF) | SPMODE_REV | SPMODE_LOOP);
if (spi->mode & SPI_CPHA)
regval |= SPMODE_CP_BEGIN_EDGECLK;
if (spi->mode & SPI_CPOL)
regval |= SPMODE_CI_INACTIVEHIGH;
+ if (!(spi->mode & SPI_LSB_FIRST))
+ regval |= SPMODE_REV;
+ if (spi->mode & SPI_LOOP)
+ regval |= SPMODE_LOOP;
regval |= SPMODE_LEN(len);
- if ((mpc83xx_spi->sysclk / spi->max_speed_hz) >= 64) {
- u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 64);
+ if ((mpc83xx_spi->spibrg / spi->max_speed_hz) >= 64) {
+ pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 64) - 1;
+ if (pm > 0x0f) {
+ dev_err(&spi->dev, "Requested speed is too "
+ "low: %d Hz. Will use %d Hz instead.\n",
+ spi->max_speed_hz,
+ mpc83xx_spi->spibrg / 1024);
+ pm = 0x0f;
+ }
regval |= SPMODE_PM(pm) | SPMODE_DIV16;
} else {
- u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 4);
+ pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 4);
+ if (pm)
+ pm--;
regval |= SPMODE_PM(pm);
}
+ /* Turn off SPI unit prior changing mode */
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0);
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
if (mpc83xx_spi->activate_cs)
mpc83xx_spi->activate_cs(spi->chip_select, pol);
@@ -197,18 +223,36 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|| ((bits_per_word > 16) && (bits_per_word != 32)))
return -EINVAL;
+ mpc83xx_spi->rx_shift = 0;
+ mpc83xx_spi->tx_shift = 0;
if (bits_per_word <= 8) {
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
+ if (mpc83xx_spi->qe_mode) {
+ mpc83xx_spi->rx_shift = 16;
+ mpc83xx_spi->tx_shift = 24;
+ }
} else if (bits_per_word <= 16) {
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16;
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16;
+ if (mpc83xx_spi->qe_mode) {
+ mpc83xx_spi->rx_shift = 16;
+ mpc83xx_spi->tx_shift = 16;
+ }
} else if (bits_per_word <= 32) {
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32;
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32;
} else
return -EINVAL;
+ if (mpc83xx_spi->qe_mode && spi->mode & SPI_LSB_FIRST) {
+ mpc83xx_spi->tx_shift = 0;
+ if (bits_per_word <= 8)
+ mpc83xx_spi->rx_shift = 8;
+ else
+ mpc83xx_spi->rx_shift = 0;
+ }
+
/* nsecs = (clock period)/2 */
if (!hz)
hz = spi->max_speed_hz;
@@ -223,21 +267,35 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
- /* Mask out bits_per_wordgth */
- regval &= 0xff0fffff;
+ /* mask out bits we are going to set */
+ regval &= ~(SPMODE_LEN(0xF) | SPMODE_REV);
regval |= SPMODE_LEN(bits_per_word);
+ if (!(spi->mode & SPI_LSB_FIRST))
+ regval |= SPMODE_REV;
+ /* Turn off SPI unit prior changing mode */
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0);
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
return 0;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
+ | SPI_LSB_FIRST | SPI_LOOP)
+
static int mpc83xx_spi_setup(struct spi_device *spi)
{
struct spi_bitbang *bitbang;
struct mpc83xx_spi *mpc83xx_spi;
int retval;
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
if (!spi->max_speed_hz)
return -EINVAL;
@@ -326,11 +384,8 @@ irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data)
mpc83xx_spi->count -= 1;
if (mpc83xx_spi->count) {
- if (mpc83xx_spi->tx) {
- u32 word = mpc83xx_spi->get_tx(mpc83xx_spi);
- mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit,
- word);
- }
+ u32 word = mpc83xx_spi->get_tx(mpc83xx_spi);
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit, word);
} else {
complete(&mpc83xx_spi->done);
}
@@ -371,18 +426,29 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev)
ret = -ENODEV;
goto free_master;
}
-
mpc83xx_spi = spi_master_get_devdata(master);
mpc83xx_spi->bitbang.master = spi_master_get(master);
mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect;
mpc83xx_spi->bitbang.setup_transfer = mpc83xx_spi_setup_transfer;
mpc83xx_spi->bitbang.txrx_bufs = mpc83xx_spi_bufs;
- mpc83xx_spi->sysclk = pdata->sysclk;
mpc83xx_spi->activate_cs = pdata->activate_cs;
mpc83xx_spi->deactivate_cs = pdata->deactivate_cs;
+ mpc83xx_spi->qe_mode = pdata->qe_mode;
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
+ if (mpc83xx_spi->qe_mode)
+ mpc83xx_spi->spibrg = pdata->sysclk / 2;
+ else
+ mpc83xx_spi->spibrg = pdata->sysclk;
+
+ mpc83xx_spi->rx_shift = 0;
+ mpc83xx_spi->tx_shift = 0;
+ if (mpc83xx_spi->qe_mode) {
+ mpc83xx_spi->rx_shift = 16;
+ mpc83xx_spi->tx_shift = 24;
+ }
+
mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup;
init_completion(&mpc83xx_spi->done);
@@ -417,6 +483,9 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev)
/* Enable SPI interface */
regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+ if (pdata->qe_mode)
+ regval |= SPMODE_OP;
+
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
ret = spi_bitbang_start(&mpc83xx_spi->bitbang);
@@ -458,6 +527,7 @@ static int __devexit mpc83xx_spi_remove(struct platform_device *dev)
return 0;
}
+MODULE_ALIAS("mpc83xx_spi"); /* for platform bus hotplug */
static struct platform_driver mpc83xx_spi_driver = {
.probe = mpc83xx_spi_probe,
.remove = __devexit_p(mpc83xx_spi_remove),
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index d5a710f6e445..e9b683f7d7b3 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -28,7 +28,7 @@
#include <asm/hardware.h>
#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-spi.h>
+#include <asm/plat-s3c24xx/regs-spi.h>
#include <asm/arch/spi.h>
struct s3c24xx_spi {
@@ -146,6 +146,9 @@ static int s3c24xx_spi_setupxfer(struct spi_device *spi,
return 0;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
static int s3c24xx_spi_setup(struct spi_device *spi)
{
int ret;
@@ -153,8 +156,11 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
if (!spi->bits_per_word)
spi->bits_per_word = 8;
- if ((spi->mode & SPI_LSB_FIRST) != 0)
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
return -EINVAL;
+ }
ret = s3c24xx_spi_setupxfer(spi, NULL);
if (ret < 0) {
@@ -421,6 +427,7 @@ static int s3c24xx_spi_resume(struct platform_device *pdev)
#define s3c24xx_spi_resume NULL
#endif
+MODULE_ALIAS("s3c2410_spi"); /* for platform bus hotplug */
static struct platform_driver s3c24xx_spidrv = {
.probe = s3c24xx_spi_probe,
.remove = s3c24xx_spi_remove,
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
index 611ac22b7cdc..0fa25e2e80fe 100644
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ b/drivers/spi/spi_s3c24xx_gpio.c
@@ -180,7 +180,7 @@ static struct platform_driver s3c2410_spigpio_drv = {
.suspend = s3c2410_spigpio_suspend,
.resume = s3c2410_spigpio_resume,
.driver = {
- .name = "s3c24xx-spi-gpio",
+ .name = "spi_s3c24xx_gpio",
.owner = THIS_MODULE,
},
};
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index d04242aee40d..c55459c592b8 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -55,9 +55,16 @@
static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG];
-/* Bit masks for spi_device.mode management */
-#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL)
-
+/* Bit masks for spi_device.mode management. Note that incorrect
+ * settings for CS_HIGH and 3WIRE can cause *lots* of trouble for other
+ * devices on a shared bus: CS_HIGH, because this device will be
+ * active when it shouldn't be; 3WIRE, because when active it won't
+ * behave as it should.
+ *
+ * REVISIT should changing those two modes be privileged?
+ */
+#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
+ | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP)
struct spidev_data {
struct device dev;
@@ -176,12 +183,15 @@ static int spidev_message(struct spidev_data *spidev,
if (u_tmp->rx_buf) {
k_tmp->rx_buf = buf;
- if (!access_ok(VERIFY_WRITE, u_tmp->rx_buf, u_tmp->len))
+ if (!access_ok(VERIFY_WRITE, (u8 __user *)
+ (ptrdiff_t) u_tmp->rx_buf,
+ u_tmp->len))
goto done;
}
if (u_tmp->tx_buf) {
k_tmp->tx_buf = buf;
- if (copy_from_user(buf, (const u8 __user *)u_tmp->tx_buf,
+ if (copy_from_user(buf, (const u8 __user *)
+ (ptrdiff_t) u_tmp->tx_buf,
u_tmp->len))
goto done;
}
@@ -213,7 +223,8 @@ static int spidev_message(struct spidev_data *spidev,
buf = spidev->buffer;
for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
if (u_tmp->rx_buf) {
- if (__copy_to_user((u8 __user *)u_tmp->rx_buf, buf,
+ if (__copy_to_user((u8 __user *)
+ (ptrdiff_t) u_tmp->rx_buf, buf,
u_tmp->len)) {
status = -EFAULT;
goto done;