Merge branch 'spi-4.18' into spi-4.19 for DSPI dep
This commit is contained in:
commit
071db7a675
|
@ -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)
|
||||||
|
|
||||||
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 @@
|
||||||
#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)
|
||||||
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)
|
||||||
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)
|
||||||
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 {
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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)) {
|
||||||
|
|
Loading…
Reference in New Issue