sunxi: add T113-S3 support
[openwrt/staging/wigyori.git] / target / linux / sunxi / patches-6.1 / 5012-spi-sun6i-add-quirk-for-dual-and-quad-SPI-modes-supp.patch
diff --git a/target/linux/sunxi/patches-6.1/5012-spi-sun6i-add-quirk-for-dual-and-quad-SPI-modes-supp.patch b/target/linux/sunxi/patches-6.1/5012-spi-sun6i-add-quirk-for-dual-and-quad-SPI-modes-supp.patch
new file mode 100644 (file)
index 0000000..025dd72
--- /dev/null
@@ -0,0 +1,92 @@
+From 7841a272e44620959d734735a231371b3b7f5ed9 Mon Sep 17 00:00:00 2001
+From: Maksim Kiselev <bigunclemax@gmail.com>
+Date: Sat, 24 Jun 2023 16:16:22 +0300
+Subject: [PATCH 12/25] spi: sun6i: add quirk for dual and quad SPI modes
+ support
+
+New Allwinner's SPI controllers can support dual and quad SPI modes.
+To enable one of these modes, we should set the corresponding bit in
+the SUN6I_BURST_CTL_CNT_REG register. DRM (28 bits) for dual mode and
+Quad_EN (29 bits) for quad transmission.
+
+Signed-off-by: Maksim Kiselev <bigunclemax@gmail.com>
+---
+ drivers/spi/spi-sun6i.c | 29 +++++++++++++++++++++++++----
+ 1 file changed, 25 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
+index 4f32cd99a81e..f7350ab86e14 100644
+--- a/drivers/spi/spi-sun6i.c
++++ b/drivers/spi/spi-sun6i.c
+@@ -83,6 +83,9 @@
+ #define SUN6I_XMIT_CNT_REG            0x34
+ #define SUN6I_BURST_CTL_CNT_REG               0x38
++#define SUN6I_BURST_CTL_CNT_STC_MASK          GENMASK(23, 0)
++#define SUN6I_BURST_CTL_CNT_DRM                       BIT(28)
++#define SUN6I_BURST_CTL_CNT_QUAD_EN           BIT(29)
+ #define SUN6I_TXDATA_REG              0x200
+ #define SUN6I_RXDATA_REG              0x300
+@@ -90,6 +93,7 @@
+ struct sun6i_spi_cfg {
+       unsigned long           fifo_depth;
+       bool                    has_clk_ctl;
++      u32                     mode_bits;
+ };
+ struct sun6i_spi {
+@@ -266,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
+       unsigned int div, div_cdr1, div_cdr2, timeout;
+       unsigned int start, end, tx_time;
+       unsigned int trig_level;
+-      unsigned int tx_len = 0, rx_len = 0;
++      unsigned int tx_len = 0, rx_len = 0, nbits = 0;
+       bool use_dma;
+       int ret = 0;
+       u32 reg;
+@@ -418,13 +422,29 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
+       sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg);
+       /* Setup the transfer now... */
+-      if (sspi->tx_buf)
++      if (sspi->tx_buf) {
+               tx_len = tfr->len;
++              nbits = tfr->tx_nbits;
++      } else if (tfr->rx_buf) {
++              nbits = tfr->rx_nbits;
++      }
++
++      switch (nbits) {
++      case SPI_NBITS_DUAL:
++              reg = SUN6I_BURST_CTL_CNT_DRM;
++              break;
++      case SPI_NBITS_QUAD:
++              reg = SUN6I_BURST_CTL_CNT_QUAD_EN;
++              break;
++      case SPI_NBITS_SINGLE:
++      default:
++              reg = FIELD_PREP(SUN6I_BURST_CTL_CNT_STC_MASK, tx_len);
++      }
+       /* Setup the counters */
++      sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, reg);
+       sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, tfr->len);
+       sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len);
+-      sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len);
+       if (!use_dma) {
+               /* Fill the TX FIFO */
+@@ -623,7 +643,8 @@ static int sun6i_spi_probe(struct platform_device *pdev)
+       master->set_cs = sun6i_spi_set_cs;
+       master->transfer_one = sun6i_spi_transfer_one;
+       master->num_chipselect = 4;
+-      master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
++      master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
++                          sspi->cfg->mode_bits;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
+       master->dev.of_node = pdev->dev.of_node;
+       master->auto_runtime_pm = true;
+-- 
+2.20.1
+