@@ -20,6 +20,11 @@
compatible = "mti,cpu-interrupt-controller";
};
+ aliases {
+ spi0 = &spi0;
+ spi1 = &spi1;
+ };
+
palmbus@10000000 {
compatible = "palmbus";
reg = <0x10000000 0x200000>;
@@ -202,9 +207,9 @@
status = "disabled";
};
- spi@b00 {
+ spi0: spi@b00 {
compatible = "ralink,mt7620a-spi", "ralink,rt2880-spi";
- reg = <0xb00 0x100>;
+ reg = <0xb00 0x40>;
resets = <&rstctrl 18>;
reset-names = "spi";
@@ -218,6 +223,22 @@
pinctrl-0 = <&spi_pins>;
};
+ spi1: spi@b40 {
+ compatible = "ralink,rt2880-spi";
+ reg = <0xb40 0x60>;
+
+ resets = <&rstctrl 18>;
+ reset-names = "spi";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ status = "disabled";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_cs1>;
+ };
+
uartlite@c00 {
compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a";
reg = <0xc00 0x100>;
@@ -305,6 +326,13 @@
};
};
+ spi_cs1: spi1 {
+ spi1 {
+ ralink,group = "spi_cs1";
+ ralink,function = "spi_cs1";
+ };
+ };
+
i2c_pins: i2c {
i2c {
ralink,group = "i2c";
@@ -20,6 +20,11 @@
compatible = "mti,cpu-interrupt-controller";
};
+ aliases {
+ spi0 = &spi0;
+ spi1 = &spi1;
+ };
+
palmbus@10000000 {
compatible = "palmbus";
reg = <0x10000000 0x200000>;
@@ -154,9 +159,9 @@
status = "disabled";
};
- spi@b00 {
+ spi0: spi@b00 {
compatible = "ralink,mt7620a-spi", "ralink,rt2880-spi";
- reg = <0xb00 0x100>;
+ reg = <0xb00 0x40>;
resets = <&rstctrl 18>;
reset-names = "spi";
@@ -170,6 +175,22 @@
pinctrl-0 = <&spi_pins>;
};
+ spi1: spi@b40 {
+ compatible = "ralink,rt2880-spi";
+ reg = <0xb40 0x60>;
+
+ resets = <&rstctrl 18>;
+ reset-names = "spi";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ status = "disabled";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_cs1>;
+ };
+
uartlite@c00 {
compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a";
reg = <0xc00 0x100>;
@@ -213,6 +234,13 @@
};
};
+ spi_cs1: spi1 {
+ spi1 {
+ ralink,group = "spi_cs1";
+ ralink,function = "spi_cs1";
+ };
+ };
+
uartlite_pins: uartlite {
uart {
ralink,group = "uartlite";
@@ -13,6 +13,10 @@
bootargs = "console=ttyS0,57600";
};
+ aliases {
+ spi0 = &spi0;
+ };
+
cpuintc: cpuintc@0 {
#address-cells = <0>;
#interrupt-cells = <1>;
@@ -144,7 +148,7 @@
status = "disabled";
};
- spi@b00 {
+ spi0: spi@b00 {
compatible = "ralink,rt3050-spi", "ralink,rt2880-spi";
reg = <0xb00 0x100>;
@@ -20,6 +20,11 @@
compatible = "mti,cpu-interrupt-controller";
};
+ aliases {
+ spi0 = &spi0;
+ spi1 = &spi1;
+ };
+
palmbus@10000000 {
compatible = "palmbus";
reg = <0x10000000 0x200000>;
@@ -140,9 +145,9 @@
status = "disabled";
};
- spi@b00 {
+ spi0: spi@b00 {
compatible = "ralink,rt3352-spi", "ralink,rt2880-spi";
- reg = <0xb00 0x100>;
+ reg = <0xb00 0x40>;
#address-cells = <1>;
#size-cells = <1>;
@@ -155,6 +160,21 @@
status = "disabled";
};
+ spi1: spi@b40 {
+ compatible = "ralink,rt3352-spi", "ralink,rt2880-spi";
+ reg = <0xb40 0x60>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ resets = <&rstctrl 18>;
+ reset-names = "spi";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_cs1>;
+
+ status = "disabled";
+ };
+
uartlite@c00 {
compatible = "ralink,rt3352-uart", "ralink,rt2880-uart", "ns16550a";
reg = <0xc00 0x100>;
@@ -188,6 +208,13 @@
};
};
+ spi_cs1: spi1 {
+ spi1 {
+ ralink,group = "spi_cs1";
+ ralink,function = "spi_cs1";
+ };
+ };
+
uartlite_pins: uartlite {
uart {
ralink,group = "uartlite";
@@ -15,6 +15,7 @@
aliases {
spi0 = &spi0;
+ spi1 = &spi1;
};
cpuintc: cpuintc@0 {
@@ -166,7 +167,7 @@
spi0: spi@b00 {
compatible = "ralink,rt3883-spi", "ralink,rt2880-spi";
- reg = <0xb00 0x100>;
+ reg = <0xb00 0x40>;
#address-cells = <1>;
#size-cells = <0>;
@@ -179,6 +180,21 @@
status = "disabled";
};
+ spi1: spi@b40 {
+ compatible = "ralink,rt3883-spi", "ralink,rt2880-spi";
+ reg = <0xb40 0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ resets = <&rstctrl 18>;
+ reset-names = "spi";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_cs1>;
+
+ status = "disabled";
+ };
+
uartlite@c00 {
compatible = "ralink,rt3883-uart", "ralink,rt2880-uart", "ns16550a";
reg = <0xc00 0x100>;
@@ -212,6 +228,13 @@
};
};
+ spi_cs1: spi1 {
+ spi1 {
+ ralink,group = "spi_cs1";
+ ralink,function = "spi_cs1";
+ };
+ };
+
uartlite_pins: uartlite {
uart {
ralink,group = "uartlite";
@@ -20,6 +20,11 @@
compatible = "mti,cpu-interrupt-controller";
};
+ aliases {
+ spi0 = &spi0;
+ spi1 = &spi1;
+ };
+
palmbus@10000000 {
compatible = "palmbus";
reg = <0x10000000 0x200000>;
@@ -150,9 +155,25 @@
status = "disabled";
};
- spi@b00 {
- compatible = "ralink,rt5350-spi";
- reg = <0xb00 0x100>;
+ spi0: spi@b00 {
+ compatible = "ralink,rt5350-spi", "ralink,rt2880-spi";
+ reg = <0xb00 0x40>;
+
+ resets = <&rstctrl 18>;
+ reset-names = "spi";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_pins>;
+
+ status = "disabled";
+ };
+
+ spi1: spi@b40 {
+ compatible = "ralink,rt5350-spi", "ralink,rt2880-spi";
+ reg = <0xb40 0x60>;
resets = <&rstctrl 18>;
reset-names = "spi";
@@ -161,7 +182,7 @@
#size-cells = <1>;
pinctrl-names = "default";
- pinctrl-0 = <&spi_pins &spi_cs1>;
+ pinctrl-0 = <&spi_cs1>;
status = "disabled";
};
@@ -41,12 +41,13 @@ Acked-by: John Crispin <blogic@openwrt.org>
spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
--- /dev/null
+++ b/drivers/spi/spi-rt2880.c
-@@ -0,0 +1,432 @@
+@@ -0,0 +1,901 @@
+/*
+ * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver
+ *
+ * Copyright (C) 2011 Sergiy <piratfm@gmail.com>
+ * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2015 Michael Lee <igvtee@gmail.com>
+ *
+ * Some parts are based on spi-orion.c:
+ * Author: Shadi Ammouri <shadi@marvell.com>
@@ -65,29 +66,45 @@ Acked-by: John Crispin <blogic@openwrt.org>
+#include <linux/io.h>
+#include <linux/reset.h>
+#include <linux/spi/spi.h>
++#include <linux/of_device.h>
+#include <linux/platform_device.h>
++#include <linux/gpio.h>
++#include <linux/mtd/spi-nor.h>
++#include <linux/list.h>
++
++#include <ralink_regs.h>
+
+#define DRIVER_NAME "spi-rt2880"
-+/* only one slave is supported*/
-+#define RALINK_NUM_CHIPSELECTS 1
-+/* in usec */
-+#define RALINK_SPI_WAIT_MAX_LOOP 2000
+
+#define RAMIPS_SPI_STAT 0x00
+#define RAMIPS_SPI_CFG 0x10
+#define RAMIPS_SPI_CTL 0x14
+#define RAMIPS_SPI_DATA 0x20
++#define RAMIPS_SPI_ADDR 0x24
++#define RAMIPS_SPI_BS 0x28
++#define RAMIPS_SPI_USER 0x2C
++#define RAMIPS_SPI_TXFIFO 0x30
++#define RAMIPS_SPI_RXFIFO 0x34
+#define RAMIPS_SPI_FIFO_STAT 0x38
++#define RAMIPS_SPI_MODE 0x3C
++#define RAMIPS_SPI_DEV_OFFSET 0x40
++#define RAMIPS_SPI_DMA 0x80
++#define RAMIPS_SPI_DMASTAT 0x84
++#define RAMIPS_SPI_ARBITER 0xF0
+
+/* SPISTAT register bit field */
+#define SPISTAT_BUSY BIT(0)
+
+/* SPICFG register bit field */
-+#define SPICFG_LSBFIRST 0
++#define SPICFG_ADDRMODE BIT(12)
++#define SPICFG_RXENVDIS BIT(11)
++#define SPICFG_RXCAP BIT(10)
++#define SPICFG_SPIENMODE BIT(9)
+#define SPICFG_MSBFIRST BIT(8)
+#define SPICFG_SPICLKPOL BIT(6)
+#define SPICFG_RXCLKEDGE_FALLING BIT(5)
+#define SPICFG_TXCLKEDGE_FALLING BIT(4)
++#define SPICFG_HIZSPI BIT(3)
+#define SPICFG_SPICLK_PRESCALE_MASK 0x7
+#define SPICFG_SPICLK_DIV2 0
+#define SPICFG_SPICLK_DIV4 1
@@ -99,21 +116,109 @@ Acked-by: John Crispin <blogic@openwrt.org>
+#define SPICFG_SPICLK_DISABLE 7
+
+/* SPICTL register bit field */
++#define SPICTL_START BIT(4)
+#define SPICTL_HIZSDO BIT(3)
+#define SPICTL_STARTWR BIT(2)
+#define SPICTL_STARTRD BIT(1)
+#define SPICTL_SPIENA BIT(0)
+
++/* SPIUSER register bit field */
++#define SPIUSER_USERMODE BIT(21)
++#define SPIUSER_INSTR_PHASE BIT(20)
++#define SPIUSER_ADDR_PHASE_MASK 0x7
++#define SPIUSER_ADDR_PHASE_OFFSET 17
++#define SPIUSER_MODE_PHASE BIT(16)
++#define SPIUSER_DUMMY_PHASE_MASK 0x3
++#define SPIUSER_DUMMY_PHASE_OFFSET 14
++#define SPIUSER_DATA_PHASE_MASK 0x3
++#define SPIUSER_DATA_PHASE_OFFSET 12
++#define SPIUSER_DATA_READ (BIT(0) << SPIUSER_DATA_PHASE_OFFSET)
++#define SPIUSER_DATA_WRITE (BIT(1) << SPIUSER_DATA_PHASE_OFFSET)
++#define SPIUSER_ADDR_TYPE_OFFSET 9
++#define SPIUSER_MODE_TYPE_OFFSET 6
++#define SPIUSER_DUMMY_TYPE_OFFSET 3
++#define SPIUSER_DATA_TYPE_OFFSET 0
++#define SPIUSER_TRANSFER_MASK 0x7
++#define SPIUSER_TRANSFER_SINGLE BIT(0)
++#define SPIUSER_TRANSFER_DUAL BIT(1)
++#define SPIUSER_TRANSFER_QUAD BIT(2)
++
++#define SPIUSER_TRANSFER_TYPE(type) ( \
++ (type << SPIUSER_ADDR_TYPE_OFFSET) | \
++ (type << SPIUSER_MODE_TYPE_OFFSET) | \
++ (type << SPIUSER_DUMMY_TYPE_OFFSET) | \
++ (type << SPIUSER_DATA_TYPE_OFFSET) \
++)
++
+/* SPIFIFOSTAT register bit field */
++#define SPIFIFOSTAT_TXEMPTY BIT(19)
++#define SPIFIFOSTAT_RXEMPTY BIT(18)
+#define SPIFIFOSTAT_TXFULL BIT(17)
++#define SPIFIFOSTAT_RXFULL BIT(16)
++#define SPIFIFOSTAT_FIFO_MASK 0xff
++#define SPIFIFOSTAT_TX_OFFSET 8
++#define SPIFIFOSTAT_RX_OFFSET 0
++
++#define SPI_FIFO_DEPTH 16
++
++/* SPIMODE register bit field */
++#define SPIMODE_MODE_OFFSET 24
++#define SPIMODE_DUMMY_OFFSET 0
++
++/* SPIARB register bit field */
++#define SPICTL_ARB_EN BIT(31)
++#define SPICTL_CSCTL1 BIT(16)
++#define SPI1_POR BIT(1)
++#define SPI0_POR BIT(0)
++
++#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | \
++ SPI_CS_HIGH)
++#define MT7620_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | \
++ SPI_CS_HIGH | SPI_RX_DUAL | SPI_RX_QUAD)
++
++static atomic_t hw_reset_count = ATOMIC_INIT(0);
++
++/* cmd flags */
++#define SPI_CMD_ADDR BIT(0)
++#define SPI_CMD_DUMMY BIT(1)
++#define SPI_CMD_TX BIT(2)
++#define SPI_CMD_RX BIT(3)
++#define SPI_CMD_USER BIT(4)
++#define SPI_CMD_EN4B BIT(5)
++#define SPI_CMD_EX4B BIT(6)
++
++/* cmd status */
++#define SPI_STATE_OPCODE 0
++#define SPI_STATE_DATA 1
++
++struct mt7620_spi_cmd {
++ u8 opcode;
++ u8 status;
++ u16 flags;
++ u32 addr;
++ const u8 *tx_buf;
++ u8 *rx_buf;
++ u32 len;
++};
++
++#define SPI_FLAG_HW_MODE 0x1
++struct rt2880_spi_ops {
++ u32 flags;
++ int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
++ struct spi_transfer *transfer);
++};
+
+struct rt2880_spi {
+ struct spi_master *master;
+ void __iomem *base;
-+ unsigned int sys_freq;
-+ unsigned int speed;
++ u32 speed;
++ u16 wait_loops;
++ u16 mode;
+ struct clk *clk;
-+ spinlock_t lock;
++ int addr_width;
++
++ struct rt2880_spi_ops *ops;
++ struct mt7620_spi_cmd cmd;
+};
+
+static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi)
@@ -126,7 +231,8 @@ Acked-by: John Crispin <blogic@openwrt.org>
+ return ioread32(rs->base + reg);
+}
+
-+static inline void rt2880_spi_write(struct rt2880_spi *rs, u32 reg, u32 val)
++static inline void rt2880_spi_write(struct rt2880_spi *rs, u32 reg,
++ const u32 val)
+{
+ iowrite32(val, rs->base + reg);
+}
@@ -134,132 +240,172 @@ Acked-by: John Crispin <blogic@openwrt.org>
+static inline void rt2880_spi_setbits(struct rt2880_spi *rs, u32 reg, u32 mask)
+{
+ void __iomem *addr = rs->base + reg;
-+ unsigned long flags;
-+ u32 val;
-+
-+ spin_lock_irqsave(&rs->lock, flags);
-+ val = ioread32(addr);
-+ val |= mask;
-+ iowrite32(val, addr);
-+ spin_unlock_irqrestore(&rs->lock, flags);
++
++ iowrite32((ioread32(addr) | mask), addr);
+}
+
+static inline void rt2880_spi_clrbits(struct rt2880_spi *rs, u32 reg, u32 mask)
+{
+ void __iomem *addr = rs->base + reg;
-+ unsigned long flags;
-+ u32 val;
-+
-+ spin_lock_irqsave(&rs->lock, flags);
-+ val = ioread32(addr);
-+ val &= ~mask;
-+ iowrite32(val, addr);
-+ spin_unlock_irqrestore(&rs->lock, flags);
++
++ iowrite32((ioread32(addr) & ~mask), addr);
+}
+
-+static int rt2880_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
++static u32 rt2880_spi_baudrate_get(struct spi_device *spi, unsigned int speed)
+{
+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
+ u32 rate;
+ u32 prescale;
-+ u32 reg;
-+
-+ dev_dbg(&spi->dev, "speed:%u\n", speed);
+
+ /*
+ * the supported rates are: 2, 4, 8, ... 128
+ * round up as we look for equal or less speed
+ */
-+ rate = DIV_ROUND_UP(rs->sys_freq, speed);
-+ dev_dbg(&spi->dev, "rate-1:%u\n", rate);
++ rate = DIV_ROUND_UP(clk_get_rate(rs->clk), speed);
+ rate = roundup_pow_of_two(rate);
-+ dev_dbg(&spi->dev, "rate-2:%u\n", rate);
-+
-+ /* check if requested speed is too small */
-+ if (rate > 128)
-+ return -EINVAL;
-+
-+ if (rate < 2)
-+ rate = 2;
+
+ /* Convert the rate to SPI clock divisor value. */
+ prescale = ilog2(rate / 2);
-+ dev_dbg(&spi->dev, "prescale:%u\n", prescale);
+
-+ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG);
-+ reg = ((reg & ~SPICFG_SPICLK_PRESCALE_MASK) | prescale);
-+ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg);
++ /* 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;
-+ return 0;
++
++ 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;
+}
+
-+/*
-+ * called only when no transfer is active on the bus
-+ */
-+static int
-+rt2880_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
++static u32 get_arbiter_offset(struct spi_master *master)
+{
-+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
-+ unsigned int speed = spi->max_speed_hz;
-+ int rc;
-+
-+ if ((t != NULL) && t->speed_hz)
-+ speed = t->speed_hz;
++ u32 offset;
+
-+ if (rs->speed != speed) {
-+ dev_dbg(&spi->dev, "speed_hz:%u\n", speed);
-+ rc = rt2880_spi_baudrate_set(spi, speed);
-+ if (rc)
-+ return rc;
-+ }
++ offset = RAMIPS_SPI_ARBITER;
++ if (master->bus_num == 1)
++ offset -= RAMIPS_SPI_DEV_OFFSET;
+
-+ return 0;
++ return offset;
+}
+
-+static void rt2880_spi_set_cs(struct rt2880_spi *rs, int enable)
++static void rt2880_spi_set_cs(struct spi_device *spi, bool enable)
+{
++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
++
+ if (enable)
++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
++ else
+ rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
++}
++
++static void mt7620_set_4byte(struct rt2880_spi *rs, bool enable)
++{
++ if (enable)
++ rt2880_spi_setbits(rs, RAMIPS_SPI_CFG, SPICFG_ADDRMODE);
+ else
-+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
++ rt2880_spi_clrbits(rs, RAMIPS_SPI_CFG, SPICFG_ADDRMODE);
+}
+
-+static inline int rt2880_spi_wait_till_ready(struct rt2880_spi *rs)
++static int rt2880_spi_wait_ready(struct rt2880_spi *rs, int len)
+{
-+ int i;
++ int loop = rs->wait_loops * len;
++
++ while ((rt2880_spi_read(rs, RAMIPS_SPI_STAT) & SPISTAT_BUSY) && --loop)
++ cpu_relax();
+
-+ for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) {
-+ u32 status;
++ if (loop)
++ return 0;
+
-+ status = rt2880_spi_read(rs, RAMIPS_SPI_STAT);
-+ if ((status & SPISTAT_BUSY) == 0)
-+ return 0;
++ return -ETIMEDOUT;
++}
++
++/* return free fifo count */
++static int mt7620_spi_fifo_ready(struct rt2880_spi *rs, u32 check_bit, bool tx)
++{
++ int loop = rs->wait_loops;
++ u32 stat;
+
++ stat = rt2880_spi_read(rs, RAMIPS_SPI_FIFO_STAT);
++ while ((stat & check_bit) && --loop) {
+ cpu_relax();
-+ udelay(1);
++ stat = rt2880_spi_read(rs, RAMIPS_SPI_FIFO_STAT);
++ }
++
++ if (loop) {
++ if (tx)
++ stat >>= SPIFIFOSTAT_TX_OFFSET;
++ stat &= SPIFIFOSTAT_FIFO_MASK;
++ if (tx)
++ stat = SPI_FIFO_DEPTH - stat;
++
++ return (int)stat;
+ }
+
+ return -ETIMEDOUT;
+}
+
-+static unsigned int
-+rt2880_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
++static void rt2880_dump_reg(struct spi_master *master)
+{
-+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
-+ unsigned count = 0;
-+ u8 *rx = xfer->rx_buf;
-+ const u8 *tx = xfer->tx_buf;
-+ int err;
++ struct rt2880_spi *rs = spi_master_get_devdata(master);
+
-+ dev_dbg(&spi->dev, "read (%d): %s %s\n", xfer->len,
-+ (tx != NULL) ? "tx" : " ",
-+ (rx != NULL) ? "rx" : " ");
++ if (rs->ops->flags && (master->bus_num == 0)) {
++ dev_dbg(&master->dev, "stat: %08x, cfg: %08x, ctl: %08x, " \
++ "data: %08x, addr: %08x, bs: %08x, " \
++ "user: %08x, txfifo: %08x, rxfifo: %08x, " \
++ "fifo_sta: %08x, mode: %08x, dma: " \
++ "%08x, dmastat: %08x, arb: %08x\n",
++ rt2880_spi_read(rs, RAMIPS_SPI_STAT),
++ rt2880_spi_read(rs, RAMIPS_SPI_CFG),
++ rt2880_spi_read(rs, RAMIPS_SPI_CTL),
++ rt2880_spi_read(rs, RAMIPS_SPI_DATA),
++ rt2880_spi_read(rs, RAMIPS_SPI_ADDR),
++ rt2880_spi_read(rs, RAMIPS_SPI_BS),
++ rt2880_spi_read(rs, RAMIPS_SPI_USER),
++ rt2880_spi_read(rs, RAMIPS_SPI_TXFIFO),
++ rt2880_spi_read(rs, RAMIPS_SPI_RXFIFO),
++ rt2880_spi_read(rs, RAMIPS_SPI_FIFO_STAT),
++ rt2880_spi_read(rs, RAMIPS_SPI_MODE),
++ rt2880_spi_read(rs, RAMIPS_SPI_DMA),
++ rt2880_spi_read(rs, RAMIPS_SPI_DMASTAT),
++ rt2880_spi_read(rs, RAMIPS_SPI_ARBITER));
++ } else {
++ dev_dbg(&master->dev, "stat: %08x, cfg: %08x, ctl: %08x, " \
++ "data: %08x, arb: %08x\n",
++ rt2880_spi_read(rs, RAMIPS_SPI_STAT),
++ rt2880_spi_read(rs, RAMIPS_SPI_CFG),
++ rt2880_spi_read(rs, RAMIPS_SPI_CTL),
++ rt2880_spi_read(rs, RAMIPS_SPI_DATA),
++ rt2880_spi_read(rs, get_arbiter_offset(master)));
++ }
++}
++
++static int rt2880_spi_transfer_one(struct spi_master *master,
++ struct spi_device *spi, struct spi_transfer *xfer)
++{
++ struct rt2880_spi *rs = spi_master_get_devdata(master);
++ unsigned len;
++ const u8 *tx = xfer->tx_buf;
++ u8 *rx = xfer->rx_buf;
++ int err = 0;
++
++ /* change clock speed */
++ if (unlikely(rs->speed != xfer->speed_hz)) {
++ u32 reg;
++ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG);
++ reg &= ~SPICFG_SPICLK_PRESCALE_MASK;
++ reg |= rt2880_spi_baudrate_get(spi, xfer->speed_hz);
++ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg);
++ }
+
+ if (tx) {
-+ for (count = 0; count < xfer->len; count++) {
-+ rt2880_spi_write(rs, RAMIPS_SPI_DATA, tx[count]);
++ len = xfer->len;
++ while (len-- > 0) {
++ rt2880_spi_write(rs, RAMIPS_SPI_DATA, *tx++);
+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR);
-+ err = rt2880_spi_wait_till_ready(rs);
++ err = rt2880_spi_wait_ready(rs, 1);
+ if (err) {
+ dev_err(&spi->dev, "TX failed, err=%d\n", err);
+ goto out;
@@ -268,125 +414,436 @@ Acked-by: John Crispin <blogic@openwrt.org>
+ }
+
+ if (rx) {
-+ for (count = 0; count < xfer->len; count++) {
++ len = xfer->len;
++ while (len-- > 0) {
+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD);
-+ err = rt2880_spi_wait_till_ready(rs);
++ err = rt2880_spi_wait_ready(rs, 1);
+ if (err) {
+ dev_err(&spi->dev, "RX failed, err=%d\n", err);
+ goto out;
+ }
-+ rx[count] = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA);
++ *rx++ = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA);
++ }
++ }
++
++out:
++ return err;
++}
++
++static unsigned int m25p_cmd2addr(int addr_width, const u8 *cmd)
++{
++ unsigned int addr;
++
++ /* opcode is in cmd[0] */
++ addr = cmd[1] << (addr_width * 8 - 8);
++ addr |= cmd[2] << (addr_width * 8 - 16);
++ addr |= cmd[3] << (addr_width * 8 - 24);
++ addr |= cmd[4] << (addr_width * 8 - 32);
++
++ return addr;
++}
++
++static int setup_spi_cmd(struct rt2880_spi *rs, const u8 *tx, u32 len,
++ struct mt7620_spi_cmd *cmd)
++{
++ int ret = 0;
++ u32 reg;
++
++ switch (tx[0]) {
++ /* hw support command */
++ case SPINOR_OP_RDSR:
++ case SPINOR_OP_RDID:
++ cmd->flags = SPI_CMD_RX;
++ break;
++ case SPINOR_OP_WRSR:
++ cmd->flags = SPI_CMD_TX;
++ cmd->tx_buf = tx + 1;
++ cmd->len = len - 1;
++ break;
++ case SPINOR_OP_WREN:
++ case SPINOR_OP_WRDI:
++ break;
++ case SPINOR_OP_SE:
++ cmd->flags = SPI_CMD_ADDR;
++ break;
++ case SPINOR_OP_READ:
++ cmd->flags = SPI_CMD_ADDR | SPI_CMD_RX;
++ break;
++ case SPINOR_OP_PP:
++ cmd->flags = SPI_CMD_ADDR | SPI_CMD_TX;
++ break;
++ case SPINOR_OP_READ_FAST:
++ case SPINOR_OP_READ_1_1_2:
++ case SPINOR_OP_READ_1_1_4:
++ cmd->flags = SPI_CMD_ADDR | SPI_CMD_DUMMY | SPI_CMD_RX;
++ break;
++ /* hw unsupport command */
++ case SPINOR_OP_EN4B:
++ cmd->flags = SPI_CMD_USER | SPI_CMD_EN4B;
++ break;
++ case SPINOR_OP_EX4B:
++ cmd->flags = SPI_CMD_USER | SPI_CMD_EX4B;
++ break;
++ case SPINOR_OP_BRWR:
++ if (tx[1] == BIT(7))
++ cmd->flags = SPI_CMD_TX | SPI_CMD_USER | SPI_CMD_EN4B;
++ else
++ cmd->flags = SPI_CMD_TX | SPI_CMD_USER | SPI_CMD_EX4B;
++ cmd->tx_buf = tx + 1;
++ cmd->len = len - 1;
++ break;
++ /* don't know hw support or not. assume unsupport */
++ case SPINOR_OP_CHIP_ERASE:
++ cmd->flags = SPI_CMD_USER;
++ break;
++ case SPINOR_OP_RDFSR:
++ case SPINOR_OP_RDCR:
++ cmd->flags = SPI_CMD_RX | SPI_CMD_USER;
++ break;
++ default:
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /* setup 4 bytes address mode */
++ if (cmd->flags & SPI_CMD_EN4B) {
++ mt7620_set_4byte(rs, true);
++ rs->addr_width = 4;
++ } else if (cmd->flags & SPI_CMD_EX4B) {
++ mt7620_set_4byte(rs, false);
++ rs->addr_width = 3;
++ }
++
++ /* opcode */
++ cmd->opcode = tx[0];
++ rt2880_spi_write(rs, RAMIPS_SPI_DATA, cmd->opcode);
++
++ /* address */
++ if (cmd->flags & SPI_CMD_ADDR) {
++ cmd->addr = m25p_cmd2addr(rs->addr_width, tx);
++ if (rs->addr_width == 3)
++ rt2880_spi_write(rs, RAMIPS_SPI_ADDR, (cmd->addr << 8));
++ else if (rs->addr_width == 4)
++ rt2880_spi_write(rs, RAMIPS_SPI_ADDR, cmd->addr);
++ else {
++ ret = -EINVAL;
++ goto out;
+ }
++ } else
++ rt2880_spi_write(rs, RAMIPS_SPI_ADDR, 0);
++
++ /* setup user mode */
++ if (cmd->flags & SPI_CMD_USER) {
++ reg = SPIUSER_USERMODE | SPIUSER_INSTR_PHASE |
++ SPIUSER_TRANSFER_TYPE(SPIUSER_TRANSFER_SINGLE);
++ if (cmd->flags & SPI_CMD_ADDR)
++ reg |= (rs->addr_width << SPIUSER_ADDR_PHASE_OFFSET);
++ if (cmd->flags & SPI_CMD_DUMMY)
++ reg |= (1 << SPIUSER_DUMMY_PHASE_OFFSET);
++ if (cmd->flags & SPI_CMD_TX)
++ reg |= SPIUSER_DATA_WRITE;
++ else if (cmd->flags & SPI_CMD_RX)
++ reg |= SPIUSER_DATA_READ;
++ rt2880_spi_write(rs, RAMIPS_SPI_USER, reg);
+ }
+
+out:
-+ return count;
++ return ret;
+}
+
-+static int rt2880_spi_transfer_one_message(struct spi_master *master,
-+ struct spi_message *m)
++static int mt7620_spi_transfer_one(struct spi_master *master,
++ struct spi_device *spi, struct spi_transfer *xfer)
+{
+ struct rt2880_spi *rs = spi_master_get_devdata(master);
-+ struct spi_device *spi = m->spi;
-+ struct spi_transfer *t = NULL;
-+ int par_override = 0;
-+ int status = 0;
-+ int cs_active = 0;
-+
-+ /* Load defaults */
-+ status = rt2880_spi_setup_transfer(spi, NULL);
-+ if (status < 0)
-+ goto msg_done;
-+
-+ list_for_each_entry(t, &m->transfers, transfer_list) {
-+ if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
-+ dev_err(&spi->dev,
-+ "message rejected: invalid transfer data buffers\n");
-+ status = -EIO;
-+ goto msg_done;
++ struct mt7620_spi_cmd *cmd;
++ const u8 *tx;
++ u8 *rx;
++ int len, ret = 0;
++
++ cmd = &rs->cmd;
++ if (cmd->status == SPI_STATE_OPCODE) {
++ if (!xfer->tx_buf)
++ dev_err(&spi->dev, "only support spi flash device\n");
++
++ memset(cmd, 0, sizeof(*cmd));
++ ret = setup_spi_cmd(rs, xfer->tx_buf, xfer->len, cmd);
++ if (ret < 0) {
++ dev_err(&spi->dev, "unknown spi command %02x\n",
++ *(u8 *)xfer->tx_buf);
++ goto err;
+ }
+
-+ if (t->speed_hz && t->speed_hz < (rs->sys_freq / 128)) {
-+ dev_err(&spi->dev,
-+ "message rejected: device min speed (%d Hz) exceeds required transfer speed (%d Hz)\n",
-+ (rs->sys_freq / 128), t->speed_hz);
-+ status = -EIO;
-+ goto msg_done;
++ /* need data at next transfer */
++ if ((cmd->flags & (SPI_CMD_TX | SPI_CMD_RX)) &&
++ !cmd->tx_buf && !cmd->rx_buf) {
++ cmd->status = SPI_STATE_DATA;
++ return ret;
++ }
++ } else {
++ if (((cmd->flags & SPI_CMD_TX) && !xfer->tx_buf) ||
++ ((cmd->flags & SPI_CMD_RX) && !xfer->rx_buf)) {
++ dev_err(&spi->dev, "no spi data found\n");
++ ret = -EINVAL;
++ goto err;
+ }
++ cmd->len = xfer->len;
++ cmd->tx_buf = xfer->tx_buf;
++ cmd->rx_buf = xfer->rx_buf;
++ }
++
++ /* set block size */
++ rt2880_spi_write(rs, RAMIPS_SPI_BS, cmd->len);
++
++ /* start transaction */
++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_START);
++
++ tx = cmd->tx_buf;
++ rx = cmd->rx_buf;
+
-+ if (par_override || t->speed_hz || t->bits_per_word) {
-+ par_override = 1;
-+ status = rt2880_spi_setup_transfer(spi, t);
-+ if (status < 0)
-+ goto msg_done;
-+ if (!t->speed_hz && !t->bits_per_word)
-+ par_override = 0;
++ /* handle data */
++ if (tx) {
++ len = cmd->len;
++ while (len) {
++ /* wait until tx fifo not full */
++ ret = mt7620_spi_fifo_ready(rs, SPIFIFOSTAT_TXFULL,
++ true);
++ if (ret < 0) {
++ dev_err(&spi->dev, "tx fifo full timeout\n");
++ goto err;
++ }
++ ret = min(len, ret);
++ len -= ret;
++ while (ret--)
++ rt2880_spi_write(rs, RAMIPS_SPI_TXFIFO, *tx++);
+ }
++ }
+
-+ if (!cs_active) {
-+ rt2880_spi_set_cs(rs, 1);
-+ cs_active = 1;
++ if (rx) {
++ len = cmd->len;
++ while (len) {
++ /* wait until rx fifo not empty */
++ ret = mt7620_spi_fifo_ready(rs, SPIFIFOSTAT_RXEMPTY,
++ false);
++ if (ret < 0) {
++ dev_err(&spi->dev, "rx fifo empty timeout\n");
++ goto err;
++ }
++ ret = min(len, ret);
++ len -= ret;
++ while (ret--)
++ *rx++ = (u8)rt2880_spi_read(rs,
++ RAMIPS_SPI_RXFIFO);
+ }
++ }
++
++ len = min((int)cmd->len + 1, SPI_FIFO_DEPTH);
++ ret = rt2880_spi_wait_ready(rs, len);
++ if (ret)
++ dev_err(&spi->dev, "wait timeout\n");
++
++err:
++ cmd->status = SPI_STATE_OPCODE;
++
++ /* clean user mode */
++ if (cmd->flags & SPI_CMD_USER)
++ rt2880_spi_write(rs, RAMIPS_SPI_USER, 0);
++
++ if (ret)
++ rt2880_dump_reg(master);
+
-+ if (t->len)
-+ m->actual_length += rt2880_spi_write_read(spi, t);
++ return ret;
++}
++
++/* copy from spi.c */
++static void spi_set_cs(struct spi_device *spi, bool enable)
++{
++ if (spi->mode & SPI_CS_HIGH)
++ enable = !enable;
++
++ if (spi->cs_gpio >= 0)
++ gpio_set_value(spi->cs_gpio, !enable);
++ else if (spi->master->set_cs)
++ spi->master->set_cs(spi, !enable);
++}
+
-+ if (t->delay_usecs)
-+ udelay(t->delay_usecs);
++static int rt2880_spi_setup(struct spi_device *spi)
++{
++ struct spi_master *master = spi->master;
++ struct rt2880_spi *rs = spi_master_get_devdata(master);
++ u32 reg, old_reg, arbit_off;
+
-+ if (t->cs_change) {
-+ rt2880_spi_set_cs(rs, 0);
-+ cs_active = 0;
++ if ((spi->max_speed_hz > master->max_speed_hz) ||
++ (spi->max_speed_hz < master->min_speed_hz)) {
++ dev_err(&spi->dev, "invalide requested speed %d Hz\n",
++ spi->max_speed_hz);
++ return -EINVAL;
++ }
++
++ if (!(master->bits_per_word_mask &
++ BIT(spi->bits_per_word - 1))) {
++ dev_err(&spi->dev, "invalide bits_per_word %d\n",
++ spi->bits_per_word);
++ return -EINVAL;
++ }
++
++ /* the hardware seems can't work on mode0 force it to mode3 */
++ if ((spi->mode & (SPI_CPOL | SPI_CPHA)) == SPI_MODE_0) {
++ dev_warn(&spi->dev, "force spi mode3\n");
++ spi->mode |= SPI_MODE_3;
++ }
++
++ /* chip polarity */
++ arbit_off = get_arbiter_offset(master);
++ reg = old_reg = rt2880_spi_read(rs, arbit_off);
++ if (spi->mode & SPI_CS_HIGH) {
++ switch (master->bus_num) {
++ case 1:
++ reg |= SPI1_POR;
++ break;
++ default:
++ reg |= SPI0_POR;
++ break;
++ }
++ } else {
++ switch (master->bus_num) {
++ case 1:
++ reg &= ~SPI1_POR;
++ break;
++ default:
++ reg &= ~SPI0_POR;
++ break;
+ }
+ }
+
-+msg_done:
-+ if (cs_active)
-+ rt2880_spi_set_cs(rs, 0);
++ /* enable spi1 */
++ if (master->bus_num == 1) {
++ reg |= SPICTL_ARB_EN;
++ /* enable cs1 support? */
++ if (rs->ops->flags & SPI_FLAG_HW_MODE)
++ reg |= SPICTL_CSCTL1;
++ }
+
-+ m->status = status;
-+ spi_finalize_current_message(master);
++ if (reg != old_reg)
++ rt2880_spi_write(rs, arbit_off, reg);
++
++ /* deselected the spi device */
++ spi_set_cs(spi, false);
+
+ return 0;
+}
+
-+static int rt2880_spi_setup(struct spi_device *spi)
++static int rt2880_spi_prepare_message(struct spi_master *master,
++ struct spi_message *msg)
+{
-+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
++ struct rt2880_spi *rs = spi_master_get_devdata(master);
++ struct spi_device *spi = msg->spi;
++ u32 reg;
+
-+ if ((spi->max_speed_hz == 0) ||
-+ (spi->max_speed_hz > (rs->sys_freq / 2)))
-+ spi->max_speed_hz = (rs->sys_freq / 2);
++ if ((rs->mode == spi->mode) && (rs->speed == spi->max_speed_hz)) {
++ if (rs->ops->flags & SPI_FLAG_HW_MODE) {
++ rt2880_spi_setbits(rs, RAMIPS_SPI_CFG,
++ (SPICFG_RXENVDIS | SPICFG_SPIENMODE));
++ rs->cmd.status = SPI_STATE_OPCODE;
++ }
++ return 0;
++ }
+
-+ if (spi->max_speed_hz < (rs->sys_freq / 128)) {
-+ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n",
-+ spi->max_speed_hz);
-+ return -EINVAL;
++#if 0
++ /* set spido to tri-state */
++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO);
++#endif
++
++ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG);
++
++ reg &= ~(SPICFG_MSBFIRST | SPICFG_SPICLKPOL |
++ SPICFG_RXCLKEDGE_FALLING |
++ SPICFG_TXCLKEDGE_FALLING |
++ SPICFG_SPICLK_PRESCALE_MASK);
++
++ /* MSB */
++ if (!(spi->mode & SPI_LSB_FIRST))
++ reg |= SPICFG_MSBFIRST;
++
++ /* spi mode */
++ switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
++ case SPI_MODE_0:
++ reg |= SPICFG_TXCLKEDGE_FALLING;
++ break;
++ case SPI_MODE_1:
++ reg |= SPICFG_RXCLKEDGE_FALLING;
++ break;
++ case SPI_MODE_2:
++ reg |= SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING;
++ break;
++ case SPI_MODE_3:
++ reg |= SPICFG_SPICLKPOL | SPICFG_TXCLKEDGE_FALLING;
++ break;
+ }
++ rs->mode = spi->mode;
++
++#if 0
++ /* set spiclk and spiena to tri-state */
++ reg |= SPICFG_HIZSPI;
++#endif
++
++ /* clock divide */
++ reg |= rt2880_spi_baudrate_get(spi, spi->max_speed_hz);
++
++ /* set chip select is control by hw */
++ if (rs->ops->flags & SPI_FLAG_HW_MODE) {
++ reg |= (SPICFG_RXENVDIS | SPICFG_SPIENMODE);
++ rs->cmd.status = SPI_STATE_OPCODE;
++ }
++
++ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg);
+
-+ /*
-+ * baudrate & width will be set rt2880_spi_setup_transfer
-+ */
+ return 0;
+}
+
-+static void rt2880_spi_reset(struct rt2880_spi *rs)
++static int rt2880_spi_unprepare_message(struct spi_master *master,
++ struct spi_message *message)
+{
-+ rt2880_spi_write(rs, RAMIPS_SPI_CFG,
-+ SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING |
-+ SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL);
-+ rt2880_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA);
++ struct rt2880_spi *rs = spi_master_get_devdata(master);
++
++ /* disable chip select is control by hw */
++ if (rs->ops->flags & SPI_FLAG_HW_MODE)
++ rt2880_spi_clrbits(rs, RAMIPS_SPI_CFG,
++ (SPICFG_RXENVDIS | SPICFG_SPIENMODE));
++
++ return 0;
+}
+
++static struct rt2880_spi_ops spi_ops[] = {
++ {
++ .transfer_one = rt2880_spi_transfer_one,
++ }, {
++ .flags = SPI_FLAG_HW_MODE,
++ .transfer_one = mt7620_spi_transfer_one,
++ },
++};
++
++static const struct of_device_id rt2880_spi_match[] = {
++ { .compatible = "ralink,rt2880-spi", .data = &spi_ops[0]},
++ { .compatible = "ralink,mt7620a-spi", .data = &spi_ops[1]},
++ {},
++};
++MODULE_DEVICE_TABLE(of, rt2880_spi_match);
++
+static int rt2880_spi_probe(struct platform_device *pdev)
+{
++ const struct of_device_id *match;
+ struct spi_master *master;
+ struct rt2880_spi *rs;
-+ unsigned long flags;
+ void __iomem *base;
+ struct resource *r;
-+ int status = 0;
+ struct clk *clk;
++ struct rt2880_spi_ops *ops;
++ int ret;
++
++ match = of_match_device(rt2880_spi_match, &pdev->dev);
++ if (!match)
++ return -EINVAL;
++ ops = (struct rt2880_spi_ops *)match->data;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, r);
@@ -395,45 +852,63 @@ Acked-by: John Crispin <blogic@openwrt.org>
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
-+ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n",
-+ status);
++ dev_err(&pdev->dev, "unable to get SYS clock\n");
+ return PTR_ERR(clk);
+ }
+
-+ status = clk_prepare_enable(clk);
-+ if (status)
-+ return status;
++ ret = clk_prepare_enable(clk);
++ if (ret)
++ goto err_clk;
+
+ master = spi_alloc_master(&pdev->dev, sizeof(*rs));
+ if (master == NULL) {
+ dev_dbg(&pdev->dev, "master allocation failed\n");
-+ return -ENOMEM;
++ ret = -ENOMEM;
++ goto err_clk;
+ }
+
-+ /* we support only mode 0, and no options */
-+ master->mode_bits = 0;
-+
-+ master->setup = rt2880_spi_setup;
-+ master->transfer_one_message = rt2880_spi_transfer_one_message;
-+ master->num_chipselect = RALINK_NUM_CHIPSELECTS;
-+ master->bits_per_word_mask = SPI_BPW_MASK(8);
+ master->dev.of_node = pdev->dev.of_node;
++ if (ops->flags)
++ master->mode_bits = MT7620_SPI_MODE_BITS;
++ else
++ master->mode_bits = RT2880_SPI_MODE_BITS;
++ master->bits_per_word_mask = SPI_BPW_MASK(8);
++ master->min_speed_hz = clk_get_rate(clk) / 128;
++ master->max_speed_hz = clk_get_rate(clk) / 2;
++ master->flags = SPI_MASTER_HALF_DUPLEX;
++ master->setup = rt2880_spi_setup;
++ master->prepare_message = rt2880_spi_prepare_message;
++ master->unprepare_message = rt2880_spi_unprepare_message;
++ master->set_cs = rt2880_spi_set_cs;
++ master->transfer_one = ops->transfer_one;
+
+ dev_set_drvdata(&pdev->dev, master);
+
+ rs = spi_master_get_devdata(master);
++ rs->master = master;
+ rs->base = base;
+ rs->clk = clk;
-+ rs->master = master;
-+ rs->sys_freq = clk_get_rate(rs->clk);
-+ dev_dbg(&pdev->dev, "sys_freq: %u\n", rs->sys_freq);
-+ spin_lock_irqsave(&rs->lock, flags);
++ rs->addr_width = 3;
++ rs->ops = ops;
++
++ if (atomic_inc_return(&hw_reset_count) == 1)
++ device_reset(&pdev->dev);
+
-+ device_reset(&pdev->dev);
++ ret = devm_spi_register_master(&pdev->dev, master);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "devm_spi_register_master error.\n");
++ goto err_master;
++ }
+
-+ rt2880_spi_reset(rs);
++ return ret;
+
-+ return spi_register_master(master);
++err_master:
++ spi_master_put(master);
++ kfree(master);
++err_clk:
++ clk_disable_unprepare(clk);
++
++ return ret;
+}
+
+static int rt2880_spi_remove(struct platform_device *pdev)
@@ -444,20 +919,14 @@ Acked-by: John Crispin <blogic@openwrt.org>
+ master = dev_get_drvdata(&pdev->dev);
+ rs = spi_master_get_devdata(master);
+
-+ clk_disable(rs->clk);
-+ spi_unregister_master(master);
++ clk_disable_unprepare(rs->clk);
++ atomic_dec(&hw_reset_count);
+
+ return 0;
+}
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+
-+static const struct of_device_id rt2880_spi_match[] = {
-+ { .compatible = "ralink,rt2880-spi" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, rt2880_spi_match);
-+
+static struct platform_driver rt2880_spi_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
deleted file mode 100644
@@ -1,368 +0,0 @@
-From 27b11d4f1888e1a3d6d75b46d4d5a4d86fc03891 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Wed, 6 Aug 2014 10:53:40 +0200
-Subject: [PATCH 51/57] SPI: MIPS: ralink: add rt5350 dual SPI support
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
----
- drivers/spi/spi-rt2880.c | 218 +++++++++++++++++++++++++++++++++++++++++++---
- 1 file changed, 205 insertions(+), 13 deletions(-)
-
---- a/drivers/spi/spi-rt2880.c
-+++ b/drivers/spi/spi-rt2880.c
-@@ -21,19 +21,25 @@
- #include <linux/io.h>
- #include <linux/reset.h>
- #include <linux/spi/spi.h>
-+#include <linux/of_device.h>
- #include <linux/platform_device.h>
-
-+#include <ralink_regs.h>
-+
-+#define SPI_BPW_MASK(bits) BIT((bits) - 1)
-+
- #define DRIVER_NAME "spi-rt2880"
--/* only one slave is supported*/
--#define RALINK_NUM_CHIPSELECTS 1
- /* in usec */
- #define RALINK_SPI_WAIT_MAX_LOOP 2000
-
--#define RAMIPS_SPI_STAT 0x00
--#define RAMIPS_SPI_CFG 0x10
--#define RAMIPS_SPI_CTL 0x14
--#define RAMIPS_SPI_DATA 0x20
--#define RAMIPS_SPI_FIFO_STAT 0x38
-+#define RAMIPS_SPI_DEV_OFFSET 0x40
-+
-+#define RAMIPS_SPI_STAT(cs) (0x00 + (cs * RAMIPS_SPI_DEV_OFFSET))
-+#define RAMIPS_SPI_CFG(cs) (0x10 + (cs * RAMIPS_SPI_DEV_OFFSET))
-+#define RAMIPS_SPI_CTL(cs) (0x14 + (cs * RAMIPS_SPI_DEV_OFFSET))
-+#define RAMIPS_SPI_DATA(cs) (0x20 + (cs * RAMIPS_SPI_DEV_OFFSET))
-+#define RAMIPS_SPI_FIFO_STAT(cs) (0x38 + (cs * RAMIPS_SPI_DEV_OFFSET))
-+#define RAMIPS_SPI_ARBITER 0xF0
-
- /* SPISTAT register bit field */
- #define SPISTAT_BUSY BIT(0)
-@@ -63,6 +69,19 @@
- /* SPIFIFOSTAT register bit field */
- #define SPIFIFOSTAT_TXFULL BIT(17)
-
-+#define SPICTL_ARB_EN BIT(31)
-+#define SPI1_POR BIT(1)
-+#define SPI0_POR BIT(0)
-+
-+#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH)
-+
-+struct rt2880_spi;
-+
-+struct rt2880_spi_ops {
-+ void (*init_hw)(struct rt2880_spi *rs);
-+ int num_cs;
-+};
-+
- struct rt2880_spi {
- struct spi_master *master;
- void __iomem *base;
-@@ -70,6 +89,8 @@ struct rt2880_spi {
- unsigned int speed;
- struct clk *clk;
- spinlock_t lock;
-+
-+ struct rt2880_spi_ops *ops;
- };
-
- static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi)
-@@ -115,6 +136,7 @@ static inline void rt2880_spi_clrbits(st
-
- static int rt2880_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
- {
-+ int cs = spi->chip_select;
- struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
- u32 rate;
- u32 prescale;
-@@ -142,9 +164,9 @@ static int rt2880_spi_baudrate_set(struc
- prescale = ilog2(rate / 2);
- dev_dbg(&spi->dev, "prescale:%u\n", prescale);
-
-- reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG);
-+ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG(cs));
- reg = ((reg & ~SPICFG_SPICLK_PRESCALE_MASK) | prescale);
-- rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg);
-+ rt2880_spi_write(rs, RAMIPS_SPI_CFG(cs), reg);
- rs->speed = speed;
- return 0;
- }
-@@ -157,7 +179,8 @@ rt2880_spi_setup_transfer(struct spi_dev
- {
- struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
- unsigned int speed = spi->max_speed_hz;
-- int rc;
-+ int rc, cs = spi->chip_select;
-+ u32 reg;
-
- if ((t != NULL) && t->speed_hz)
- speed = t->speed_hz;
-@@ -169,25 +192,68 @@ rt2880_spi_setup_transfer(struct spi_dev
- return rc;
- }
-
-+ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG(cs));
-+
-+ reg = (reg & ~SPICFG_MSBFIRST);
-+ if (!(spi->mode & SPI_LSB_FIRST))
-+ reg |= SPICFG_MSBFIRST;
-+
-+ reg = (reg & ~(SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING |SPICFG_TXCLKEDGE_FALLING));
-+ switch(spi->mode & (SPI_CPOL | SPI_CPHA)) {
-+ case SPI_MODE_0:
-+ reg |= SPICFG_SPICLKPOL | SPICFG_TXCLKEDGE_FALLING;
-+ break;
-+ case SPI_MODE_1:
-+ reg |= SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING;
-+ break;
-+ case SPI_MODE_2:
-+ reg |= SPICFG_RXCLKEDGE_FALLING;
-+ break;
-+ case SPI_MODE_3:
-+ reg |= SPICFG_TXCLKEDGE_FALLING;
-+ break;
-+ }
-+
-+ rt2880_spi_write(rs, RAMIPS_SPI_CFG(cs), reg);
-+
-+ reg = SPICTL_ARB_EN;
-+ if (spi->mode & SPI_CS_HIGH) {
-+ switch(cs) {
-+ case 0:
-+ reg |= SPI0_POR;
-+ break;
-+ case 1:
-+ reg |= SPI1_POR;
-+ break;
-+ }
-+ }
-+
-+ rt2880_spi_write(rs, RAMIPS_SPI_ARBITER, reg);
-+
- return 0;
- }
-
--static void rt2880_spi_set_cs(struct rt2880_spi *rs, int enable)
-+static void rt2880_spi_set_cs(struct spi_device *spi, int enable)
- {
-+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
-+ int cs = spi->chip_select;
-+
- if (enable)
-- rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
-+ rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_SPIENA);
- else
-- rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
-+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_SPIENA);
- }
-
--static inline int rt2880_spi_wait_till_ready(struct rt2880_spi *rs)
-+static inline int rt2880_spi_wait_till_ready(struct spi_device *spi)
- {
-+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
-+ int cs = spi->chip_select;
- int i;
-
- for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) {
- u32 status;
-
-- status = rt2880_spi_read(rs, RAMIPS_SPI_STAT);
-+ status = rt2880_spi_read(rs, RAMIPS_SPI_STAT(cs));
- if ((status & SPISTAT_BUSY) == 0)
- return 0;
-
-@@ -199,9 +265,10 @@ static inline int rt2880_spi_wait_till_r
- }
-
- static unsigned int
--rt2880_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
-+rt2880_spi_write_read(struct spi_device *spi, struct list_head *list, struct spi_transfer *xfer)
- {
- struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
-+ int cs = spi->chip_select;
- unsigned count = 0;
- u8 *rx = xfer->rx_buf;
- const u8 *tx = xfer->tx_buf;
-@@ -213,9 +280,9 @@ rt2880_spi_write_read(struct spi_device
-
- if (tx) {
- for (count = 0; count < xfer->len; count++) {
-- rt2880_spi_write(rs, RAMIPS_SPI_DATA, tx[count]);
-- rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR);
-- err = rt2880_spi_wait_till_ready(rs);
-+ rt2880_spi_write(rs, RAMIPS_SPI_DATA(cs), tx[count]);
-+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_STARTWR);
-+ err = rt2880_spi_wait_till_ready(spi);
- if (err) {
- dev_err(&spi->dev, "TX failed, err=%d\n", err);
- goto out;
-@@ -225,13 +292,13 @@ rt2880_spi_write_read(struct spi_device
-
- if (rx) {
- for (count = 0; count < xfer->len; count++) {
-- rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD);
-- err = rt2880_spi_wait_till_ready(rs);
-+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_STARTRD);
-+ err = rt2880_spi_wait_till_ready(spi);
- if (err) {
- dev_err(&spi->dev, "RX failed, err=%d\n", err);
- goto out;
- }
-- rx[count] = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA);
-+ rx[count] = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA(cs));
- }
- }
-
-@@ -280,25 +347,25 @@ static int rt2880_spi_transfer_one_messa
- }
-
- if (!cs_active) {
-- rt2880_spi_set_cs(rs, 1);
-+ rt2880_spi_set_cs(spi, 1);
- cs_active = 1;
- }
-
- if (t->len)
-- m->actual_length += rt2880_spi_write_read(spi, t);
-+ m->actual_length += rt2880_spi_write_read(spi, &m->transfers, t);
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (t->cs_change) {
-- rt2880_spi_set_cs(rs, 0);
-+ rt2880_spi_set_cs(spi, 0);
- cs_active = 0;
- }
- }
-
- msg_done:
- if (cs_active)
-- rt2880_spi_set_cs(rs, 0);
-+ rt2880_spi_set_cs(spi, 0);
-
- m->status = status;
- spi_finalize_current_message(master);
-@@ -311,7 +378,7 @@ static int rt2880_spi_setup(struct spi_d
- struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
-
- if ((spi->max_speed_hz == 0) ||
-- (spi->max_speed_hz > (rs->sys_freq / 2)))
-+ (spi->max_speed_hz > (rs->sys_freq / 2)))
- spi->max_speed_hz = (rs->sys_freq / 2);
-
- if (spi->max_speed_hz < (rs->sys_freq / 128)) {
-@@ -328,14 +395,47 @@ static int rt2880_spi_setup(struct spi_d
-
- static void rt2880_spi_reset(struct rt2880_spi *rs)
- {
-- rt2880_spi_write(rs, RAMIPS_SPI_CFG,
-+ rt2880_spi_write(rs, RAMIPS_SPI_CFG(0),
- SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING |
- SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL);
-- rt2880_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA);
-+ rt2880_spi_write(rs, RAMIPS_SPI_CTL(0), SPICTL_HIZSDO | SPICTL_SPIENA);
- }
-
-+static void rt5350_spi_reset(struct rt2880_spi *rs)
-+{
-+ int cs;
-+
-+ rt2880_spi_write(rs, RAMIPS_SPI_ARBITER,
-+ SPICTL_ARB_EN);
-+
-+ for (cs = 0; cs < rs->ops->num_cs; cs++) {
-+ rt2880_spi_write(rs, RAMIPS_SPI_CFG(cs),
-+ SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING |
-+ SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL);
-+ rt2880_spi_write(rs, RAMIPS_SPI_CTL(cs), SPICTL_HIZSDO | SPICTL_SPIENA);
-+ }
-+}
-+
-+static struct rt2880_spi_ops spi_ops[] = {
-+ {
-+ .init_hw = rt2880_spi_reset,
-+ .num_cs = 1,
-+ }, {
-+ .init_hw = rt5350_spi_reset,
-+ .num_cs = 2,
-+ },
-+};
-+
-+static const struct of_device_id rt2880_spi_match[] = {
-+ { .compatible = "ralink,rt2880-spi", .data = &spi_ops[0]},
-+ { .compatible = "ralink,rt5350-spi", .data = &spi_ops[1]},
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, rt2880_spi_match);
-+
- static int rt2880_spi_probe(struct platform_device *pdev)
- {
-+ const struct of_device_id *match;
- struct spi_master *master;
- struct rt2880_spi *rs;
- unsigned long flags;
-@@ -343,6 +443,12 @@ static int rt2880_spi_probe(struct platf
- struct resource *r;
- int status = 0;
- struct clk *clk;
-+ struct rt2880_spi_ops *ops;
-+
-+ match = of_match_device(rt2880_spi_match, &pdev->dev);
-+ if (!match)
-+ return -EINVAL;
-+ ops = (struct rt2880_spi_ops *)match->data;
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, r);
-@@ -366,14 +472,13 @@ static int rt2880_spi_probe(struct platf
- return -ENOMEM;
- }
-
-- /* we support only mode 0, and no options */
-- master->mode_bits = 0;
-+ master->mode_bits = RT2880_SPI_MODE_BITS;
-
- master->setup = rt2880_spi_setup;
- master->transfer_one_message = rt2880_spi_transfer_one_message;
-- master->num_chipselect = RALINK_NUM_CHIPSELECTS;
- master->bits_per_word_mask = SPI_BPW_MASK(8);
- master->dev.of_node = pdev->dev.of_node;
-+ master->num_chipselect = ops->num_cs;
-
- dev_set_drvdata(&pdev->dev, master);
-
-@@ -382,12 +487,13 @@ static int rt2880_spi_probe(struct platf
- rs->clk = clk;
- rs->master = master;
- rs->sys_freq = clk_get_rate(rs->clk);
-+ rs->ops = ops;
- dev_dbg(&pdev->dev, "sys_freq: %u\n", rs->sys_freq);
- spin_lock_irqsave(&rs->lock, flags);
-
- device_reset(&pdev->dev);
-
-- rt2880_spi_reset(rs);
-+ rs->ops->init_hw(rs);
-
- return spi_register_master(master);
- }
-@@ -408,12 +514,6 @@ static int rt2880_spi_remove(struct plat
-
- MODULE_ALIAS("platform:" DRIVER_NAME);
-
--static const struct of_device_id rt2880_spi_match[] = {
-- { .compatible = "ralink,rt2880-spi" },
-- {},
--};
--MODULE_DEVICE_TABLE(of, rt2880_spi_match);
--
- static struct platform_driver rt2880_spi_driver = {
- .driver = {
- .name = DRIVER_NAME,