diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/linux/ramips/patches-4.14/0043-spi-add-mt7621-support.patch | 219 |
1 files changed, 98 insertions, 121 deletions
diff --git a/target/linux/ramips/patches-4.14/0043-spi-add-mt7621-support.patch b/target/linux/ramips/patches-4.14/0043-spi-add-mt7621-support.patch index 8367675ff5..d9bc48d69b 100644 --- a/target/linux/ramips/patches-4.14/0043-spi-add-mt7621-support.patch +++ b/target/linux/ramips/patches-4.14/0043-spi-add-mt7621-support.patch @@ -5,8 +5,6 @@ Subject: [PATCH 43/53] spi: add mt7621 support Signed-off-by: John Crispin <blogic@openwrt.org> --- -Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d9e8610c85 - drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/spi-mt7621.c | 480 ++++++++++++++++++++++++++++++++++++++++++++++ @@ -40,7 +38,7 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o --- /dev/null +++ b/drivers/spi/spi-mt7621.c -@@ -0,0 +1,515 @@ +@@ -0,0 +1,494 @@ +/* + * spi-mt7621.c -- MediaTek MT7621 SPI controller driver + * @@ -98,8 +96,7 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d +#define MT7621_CPOL BIT(4) +#define MT7621_LSB_FIRST BIT(3) + -+#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | \ -+ SPI_LSB_FIRST | SPI_CS_HIGH) ++#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH) + +struct mt7621_spi; + @@ -109,7 +106,6 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + unsigned int sys_freq; + unsigned int speed; + struct clk *clk; -+ int pending_write; + + struct mt7621_spi_ops *ops; +}; @@ -135,13 +131,14 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + + master |= 7 << 29; + master |= 1 << 2; ++#ifdef CONFIG_SOC_MT7620 + if (duplex) + master |= 1 << 10; + else ++#endif + master &= ~(1 << 10); + + mt7621_spi_write(rs, MT7621_SPI_MASTER, master); -+ rs->pending_write = 0; +} + +static void mt7621_spi_set_cs(struct spi_device *spi, int enable) @@ -150,7 +147,7 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + int cs = spi->chip_select; + u32 polar = 0; + -+ mt7621_spi_reset(rs, cs); ++ mt7621_spi_reset(rs, cs); + if (enable) + polar = BIT(cs); + mt7621_spi_write(rs, MT7621_SPI_POLAR, polar); @@ -183,34 +180,36 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + reg |= MT7621_LSB_FIRST; + + reg &= ~(MT7621_CPHA | MT7621_CPOL); -+ switch (spi->mode & (SPI_CPOL | SPI_CPHA)) { -+ case SPI_MODE_0: -+ break; -+ case SPI_MODE_1: -+ reg |= MT7621_CPHA; -+ break; -+ case SPI_MODE_2: -+ reg |= MT7621_CPOL; -+ break; -+ case SPI_MODE_3: -+ reg |= MT7621_CPOL | MT7621_CPHA; -+ break; ++ switch(spi->mode & (SPI_CPOL | SPI_CPHA)) { ++ case SPI_MODE_0: ++ break; ++ case SPI_MODE_1: ++ reg |= MT7621_CPHA; ++ break; ++ case SPI_MODE_2: ++ reg |= MT7621_CPOL; ++ break; ++ case SPI_MODE_3: ++ reg |= MT7621_CPOL | MT7621_CPHA; ++ break; + } + mt7621_spi_write(rs, MT7621_SPI_MASTER, reg); + + return 0; +} + -+static inline int mt7621_spi_wait_till_ready(struct mt7621_spi *rs) ++static inline int mt7621_spi_wait_till_ready(struct spi_device *spi) +{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); + int i; + + for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) { + u32 status; + + status = mt7621_spi_read(rs, MT7621_SPI_TRANS); -+ if ((status & SPITRANS_BUSY) == 0) ++ if ((status & SPITRANS_BUSY) == 0) { + return 0; ++ } + cpu_relax(); + udelay(1); + } @@ -218,92 +217,6 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + return -ETIMEDOUT; +} + -+static void mt7621_spi_read_half_duplex(struct mt7621_spi *rs, -+ int rx_len, u8 *buf) -+{ -+ /* Combine with any pending write, and perform one or -+ * more half-duplex transactions reading 'len' bytes. -+ * Data to be written is already in MT7621_SPI_DATA* -+ */ -+ int tx_len = rs->pending_write; -+ -+ rs->pending_write = 0; -+ -+ while (rx_len || tx_len) { -+ int i; -+ u32 val = (min(tx_len, 4) * 8) << 24; -+ int rx = min(rx_len, 32); -+ -+ if (tx_len > 4) -+ val |= (tx_len - 4) * 8; -+ val |= (rx * 8) << 12; -+ mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); -+ -+ tx_len = 0; -+ -+ val = mt7621_spi_read(rs, MT7621_SPI_TRANS); -+ val |= SPI_CTL_START; -+ mt7621_spi_write(rs, MT7621_SPI_TRANS, val); -+ -+ mt7621_spi_wait_till_ready(rs); -+ -+ for (i = 0; i < rx; i++) { -+ if ((i % 4) == 0) -+ val = mt7621_spi_read(rs, MT7621_SPI_DATA0 + i); -+ *buf++ = val & 0xff; -+ val >>= 8; -+ } -+ rx_len -= i; -+ } -+} -+ -+static inline void mt7621_spi_flush(struct mt7621_spi *rs) -+{ -+ mt7621_spi_read_half_duplex(rs, 0, NULL); -+} -+ -+static void mt7621_spi_write_half_duplex(struct mt7621_spi *rs, -+ int tx_len, const u8 *buf) -+{ -+ int val = 0; -+ int len = rs->pending_write; -+ -+ if (len & 3) { -+ val = mt7621_spi_read(rs, MT7621_SPI_OPCODE + (len & ~3)); -+ if (len < 4) { -+ val <<= (4 - len) * 8; -+ val = swab32(val); -+ } -+ } -+ -+ while (tx_len > 0) { -+ if (len >= 36) { -+ rs->pending_write = len; -+ mt7621_spi_flush(rs); -+ len = 0; -+ } -+ -+ val |= *buf++ << (8 * (len & 3)); -+ len++; -+ if ((len & 3) == 0) { -+ if (len == 4) -+ /* The byte-order of the opcode is weird! */ -+ val = swab32(val); -+ mt7621_spi_write(rs, MT7621_SPI_OPCODE + len - 4, val); -+ val = 0; -+ } -+ tx_len -= 1; -+ } -+ if (len & 3) { -+ if (len < 4) { -+ val = swab32(val); -+ val >>= (4 - len) * 8; -+ } -+ mt7621_spi_write(rs, MT7621_SPI_OPCODE + (len & ~3), val); -+ } -+ rs->pending_write = len; -+} -+ +static int mt7621_spi_transfer_half_duplex(struct spi_master *master, + struct spi_message *m) +{ @@ -312,30 +225,84 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + unsigned int speed = spi->max_speed_hz; + struct spi_transfer *t = NULL; + int status = 0; ++ int i, len = 0; ++ int rx_len = 0; ++ u32 data[9] = { 0 }; ++ u32 val; ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ const u8 *buf = t->tx_buf; ++ ++ if (t->rx_buf) ++ rx_len += t->len; + -+ mt7621_spi_wait_till_ready(rs); ++ if (!buf) ++ continue; + -+ list_for_each_entry(t, &m->transfers, transfer_list) + if (t->speed_hz < speed) + speed = t->speed_hz; + ++ /* ++ * m25p80 might attempt to write more data than we can handle. ++ * truncate the message to what we can fit into the registers ++ */ ++ if (len + t->len > 36) ++ t->len = 36 - len; ++ ++ for (i = 0; i < t->len; i++, len++) ++ data[len / 4] |= buf[i] << (8 * (len & 3)); ++ } ++ ++ if (WARN_ON(rx_len > 32)) { ++ status = -EIO; ++ 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; ++ ++ for (i = 0; i < len; i += 4) ++ mt7621_spi_write(rs, MT7621_SPI_OPCODE + i, data[i / 4]); ++ ++ val = (min_t(int, len, 4) * 8) << 24; ++ if (len > 4) ++ val |= (len - 4) * 8; ++ val |= (rx_len * 8) << 12; ++ mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); + + mt7621_spi_set_cs(spi, 1); -+ m->actual_length = 0; ++ ++ val = mt7621_spi_read(rs, MT7621_SPI_TRANS); ++ val |= SPI_CTL_START; ++ mt7621_spi_write(rs, MT7621_SPI_TRANS, val); ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ mt7621_spi_set_cs(spi, 0); ++ ++ for (i = 0; i < rx_len; i += 4) ++ data[i / 4] = mt7621_spi_read(rs, MT7621_SPI_DATA0 + i); ++ ++ m->actual_length = len + rx_len; ++ ++ len = 0; + list_for_each_entry(t, &m->transfers, transfer_list) { -+ if (t->rx_buf) -+ mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf); -+ else if (t->tx_buf) -+ mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf); -+ m->actual_length += t->len; ++ u8 *buf = t->rx_buf; ++ ++ if (!buf) ++ continue; ++ ++ for (i = 0; i < t->len; i++, len++) ++ buf[i] = data[len / 4] >> (8 * (len & 3)); + } -+ mt7621_spi_flush(rs); + -+ mt7621_spi_set_cs(spi, 0); +msg_done: + m->status = status; + spi_finalize_current_message(master); @@ -343,6 +310,7 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + return 0; +} + ++#ifdef CONFIG_SOC_MT7620 +static int mt7621_spi_transfer_full_duplex(struct spi_master *master, + struct spi_message *m) +{ @@ -356,7 +324,7 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + u32 data[9] = { 0 }; + u32 val = 0; + -+ mt7621_spi_wait_till_ready(rs); ++ mt7621_spi_wait_till_ready(spi); + + list_for_each_entry(t, &m->transfers, transfer_list) { + const u8 *buf = t->tx_buf; @@ -401,7 +369,7 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + val |= SPI_CTL_START; + mt7621_spi_write(rs, MT7621_SPI_TRANS, val); + -+ mt7621_spi_wait_till_ready(rs); ++ mt7621_spi_wait_till_ready(spi); + + mt7621_spi_set_cs(spi, 0); + @@ -427,15 +395,18 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + + return 0; +} ++#endif + +static int mt7621_spi_transfer_one_message(struct spi_master *master, + struct spi_message *m) +{ + struct spi_device *spi = m->spi; ++#ifdef CONFIG_SOC_MT7620 + int cs = spi->chip_select; + + if (cs) + return mt7621_spi_transfer_full_duplex(master, m); ++#endif + return mt7621_spi_transfer_half_duplex(master, m); +} + @@ -462,6 +433,11 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d +}; +MODULE_DEVICE_TABLE(of, mt7621_spi_match); + ++static size_t mt7621_max_transfer_size(struct spi_device *spi) ++{ ++ return 32; ++} ++ +static int mt7621_spi_probe(struct platform_device *pdev) +{ + const struct of_device_id *match; @@ -507,6 +483,7 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + master->bits_per_word_mask = SPI_BPW_MASK(8); + master->dev.of_node = pdev->dev.of_node; + master->num_chipselect = 2; ++ master->max_transfer_size = mt7621_max_transfer_size; + + dev_set_drvdata(&pdev->dev, master); + @@ -516,7 +493,6 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d + rs->master = master; + rs->sys_freq = clk_get_rate(rs->clk); + rs->ops = ops; -+ rs->pending_write = 0; + dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); + + device_reset(&pdev->dev); @@ -545,6 +521,7 @@ Note: This patch contains upstream mt7621-spi at 9c562d8411a54f6731cdc587c29968d +static struct platform_driver mt7621_spi_driver = { + .driver = { + .name = DRIVER_NAME, ++ .owner = THIS_MODULE, + .of_match_table = mt7621_spi_match, + }, + .probe = mt7621_spi_probe, |