Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 635b9b2e authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'spi/topic/dw', 'spi/topic/dw-mid',...

Merge remote-tracking branches 'spi/topic/dw', 'spi/topic/dw-mid', 'spi/topic/fsl-espi' and 'spi/topic/imx' into spi-next
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -283,7 +283,7 @@ static void mid_spi_dma_stop(struct dw_spi *dws)
	}
}

static struct dw_spi_dma_ops mid_dma_ops = {
static const struct dw_spi_dma_ops mid_dma_ops = {
	.dma_init	= mid_spi_dma_init,
	.dma_exit	= mid_spi_dma_exit,
	.dma_setup	= mid_spi_dma_setup,
+1 −1
Original line number Diff line number Diff line
@@ -425,7 +425,7 @@ static int dw_spi_setup(struct spi_device *spi)
		chip->type = chip_info->type;
	}

	chip->tmode = 0; /* Tx & Rx */
	chip->tmode = SPI_TMOD_TR;

	if (gpio_is_valid(spi->cs_gpio)) {
		ret = gpio_direction_output(spi->cs_gpio,
+1 −1
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ struct dw_spi {
	struct dma_chan		*rxchan;
	unsigned long		dma_chan_busy;
	dma_addr_t		dma_addr; /* phy address of the Data register */
	struct dw_spi_dma_ops	*dma_ops;
	const struct dw_spi_dma_ops *dma_ops;
	void			*dma_tx;
	void			*dma_rx;

+6 −0
Original line number Diff line number Diff line
@@ -643,6 +643,11 @@ static int fsl_espi_runtime_resume(struct device *dev)
}
#endif

static size_t fsl_espi_max_transfer_size(struct spi_device *spi)
{
	return SPCOM_TRANLEN_MAX;
}

static struct spi_master * fsl_espi_probe(struct device *dev,
		struct resource *mem, unsigned int irq)
{
@@ -670,6 +675,7 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
	master->cleanup = fsl_espi_cleanup;
	master->transfer_one_message = fsl_espi_do_one_msg;
	master->auto_runtime_pm = true;
	master->max_transfer_size = fsl_espi_max_transfer_size;

	mpc8xxx_spi = spi_master_get_devdata(master);

+67 −34
Original line number Diff line number Diff line
@@ -104,9 +104,7 @@ struct spi_imx_data {
	unsigned int dma_is_inited;
	unsigned int dma_finished;
	bool usedma;
	u32 rx_wml;
	u32 tx_wml;
	u32 rxt_wml;
	u32 wml;
	struct completion dma_rx_completion;
	struct completion dma_tx_completion;

@@ -124,9 +122,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
	return d->devtype_data->devtype == IMX35_CSPI;
}

static inline int is_imx51_ecspi(struct spi_imx_data *d)
{
	return d->devtype_data->devtype == IMX51_ECSPI;
}

static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
{
	return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
	return is_imx51_ecspi(d) ? 64 : 8;
}

#define MXC_SPI_BUF_RX(type)						\
@@ -201,9 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
{
	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);

	if (spi_imx->dma_is_inited
	    && transfer->len > spi_imx->rx_wml * sizeof(u32)
	    && transfer->len > spi_imx->tx_wml * sizeof(u32))
	if (spi_imx->dma_is_inited &&
	    transfer->len > spi_imx->wml * sizeof(u32))
		return true;
	return false;
}
@@ -244,6 +246,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
#define MX51_ECSPI_STAT		0x18
#define MX51_ECSPI_STAT_RR		(1 <<  3)

#define MX51_ECSPI_TESTREG	0x20
#define MX51_ECSPI_TESTREG_LBC	BIT(31)

/* MX51 eCSPI */
static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
				      unsigned int *fres)
@@ -313,7 +318,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
{
	u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
	u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
	u32 clk = config->speed_hz, delay;
	u32 clk = config->speed_hz, delay, reg;

	/*
	 * The hardware seems to have a race condition when changing modes. The
@@ -351,7 +356,16 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
	else
		cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs);

	/* CTRL register always go first to bring out controller from reset */
	writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);

	reg = readl(spi_imx->base + MX51_ECSPI_TESTREG);
	if (config->mode & SPI_LOOP)
		reg |= MX51_ECSPI_TESTREG_LBC;
	else
		reg &= ~MX51_ECSPI_TESTREG_LBC;
	writel(reg, spi_imx->base + MX51_ECSPI_TESTREG);

	writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);

	/*
@@ -378,10 +392,9 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
	if (spi_imx->dma_is_inited) {
		dma = readl(spi_imx->base + MX51_ECSPI_DMA);

		spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
		rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
		tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
		rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
		rx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
		tx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
		rxt_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
		dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
			   & ~MX51_ECSPI_DMA_RX_WML_MASK
			   & ~MX51_ECSPI_DMA_RXT_WML_MASK)
@@ -832,18 +845,21 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
	if (of_machine_is_compatible("fsl,imx6dl"))
		return 0;

	spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;

	/* Prepare for TX DMA: */
	master->dma_tx = dma_request_slave_channel(dev, "tx");
	if (!master->dma_tx) {
		dev_err(dev, "cannot get the TX DMA channel!\n");
		ret = -EINVAL;
	master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
	if (IS_ERR(master->dma_tx)) {
		ret = PTR_ERR(master->dma_tx);
		dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret);
		master->dma_tx = NULL;
		goto err;
	}

