diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-au1550.c | 6 | ||||
-rw-r--r-- | drivers/spi/spi-cadence.c | 35 | ||||
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 14 | ||||
-rw-r--r-- | drivers/spi/spi-orion.c | 10 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx-dma.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 8 | ||||
-rw-r--r-- | drivers/spi/spi-qup.c | 44 | ||||
-rw-r--r-- | drivers/spi/spi-s3c64xx.c | 54 | ||||
-rw-r--r-- | drivers/spi/spi-sh-sci.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi-xilinx.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi.c | 10 |
11 files changed, 99 insertions, 90 deletions
diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 67375a11d4bd..fb61464348a1 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -925,8 +925,7 @@ err_no_txdma: iounmap((void __iomem *)hw->regs); err_ioremap: - release_resource(hw->ioarea); - kfree(hw->ioarea); + release_mem_region(r->start, sizeof(psc_spi_t)); err_no_iores: err_no_pdata: @@ -946,8 +945,7 @@ static int au1550_spi_remove(struct platform_device *pdev) spi_bitbang_stop(&hw->bitbang); free_irq(hw->irq, hw); iounmap((void __iomem *)hw->regs); - release_resource(hw->ioarea); - kfree(hw->ioarea); + release_mem_region(r->start, sizeof(psc_spi_t)); if (hw->usedma) { au1550_spi_dma_rxtmp_free(hw); diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index bb758978465d..3312eccb18c1 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -205,18 +205,30 @@ static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) static void cdns_spi_config_clock_mode(struct spi_device *spi) { struct cdns_spi *xspi = spi_master_get_devdata(spi->master); - u32 ctrl_reg; + u32 ctrl_reg, new_ctrl_reg; - ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); + new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); /* Set the SPI clock phase and clock polarity */ - ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); + new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); if (spi->mode & SPI_CPHA) - ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; + new_ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; if (spi->mode & SPI_CPOL) - ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; - - cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); + new_ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; + + if (new_ctrl_reg != ctrl_reg) { + /* + * Just writing the CR register does not seem to apply the clock + * setting changes. This is problematic when changing the clock + * polarity as it will cause the SPI slave to see spurious clock + * transitions. To workaround the issue toggle the ER register. + */ + cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, + CDNS_SPI_ER_DISABLE_MASK); + cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, new_ctrl_reg); + cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, + CDNS_SPI_ER_ENABLE_MASK); + } } /** @@ -370,6 +382,12 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) return status; } +static int cdns_prepare_message(struct spi_master *master, + struct spi_message *msg) +{ + cdns_spi_config_clock_mode(msg->spi); + return 0; +} /** * cdns_transfer_one - Initiates the SPI transfer @@ -416,8 +434,6 @@ static int cdns_prepare_transfer_hardware(struct spi_master *master) { struct cdns_spi *xspi = spi_master_get_devdata(master); - cdns_spi_config_clock_mode(master->cur_msg->spi); - cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, CDNS_SPI_ER_ENABLE_MASK); @@ -532,6 +548,7 @@ static int cdns_spi_probe(struct platform_device *pdev) xspi->is_decoded_cs = 0; master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; + master->prepare_message = cdns_prepare_message; master->transfer_one = cdns_transfer_one; master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; master->set_cs = cdns_spi_chipselect; diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 4dc77df38864..68441fa448de 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -149,6 +149,7 @@ struct omap2_mcspi_cs { void __iomem *base; unsigned long phys; int word_len; + u16 mode; struct list_head node; /* Context save and restore shadow register */ u32 chconf0, chctrl0; @@ -926,6 +927,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, mcspi_write_chconf0(spi, l); + cs->mode = spi->mode; + dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", speed_hz, (spi->mode & SPI_CPHA) ? "trailing" : "leading", @@ -998,6 +1001,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) return -ENOMEM; cs->base = mcspi->base + spi->chip_select * 0x14; cs->phys = mcspi->phys + spi->chip_select * 0x14; + cs->mode = 0; cs->chconf0 = 0; cs->chctrl0 = 0; spi->controller_state = cs; @@ -1079,6 +1083,16 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) cs = spi->controller_state; cd = spi->controller_data; + /* + * The slave driver could have changed spi->mode in which case + * it will be different from cs->mode (the current hardware setup). + * If so, set par_override (even though its not a parity issue) so + * omap2_mcspi_setup_transfer will be called to configure the hardware + * with the correct mode on the first iteration of the loop below. + */ + if (spi->mode != cs->mode) + par_override = 1; + omap2_mcspi_set_enable(spi, 0); list_for_each_entry(t, &m->transfers, transfer_list) { if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index d018a4aac3a1..c206a4ad83cd 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -346,8 +346,6 @@ static int orion_spi_probe(struct platform_device *pdev) struct resource *r; unsigned long tclk_hz; int status = 0; - const u32 *iprop; - int size; master = spi_alloc_master(&pdev->dev, sizeof(*spi)); if (master == NULL) { @@ -358,10 +356,10 @@ static int orion_spi_probe(struct platform_device *pdev) if (pdev->id != -1) master->bus_num = pdev->id; if (pdev->dev.of_node) { - iprop = of_get_property(pdev->dev.of_node, "cell-index", - &size); - if (iprop && size == sizeof(*iprop)) - master->bus_num = *iprop; + u32 cell_index; + if (!of_property_read_u32(pdev->dev.of_node, "cell-index", + &cell_index)) + master->bus_num = cell_index; } /* we support only mode 0, and no options */ diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index f6759dc0153b..c41ff148a2b4 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -368,7 +368,7 @@ int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip, * otherwise we use the default. Also we use the default FIFO * thresholds for now. */ - *burst_code = chip_info ? chip_info->dma_burst_size : 16; + *burst_code = chip_info ? chip_info->dma_burst_size : 1; *threshold = SSCR1_RxTresh(RX_THRESH_DFLT) | SSCR1_TxTresh(TX_THRESH_DFLT); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index a98df7eeb42d..fe792106bdc5 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -118,6 +118,7 @@ static void lpss_ssp_setup(struct driver_data *drv_data) */ orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); + /* Test SPI_CS_CONTROL_SW_MODE bit enabling */ value = orig | SPI_CS_CONTROL_SW_MODE; writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); @@ -126,10 +127,13 @@ static void lpss_ssp_setup(struct driver_data *drv_data) goto detection_done; } - value &= ~SPI_CS_CONTROL_SW_MODE; + orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); + + /* Test SPI_CS_CONTROL_SW_MODE bit disabling */ + value = orig & ~SPI_CS_CONTROL_SW_MODE; writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); - if (value != orig) { + if (value != (orig & ~SPI_CS_CONTROL_SW_MODE)) { offset = 0x800; goto detection_done; } diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index fc1de86d3c8a..c08da380cb23 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -424,31 +424,6 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) return 0; } -static void spi_qup_set_cs(struct spi_device *spi, bool enable) -{ - struct spi_qup *controller = spi_master_get_devdata(spi->master); - - u32 iocontol, mask; - - iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL); - - /* Disable auto CS toggle and use manual */ - iocontol &= ~SPI_IO_C_MX_CS_MODE; - iocontol |= SPI_IO_C_FORCE_CS; - - iocontol &= ~SPI_IO_C_CS_SELECT_MASK; - iocontol |= SPI_IO_C_CS_SELECT(spi->chip_select); - - mask = SPI_IO_C_CS_N_POLARITY_0 << spi->chip_select; - - if (enable) - iocontol |= mask; - else - iocontol &= ~mask; - - writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL); -} - static int spi_qup_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) @@ -571,12 +546,16 @@ static int spi_qup_probe(struct platform_device *pdev) return -ENOMEM; } + /* use num-cs unless not present or out of range */ + if (of_property_read_u16(dev->of_node, "num-cs", + &master->num_chipselect) || + (master->num_chipselect > SPI_NUM_CHIPSELECTS)) + master->num_chipselect = SPI_NUM_CHIPSELECTS; + master->bus_num = pdev->id; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; - master->num_chipselect = SPI_NUM_CHIPSELECTS; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->max_speed_hz = max_freq; - master->set_cs = spi_qup_set_cs; master->transfer_one = spi_qup_transfer_one; master->dev.of_node = pdev->dev.of_node; master->auto_runtime_pm = true; @@ -640,16 +619,19 @@ static int spi_qup_probe(struct platform_device *pdev) if (ret) goto error; - ret = devm_spi_register_master(dev, master); - if (ret) - goto error; - pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); pm_runtime_use_autosuspend(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); + + ret = devm_spi_register_master(dev, master); + if (ret) + goto disable_pm; + return 0; +disable_pm: + pm_runtime_disable(&pdev->dev); error: clk_disable_unprepare(cclk); clk_disable_unprepare(iclk); diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 75a56968b14c..1c36311935d7 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -197,7 +197,6 @@ struct s3c64xx_spi_driver_data { struct s3c64xx_spi_dma_data tx_dma; struct s3c64xx_spi_port_config *port_conf; unsigned int port_id; - bool cs_gpio; }; static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) @@ -754,10 +753,8 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( { struct s3c64xx_spi_csinfo *cs; struct device_node *slave_np, *data_np = NULL; - struct s3c64xx_spi_driver_data *sdd; u32 fb_delay = 0; - sdd = spi_master_get_devdata(spi->master); slave_np = spi->dev.of_node; if (!slave_np) { dev_err(&spi->dev, "device node not found\n"); @@ -776,17 +773,6 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( return ERR_PTR(-ENOMEM); } - /* The CS line is asserted/deasserted by the gpio pin */ - if (sdd->cs_gpio) - cs->line = of_get_named_gpio(data_np, "cs-gpio", 0); - - if (!gpio_is_valid(cs->line)) { - dev_err(&spi->dev, "chip select gpio is not specified or invalid\n"); - kfree(cs); - of_node_put(data_np); - return ERR_PTR(-EINVAL); - } - of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay); cs->fb_delay = fb_delay; of_node_put(data_np); @@ -807,9 +793,16 @@ static int s3c64xx_spi_setup(struct spi_device *spi) int err; sdd = spi_master_get_devdata(spi->master); - if (!cs && spi->dev.of_node) { + if (spi->dev.of_node) { cs = s3c64xx_get_slave_ctrldata(spi); spi->controller_data = cs; + } else if (cs) { + /* On non-DT platforms the SPI core will set spi->cs_gpio + * to -ENOENT. The GPIO pin used to drive the chip select + * is defined by using platform data so spi->cs_gpio value + * has to be override to have the proper GPIO pin number. + */ + spi->cs_gpio = cs->line; } if (IS_ERR_OR_NULL(cs)) { @@ -818,18 +811,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi) } if (!spi_get_ctldata(spi)) { - /* Request gpio only if cs line is asserted by gpio pins */ - if (sdd->cs_gpio) { - err = gpio_request_one(cs->line, GPIOF_OUT_INIT_HIGH, - dev_name(&spi->dev)); + if (gpio_is_valid(spi->cs_gpio)) { + err = gpio_request_one(spi->cs_gpio, GPIOF_OUT_INIT_HIGH, + dev_name(&spi->dev)); if (err) { dev_err(&spi->dev, "Failed to get /CS gpio [%d]: %d\n", - cs->line, err); + spi->cs_gpio, err); goto err_gpio_req; } - - spi->cs_gpio = cs->line; } spi_set_ctldata(spi, cs); @@ -884,7 +874,8 @@ setup_exit: /* setup() returns with device de-selected */ writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); - gpio_free(cs->line); + if (gpio_is_valid(spi->cs_gpio)) + gpio_free(spi->cs_gpio); spi_set_ctldata(spi, NULL); err_gpio_req: @@ -897,14 +888,21 @@ err_gpio_req: static void s3c64xx_spi_cleanup(struct spi_device *spi) { struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi); - struct s3c64xx_spi_driver_data *sdd; - sdd = spi_master_get_devdata(spi->master); - if (spi->cs_gpio) { + if (gpio_is_valid(spi->cs_gpio)) { gpio_free(spi->cs_gpio); if (spi->dev.of_node) kfree(cs); + else { + /* On non-DT platforms, the SPI core sets + * spi->cs_gpio to -ENOENT and .setup() + * overrides it with the GPIO pin value + * passed using platform data. + */ + spi->cs_gpio = -ENOENT; + } } + spi_set_ctldata(spi, NULL); } @@ -1075,11 +1073,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->cntrlr_info = sci; sdd->pdev = pdev; sdd->sfr_start = mem_res->start; - sdd->cs_gpio = true; if (pdev->dev.of_node) { - if (!of_find_property(pdev->dev.of_node, "cs-gpio", NULL)) - sdd->cs_gpio = false; - ret = of_alias_get_id(pdev->dev.of_node, "spi"); if (ret < 0) { dev_err(&pdev->dev, "failed to get alias id, errno %d\n", diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c index 1f56ef651d1a..b83dd733684c 100644 --- a/drivers/spi/spi-sh-sci.c +++ b/drivers/spi/spi-sh-sci.c @@ -175,9 +175,9 @@ static int sh_sci_spi_remove(struct platform_device *dev) { struct sh_sci_spi *sp = platform_get_drvdata(dev); - iounmap(sp->membase); - setbits(sp, PIN_INIT, 0); spi_bitbang_stop(&sp->bitbang); + setbits(sp, PIN_INIT, 0); + iounmap(sp->membase); spi_master_put(sp->bitbang.master); return 0; } diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index a3b0b9944bf0..4d8efb16573d 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -369,7 +369,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) goto put_master; } - master->bus_num = pdev->dev.id; + master->bus_num = pdev->id; master->num_chipselect = num_cs; master->dev.of_node = pdev->dev.of_node; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index d4f9670b51bc..e691e281e3a2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -619,6 +619,8 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, } ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir); + if (!ret) + ret = -ENOMEM; if (ret < 0) { sg_free_table(sgt); return ret; @@ -647,8 +649,8 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg) if (!master->can_dma) return 0; - tx_dev = &master->dma_tx->dev->device; - rx_dev = &master->dma_rx->dev->device; + tx_dev = master->dma_tx->device->dev; + rx_dev = master->dma_rx->device->dev; list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (!master->can_dma(master, msg->spi, xfer)) @@ -687,8 +689,8 @@ static int spi_unmap_msg(struct spi_master *master, struct spi_message *msg) if (!master->cur_msg_mapped || !master->can_dma) return 0; - tx_dev = &master->dma_tx->dev->device; - rx_dev = &master->dma_rx->dev->device; + tx_dev = master->dma_tx->device->dev; + rx_dev = master->dma_rx->device->dev; list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (!master->can_dma(master, msg->spi, xfer)) |