before spi transfer. use spi_prepare_message to setup spi hardware. it will setup MSB, spi mode and speed
Signed-off-by: Michael Lee <igv...@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@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel