Commit 071db7a6 authored by Mark Brown's avatar Mark Brown

Merge branch 'spi-4.18' into spi-4.19 for DSPI dep

parents d87e08f1 8570043e
...@@ -319,7 +319,7 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) ...@@ -319,7 +319,7 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
*/ */
if (cdns_spi_read(xspi, CDNS_SPI_ISR) & if (cdns_spi_read(xspi, CDNS_SPI_ISR) &
CDNS_SPI_IXR_TXFULL) CDNS_SPI_IXR_TXFULL)
usleep_range(10, 20); udelay(10);
if (xspi->txbuf) if (xspi->txbuf)
cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
......
...@@ -857,11 +857,23 @@ static int dspi_resume(struct device *dev) ...@@ -857,11 +857,23 @@ static int dspi_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume); static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume);
static const struct regmap_range dspi_volatile_ranges[] = {
regmap_reg_range(SPI_MCR, SPI_TCR),
regmap_reg_range(SPI_SR, SPI_SR),
regmap_reg_range(SPI_PUSHR, SPI_RXFR3),
};
static const struct regmap_access_table dspi_volatile_table = {
.yes_ranges = dspi_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(dspi_volatile_ranges),
};
static const struct regmap_config dspi_regmap_config = { static const struct regmap_config dspi_regmap_config = {
.reg_bits = 32, .reg_bits = 32,
.val_bits = 32, .val_bits = 32,
.reg_stride = 4, .reg_stride = 4,
.max_register = 0x88, .max_register = 0x88,
.volatile_table = &dspi_volatile_table,
}; };
static void dspi_init(struct fsl_dspi *dspi) static void dspi_init(struct fsl_dspi *dspi)
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/gpio.h> #include <linux/gpio.h>
...@@ -681,9 +682,9 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -681,9 +682,9 @@ static int orion_spi_probe(struct platform_device *pdev)
goto out_rel_axi_clk; goto out_rel_axi_clk;
} }
/* Scan all SPI devices of this controller for direct mapped devices */
for_each_available_child_of_node(pdev->dev.of_node, np) { for_each_available_child_of_node(pdev->dev.of_node, np) {
u32 cs; u32 cs;
int cs_gpio;
/* Get chip-select number from the "reg" property */ /* Get chip-select number from the "reg" property */
status = of_property_read_u32(np, "reg", &cs); status = of_property_read_u32(np, "reg", &cs);
...@@ -694,6 +695,44 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -694,6 +695,44 @@ static int orion_spi_probe(struct platform_device *pdev)
continue; continue;
} }
/*
* Initialize the CS GPIO:
* - properly request the actual GPIO signal
* - de-assert the logical signal so that all GPIO CS lines
* are inactive when probing for slaves
* - find an unused physical CS which will be driven for any
* slave which uses a CS GPIO
*/
cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", cs);
if (cs_gpio > 0) {
char *gpio_name;
int cs_flags;
if (spi->unused_hw_gpio == -1) {
dev_info(&pdev->dev,
"Selected unused HW CS#%d for any GPIO CSes\n",
cs);
spi->unused_hw_gpio = cs;
}
gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%s-CS%d", dev_name(&pdev->dev), cs);
if (!gpio_name) {
status = -ENOMEM;
goto out_rel_axi_clk;
}
cs_flags = of_property_read_bool(np, "spi-cs-high") ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
status = devm_gpio_request_one(&pdev->dev, cs_gpio,
cs_flags, gpio_name);
if (status) {
dev_err(&pdev->dev,
"Can't request GPIO for CS %d\n", cs);
goto out_rel_axi_clk;
}
}
/* /*
* Check if an address is configured for this SPI device. If * Check if an address is configured for this SPI device. If
* not, the MBus mapping via the 'ranges' property in the 'soc' * not, the MBus mapping via the 'ranges' property in the 'soc'
...@@ -740,44 +779,8 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -740,44 +779,8 @@ static int orion_spi_probe(struct platform_device *pdev)
if (status < 0) if (status < 0)
goto out_rel_pm; goto out_rel_pm;
if (master->cs_gpios) {
int i;
for (i = 0; i < master->num_chipselect; ++i) {
char *gpio_name;
if (!gpio_is_valid(master->cs_gpios[i])) {
continue;
}
gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%s-CS%d", dev_name(&pdev->dev), i);
if (!gpio_name) {
status = -ENOMEM;
goto out_rel_master;
}
status = devm_gpio_request(&pdev->dev,
master->cs_gpios[i], gpio_name);
if (status) {
dev_err(&pdev->dev,
"Can't request GPIO for CS %d\n",
master->cs_gpios[i]);
goto out_rel_master;
}
if (spi->unused_hw_gpio == -1) {
dev_info(&pdev->dev,
"Selected unused HW CS#%d for any GPIO CSes\n",
i);
spi->unused_hw_gpio = i;
}
}
}
return status; return status;
out_rel_master:
spi_unregister_master(master);
out_rel_pm: out_rel_pm:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
out_rel_axi_clk: out_rel_axi_clk:
......
...@@ -49,6 +49,7 @@ struct sh_msiof_spi_priv { ...@@ -49,6 +49,7 @@ struct sh_msiof_spi_priv {
struct platform_device *pdev; struct platform_device *pdev;
struct sh_msiof_spi_info *info; struct sh_msiof_spi_info *info;
struct completion done; struct completion done;
struct completion done_txdma;
unsigned int tx_fifo_size; unsigned int tx_fifo_size;
unsigned int rx_fifo_size; unsigned int rx_fifo_size;
unsigned int min_div_pow; unsigned int min_div_pow;
...@@ -649,19 +650,21 @@ static int sh_msiof_slave_abort(struct spi_master *master) ...@@ -649,19 +650,21 @@ static int sh_msiof_slave_abort(struct spi_master *master)
p->slave_aborted = true; p->slave_aborted = true;
complete(&p->done); complete(&p->done);
complete(&p->done_txdma);
return 0; return 0;
} }
static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p) static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p,
struct completion *x)
{ {
if (spi_controller_is_slave(p->master)) { if (spi_controller_is_slave(p->master)) {
if (wait_for_completion_interruptible(&p->done) || if (wait_for_completion_interruptible(x) ||
p->slave_aborted) { p->slave_aborted) {
dev_dbg(&p->pdev->dev, "interrupted\n"); dev_dbg(&p->pdev->dev, "interrupted\n");
return -EINTR; return -EINTR;
} }
} else { } else {
if (!wait_for_completion_timeout(&p->done, HZ)) { if (!wait_for_completion_timeout(x, HZ)) {
dev_err(&p->pdev->dev, "timeout\n"); dev_err(&p->pdev->dev, "timeout\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -711,7 +714,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, ...@@ -711,7 +714,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
} }
/* wait for tx fifo to be emptied / rx fifo to be filled */ /* wait for tx fifo to be emptied / rx fifo to be filled */
ret = sh_msiof_wait_for_completion(p); ret = sh_msiof_wait_for_completion(p, &p->done);
if (ret) if (ret)
goto stop_reset; goto stop_reset;
...@@ -740,10 +743,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, ...@@ -740,10 +743,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
static void sh_msiof_dma_complete(void *arg) static void sh_msiof_dma_complete(void *arg)
{ {
struct sh_msiof_spi_priv *p = arg; complete(arg);
sh_msiof_write(p, IER, 0);
complete(&p->done);
} }
static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
...@@ -764,7 +764,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -764,7 +764,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
return -EAGAIN; return -EAGAIN;
desc_rx->callback = sh_msiof_dma_complete; desc_rx->callback = sh_msiof_dma_complete;
desc_rx->callback_param = p; desc_rx->callback_param = &p->done;
cookie = dmaengine_submit(desc_rx); cookie = dmaengine_submit(desc_rx);
if (dma_submit_error(cookie)) if (dma_submit_error(cookie))
return cookie; return cookie;
...@@ -782,13 +782,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -782,13 +782,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
goto no_dma_tx; goto no_dma_tx;
} }
if (rx) { desc_tx->callback = sh_msiof_dma_complete;
/* No callback */ desc_tx->callback_param = &p->done_txdma;
desc_tx->callback = NULL;
} else {
desc_tx->callback = sh_msiof_dma_complete;
desc_tx->callback_param = p;
}
cookie = dmaengine_submit(desc_tx); cookie = dmaengine_submit(desc_tx);
if (dma_submit_error(cookie)) { if (dma_submit_error(cookie)) {
ret = cookie; ret = cookie;
...@@ -805,6 +800,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -805,6 +800,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
sh_msiof_write(p, IER, ier_bits); sh_msiof_write(p, IER, ier_bits);
reinit_completion(&p->done); reinit_completion(&p->done);
if (tx)
reinit_completion(&p->done_txdma);
p->slave_aborted = false; p->slave_aborted = false;
/* Now start DMA */ /* Now start DMA */
...@@ -819,17 +816,24 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -819,17 +816,24 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
goto stop_dma; goto stop_dma;
} }
/* wait for tx/rx DMA completion */ if (tx) {
ret = sh_msiof_wait_for_completion(p); /* wait for tx DMA completion */
if (ret) ret = sh_msiof_wait_for_completion(p, &p->done_txdma);
goto stop_reset; if (ret)
goto stop_reset;
}
if (!rx) { if (rx) {
reinit_completion(&p->done); /* wait for rx DMA completion */
sh_msiof_write(p, IER, IER_TEOFE); ret = sh_msiof_wait_for_completion(p, &p->done);
if (ret)
goto stop_reset;
sh_msiof_write(p, IER, 0);
} else {
/* wait for tx fifo to be emptied */ /* wait for tx fifo to be emptied */
ret = sh_msiof_wait_for_completion(p); sh_msiof_write(p, IER, IER_TEOFE);
ret = sh_msiof_wait_for_completion(p, &p->done);
if (ret) if (ret)
goto stop_reset; goto stop_reset;
} }
...@@ -1327,6 +1331,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) ...@@ -1327,6 +1331,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
p->min_div_pow = chipdata->min_div_pow; p->min_div_pow = chipdata->min_div_pow;
init_completion(&p->done); init_completion(&p->done);
init_completion(&p->done_txdma);
p->clk = devm_clk_get(&pdev->dev, NULL); p->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(p->clk)) { if (IS_ERR(p->clk)) {
......
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