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>
Link: https://lore.kernel.org/r/20230624131632.2972546-2-bigunclemax@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Maksim Kiselev 2023-06-24 16:16:22 +03:00 committed by Mark Brown
parent 06c2afb862
commit 0605d9fb41
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0

View file

@ -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;