diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/atmel_spi.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi.c | 55 | ||||
-rw-r--r-- | drivers/spi/spi_bfin5xx.c | 3 | ||||
-rw-r--r-- | drivers/spi/spi_imx.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi_mpc83xx.c | 63 | ||||
-rw-r--r-- | drivers/spi/spi_s3c24xx.c | 3 | ||||
-rw-r--r-- | drivers/spi/spi_s3c24xx_gpio.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi_txx9.c | 2 | ||||
-rw-r--r-- | drivers/spi/spidev.c | 17 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi.c | 2 |
10 files changed, 101 insertions, 50 deletions
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index ad144054da3..b0469749310 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -251,7 +251,7 @@ atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer) xfer->rx_dma = dma_map_single(dev, xfer->rx_buf, xfer->len, DMA_FROM_DEVICE); - if (dma_mapping_error(xfer->tx_dma)) { + if (dma_mapping_error(xfer->rx_dma)) { if (xfer->tx_buf) dma_unmap_single(dev, xfer->tx_dma, xfer->len, diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 018884d7a5f..bcb8dd5fb0b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -67,14 +67,11 @@ static int spi_match_device(struct device *dev, struct device_driver *drv) return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; } -static int spi_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) { const struct spi_device *spi = to_spi_device(dev); - envp[0] = buffer; - snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias); - envp[1] = NULL; + add_uevent_var(env, "MODALIAS=%s", spi->modalias); return 0; } @@ -200,6 +197,8 @@ static DEFINE_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) @@ -208,7 +207,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; @@ -236,10 +248,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; } @@ -249,7 +261,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; } @@ -303,11 +315,9 @@ 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; mutex_lock(&board_lock); list_for_each_entry(bi, &board_list, list) { @@ -317,17 +327,9 @@ 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); } } @@ -420,8 +422,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 48587c27050..f540ed77a10 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_imx.c b/drivers/spi/spi_imx.c index aee9ad6f633..bd9177f51de 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -1735,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 3295cfcc9f2..32cda77b31c 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) @@ -85,7 +86,7 @@ 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 */ @@ -147,35 +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) { - printk(KERN_WARNING "MPC83xx SPI: SPICLK can't be less then a SYSCLK/1024!\n" - "Requested SPICLK is %d Hz. Will use %d Hz instead.\n", - spi->max_speed_hz, mpc83xx_spi->sysclk / 1024); + 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); @@ -231,6 +245,14 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) } 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; @@ -245,17 +267,22 @@ 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) +#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ + | SPI_LSB_FIRST | SPI_LOOP) static int mpc83xx_spi_setup(struct spi_device *spi) { @@ -357,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); } @@ -407,13 +431,17 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) 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) { @@ -499,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 7071ff8da63..e9b683f7d7b 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 { @@ -427,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 611ac22b7cd..0fa25e2e80f 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/spi_txx9.c b/drivers/spi/spi_txx9.c index 08e981c4064..b7f4bb239ea 100644 --- a/drivers/spi/spi_txx9.c +++ b/drivers/spi/spi_txx9.c @@ -453,7 +453,7 @@ static int __exit txx9spi_remove(struct platform_device *dev) static struct platform_driver txx9spi_driver = { .remove = __exit_p(txx9spi_remove), .driver = { - .name = "txx9spi", + .name = "spi_txx9", .owner = THIS_MODULE, }, }; diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 38b60ad0eda..c55459c592b 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,7 +183,9 @@ 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) { diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index f0bf9a68e96..5d04f520c12 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -21,7 +21,7 @@ #include <syslib/virtex_devices.h> -#define XILINX_SPI_NAME "xspi" +#define XILINX_SPI_NAME "xilinx_spi" /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) * Product Specification", DS464 |