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 |
4 files changed, 46 insertions, 19 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 */ |