	slave_config.direction = DMA_MEM_TO_DEV;
	slave_config.dst_addr = res->start + MXC_CSPITXDATA;
	slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
	slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
	slave_config.dst_maxburst = spi_imx->wml;
	ret = dmaengine_slave_config(master->dma_tx, &slave_config);
	if (ret) {
		dev_err(dev, "error in TX dma configuration.\n");
@@ -851,17 +867,18 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
	}

	/* Prepare for RX : */
	master->dma_rx = dma_request_slave_channel(dev, "rx");
	if (!master->dma_rx) {
		dev_dbg(dev, "cannot get the DMA channel.\n");
		ret = -EINVAL;
	master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
	if (IS_ERR(master->dma_rx)) {
		ret = PTR_ERR(master->dma_rx);
		dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret);
		master->dma_rx = NULL;
		goto err;
	}

	slave_config.direction = DMA_DEV_TO_MEM;
	slave_config.src_addr = res->start + MXC_CSPIRXDATA;
	slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
	slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
	slave_config.src_maxburst = spi_imx->wml;
	ret = dmaengine_slave_config(master->dma_rx, &slave_config);
	if (ret) {
		dev_err(dev, "error in RX dma configuration.\n");
@@ -874,8 +891,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
	master->max_dma_len = MAX_SDMA_BD_BYTES;
	spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
					 SPI_MASTER_MUST_TX;
	spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2;
	spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2;
	spi_imx->dma_is_inited = 1;

	return 0;
@@ -942,14 +957,22 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
	dma = readl(spi_imx->base + MX51_ECSPI_DMA);
	dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
	/* Change RX_DMA_LENGTH trigger dma fetch tail data */
	left = transfer->len % spi_imx->rxt_wml;
	left = transfer->len % spi_imx->wml;
	if (left)
		writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
				spi_imx->base + MX51_ECSPI_DMA);
	/*
	 * Set these order to avoid potential RX overflow. The overflow may
	 * happen if we enable SPI HW before starting RX DMA due to rescheduling
	 * for another task and/or interrupt.
	 * So RX DMA enabled first to make sure data would be read out from FIFO
	 * ASAP. TX DMA enabled next to start filling TX FIFO with new data.
	 * And finaly SPI HW enabled to start actual data transfer.
	 */
	dma_async_issue_pending(master->dma_rx);
	dma_async_issue_pending(master->dma_tx);
	spi_imx->devtype_data->trigger(spi_imx);

	dma_async_issue_pending(master->dma_tx);
	dma_async_issue_pending(master->dma_rx);
	/* Wait SDMA to finish the data transfer.*/
	timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion,
						IMX_DMA_TIMEOUT);
@@ -958,6 +981,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
			dev_driver_string(&master->dev),
			dev_name(&master->dev));
		dmaengine_terminate_all(master->dma_tx);
		dmaengine_terminate_all(master->dma_rx);
	} else {
		timeout = wait_for_completion_timeout(
				&spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT);
@@ -968,8 +992,9 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
			spi_imx->devtype_data->reset(spi_imx);
			dmaengine_terminate_all(master->dma_rx);
		}
		dma &= ~MX51_ECSPI_DMA_RXT_WML_MASK;
		writel(dma |
		       spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET,
		       spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET,
		       spi_imx->base + MX51_ECSPI_DMA);
	}

@@ -1117,6 +1142,9 @@ static int spi_imx_probe(struct platform_device *pdev)
	spi_imx = spi_master_get_devdata(master);
	spi_imx->bitbang.master = master;

	spi_imx->devtype_data = of_id ? of_id->data :
		(struct spi_imx_devtype_data *)pdev->id_entry->driver_data;

	for (i = 0; i < master->num_chipselect; i++) {
		int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
		if (!gpio_is_valid(cs_gpio) && mxc_platform_info)
@@ -1142,12 +1170,11 @@ static int spi_imx_probe(struct platform_device *pdev)
	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
	if (is_imx51_ecspi(spi_imx))
		spi_imx->bitbang.master->mode_bits |= SPI_LOOP;

	init_completion(&spi_imx->xfer_done);

	spi_imx->devtype_data = of_id ? of_id->data :
		(struct spi_imx_devtype_data *) pdev->id_entry->driver_data;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(spi_imx->base)) {
@@ -1193,9 +1220,15 @@ static int spi_imx_probe(struct platform_device *pdev)
	 * Only validated on i.mx6 now, can remove the constrain if validated on
	 * other chips.
	 */
	if (spi_imx->devtype_data == &imx51_ecspi_devtype_data
	    && spi_imx_sdma_init(&pdev->dev, spi_imx, master, res))
		dev_err(&pdev->dev, "dma setup error,use pio instead\n");
	if (is_imx51_ecspi(spi_imx)) {
		ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master, res);
		if (ret == -EPROBE_DEFER)
			goto out_clk_put;

		if (ret < 0)
			dev_err(&pdev->dev, "dma setup error %d, use pio\n",
				ret);
	}

	spi_imx->devtype_data->reset(spi_imx);

Loading