Commit 0f516226 authored by Mark Brown's avatar Mark Brown

Allwinner R329/D1/R528/T113s Dual/Quad SPI modes

Merge series from Maksim Kiselev <bigunclemax@gmail.com>:

This series extends the previous https://lore.kernel.org/all/20230510081121.3463710-1-bigunclemax@gmail.com
And adds support for Dual and Quad SPI modes for the listed SoCs.
Both modes have been tested on the T113s and should work on
other Allwinner's SoCs that have a similar SPI conttoller.
It may also work for previous SoCs that support Dual/Quad modes.
One of them are H6 and H616.
parents 1dc8ca71 25453d79
...@@ -83,6 +83,9 @@ ...@@ -83,6 +83,9 @@
#define SUN6I_XMIT_CNT_REG 0x34 #define SUN6I_XMIT_CNT_REG 0x34
#define SUN6I_BURST_CTL_CNT_REG 0x38 #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_TXDATA_REG 0x200
#define SUN6I_RXDATA_REG 0x300 #define SUN6I_RXDATA_REG 0x300
...@@ -90,6 +93,7 @@ ...@@ -90,6 +93,7 @@
struct sun6i_spi_cfg { struct sun6i_spi_cfg {
unsigned long fifo_depth; unsigned long fifo_depth;
bool has_clk_ctl; bool has_clk_ctl;
u32 mode_bits;
}; };
struct sun6i_spi { struct sun6i_spi {
...@@ -266,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, ...@@ -266,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
unsigned int div, div_cdr1, div_cdr2, timeout; unsigned int div, div_cdr1, div_cdr2, timeout;
unsigned int start, end, tx_time; unsigned int start, end, tx_time;
unsigned int trig_level; 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; bool use_dma;
int ret = 0; int ret = 0;
u32 reg; u32 reg;
...@@ -418,13 +422,29 @@ static int sun6i_spi_transfer_one(struct spi_master *master, ...@@ -418,13 +422,29 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg); sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg);
/* Setup the transfer now... */ /* Setup the transfer now... */
if (sspi->tx_buf) if (sspi->tx_buf) {
tx_len = tfr->len; 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 */ /* 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_BURST_CNT_REG, tfr->len);
sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_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) { if (!use_dma) {
/* Fill the TX FIFO */ /* Fill the TX FIFO */
...@@ -623,7 +643,8 @@ static int sun6i_spi_probe(struct platform_device *pdev) ...@@ -623,7 +643,8 @@ static int sun6i_spi_probe(struct platform_device *pdev)
master->set_cs = sun6i_spi_set_cs; master->set_cs = sun6i_spi_set_cs;
master->transfer_one = sun6i_spi_transfer_one; master->transfer_one = sun6i_spi_transfer_one;
master->num_chipselect = 4; 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->bits_per_word_mask = SPI_BPW_MASK(8);
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
...@@ -740,6 +761,7 @@ static const struct sun6i_spi_cfg sun8i_h3_spi_cfg = { ...@@ -740,6 +761,7 @@ static const struct sun6i_spi_cfg sun8i_h3_spi_cfg = {
static const struct sun6i_spi_cfg sun50i_r329_spi_cfg = { static const struct sun6i_spi_cfg sun50i_r329_spi_cfg = {
.fifo_depth = SUN8I_FIFO_DEPTH, .fifo_depth = SUN8I_FIFO_DEPTH,
.mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD,
}; };
static const struct of_device_id sun6i_spi_match[] = { static const struct of_device_id sun6i_spi_match[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment