Unverified Commit 6a23e577 authored by Mark Brown's avatar Mark Brown
Browse files

Merge series "spi: rspi: Bit rate improvements" from Geert Uytterhoeven <geert+renesas@glider.be>:

	Hi Mark,

This patch series contains several improvements for the Renesas SPI/QSPI
driver related to bit rate configuration.

Changes compared to v1
(https://lore.kernel.org/r/20200608095940.30516-1-geert+renesas@glider.be):
  - Drop accepted patch.

This has been tested on RSK+RZA1 (RSPI) and R-Car M2-W/Koelsch (QSPI),
using a scope and logic analyzer, except for the by-one divider on QSPI.
This has not been tested on legacy SuperH, due to lack of hardware.

Thanks for your comments!

Geert Uytterhoeven (7):
  spi: rspi: Remove useless .set_config_register() check
  spi: rspi: Clean up Bit Rate Division Setting handling
  spi: rspi: Increase bit rate accuracy on RZ/A
  spi: rspi: Increase bit rate range for RSPI on SH
  spi: rspi: Increase bit rate range for QSPI
  spi: rspi: Fill in spi_transfer.effective_speed_hz
  spi: rspi: Fill in controller speed limits

 drivers/spi/spi-rspi.c | 81 +++++++++++++++++++++++++++---------------
 1 file changed, 52 insertions(+), 29 deletions(-)

--
2.17.1

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds
parents c76964e8 c3197974
Loading
Loading
Loading
Loading
+52 −29
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@
#define SPCMD_SPRW		0x0010	/* SPI Read/Write Access (Dual/Quad) */
#define SPCMD_SSLA(i)		((i) << 4)	/* SSL Assert Signal Setting */
#define SPCMD_BRDV_MASK		0x000c	/* Bit Rate Division Setting */
#define SPCMD_BRDV(brdv)	((brdv) << 2)
#define SPCMD_CPOL		0x0002	/* Clock Polarity Setting */
#define SPCMD_CPHA		0x0001	/* Clock Phase Setting */

@@ -242,24 +243,40 @@ struct spi_ops {
	int (*transfer_one)(struct spi_controller *ctlr,
			    struct spi_device *spi, struct spi_transfer *xfer);
	u16 extra_mode_bits;
	u16 min_div;
	u16 max_div;
	u16 flags;
	u16 fifo_size;
	u8 num_hw_ss;
};

static void rspi_set_rate(struct rspi_data *rspi)
{
	unsigned long clksrc;
	int brdv = 0, spbr;

	clksrc = clk_get_rate(rspi->clk);
	spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz) - 1;
	while (spbr > 255 && brdv < 3) {
		brdv++;
		spbr = DIV_ROUND_UP(spbr + 1, 2) - 1;
	}

	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
	rspi->spcmd |= SPCMD_BRDV(brdv);
	rspi->speed_hz = DIV_ROUND_UP(clksrc, (2U << brdv) * (spbr + 1));
}

/*
 * functions for RSPI on legacy SH
 */
static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
{
	int spbr;

	/* Sets output mode, MOSI signal, and (optionally) loopback */
	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);

	/* Sets transfer bit rate */
	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->speed_hz) - 1;
	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
	rspi_set_rate(rspi);

	/* Disable dummy transmission, set 16-bit word access, 1 frame */
	rspi_write8(rspi, 0, RSPI_SPDCR);
@@ -289,25 +306,11 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
 */
static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
{
	int spbr;
	int div = 0;
	unsigned long clksrc;

	/* Sets output mode, MOSI signal, and (optionally) loopback */
	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);

	clksrc = clk_get_rate(rspi->clk);
	while (div < 3) {
		if (rspi->speed_hz >= clksrc/4) /* 4=(CLK/2)/2 */
			break;
		div++;
		clksrc /= 2;
	}

	/* Sets transfer bit rate */
	spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz) - 1;
	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
	rspi->spcmd |= div << 2;
	rspi_set_rate(rspi);

	/* Disable dummy transmission, set byte access */
	rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR);
@@ -334,14 +337,28 @@ static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
 */
static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
{
	int spbr;
	unsigned long clksrc;
	int brdv = 0, spbr;

	/* Sets output mode, MOSI signal, and (optionally) loopback */
	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);

	/* Sets transfer bit rate */
	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->speed_hz);
	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
	clksrc = clk_get_rate(rspi->clk);
	if (rspi->speed_hz >= clksrc) {
		spbr = 0;
		rspi->speed_hz = clksrc;
	} else {
		spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz);
		while (spbr > 255 && brdv < 3) {
			brdv++;
			spbr = DIV_ROUND_UP(spbr, 2);
		}
		spbr = clamp(spbr, 0, 255);
		rspi->speed_hz = DIV_ROUND_UP(clksrc, (2U << brdv) * spbr);
	}
	rspi_write8(rspi, spbr, RSPI_SPBR);
	rspi->spcmd |= SPCMD_BRDV(brdv);

	/* Disable dummy transmission, set byte access */
	rspi_write8(rspi, 0, RSPI_SPDCR);
@@ -686,6 +703,8 @@ static int rspi_common_transfer(struct rspi_data *rspi,
{
	int ret;

	xfer->effective_speed_hz = rspi->speed_hz;

	ret = rspi_dma_check_then_transfer(rspi, xfer);
	if (ret != -EAGAIN)
		return ret;
@@ -841,6 +860,7 @@ static int qspi_transfer_one(struct spi_controller *ctlr,
{
	struct rspi_data *rspi = spi_controller_get_devdata(ctlr);

	xfer->effective_speed_hz = rspi->speed_hz;
	if (spi->mode & SPI_LOOP) {
		return qspi_transfer_out_in(rspi, xfer);
	} else if (xfer->tx_nbits > SPI_NBITS_SINGLE) {
@@ -1163,6 +1183,8 @@ static int rspi_remove(struct platform_device *pdev)
static const struct spi_ops rspi_ops = {
	.set_config_register =	rspi_set_config_register,
	.transfer_one =		rspi_transfer_one,
	.min_div =		2,
	.max_div =		4096,
	.flags =		SPI_CONTROLLER_MUST_TX,
	.fifo_size =		8,
	.num_hw_ss =		2,
@@ -1171,6 +1193,8 @@ static const struct spi_ops rspi_ops = {
static const struct spi_ops rspi_rz_ops = {
	.set_config_register =	rspi_rz_set_config_register,
	.transfer_one =		rspi_rz_transfer_one,
	.min_div =		2,
	.max_div =		4096,
	.flags =		SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX,
	.fifo_size =		8,	/* 8 for TX, 32 for RX */
	.num_hw_ss =		1,
@@ -1181,6 +1205,8 @@ static const struct spi_ops qspi_ops = {
	.transfer_one =		qspi_transfer_one,
	.extra_mode_bits =	SPI_TX_DUAL | SPI_TX_QUAD |
				SPI_RX_DUAL | SPI_RX_QUAD,
	.min_div =		1,
	.max_div =		4080,
	.flags =		SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX,
	.fifo_size =		32,
	.num_hw_ss =		1,
@@ -1242,6 +1268,7 @@ static int rspi_probe(struct platform_device *pdev)
	int ret;
	const struct rspi_plat_data *rspi_pd;
	const struct spi_ops *ops;
	unsigned long clksrc;

	ctlr = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
	if (ctlr == NULL)
@@ -1261,13 +1288,6 @@ static int rspi_probe(struct platform_device *pdev)
			ctlr->num_chipselect = 2; /* default */
	}

	/* ops parameter check */
	if (!ops->set_config_register) {
		dev_err(&pdev->dev, "there is no set_config_register\n");
		ret = -ENODEV;
		goto error1;
	}

	rspi = spi_controller_get_devdata(ctlr);
	platform_set_drvdata(pdev, rspi);
	rspi->ops = ops;
@@ -1301,6 +1321,9 @@ static int rspi_probe(struct platform_device *pdev)
	ctlr->unprepare_message = rspi_unprepare_message;
	ctlr->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST |
			  SPI_LOOP | ops->extra_mode_bits;
	clksrc = clk_get_rate(rspi->clk);
	ctlr->min_speed_hz = DIV_ROUND_UP(clksrc, ops->max_div);
	ctlr->max_speed_hz = DIV_ROUND_UP(clksrc, ops->min_div);
	ctlr->flags = ops->flags;
	ctlr->dev.of_node = pdev->dev.of_node;
	ctlr->use_gpio_descriptors = true;