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

Reply via email to