Commit af211211 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/fix/bcm2835', 'spi/fix/bitbang',...

Merge remote-tracking branches 'spi/fix/bcm2835', 'spi/fix/bitbang', 'spi/fix/img-spfi', 'spi/fix/omap2-mcspi', 'spi/fix/orion' and 'spi/fix/xilinx' into spi-linus
...@@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master, ...@@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master,
struct spi_device *spi, struct spi_device *spi,
struct spi_transfer *tfr, struct spi_transfer *tfr,
u32 cs, u32 cs,
unsigned long xfer_time_us) unsigned long long xfer_time_us)
{ {
struct bcm2835_spi *bs = spi_master_get_devdata(master); struct bcm2835_spi *bs = spi_master_get_devdata(master);
unsigned long timeout; unsigned long timeout;
...@@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, ...@@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
{ {
struct bcm2835_spi *bs = spi_master_get_devdata(master); struct bcm2835_spi *bs = spi_master_get_devdata(master);
unsigned long spi_hz, clk_hz, cdiv; unsigned long spi_hz, clk_hz, cdiv;
unsigned long spi_used_hz, xfer_time_us; unsigned long spi_used_hz;
unsigned long long xfer_time_us;
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
/* set clock */ /* set clock */
...@@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, ...@@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536); spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
/* handle all the modes */ /* handle all the 3-wire mode */
if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf))
cs |= BCM2835_SPI_CS_REN; cs |= BCM2835_SPI_CS_REN;
if (spi->mode & SPI_CPOL) else
cs |= BCM2835_SPI_CS_CPOL; cs &= ~BCM2835_SPI_CS_REN;
if (spi->mode & SPI_CPHA)
cs |= BCM2835_SPI_CS_CPHA;
/* for gpio_cs set dummy CS so that no HW-CS get changed /* for gpio_cs set dummy CS so that no HW-CS get changed
* we can not run this in bcm2835_spi_set_cs, as it does * we can not run this in bcm2835_spi_set_cs, as it does
...@@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, ...@@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
bs->rx_len = tfr->len; bs->rx_len = tfr->len;
/* calculate the estimated time in us the transfer runs */ /* calculate the estimated time in us the transfer runs */
xfer_time_us = tfr->len xfer_time_us = (unsigned long long)tfr->len
* 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */ * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */
* 1000000 / spi_used_hz; * 1000000;
do_div(xfer_time_us, spi_used_hz);
/* for short requests run polling*/ /* for short requests run polling*/
if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US) if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US)
...@@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, ...@@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs); return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs);
} }
static int bcm2835_spi_prepare_message(struct spi_master *master,
struct spi_message *msg)
{
struct spi_device *spi = msg->spi;
struct bcm2835_spi *bs = spi_master_get_devdata(master);
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
if (spi->mode & SPI_CPOL)
cs |= BCM2835_SPI_CS_CPOL;
if (spi->mode & SPI_CPHA)
cs |= BCM2835_SPI_CS_CPHA;
bcm2835_wr(bs, BCM2835_SPI_CS, cs);
return 0;
}
static void bcm2835_spi_handle_err(struct spi_master *master, static void bcm2835_spi_handle_err(struct spi_master *master,
struct spi_message *msg) struct spi_message *msg)
{ {
...@@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ...@@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
master->set_cs = bcm2835_spi_set_cs; master->set_cs = bcm2835_spi_set_cs;
master->transfer_one = bcm2835_spi_transfer_one; master->transfer_one = bcm2835_spi_transfer_one;
master->handle_err = bcm2835_spi_handle_err; master->handle_err = bcm2835_spi_handle_err;
master->prepare_message = bcm2835_spi_prepare_message;
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
bs = spi_master_get_devdata(master); bs = spi_master_get_devdata(master);
......
...@@ -49,7 +49,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, ...@@ -49,7 +49,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
{ {
/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
bool oldbit = !(word & 1); u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
/* clock starts at inactive polarity */ /* clock starts at inactive polarity */
for (word <<= (32 - bits); likely(bits); bits--) { for (word <<= (32 - bits); likely(bits); bits--) {
...@@ -81,7 +81,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, ...@@ -81,7 +81,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
{ {
/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
bool oldbit = !(word & (1 << 31)); u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
/* clock starts at inactive polarity */ /* clock starts at inactive polarity */
for (word <<= (32 - bits); likely(bits); bits--) { for (word <<= (32 - bits); likely(bits); bits--) {
......
...@@ -105,6 +105,10 @@ struct img_spfi { ...@@ -105,6 +105,10 @@ struct img_spfi {
bool rx_dma_busy; bool rx_dma_busy;
}; };
struct img_spfi_device_data {
bool gpio_requested;
};
static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg) static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg)
{ {
return readl(spfi->regs + reg); return readl(spfi->regs + reg);
...@@ -267,15 +271,15 @@ static int img_spfi_start_pio(struct spi_master *master, ...@@ -267,15 +271,15 @@ static int img_spfi_start_pio(struct spi_master *master,
cpu_relax(); cpu_relax();
} }
ret = spfi_wait_all_done(spfi);
if (ret < 0)
return ret;
if (rx_bytes > 0 || tx_bytes > 0) { if (rx_bytes > 0 || tx_bytes > 0) {
dev_err(spfi->dev, "PIO transfer timed out\n"); dev_err(spfi->dev, "PIO transfer timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
ret = spfi_wait_all_done(spfi);
if (ret < 0)
return ret;
return 0; return 0;
} }
...@@ -440,21 +444,50 @@ static int img_spfi_unprepare(struct spi_master *master, ...@@ -440,21 +444,50 @@ static int img_spfi_unprepare(struct spi_master *master,
static int img_spfi_setup(struct spi_device *spi) static int img_spfi_setup(struct spi_device *spi)
{ {
int ret; int ret = -EINVAL;
struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
ret = gpio_request_one(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? if (!spfi_data) {
spfi_data = kzalloc(sizeof(*spfi_data), GFP_KERNEL);
if (!spfi_data)
return -ENOMEM;
spfi_data->gpio_requested = false;
spi_set_ctldata(spi, spfi_data);
}
if (!spfi_data->gpio_requested) {
ret = gpio_request_one(spi->cs_gpio,
(spi->mode & SPI_CS_HIGH) ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
dev_name(&spi->dev)); dev_name(&spi->dev));
if (ret) if (ret)
dev_err(&spi->dev, "can't request chipselect gpio %d\n", dev_err(&spi->dev, "can't request chipselect gpio %d\n",
spi->cs_gpio); spi->cs_gpio);
else
spfi_data->gpio_requested = true;
} else {
if (gpio_is_valid(spi->cs_gpio)) {
int mode = ((spi->mode & SPI_CS_HIGH) ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH);
ret = gpio_direction_output(spi->cs_gpio, mode);
if (ret)
dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n",
spi->cs_gpio, ret);
}
}
return ret; return ret;
} }
static void img_spfi_cleanup(struct spi_device *spi) static void img_spfi_cleanup(struct spi_device *spi)
{ {
struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
if (spfi_data) {
if (spfi_data->gpio_requested)
gpio_free(spi->cs_gpio); gpio_free(spi->cs_gpio);
kfree(spfi_data);
spi_set_ctldata(spi, NULL);
}
} }
static void img_spfi_config(struct spi_master *master, struct spi_device *spi, static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
......
...@@ -245,6 +245,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) ...@@ -245,6 +245,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
{ {
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
u32 l; u32 l;
/* The controller handles the inverted chip selects /* The controller handles the inverted chip selects
...@@ -255,6 +256,12 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) ...@@ -255,6 +256,12 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
enable = !enable; enable = !enable;
if (spi->controller_state) { if (spi->controller_state) {
int err = pm_runtime_get_sync(mcspi->dev);
if (err < 0) {
dev_err(mcspi->dev, "failed to get sync: %d\n", err);
return;
}
l = mcspi_cached_chconf0(spi); l = mcspi_cached_chconf0(spi);
if (enable) if (enable)
...@@ -263,6 +270,9 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) ...@@ -263,6 +270,9 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
l |= OMAP2_MCSPI_CHCONF_FORCE; l |= OMAP2_MCSPI_CHCONF_FORCE;
mcspi_write_chconf0(spi, l); mcspi_write_chconf0(spi, l);
pm_runtime_mark_last_busy(mcspi->dev);
pm_runtime_put_autosuspend(mcspi->dev);
} }
} }
......
...@@ -41,6 +41,11 @@ ...@@ -41,6 +41,11 @@
#define ORION_SPI_DATA_OUT_REG 0x08 #define ORION_SPI_DATA_OUT_REG 0x08
#define ORION_SPI_DATA_IN_REG 0x0c #define ORION_SPI_DATA_IN_REG 0x0c
#define ORION_SPI_INT_CAUSE_REG 0x10 #define ORION_SPI_INT_CAUSE_REG 0x10
#define ORION_SPI_TIMING_PARAMS_REG 0x18
#define ORION_SPI_TMISO_SAMPLE_MASK (0x3 << 6)
#define ORION_SPI_TMISO_SAMPLE_1 (1 << 6)
#define ORION_SPI_TMISO_SAMPLE_2 (2 << 6)
#define ORION_SPI_MODE_CPOL (1 << 11) #define ORION_SPI_MODE_CPOL (1 << 11)
#define ORION_SPI_MODE_CPHA (1 << 12) #define ORION_SPI_MODE_CPHA (1 << 12)
...@@ -70,6 +75,7 @@ struct orion_spi_dev { ...@@ -70,6 +75,7 @@ struct orion_spi_dev {
unsigned int min_divisor; unsigned int min_divisor;
unsigned int max_divisor; unsigned int max_divisor;
u32 prescale_mask; u32 prescale_mask;
bool is_errata_50mhz_ac;
}; };
struct orion_spi { struct orion_spi {
...@@ -195,6 +201,41 @@ orion_spi_mode_set(struct spi_device *spi) ...@@ -195,6 +201,41 @@ orion_spi_mode_set(struct spi_device *spi)
writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
} }
static void
orion_spi_50mhz_ac_timing_erratum(struct spi_device *spi, unsigned int speed)
{
u32 reg;
struct orion_spi *orion_spi;
orion_spi = spi_master_get_devdata(spi->master);
/*
* Erratum description: (Erratum NO. FE-9144572) The device
* SPI interface supports frequencies of up to 50 MHz.
* However, due to this erratum, when the device core clock is
* 250 MHz and the SPI interfaces is configured for 50MHz SPI
* clock and CPOL=CPHA=1 there might occur data corruption on
* reads from the SPI device.
* Erratum Workaround:
* Work in one of the following configurations:
* 1. Set CPOL=CPHA=0 in "SPI Interface Configuration
* Register".
* 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1
* Register" before setting the interface.
*/
reg = readl(spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG));
reg &= ~ORION_SPI_TMISO_SAMPLE_MASK;
if (clk_get_rate(orion_spi->clk) == 250000000 &&
speed == 50000000 && spi->mode & SPI_CPOL &&
spi->mode & SPI_CPHA)
reg |= ORION_SPI_TMISO_SAMPLE_2;
else
reg |= ORION_SPI_TMISO_SAMPLE_1; /* This is the default value */
writel(reg, spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG));
}
/* /*
* called only when no transfer is active on the bus * called only when no transfer is active on the bus
*/ */
...@@ -216,6 +257,9 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -216,6 +257,9 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
orion_spi_mode_set(spi); orion_spi_mode_set(spi);
if (orion_spi->devdata->is_errata_50mhz_ac)
orion_spi_50mhz_ac_timing_erratum(spi, speed);
rc = orion_spi_baudrate_set(spi, speed); rc = orion_spi_baudrate_set(spi, speed);
if (rc) if (rc)
return rc; return rc;
...@@ -413,6 +457,14 @@ static const struct orion_spi_dev armada_375_spi_dev_data = { ...@@ -413,6 +457,14 @@ static const struct orion_spi_dev armada_375_spi_dev_data = {
.prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK, .prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,
}; };
static const struct orion_spi_dev armada_380_spi_dev_data = {
.typ = ARMADA_SPI,
.max_hz = 50000000,
.max_divisor = 1920,
.prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,
.is_errata_50mhz_ac = true,
};
static const struct of_device_id orion_spi_of_match_table[] = { static const struct of_device_id orion_spi_of_match_table[] = {
{ {
.compatible = "marvell,orion-spi", .compatible = "marvell,orion-spi",
...@@ -428,7 +480,7 @@ static const struct of_device_id orion_spi_of_match_table[] = { ...@@ -428,7 +480,7 @@ static const struct of_device_id orion_spi_of_match_table[] = {
}, },
{ {
.compatible = "marvell,armada-380-spi", .compatible = "marvell,armada-380-spi",
.data = &armada_xp_spi_dev_data, .data = &armada_380_spi_dev_data,
}, },
{ {
.compatible = "marvell,armada-390-spi", .compatible = "marvell,armada-390-spi",
......
...@@ -249,19 +249,23 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -249,19 +249,23 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->tx_ptr = t->tx_buf; xspi->tx_ptr = t->tx_buf;
xspi->rx_ptr = t->rx_buf; xspi->rx_ptr = t->rx_buf;
remaining_words = t->len / xspi->bytes_per_word; remaining_words = t->len / xspi->bytes_per_word;
reinit_completion(&xspi->done);
if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) { if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) {
u32 isr;
use_irq = true; use_irq = true;
xspi->write_fn(XSPI_INTR_TX_EMPTY,
xspi->regs + XIPIF_V123B_IISR_OFFSET);
/* Enable the global IPIF interrupt */
xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
xspi->regs + XIPIF_V123B_DGIER_OFFSET);
/* Inhibit irq to avoid spurious irqs on tx_empty*/ /* Inhibit irq to avoid spurious irqs on tx_empty*/
cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
xspi->regs + XSPI_CR_OFFSET); xspi->regs + XSPI_CR_OFFSET);
/* ACK old irqs (if any) */
isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
if (isr)
xspi->write_fn(isr,
xspi->regs + XIPIF_V123B_IISR_OFFSET);
/* Enable the global IPIF interrupt */
xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
xspi->regs + XIPIF_V123B_DGIER_OFFSET);
reinit_completion(&xspi->done);
} }
while (remaining_words) { while (remaining_words) {
...@@ -302,8 +306,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -302,8 +306,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
remaining_words -= n_words; remaining_words -= n_words;
} }
if (use_irq) if (use_irq) {
xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET); xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
}
return t->len; return t->len;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment