From: Jun Guo <jun.guo@cixtech.com>
To: peter.chen@cixtech.com, fugang.duan@cixtech.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, broonie@kernel.org
Cc: linux-spi@vger.kernel.org, michal.simek@amd.com,
cix-kernel-upstream@cixtech.com,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, Jun Guo <jun.guo@cixtech.com>
Subject: [PATCH v3 2/3] spi: spi-cadence: supports transmission with bits_per_word of 16 and 32
Date: Fri, 31 Oct 2025 15:30:02 +0800 [thread overview]
Message-ID: <20251031073003.3289573-3-jun.guo@cixtech.com> (raw)
In-Reply-To: <20251031073003.3289573-1-jun.guo@cixtech.com>
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>
---
drivers/spi/spi-cadence.c | 106 +++++++++++++++++++++++++++++++++-----
1 file changed, 93 insertions(+), 13 deletions(-)
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index 5ae09b21d23a..47054da630d0 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -109,6 +109,7 @@
* @rxbuf: Pointer to the RX buffer
* @tx_bytes: Number of bytes left to transfer
* @rx_bytes: Number of bytes requested
+ * @n_bytes: Number of bytes per word
* @dev_busy: Device busy flag
* @is_decoded_cs: Flag for decoder property set or not
* @tx_fifo_depth: Depth of the TX FIFO
@@ -120,16 +121,24 @@ struct cdns_spi {
struct clk *pclk;
unsigned int clk_rate;
u32 speed_hz;
- const u8 *txbuf;
- u8 *rxbuf;
+ const void *txbuf;
+ void *rxbuf;
int tx_bytes;
int rx_bytes;
+ u8 n_bytes;
u8 dev_busy;
u32 is_decoded_cs;
unsigned int tx_fifo_depth;
struct reset_control *rstc;
};
+enum cdns_spi_frame_n_bytes {
+ CDNS_SPI_N_BYTES_NULL = 0,
+ CDNS_SPI_N_BYTES_U8 = 1,
+ CDNS_SPI_N_BYTES_U16 = 2,
+ CDNS_SPI_N_BYTES_U32 = 4
+};
+
/* Macros for the SPI controller read/write */
static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset)
{
@@ -305,6 +314,78 @@ static int cdns_spi_setup_transfer(struct spi_device *spi,
return 0;
}
+static u8 cdns_spi_n_bytes(struct spi_transfer *transfer)
+{
+ if (transfer->bits_per_word <= 8)
+ return CDNS_SPI_N_BYTES_U8;
+ else if (transfer->bits_per_word <= 16)
+ return CDNS_SPI_N_BYTES_U16;
+ else
+ return CDNS_SPI_N_BYTES_U32;
+}
+
+static inline void cdns_spi_reader(struct cdns_spi *xspi)
+{
+ u32 rxw = 0;
+
+ if (xspi->rxbuf && !IS_ALIGNED((uintptr_t)xspi->rxbuf, xspi->n_bytes)) {
+ pr_err("%s: rxbuf address is not aligned for %d bytes\n",
+ __func__, xspi->n_bytes);
+ return;
+ }
+
+ rxw = cdns_spi_read(xspi, CDNS_SPI_RXD);
+ if (xspi->rxbuf) {
+ switch (xspi->n_bytes) {
+ case CDNS_SPI_N_BYTES_U8:
+ *(u8 *)xspi->rxbuf = rxw;
+ break;
+ case CDNS_SPI_N_BYTES_U16:
+ *(u16 *)xspi->rxbuf = rxw;
+ break;
+ case CDNS_SPI_N_BYTES_U32:
+ *(u32 *)xspi->rxbuf = rxw;
+ break;
+ default:
+ pr_err("%s invalid n_bytes %d\n", __func__,
+ xspi->n_bytes);
+ return;
+ }
+ xspi->rxbuf = (u8 *)xspi->rxbuf + xspi->n_bytes;
+ }
+}
+
+static inline void cdns_spi_writer(struct cdns_spi *xspi)
+{
+ u32 txw = 0;
+
+ if (xspi->txbuf && !IS_ALIGNED((uintptr_t)xspi->txbuf, xspi->n_bytes)) {
+ pr_err("%s: txbuf address is not aligned for %d bytes\n",
+ __func__, xspi->n_bytes);
+ return;
+ }
+
+ if (xspi->txbuf) {
+ switch (xspi->n_bytes) {
+ case CDNS_SPI_N_BYTES_U8:
+ txw = *(u8 *)xspi->txbuf;
+ break;
+ case CDNS_SPI_N_BYTES_U16:
+ txw = *(u16 *)xspi->txbuf;
+ break;
+ case CDNS_SPI_N_BYTES_U32:
+ txw = *(u32 *)xspi->txbuf;
+ break;
+ default:
+ pr_err("%s invalid n_bytes %d\n", __func__,
+ xspi->n_bytes);
+ return;
+ }
+ cdns_spi_write(xspi, CDNS_SPI_TXD, txw);
+ xspi->txbuf = (u8 *)xspi->txbuf + xspi->n_bytes;
+ }
+}
+
/**
* cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO
* @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)
while (ntx || nrx) {
if (nrx) {
- u8 data = cdns_spi_read(xspi, CDNS_SPI_RXD);
-
- if (xspi->rxbuf)
- *xspi->rxbuf++ = data;
-
+ cdns_spi_reader(xspi);
nrx--;
}
if (ntx) {
- if (xspi->txbuf)
- cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
- else
- cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
-
+ cdns_spi_writer(xspi);
ntx--;
}
-
}
}
@@ -454,6 +526,10 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
udelay(10);
+ xspi->n_bytes = cdns_spi_n_bytes(transfer);
+ xspi->tx_bytes = DIV_ROUND_UP(xspi->tx_bytes, xspi->n_bytes);
+ xspi->rx_bytes = DIV_ROUND_UP(xspi->rx_bytes, xspi->n_bytes);
+
cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0);
cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT);
@@ -654,6 +730,9 @@ static int cdns_spi_probe(struct platform_device *pdev)
ctlr->mode_bits = SPI_CPOL | SPI_CPHA;
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
+ if (of_device_is_compatible(pdev->dev.of_node, "cix,sky1-spi-r1p6"))
+ ctlr->bits_per_word_mask |= SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
+
if (!spi_controller_is_target(ctlr)) {
ctlr->mode_bits |= SPI_CS_HIGH;
ctlr->set_cs = cdns_spi_chipselect;
@@ -797,6 +876,7 @@ static const struct dev_pm_ops cdns_spi_dev_pm_ops = {
static const struct of_device_id cdns_spi_of_match[] = {
{ .compatible = "xlnx,zynq-spi-r1p6" },
+ { .compatible = "cix,sky1-spi-r1p6" },
{ .compatible = "cdns,spi-r1p6" },
{ /* end of table */ }
};
--
2.34.1
next prev parent reply other threads:[~2025-10-31 7:30 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-31 7:30 [PATCH v3 0/3] spi-cadence: support transmission with bits_per_word of 16 and 32 Jun Guo
2025-10-31 7:30 ` [PATCH v3 1/3] dt-bindings: spi: spi-cadence: update DT binding docs to support cix sky1 SoC Jun Guo
2025-10-31 15:10 ` Conor Dooley
2025-10-31 7:30 ` Jun Guo [this message]
2026-01-14 14:14 ` [PATCH v3 2/3] spi: spi-cadence: supports transmission with bits_per_word of 16 and 32 Rodrigo Alencar
2026-01-14 14:16 ` Mark Brown
2026-01-14 16:09 ` Rodrigo Alencar
2026-01-15 2:14 ` Jun Guo
2025-10-31 7:30 ` [PATCH v3 3/3] arm64: dts: cix: add a compatible string for the cix sky1 SoC Jun Guo
2025-11-17 9:32 ` Peter Chen
2025-11-14 17:07 ` (subset) [PATCH v3 0/3] spi-cadence: support transmission with bits_per_word of 16 and 32 Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251031073003.3289573-3-jun.guo@cixtech.com \
--to=jun.guo@cixtech.com \
--cc=broonie@kernel.org \
--cc=cix-kernel-upstream@cixtech.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=fugang.duan@cixtech.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=michal.simek@amd.com \
--cc=peter.chen@cixtech.com \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.