aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/mpc52xx_psc_spi.c61
-rw-r--r--drivers/spi/omap2_mcspi.c18
-rw-r--r--drivers/spi/omap_uwire.c23
-rw-r--r--drivers/spi/orion_spi.c7
-rw-r--r--drivers/spi/pxa2xx_spi.c170
-rw-r--r--drivers/spi/spi.c24
-rw-r--r--drivers/spi/spi_mpc83xx.c26
-rw-r--r--drivers/spi/spi_s3c24xx.c12
-rw-r--r--drivers/spi/spidev.c7
9 files changed, 203 insertions, 145 deletions
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 25eda71..0debe11 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -15,13 +15,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
-
-#if defined(CONFIG_PPC_MERGE)
#include <linux/of_platform.h>
-#else
-#include <linux/platform_device.h>
-#endif
-
#include <linux/workqueue.h>
#include <linux/completion.h>
#include <linux/io.h>
@@ -108,13 +102,13 @@ static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
* Because psc->ccr is defined as 16bit register instead of 32bit
* just set the lower byte of BitClkDiv
*/
- ccr = in_be16(&psc->ccr);
+ ccr = in_be16((u16 __iomem *)&psc->ccr);
ccr &= 0xFF00;
if (cs->speed_hz)
ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
else /* by default SPI Clk 1MHz */
ccr |= (MCLK / 1000000 - 1) & 0xFF;
- out_be16(&psc->ccr, ccr);
+ out_be16((u16 __iomem *)&psc->ccr, ccr);
mps->bits_per_word = cs->bits_per_word;
if (mps->activate_cs)
@@ -347,7 +341,7 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
/* Configure 8bit codec mode as a SPI master and use EOF flags */
/* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
out_be32(&psc->sicr, 0x0180C800);
- out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */
+ out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
/* Set 2ms DTL delay */
out_8(&psc->ctur, 0x00);
@@ -471,53 +465,6 @@ static int __exit mpc52xx_psc_spi_do_remove(struct device *dev)
return 0;
}
-#if !defined(CONFIG_PPC_MERGE)
-static int __init mpc52xx_psc_spi_probe(struct platform_device *dev)
-{
- switch(dev->id) {
- case 1:
- case 2:
- case 3:
- case 6:
- return mpc52xx_psc_spi_do_probe(&dev->dev,
- MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)),
- MPC52xx_PSC_SIZE, platform_get_irq(dev, 0), dev->id);
- default:
- return -EINVAL;
- }
-}
-
-static int __exit mpc52xx_psc_spi_remove(struct platform_device *dev)
-{
- return mpc52xx_psc_spi_do_remove(&dev->dev);
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:mpc52xx-psc-spi");
-
-static struct platform_driver mpc52xx_psc_spi_platform_driver = {
- .remove = __exit_p(mpc52xx_psc_spi_remove),
- .driver = {
- .name = "mpc52xx-psc-spi",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init mpc52xx_psc_spi_init(void)
-{
- return platform_driver_probe(&mpc52xx_psc_spi_platform_driver,
- mpc52xx_psc_spi_probe);
-}
-module_init(mpc52xx_psc_spi_init);
-
-static void __exit mpc52xx_psc_spi_exit(void)
-{
- platform_driver_unregister(&mpc52xx_psc_spi_platform_driver);
-}
-module_exit(mpc52xx_psc_spi_exit);
-
-#else /* defined(CONFIG_PPC_MERGE) */
-
static int __init mpc52xx_psc_spi_of_probe(struct of_device *op,
const struct of_device_id *match)
{
@@ -586,8 +533,6 @@ static void __exit mpc52xx_psc_spi_exit(void)
}
module_exit(mpc52xx_psc_spi_exit);
-#endif /* defined(CONFIG_PPC_MERGE) */
-
MODULE_AUTHOR("Dragos Carp");
MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 9d2186f..454a271 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -119,12 +119,14 @@ struct omap2_mcspi {
struct clk *fck;
/* Virtual base address of the controller */
void __iomem *base;
+ unsigned long phys;
/* SPI1 has 4 channels, while SPI2 has 2 */
struct omap2_mcspi_dma *dma_channels;
};
struct omap2_mcspi_cs {
void __iomem *base;
+ unsigned long phys;
int word_len;
};
@@ -233,7 +235,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
c = count;
word_len = cs->word_len;
- base = (unsigned long) io_v2p(cs->base);
+ base = cs->phys;
tx_reg = base + OMAP2_MCSPI_TX0;
rx_reg = base + OMAP2_MCSPI_RX0;
rx = xfer->rx_buf;
@@ -633,6 +635,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
if (!cs)
return -ENOMEM;
cs->base = mcspi->base + spi->chip_select * 0x14;
+ cs->phys = mcspi->phys + spi->chip_select * 0x14;
spi->controller_state = cs;
}
@@ -1005,7 +1008,13 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
goto err1;
}
- mcspi->base = (void __iomem *) io_p2v(r->start);
+ mcspi->phys = r->start;
+ mcspi->base = ioremap(r->start, r->end - r->start + 1);
+ if (!mcspi->base) {
+ dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
+ status = -ENOMEM;
+ goto err1aa;
+ }
INIT_WORK(&mcspi->work, omap2_mcspi_work);
@@ -1055,6 +1064,8 @@ err3:
err2:
clk_put(mcspi->ick);
err1a:
+ iounmap(mcspi->base);
+err1aa:
release_mem_region(r->start, (r->end - r->start) + 1);
err1:
spi_master_put(master);
@@ -1067,6 +1078,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
struct omap2_mcspi *mcspi;
struct omap2_mcspi_dma *dma_channels;
struct resource *r;
+ void __iomem *base;
master = dev_get_drvdata(&pdev->dev);
mcspi = spi_master_get_devdata(master);
@@ -1078,7 +1090,9 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(r->start, (r->end - r->start) + 1);
+ base = mcspi->base;
spi_unregister_master(master);
+ iounmap(base);
kfree(dma_channels);
return 0;
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
index 5515eb9..bab6ff0 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/omap_uwire.c
@@ -59,7 +59,6 @@
* and irqs should show there too...
*/
#define UWIRE_BASE_PHYS 0xFFFB3000
-#define UWIRE_BASE ((void *__iomem)IO_ADDRESS(UWIRE_BASE_PHYS))
/* uWire Registers: */
#define UWIRE_IO_SIZE 0x20
@@ -103,16 +102,21 @@ struct uwire_state {
};
/* REVISIT compile time constant for idx_shift? */
+/*
+ * Or, put it in a structure which is used throughout the driver;
+ * that avoids having to issue two loads for each bit of static data.
+ */
static unsigned int uwire_idx_shift;
+static void __iomem *uwire_base;
static inline void uwire_write_reg(int idx, u16 val)
{
- __raw_writew(val, UWIRE_BASE + (idx << uwire_idx_shift));
+ __raw_writew(val, uwire_base + (idx << uwire_idx_shift));
}
static inline u16 uwire_read_reg(int idx)
{
- return __raw_readw(UWIRE_BASE + (idx << uwire_idx_shift));
+ return __raw_readw(uwire_base + (idx << uwire_idx_shift));
}
static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags)
@@ -492,6 +496,14 @@ static int __init uwire_probe(struct platform_device *pdev)
return -ENODEV;
uwire = spi_master_get_devdata(master);
+
+ uwire_base = ioremap(UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
+ if (!uwire_base) {
+ dev_dbg(&pdev->dev, "can't ioremap UWIRE\n");
+ spi_master_put(master);
+ return -ENOMEM;
+ }
+
dev_set_drvdata(&pdev->dev, uwire);
uwire->ck = clk_get(&pdev->dev, "armxor_ck");
@@ -520,8 +532,10 @@ static int __init uwire_probe(struct platform_device *pdev)
uwire->bitbang.txrx_bufs = uwire_txrx;
status = spi_bitbang_start(&uwire->bitbang);
- if (status < 0)
+ if (status < 0) {
uwire_off(uwire);
+ iounmap(uwire_base);
+ }
return status;
}
@@ -534,6 +548,7 @@ static int __exit uwire_remove(struct platform_device *pdev)
status = spi_bitbang_stop(&uwire->bitbang);
uwire_off(uwire);
+ iounmap(uwire_base);
return status;
}
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c
index c4eaacd..014becb 100644
--- a/drivers/spi/orion_spi.c
+++ b/drivers/spi/orion_spi.c
@@ -364,6 +364,11 @@ static int orion_spi_setup(struct spi_device *spi)
return -EINVAL;
}
+ /* Fix ac timing if required. */
+ if (orion_spi->spi_info->enable_clock_fix)
+ orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+ (1 << 14));
+
if (spi->bits_per_word == 0)
spi->bits_per_word = 8;
@@ -427,7 +432,7 @@ static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
goto msg_rejected;
}
- if (t->speed_hz < orion_spi->min_speed) {
+ if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
dev_err(&spi->dev,
"message rejected : "
"device min speed (%d Hz) exceeds "
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 34c7c98..dae87b1 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -47,9 +47,14 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define MAX_BUSES 3
-#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
-#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
-#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
+#define RX_THRESH_DFLT 8
+#define TX_THRESH_DFLT 8
+#define TIMOUT_DFLT 1000
+
+#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
+#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
+#define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0)
+#define MAX_DMA_LEN 8191
/*
* for testing SSCR1 changes that require SSP restart, basically
@@ -144,7 +149,6 @@ struct driver_data {
size_t tx_map_len;
u8 n_bytes;
u32 dma_width;
- int cs_change;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
@@ -406,8 +410,45 @@ static void giveback(struct driver_data *drv_data)
struct spi_transfer,
transfer_list);
+ /* Delay if requested before any change in chip select */
+ if (last_transfer->delay_usecs)
+ udelay(last_transfer->delay_usecs);
+
+ /* Drop chip select UNLESS cs_change is true or we are returning
+ * a message with an error, or next message is for another chip
+ */
if (!last_transfer->cs_change)
drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ else {
+ struct spi_message *next_msg;
+
+ /* Holding of cs was hinted, but we need to make sure
+ * the next message is for the same chip. Don't waste
+ * time with the following tests unless this was hinted.
+ *
+ * We cannot postpone this until pump_messages, because
+ * after calling msg->complete (below) the driver that
+ * sent the current message could be unloaded, which
+ * could invalidate the cs_control() callback...
+ */
+
+ /* get a pointer to the next message, if any */
+ spin_lock_irqsave(&drv_data->lock, flags);
+ if (list_empty(&drv_data->queue))
+ next_msg = NULL;
+ else
+ next_msg = list_entry(drv_data->queue.next,
+ struct spi_message, queue);
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+
+ /* see if the next and current messages point
+ * to the same chip
+ */
+ if (next_msg && next_msg->spi != msg->spi)
+ next_msg = NULL;
+ if (!next_msg || msg->state == ERROR_STATE)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ }
msg->state = NULL;
if (msg->complete)
@@ -490,10 +531,9 @@ static void dma_transfer_complete(struct driver_data *drv_data)
msg->actual_length += drv_data->len -
(drv_data->rx_end - drv_data->rx);
- /* Release chip select if requested, transfer delays are
- * handled in pump_transfers */
- if (drv_data->cs_change)
- drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ /* Transfer delays and chip select release are
+ * handled in pump_transfers or giveback
+ */
/* Move to next transfer */
msg->state = next_transfer(drv_data);
@@ -602,10 +642,9 @@ static void int_transfer_complete(struct driver_data *drv_data)
drv_data->cur_msg->actual_length += drv_data->len -
(drv_data->rx_end - drv_data->rx);
- /* Release chip select if requested, transfer delays are
- * handled in pump_transfers */
- if (drv_data->cs_change)
- drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ /* Transfer delays and chip select release are
+ * handled in pump_transfers or giveback
+ */
/* Move to next transfer */
drv_data->cur_msg->state = next_transfer(drv_data);
@@ -840,23 +879,40 @@ static void pump_transfers(unsigned long data)
return;
}
- /* Delay if requested at end of transfer*/
+ /* Delay if requested at end of transfer before CS change */
if (message->state == RUNNING_STATE) {
previous = list_entry(transfer->transfer_list.prev,
struct spi_transfer,
transfer_list);
if (previous->delay_usecs)
udelay(previous->delay_usecs);
+
+ /* Drop chip select only if cs_change is requested */
+ if (previous->cs_change)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
}
- /* Check transfer length */
- if (transfer->len > 8191)
- {
- dev_warn(&drv_data->pdev->dev, "pump_transfers: transfer "
- "length greater than 8191\n");
- message->status = -EINVAL;
- giveback(drv_data);
- return;
+ /* Check for transfers that need multiple DMA segments */
+ if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
+
+ /* reject already-mapped transfers; PIO won't always work */
+ if (message->is_dma_mapped
+ || transfer->rx_dma || transfer->tx_dma) {
+ dev_err(&drv_data->pdev->dev,
+ "pump_transfers: mapped transfer length "
+ "of %u is greater than %d\n",
+ transfer->len, MAX_DMA_LEN);
+ message->status = -EINVAL;
+ giveback(drv_data);
+ return;
+ }
+
+ /* warn ... we force this to PIO mode */
+ if (printk_ratelimit())
+ dev_warn(&message->spi->dev, "pump_transfers: "
+ "DMA disabled for transfer length %ld "
+ "greater than %d\n",
+ (long)drv_data->len, MAX_DMA_LEN);
}
/* Setup the transfer state based on the type of transfer */
@@ -878,7 +934,6 @@ static void pump_transfers(unsigned long data)
drv_data->len = transfer->len & DCMD_LENGTH;
drv_data->write = drv_data->tx ? chip->write : null_writer;
drv_data->read = drv_data->rx ? chip->read : null_reader;
- drv_data->cs_change = transfer->cs_change;
/* Change speed and bit per word on a per transfer */
cr0 = chip->cr0;
@@ -925,7 +980,7 @@ static void pump_transfers(unsigned long data)
&dma_thresh))
if (printk_ratelimit())
dev_warn(&message->spi->dev,
- "pump_transfer: "
+ "pump_transfers: "
"DMA burst size reduced to "
"match bits_per_word\n");
}
@@ -939,8 +994,23 @@ static void pump_transfers(unsigned long data)
message->state = RUNNING_STATE;
- /* Try to map dma buffer and do a dma transfer if successful */
- if ((drv_data->dma_mapped = map_dma_buffers(drv_data))) {
+ /* Try to map dma buffer and do a dma transfer if successful, but
+ * only if the length is non-zero and less than MAX_DMA_LEN.
+ *
+ * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
+ * of PIO instead. Care is needed above because the transfer may
+ * have have been passed with buffers that are already dma mapped.
+ * A zero-length transfer in PIO mode will not try to write/read
+ * to/from the buffers
+ *
+ * REVISIT large transfers are exactly where we most want to be
+ * using DMA. If this happens much, split those transfers into
+ * multiple DMA segments rather than forcing PIO.
+ */
+ drv_data->dma_mapped = 0;
+ if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN)
+ drv_data->dma_mapped = map_dma_buffers(drv_data);
+ if (drv_data->dma_mapped) {
/* Ensure we have the correct interrupt handler */
drv_data->transfer_handler = dma_transfer;
@@ -1105,6 +1175,8 @@ static int setup(struct spi_device *spi)
struct driver_data *drv_data = spi_master_get_devdata(spi->master);
struct ssp_device *ssp = drv_data->ssp;
unsigned int clk_div;
+ uint tx_thres = TX_THRESH_DFLT;
+ uint rx_thres = RX_THRESH_DFLT;
if (!spi->bits_per_word)
spi->bits_per_word = 8;
@@ -1143,8 +1215,7 @@ static int setup(struct spi_device *spi)
chip->cs_control = null_cs_control;
chip->enable_dma = 0;
- chip->timeout = 1000;
- chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
+ chip->timeout = TIMOUT_DFLT;
chip->dma_burst_size = drv_data->master_info->enable_dma ?
DCMD_BURST8 : 0;
}
@@ -1158,22 +1229,21 @@ static int setup(struct spi_device *spi)
if (chip_info) {
if (chip_info->cs_control)
chip->cs_control = chip_info->cs_control;
-
- chip->timeout = chip_info->timeout;
-
- chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) &
- SSCR1_RFT) |
- (SSCR1_TxTresh(chip_info->tx_threshold) &
- SSCR1_TFT);
-
- chip->enable_dma = chip_info->dma_burst_size != 0
- && drv_data->master_info->enable_dma;
+ if (chip_info->timeout)
+ chip->timeout = chip_info->timeout;
+ if (chip_info->tx_threshold)
+ tx_thres = chip_info->tx_threshold;
+ if (chip_info->rx_threshold)
+ rx_thres = chip_info->rx_threshold;
+ chip->enable_dma = drv_data->master_info->enable_dma;
chip->dma_threshold = 0;
-
if (chip_info->enable_loopback)
chip->cr1 = SSCR1_LBM;
}
+ chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
+ (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
+
/* set dma burst and threshold outside of chip_info path so that if
* chip_info goes away after setting chip->enable_dma, the
* burst and threshold can still respond to changes in bits_per_word */
@@ -1202,17 +1272,19 @@ static int setup(struct spi_device *spi)
/* NOTE: PXA25x_SSP _could_ use external clocking ... */
if (drv_data->ssp_type != PXA25x_SSP)
- dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n",
+ dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n",
spi->bits_per_word,
clk_get_rate(ssp->clk)
/ (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
- spi->mode & 0x3);
+ spi->mode & 0x3,
+ chip->enable_dma ? "DMA" : "PIO");
else
- dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n",
+ dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n",
spi->bits_per_word,
- clk_get_rate(ssp->clk)
+ clk_get_rate(ssp->clk) / 2
/ (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
- spi->mode & 0x3);
+ spi->mode & 0x3,
+ chip->enable_dma ? "DMA" : "PIO");
if (spi->bits_per_word <= 8) {
chip->n_bytes = 1;
@@ -1341,9 +1413,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct pxa2xx_spi_master *platform_info;
struct spi_master *master;
- struct driver_data *drv_data = NULL;
+ struct driver_data *drv_data;
struct ssp_device *ssp;
- int status = 0;
+ int status;
platform_info = dev->platform_data;
@@ -1356,7 +1428,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
/* Allocate master with space for drv_data and null dma buffer */
master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
if (!master) {
- dev_err(&pdev->dev, "can not alloc spi_master\n");
+ dev_err(&pdev->dev, "cannot alloc spi_master\n");
ssp_free(ssp);
return -ENOMEM;
}
@@ -1392,7 +1464,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data);
if (status < 0) {
- dev_err(&pdev->dev, "can not get IRQ\n");
+ dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
goto out_error_master_alloc;
}
@@ -1432,7 +1504,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
/* Load default SSP configuration */
write_SSCR0(0, drv_data->ioaddr);
- write_SSCR1(SSCR1_RxTresh(4) | SSCR1_TxTresh(12), drv_data->ioaddr);
+ write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
+ SSCR1_TxTresh(TX_THRESH_DFLT),
+ drv_data->ioaddr);
write_SSCR0(SSCR0_SerClkDiv(2)
| SSCR0_Motorola
| SSCR0_DataSize(8),
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 75e8686..3734dc9 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -660,7 +660,7 @@ int spi_write_then_read(struct spi_device *spi,
int status;
struct spi_message message;
- struct spi_transfer x[2];
+ struct spi_transfer x;
u8 *local_buf;
/* Use preallocated DMA-safe buffer. We can't avoid copying here,
@@ -671,15 +671,9 @@ int spi_write_then_read(struct spi_device *spi,
return -EINVAL;
spi_message_init(&message);
- memset(x, 0, sizeof x);
- if (n_tx) {
- x[0].len = n_tx;
- spi_message_add_tail(&x[0], &message);
- }
- if (n_rx) {
- x[1].len = n_rx;
- spi_message_add_tail(&x[1], &message);
- }
+ memset(&x, 0, sizeof x);
+ x.len = n_tx + n_rx;
+ spi_message_add_tail(&x, &message);
/* ... unless someone else is using the pre-allocated buffer */
if (!mutex_trylock(&lock)) {
@@ -690,15 +684,15 @@ int spi_write_then_read(struct spi_device *spi,
local_buf = buf;
memcpy(local_buf, txbuf, n_tx);
- x[0].tx_buf = local_buf;
- x[1].rx_buf = local_buf + n_tx;
+ x.tx_buf = local_buf;
+ x.rx_buf = local_buf;
/* do the i/o */
status = spi_sync(spi, &message);
if (status == 0)
- memcpy(rxbuf, x[1].rx_buf, n_rx);
+ memcpy(rxbuf, x.rx_buf + n_tx, n_rx);
- if (x[0].tx_buf == buf)
+ if (x.tx_buf == buf)
mutex_unlock(&lock);
else
kfree(local_buf);
@@ -744,5 +738,5 @@ err0:
* driver registration) _could_ be dynamically linked (modular) ... costs
* include needing to have boardinfo data structures be much more public.
*/
-subsys_initcall(spi_init);
+postcore_initcall(spi_init);
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index 070c621..ac0e3e4 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -267,16 +267,13 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
cs->hw_mode |= SPMODE_LEN(bits_per_word);
if ((mpc83xx_spi->spibrg / hz) > 64) {
+ cs->hw_mode |= SPMODE_DIV16;
pm = mpc83xx_spi->spibrg / (hz * 64);
if (pm > 16) {
- cs->hw_mode |= SPMODE_DIV16;
- pm /= 16;
- if (pm > 16) {
- dev_err(&spi->dev, "Requested speed is too "
- "low: %d Hz. Will use %d Hz instead.\n",
- hz, mpc83xx_spi->spibrg / 1024);
- pm = 16;
- }
+ dev_err(&spi->dev, "Requested speed is too "
+ "low: %d Hz. Will use %d Hz instead.\n",
+ hz, mpc83xx_spi->spibrg / 1024);
+ pm = 16;
}
} else
pm = mpc83xx_spi->spibrg / (hz * 4);
@@ -315,11 +312,20 @@ static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
if (t->bits_per_word)
bits_per_word = t->bits_per_word;
len = t->len;
- if (bits_per_word > 8)
+ if (bits_per_word > 8) {
+ /* invalid length? */
+ if (len & 1)
+ return -EINVAL;
len /= 2;
- if (bits_per_word > 16)
+ }
+ if (bits_per_word > 16) {
+ /* invalid length? */
+ if (len & 1)
+ return -EINVAL;
len /= 2;
+ }
mpc83xx_spi->count = len;
+
INIT_COMPLETION(mpc83xx_spi->done);
/* enable rx ints */
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 98abc73..c252cba 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -247,6 +247,9 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
writeb(0xff, hw->regs + S3C2410_SPPRE);
writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
+
+ if (hw->pdata && hw->pdata->gpio_setup)
+ hw->pdata->gpio_setup(hw->pdata, 1);
}
static int __init s3c24xx_spi_probe(struct platform_device *pdev)
@@ -412,6 +415,9 @@ static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
{
struct s3c24xx_spi *hw = platform_get_drvdata(pdev);
+ if (hw->pdata && hw->pdata->gpio_setup)
+ hw->pdata->gpio_setup(hw->pdata, 0);
+
clk_disable(hw->clk);
return 0;
}
@@ -430,7 +436,7 @@ static int s3c24xx_spi_resume(struct platform_device *pdev)
#endif
MODULE_ALIAS("platform:s3c2410-spi");
-static struct platform_driver s3c24xx_spidrv = {
+static struct platform_driver s3c24xx_spi_driver = {
.remove = __exit_p(s3c24xx_spi_remove),
.suspend = s3c24xx_spi_suspend,
.resume = s3c24xx_spi_resume,
@@ -442,12 +448,12 @@ static struct platform_driver s3c24xx_spidrv = {
static int __init s3c24xx_spi_init(void)
{
- return platform_driver_probe(&s3c24xx_spidrv, s3c24xx_spi_probe);
+ return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);
}
static void __exit s3c24xx_spi_exit(void)
{
- platform_driver_unregister(&s3c24xx_spidrv);
+ platform_driver_unregister(&s3c24xx_spi_driver);
}
module_init(s3c24xx_spi_init);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index e5e0cfe..89a4375 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -583,10 +583,9 @@ static int spidev_probe(struct spi_device *spi)
struct device *dev;
spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
- dev = device_create_drvdata(spidev_class, &spi->dev,
- spidev->devt, spidev,
- "spidev%d.%d",
- spi->master->bus_num, spi->chip_select);
+ 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");