Skip to content

Commit 4e00135

Browse files
Jun Guobroonie
authored andcommitted
spi: spi-cadence: supports transmission with bits_per_word of 16 and 32
The default FIFO data width of the Cadence SPI IP is 8 bits, but the hardware supports configurations of 16 bits and 32 bits. This patch enhances the driver to support communication with both 16-bits and 32-bits FIFO data widths. Signed-off-by: Jun Guo <jun.guo@cixtech.com> Link: https://patch.msgid.link/20251031073003.3289573-3-jun.guo@cixtech.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 55b5d19 commit 4e00135

1 file changed

Lines changed: 93 additions & 13 deletions

File tree

drivers/spi/spi-cadence.c

Lines changed: 93 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
* @rxbuf: Pointer to the RX buffer
110110
* @tx_bytes: Number of bytes left to transfer
111111
* @rx_bytes: Number of bytes requested
112+
* @n_bytes: Number of bytes per word
112113
* @dev_busy: Device busy flag
113114
* @is_decoded_cs: Flag for decoder property set or not
114115
* @tx_fifo_depth: Depth of the TX FIFO
@@ -120,16 +121,24 @@ struct cdns_spi {
120121
struct clk *pclk;
121122
unsigned int clk_rate;
122123
u32 speed_hz;
123-
const u8 *txbuf;
124-
u8 *rxbuf;
124+
const void *txbuf;
125+
void *rxbuf;
125126
int tx_bytes;
126127
int rx_bytes;
128+
u8 n_bytes;
127129
u8 dev_busy;
128130
u32 is_decoded_cs;
129131
unsigned int tx_fifo_depth;
130132
struct reset_control *rstc;
131133
};
132134

135+
enum cdns_spi_frame_n_bytes {
136+
CDNS_SPI_N_BYTES_NULL = 0,
137+
CDNS_SPI_N_BYTES_U8 = 1,
138+
CDNS_SPI_N_BYTES_U16 = 2,
139+
CDNS_SPI_N_BYTES_U32 = 4
140+
};
141+
133142
/* Macros for the SPI controller read/write */
134143
static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset)
135144
{
@@ -305,6 +314,78 @@ static int cdns_spi_setup_transfer(struct spi_device *spi,
305314
return 0;
306315
}
307316

317+
static u8 cdns_spi_n_bytes(struct spi_transfer *transfer)
318+
{
319+
if (transfer->bits_per_word <= 8)
320+
return CDNS_SPI_N_BYTES_U8;
321+
else if (transfer->bits_per_word <= 16)
322+
return CDNS_SPI_N_BYTES_U16;
323+
else
324+
return CDNS_SPI_N_BYTES_U32;
325+
}
326+
327+
static inline void cdns_spi_reader(struct cdns_spi *xspi)
328+
{
329+
u32 rxw = 0;
330+
331+
if (xspi->rxbuf && !IS_ALIGNED((uintptr_t)xspi->rxbuf, xspi->n_bytes)) {
332+
pr_err("%s: rxbuf address is not aligned for %d bytes\n",
333+
__func__, xspi->n_bytes);
334+
return;
335+
}
336+
337+
rxw = cdns_spi_read(xspi, CDNS_SPI_RXD);
338+
if (xspi->rxbuf) {
339+
switch (xspi->n_bytes) {
340+
case CDNS_SPI_N_BYTES_U8:
341+
*(u8 *)xspi->rxbuf = rxw;
342+
break;
343+
case CDNS_SPI_N_BYTES_U16:
344+
*(u16 *)xspi->rxbuf = rxw;
345+
break;
346+
case CDNS_SPI_N_BYTES_U32:
347+
*(u32 *)xspi->rxbuf = rxw;
348+
break;
349+
default:
350+
pr_err("%s invalid n_bytes %d\n", __func__,
351+
xspi->n_bytes);
352+
return;
353+
}
354+
xspi->rxbuf = (u8 *)xspi->rxbuf + xspi->n_bytes;
355+
}
356+
}
357+
358+
static inline void cdns_spi_writer(struct cdns_spi *xspi)
359+
{
360+
u32 txw = 0;
361+
362+
if (xspi->txbuf && !IS_ALIGNED((uintptr_t)xspi->txbuf, xspi->n_bytes)) {
363+
pr_err("%s: txbuf address is not aligned for %d bytes\n",
364+
__func__, xspi->n_bytes);
365+
return;
366+
}
367+
368+
if (xspi->txbuf) {
369+
switch (xspi->n_bytes) {
370+
case CDNS_SPI_N_BYTES_U8:
371+
txw = *(u8 *)xspi->txbuf;
372+
break;
373+
case CDNS_SPI_N_BYTES_U16:
374+
txw = *(u16 *)xspi->txbuf;
375+
break;
376+
case CDNS_SPI_N_BYTES_U32:
377+
txw = *(u32 *)xspi->txbuf;
378+
break;
379+
default:
380+
pr_err("%s invalid n_bytes %d\n", __func__,
381+
xspi->n_bytes);
382+
return;
383+
}
384+
cdns_spi_write(xspi, CDNS_SPI_TXD, txw);
385+
xspi->txbuf = (u8 *)xspi->txbuf + xspi->n_bytes;
386+
}
387+
}
388+
308389
/**
309390
* cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO
310391
* @xspi: Pointer to the cdns_spi structure
@@ -321,23 +402,14 @@ static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)
321402

322403
while (ntx || nrx) {
323404
if (nrx) {
324-
u8 data = cdns_spi_read(xspi, CDNS_SPI_RXD);
325-
326-
if (xspi->rxbuf)
327-
*xspi->rxbuf++ = data;
328-
405+
cdns_spi_reader(xspi);
329406
nrx--;
330407
}
331408

332409
if (ntx) {
333-
if (xspi->txbuf)
334-
cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
335-
else
336-
cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
337-
410+
cdns_spi_writer(xspi);
338411
ntx--;
339412
}
340-
341413
}
342414
}
343415

@@ -454,6 +526,10 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
454526
if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
455527
udelay(10);
456528

529+
xspi->n_bytes = cdns_spi_n_bytes(transfer);
530+
xspi->tx_bytes = DIV_ROUND_UP(xspi->tx_bytes, xspi->n_bytes);
531+
xspi->rx_bytes = DIV_ROUND_UP(xspi->rx_bytes, xspi->n_bytes);
532+
457533
cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0);
458534

459535
cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT);
@@ -654,6 +730,9 @@ static int cdns_spi_probe(struct platform_device *pdev)
654730
ctlr->mode_bits = SPI_CPOL | SPI_CPHA;
655731
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
656732

733+
if (of_device_is_compatible(pdev->dev.of_node, "cix,sky1-spi-r1p6"))
734+
ctlr->bits_per_word_mask |= SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
735+
657736
if (!spi_controller_is_target(ctlr)) {
658737
ctlr->mode_bits |= SPI_CS_HIGH;
659738
ctlr->set_cs = cdns_spi_chipselect;
@@ -797,6 +876,7 @@ static const struct dev_pm_ops cdns_spi_dev_pm_ops = {
797876

798877
static const struct of_device_id cdns_spi_of_match[] = {
799878
{ .compatible = "xlnx,zynq-spi-r1p6" },
879+
{ .compatible = "cix,sky1-spi-r1p6" },
800880
{ .compatible = "cdns,spi-r1p6" },
801881
{ /* end of table */ }
802882
};

0 commit comments

Comments
 (0)