Merge remote-tracking branches 'spi/fix/au1550', 'spi/fix/cadence', 'spi/fix/omap2-mcspi' and 'spi/fix/orion' into spi-linus
This commit is contained in:
commit
95607c3033
4 changed files with 45 additions and 18 deletions
|
@ -925,8 +925,7 @@ err_no_txdma:
|
||||||
iounmap((void __iomem *)hw->regs);
|
iounmap((void __iomem *)hw->regs);
|
||||||
|
|
||||||
err_ioremap:
|
err_ioremap:
|
||||||
release_resource(hw->ioarea);
|
release_mem_region(r->start, sizeof(psc_spi_t));
|
||||||
kfree(hw->ioarea);
|
|
||||||
|
|
||||||
err_no_iores:
|
err_no_iores:
|
||||||
err_no_pdata:
|
err_no_pdata:
|
||||||
|
@ -946,8 +945,7 @@ static int au1550_spi_remove(struct platform_device *pdev)
|
||||||
spi_bitbang_stop(&hw->bitbang);
|
spi_bitbang_stop(&hw->bitbang);
|
||||||
free_irq(hw->irq, hw);
|
free_irq(hw->irq, hw);
|
||||||
iounmap((void __iomem *)hw->regs);
|
iounmap((void __iomem *)hw->regs);
|
||||||
release_resource(hw->ioarea);
|
release_mem_region(r->start, sizeof(psc_spi_t));
|
||||||
kfree(hw->ioarea);
|
|
||||||
|
|
||||||
if (hw->usedma) {
|
if (hw->usedma) {
|
||||||
au1550_spi_dma_rxtmp_free(hw);
|
au1550_spi_dma_rxtmp_free(hw);
|
||||||
|
|
|
@ -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)
|
static void cdns_spi_config_clock_mode(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
|
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 */
|
/* 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)
|
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)
|
if (spi->mode & SPI_CPOL)
|
||||||
ctrl_reg |= CDNS_SPI_CR_CPOL_MASK;
|
new_ctrl_reg |= CDNS_SPI_CR_CPOL_MASK;
|
||||||
|
|
||||||
cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg);
|
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;
|
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
|
* 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);
|
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_write(xspi, CDNS_SPI_ER_OFFSET,
|
||||||
CDNS_SPI_ER_ENABLE_MASK);
|
CDNS_SPI_ER_ENABLE_MASK);
|
||||||
|
|
||||||
|
@ -532,6 +548,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
||||||
xspi->is_decoded_cs = 0;
|
xspi->is_decoded_cs = 0;
|
||||||
|
|
||||||
master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
|
master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
|
||||||
|
master->prepare_message = cdns_prepare_message;
|
||||||
master->transfer_one = cdns_transfer_one;
|
master->transfer_one = cdns_transfer_one;
|
||||||
master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
|
master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
|
||||||
master->set_cs = cdns_spi_chipselect;
|
master->set_cs = cdns_spi_chipselect;
|
||||||
|
|
|
@ -149,6 +149,7 @@ struct omap2_mcspi_cs {
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
unsigned long phys;
|
unsigned long phys;
|
||||||
int word_len;
|
int word_len;
|
||||||
|
u16 mode;
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
/* Context save and restore shadow register */
|
/* Context save and restore shadow register */
|
||||||
u32 chconf0, chctrl0;
|
u32 chconf0, chctrl0;
|
||||||
|
@ -926,6 +927,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
|
||||||
|
|
||||||
mcspi_write_chconf0(spi, l);
|
mcspi_write_chconf0(spi, l);
|
||||||
|
|
||||||
|
cs->mode = spi->mode;
|
||||||
|
|
||||||
dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
|
dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
|
||||||
speed_hz,
|
speed_hz,
|
||||||
(spi->mode & SPI_CPHA) ? "trailing" : "leading",
|
(spi->mode & SPI_CPHA) ? "trailing" : "leading",
|
||||||
|
@ -998,6 +1001,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
cs->base = mcspi->base + spi->chip_select * 0x14;
|
cs->base = mcspi->base + spi->chip_select * 0x14;
|
||||||
cs->phys = mcspi->phys + spi->chip_select * 0x14;
|
cs->phys = mcspi->phys + spi->chip_select * 0x14;
|
||||||
|
cs->mode = 0;
|
||||||
cs->chconf0 = 0;
|
cs->chconf0 = 0;
|
||||||
cs->chctrl0 = 0;
|
cs->chctrl0 = 0;
|
||||||
spi->controller_state = cs;
|
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;
|
cs = spi->controller_state;
|
||||||
cd = spi->controller_data;
|
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);
|
omap2_mcspi_set_enable(spi, 0);
|
||||||
list_for_each_entry(t, &m->transfers, transfer_list) {
|
list_for_each_entry(t, &m->transfers, transfer_list) {
|
||||||
if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
|
if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
|
||||||
|
|
|
@ -346,8 +346,6 @@ static int orion_spi_probe(struct platform_device *pdev)
|
||||||
struct resource *r;
|
struct resource *r;
|
||||||
unsigned long tclk_hz;
|
unsigned long tclk_hz;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
const u32 *iprop;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
master = spi_alloc_master(&pdev->dev, sizeof(*spi));
|
master = spi_alloc_master(&pdev->dev, sizeof(*spi));
|
||||||
if (master == NULL) {
|
if (master == NULL) {
|
||||||
|
@ -358,10 +356,10 @@ static int orion_spi_probe(struct platform_device *pdev)
|
||||||
if (pdev->id != -1)
|
if (pdev->id != -1)
|
||||||
master->bus_num = pdev->id;
|
master->bus_num = pdev->id;
|
||||||
if (pdev->dev.of_node) {
|
if (pdev->dev.of_node) {
|
||||||
iprop = of_get_property(pdev->dev.of_node, "cell-index",
|
u32 cell_index;
|
||||||
&size);
|
if (!of_property_read_u32(pdev->dev.of_node, "cell-index",
|
||||||
if (iprop && size == sizeof(*iprop))
|
&cell_index))
|
||||||
master->bus_num = *iprop;
|
master->bus_num = cell_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we support only mode 0, and no options */
|
/* we support only mode 0, and no options */
|
||||||
|
|
Loading…
Add table
Reference in a new issue