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
This commit is contained in:
commit
af211211e3
|
@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master,
|
|||
struct spi_device *spi,
|
||||
struct spi_transfer *tfr,
|
||||
u32 cs,
|
||||
unsigned long xfer_time_us)
|
||||
unsigned long long xfer_time_us)
|
||||
{
|
||||
struct bcm2835_spi *bs = spi_master_get_devdata(master);
|
||||
unsigned long timeout;
|
||||
|
@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
|
|||
{
|
||||
struct bcm2835_spi *bs = spi_master_get_devdata(master);
|
||||
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);
|
||||
|
||||
/* set clock */
|
||||
|
@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
|
|||
spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
|
||||
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))
|
||||
cs |= BCM2835_SPI_CS_REN;
|
||||
if (spi->mode & SPI_CPOL)
|
||||
cs |= BCM2835_SPI_CS_CPOL;
|
||||
if (spi->mode & SPI_CPHA)
|
||||
cs |= BCM2835_SPI_CS_CPHA;
|
||||
else
|
||||
cs &= ~BCM2835_SPI_CS_REN;
|
||||
|
||||
/* 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
|
||||
|
@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
|
|||
bs->rx_len = tfr->len;
|
||||
|
||||
/* 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 */
|
||||
* 1000000 / spi_used_hz;
|
||||
* 1000000;
|
||||
do_div(xfer_time_us, spi_used_hz);
|
||||
|
||||
/* for short requests run polling*/
|
||||
if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US)
|
||||
|
@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
|
|||
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,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
|
@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
|
|||
master->set_cs = bcm2835_spi_set_cs;
|
||||
master->transfer_one = bcm2835_spi_transfer_one;
|
||||
master->handle_err = bcm2835_spi_handle_err;
|
||||
master->prepare_message = bcm2835_spi_prepare_message;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
bs = spi_master_get_devdata(master);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
bool oldbit = !(word & 1);
|
||||
u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
|
||||
/* clock starts at inactive polarity */
|
||||
for (word <<= (32 - bits); likely(bits); bits--) {
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
bool oldbit = !(word & (1 << 31));
|
||||
u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
|
||||
/* clock starts at inactive polarity */
|
||||
for (word <<= (32 - bits); likely(bits); bits--) {
|
||||
|
||||
|
|
|
@ -105,6 +105,10 @@ struct img_spfi {
|
|||
bool rx_dma_busy;
|
||||
};
|
||||
|
||||
struct img_spfi_device_data {
|
||||
bool gpio_requested;
|
||||
};
|
||||
|
||||
static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg)
|
||||
{
|
||||
return readl(spfi->regs + reg);
|
||||
|
@ -267,15 +271,15 @@ static int img_spfi_start_pio(struct spi_master *master,
|
|||
cpu_relax();
|
||||
}
|
||||
|
||||
ret = spfi_wait_all_done(spfi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (rx_bytes > 0 || tx_bytes > 0) {
|
||||
dev_err(spfi->dev, "PIO transfer timed out\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
ret = spfi_wait_all_done(spfi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -440,21 +444,50 @@ static int img_spfi_unprepare(struct spi_master *master,
|
|||
|
||||
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) ?
|
||||
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
|
||||
dev_name(&spi->dev));
|
||||
if (ret)
|
||||
dev_err(&spi->dev, "can't request chipselect gpio %d\n",
|
||||
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,
|
||||
dev_name(&spi->dev));
|
||||
if (ret)
|
||||
dev_err(&spi->dev, "can't request chipselect gpio %d\n",
|
||||
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;
|
||||
}
|
||||
|
||||
static void img_spfi_cleanup(struct spi_device *spi)
|
||||
{
|
||||
gpio_free(spi->cs_gpio);
|
||||
struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
|
||||
|
||||
if (spfi_data) {
|
||||
if (spfi_data->gpio_requested)
|
||||
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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
|
||||
u32 l;
|
||||
|
||||
/* The controller handles the inverted chip selects
|
||||
|
@ -255,6 +256,12 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
|
|||
enable = !enable;
|
||||
|
||||
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);
|
||||
|
||||
if (enable)
|
||||
|
@ -263,6 +270,9 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
|
|||
l |= OMAP2_MCSPI_CHCONF_FORCE;
|
||||
|
||||
mcspi_write_chconf0(spi, l);
|
||||
|
||||
pm_runtime_mark_last_busy(mcspi->dev);
|
||||
pm_runtime_put_autosuspend(mcspi->dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,11 @@
|
|||
#define ORION_SPI_DATA_OUT_REG 0x08
|
||||
#define ORION_SPI_DATA_IN_REG 0x0c
|
||||
#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_CPHA (1 << 12)
|
||||
|
@ -70,6 +75,7 @@ struct orion_spi_dev {
|
|||
unsigned int min_divisor;
|
||||
unsigned int max_divisor;
|
||||
u32 prescale_mask;
|
||||
bool is_errata_50mhz_ac;
|
||||
};
|
||||
|
||||
struct orion_spi {
|
||||
|
@ -195,6 +201,41 @@ orion_spi_mode_set(struct spi_device *spi)
|
|||
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
|
||||
*/
|
||||
|
@ -216,6 +257,9 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
|||
|
||||
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);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@ -413,6 +457,14 @@ static const struct orion_spi_dev armada_375_spi_dev_data = {
|
|||
.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[] = {
|
||||
{
|
||||
.compatible = "marvell,orion-spi",
|
||||
|
@ -428,7 +480,7 @@ static const struct of_device_id orion_spi_of_match_table[] = {
|
|||
},
|
||||
{
|
||||
.compatible = "marvell,armada-380-spi",
|
||||
.data = &armada_xp_spi_dev_data,
|
||||
.data = &armada_380_spi_dev_data,
|
||||
},
|
||||
{
|
||||
.compatible = "marvell,armada-390-spi",
|
||||
|
|
|
@ -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->rx_ptr = t->rx_buf;
|
||||
remaining_words = t->len / xspi->bytes_per_word;
|
||||
reinit_completion(&xspi->done);
|
||||
|
||||
if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) {
|
||||
u32 isr;
|
||||
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*/
|
||||
cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
|
||||
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
|
||||
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) {
|
||||
|
@ -302,8 +306,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|||
remaining_words -= n_words;
|
||||
}
|
||||
|
||||
if (use_irq)
|
||||
if (use_irq) {
|
||||
xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
|
||||
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
|
||||
}
|
||||
|
||||
return t->len;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue