From: Chris Lesiak <chris.lesiak@licor.com>
To: Mark Brown <broonie@kernel.org>
Cc: linux-spi@vger.kernel.org, Chris Lesiak <chris.lesiak@licor.com>
Subject: [PATCH] spi: spi-imx: mx51 support for more than 4 gpio chip selects
Date: Wed, 12 Oct 2022 10:07:09 -0500 [thread overview]
Message-ID: <20221012150709.996967-1-chris.lesiak@licor.com> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 4891 bytes --]
The MX51_ECSPI_CTRL and MX51_ECSPI_CONFIG registers have bit fields
that only support the four slave select channels. If we are using
a gpio to support chip_select > 3, we need to be careful not to
write outside the bit fields. Probably the biggest issue is the
2-bit CHANNEL_SELECT field of MX51_ECSPI_CTRL overflowing into the
BURST_LENGTH field. That will likely cause a DMA TX timeout.
To prevent this, when chip_select > 3, use slave select = 3.
This should allow up to four channels using the built-in slave
selects, or any of the first three chip selects optionally using
built-in slave selects with gpio used for additional channels.
Signed-off-by: Chris Lesiak <chris.lesiak@licor.com>
---
drivers/spi/spi-imx.c | 43 ++++++++++++++++++++++++++++++++-----------
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 30d82cc7300b..9c4e979ab74d 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -253,6 +253,8 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device
return true;
}
+#define MX51_ECSPI_MAX_HW_CS 3
+
#define MX51_ECSPI_CTRL 0x08
#define MX51_ECSPI_CTRL_ENABLE (1 << 0)
#define MX51_ECSPI_CTRL_XCH (1 << 2)
@@ -521,6 +523,17 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
u32 testreg, delay;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
u32 current_cfg = cfg;
+ u8 hw_chip_select;
+
+ if (spi->cs_gpiod) {
+ hw_chip_select = MX51_ECSPI_MAX_HW_CS;
+ } else if (spi->chip_select <= MX51_ECSPI_MAX_HW_CS) {
+ hw_chip_select = spi->chip_select;
+ } else {
+ dev_err(spi_imx->dev, "hardware chip select is out of range: %i\n",
+ spi->chip_select);
+ return -EINVAL;
+ }
/* set Master or Slave mode */
if (spi_imx->slave_mode)
@@ -535,7 +548,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl);
/* set chip select to use */
- ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select);
+ ctrl |= MX51_ECSPI_CTRL_CS(hw_chip_select);
/*
* The ctrl register must be written first, with the EN bit set other
@@ -556,22 +569,22 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
* BURST_LENGTH + 1 bits are received
*/
if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
- cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
+ cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(hw_chip_select);
else
- cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
+ cfg |= MX51_ECSPI_CONFIG_SBBCTRL(hw_chip_select);
if (spi->mode & SPI_CPOL) {
- cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select);
- cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select);
+ cfg |= MX51_ECSPI_CONFIG_SCLKPOL(hw_chip_select);
+ cfg |= MX51_ECSPI_CONFIG_SCLKCTL(hw_chip_select);
} else {
- cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select);
- cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select);
+ cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(hw_chip_select);
+ cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(hw_chip_select);
}
if (spi->mode & SPI_CS_HIGH)
- cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
+ cfg |= MX51_ECSPI_CONFIG_SSBPOL(hw_chip_select);
else
- cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
+ cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(hw_chip_select);
if (cfg == current_cfg)
return 0;
@@ -616,14 +629,22 @@ static void mx51_configure_cpha(struct spi_imx_data *spi_imx,
bool cpha = (spi->mode & SPI_CPHA);
bool flip_cpha = (spi->mode & SPI_RX_CPHA_FLIP) && spi_imx->rx_only;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
+ u8 hw_chip_select;
+
+ if (spi->cs_gpiod)
+ hw_chip_select = MX51_ECSPI_MAX_HW_CS;
+ else if (spi->chip_select <= MX51_ECSPI_MAX_HW_CS)
+ hw_chip_select = spi->chip_select;
+ else
+ return;
/* Flip cpha logical value iff flip_cpha */
cpha ^= flip_cpha;
if (cpha)
- cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select);
+ cfg |= MX51_ECSPI_CONFIG_SCLKPHA(hw_chip_select);
else
- cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select);
+ cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(hw_chip_select);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
}
--
2.26.2
Chris Lesiak
Principal Design Engineer, Software
402-467-0693
[-- Attachment #1.2.1: Type: text/html, Size: 11202 bytes --]
[-- Attachment #1.2.2: logo.png --]
[-- Type: image/png, Size: 15564 bytes --]
next reply other threads:[~2022-10-17 12:00 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-12 15:07 Chris Lesiak [this message]
-- strict thread matches above, loose matches on Subject: below --
2022-10-07 15:28 [PATCH] spi: spi-imx: mx51 support for more than 4 gpio chip selects Chris Lesiak
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=20221012150709.996967-1-chris.lesiak@licor.com \
--to=chris.lesiak@licor.com \
--cc=broonie@kernel.org \
--cc=linux-spi@vger.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox