[OpenWrt-Devel] [PATCH 5/8] ramips: move mt7621 spi clock set to spi_prepare_message

Michael Lee igvtee at gmail.com
Sat Oct 10 23:54:31 EDT 2015


before spi transfer. use spi_prepare_message to setup spi hardware. it
will setup MSB, spi mode and speed

Signed-off-by: Michael Lee <igvtee at gmail.com>
---
 ...0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch | 133 ++++++++++++---------
 1 file changed, 75 insertions(+), 58 deletions(-)

diff --git a/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch b/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch
index 0ea0508..d1067ea 100644
--- a/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch
+++ b/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch
@@ -25,7 +25,7 @@
  obj-$(CONFIG_SPI_OC_TINY)		+= spi-oc-tiny.o
 --- /dev/null
 +++ b/drivers/spi/spi-mt7621.c
-@@ -0,0 +1,565 @@
+@@ -0,0 +1,582 @@
 +/*
 + * spi-mt7621.c -- MediaTek MT7621 SPI controller driver
 + *
@@ -57,8 +57,6 @@
 +#include <ralink_regs.h>
 +
 +#define DRIVER_NAME			"spi-mt7621"
-+/* in usec */
-+#define RALINK_SPI_WAIT_MAX_LOOP	2000
 +
 +#define MT7621_SPI_TRANS	0x00
 +#define MT7621_SPI_OPCODE	0x04
@@ -147,8 +145,9 @@
 +struct mt7621_spi {
 +	struct spi_master	*master;
 +	void __iomem		*base;
-+	unsigned int		speed;
++	u32			speed;
 +	u16			wait_loops;
++	u16			mode;
 +	struct clk		*clk;
 +};
 +
@@ -181,6 +180,34 @@
 +	iowrite32((ioread32(addr) & ~mask), addr);
 +}
 +
++static u32 mt7621_spi_baudrate_get(struct spi_device *spi, unsigned int speed)
++{
++	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
++	u32 rate;
++	u32 prescale;
++
++	/*
++	 * the supported rates are: 2, 3, 4, ... 4096
++	 * round up as we look for equal or less speed
++	 */
++	rate = DIV_ROUND_UP(clk_get_rate(rs->clk), speed);
++
++	/* Convert the rate to SPI clock divisor value.	*/
++	prescale = rate - 2;
++
++	/* some tolerance. double and add 100 */
++	rs->wait_loops = (8 * HZ * loops_per_jiffy) /
++		(clk_get_rate(rs->clk) / rate);
++	rs->wait_loops = (rs->wait_loops << 1) + 100;
++	rs->speed = speed;
++
++	dev_dbg(&spi->dev, "speed: %lu/%u, rate: %u, prescal: %u, loops: %hu\n",
++			clk_get_rate(rs->clk) / rate, speed, rate, prescale,
++			rs->wait_loops);
++
++	return (prescale << SPIMASTER_CLKSEL_OFFSET);
++}
++
 +static void mt7621_spi_reset(struct mt7621_spi *rs, int duplex)
 +{
 +	u32 master = mt7621_spi_read(rs, MT7621_SPI_MASTER);
@@ -207,50 +234,6 @@
 +	mt7621_spi_write(rs, MT7621_SPI_POLAR, polar);
 +}
 +
-+static int mt7621_spi_prepare(struct spi_device *spi, unsigned int speed)
-+{
-+	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
-+	u32 rate;
-+	u32 reg;
-+
-+	dev_dbg(&spi->dev, "speed:%u\n", speed);
-+
-+	rate = DIV_ROUND_UP(clk_get_rate(rs->clk), speed);
-+	dev_dbg(&spi->dev, "rate-1:%u\n", rate);
-+
-+	reg = mt7621_spi_read(rs, MT7621_SPI_MASTER);
-+	reg &= ~(0xfff << 16);
-+	reg |= (rate - 2) << 16;
-+
-+	/* some tolerance. double and add 100 */
-+	rs->wait_loops = (8 * HZ * loops_per_jiffy) /
-+		(clk_get_rate(rs->clk) / rate);
-+	rs->wait_loops = (rs->wait_loops << 1) + 100;
-+	rs->speed = speed;
-+
-+	reg &= ~SPIMASTER_LSB;
-+	if (spi->mode & SPI_LSB_FIRST)
-+		reg |= SPIMASTER_LSB;
-+
-+	reg &= ~(SPIMASTER_CPHA | SPIMASTER_CPOL);
-+	switch(spi->mode & (SPI_CPOL | SPI_CPHA)) {
-+		case SPI_MODE_0:
-+			break;
-+		case SPI_MODE_1:
-+			reg |= SPIMASTER_CPHA;
-+			break;
-+		case SPI_MODE_2:
-+			reg |= SPIMASTER_CPOL;
-+			break;
-+		case SPI_MODE_3:
-+			reg |= SPIMASTER_CPOL | SPIMASTER_CPHA;
-+			break;
-+	}
-+	mt7621_spi_write(rs, MT7621_SPI_MASTER, reg);
-+
-+	return 0;
-+}
-+
 +static inline int mt7621_spi_wait_ready(struct mt7621_spi *rs, int len)
 +{
 +	int loop = rs->wait_loops * len;
@@ -269,7 +252,6 @@
 +{
 +	struct mt7621_spi *rs = spi_master_get_devdata(master);
 +	struct spi_device *spi = m->spi;
-+	unsigned int speed = spi->max_speed_hz;
 +	struct spi_transfer *t = NULL;
 +	int status = 0;
 +	int i, len = 0;
@@ -302,10 +284,6 @@
 +		goto msg_done;
 +	}
 +
-+	if (mt7621_spi_prepare(spi, speed)) {
-+		status = -EIO;
-+		goto msg_done;
-+	}
 +	data[0] = swab32(data[0]);
 +	if (len < 4)
 +		data[0] >>= (4 - len) * 8;
@@ -392,11 +370,6 @@
 +		goto msg_done;
 +	}
 +
-+	if (mt7621_spi_prepare(spi, speed)) {
-+		status = -EIO;
-+		goto msg_done;
-+	}
-+
 +	for (i = 0; i < len; i += 4)
 +		mt7621_spi_write(rs, MT7621_SPI_DATA0 + i, data[i / 4]);
 +
@@ -481,6 +454,49 @@
 +	return 0;
 +}
 +
++static int mt7621_spi_prepare_message(struct spi_master *master,
++		struct spi_message *msg)
++{
++	struct mt7621_spi *rs = spi_master_get_devdata(master);
++	struct spi_device *spi = msg->spi;
++	u32 reg;
++
++	if ((rs->mode == spi->mode) && (rs->speed == spi->max_speed_hz))
++		return 0;
++
++	reg = mt7621_spi_read(rs, MT7621_SPI_MASTER);
++	reg &= ~((SPIMASTER_CLKSEL_MASK << SPIMASTER_CLKSEL_OFFSET) |
++			SPIMASTER_CPHA | SPIMASTER_CPOL |
++			SPIMASTER_LSB);
++
++	/* LSB */
++	if (spi->mode & SPI_LSB_FIRST)
++		reg |= SPIMASTER_LSB;
++
++	/* spi mode */
++	switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
++	case SPI_MODE_0:
++		break;
++	case SPI_MODE_1:
++		reg |= SPIMASTER_CPHA;
++		break;
++	case SPI_MODE_2:
++		reg |= SPIMASTER_CPOL;
++		break;
++	case SPI_MODE_3:
++		reg |= SPIMASTER_CPOL | SPIMASTER_CPHA;
++		break;
++	}
++	rs->mode = spi->mode;
++
++	/* clock divide */
++	reg |= mt7621_spi_baudrate_get(spi, spi->max_speed_hz);
++
++	mt7621_spi_write(rs, MT7621_SPI_MASTER, reg);
++
++	return 0;
++}
++
 +static const struct of_device_id mt7621_spi_match[] = {
 +	{ .compatible = "ralink,mt7621-spi" },
 +	{},
@@ -530,6 +546,7 @@
 +	master->max_speed_hz = clk_get_rate(clk) / 2;
 +	master->flags = SPI_MASTER_HALF_DUPLEX;
 +	master->setup = mt7621_spi_setup;
++	master->prepare_message = mt7621_spi_prepare_message;
 +	master->transfer_one_message = mt7621_spi_transfer_one_message;
 +	master->num_chipselect = 2;
 +
-- 
2.3.6
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list