* [PATCH v1 0/6] spi-microchip-core fixes & variable word size support
@ 2024-07-15 11:13 Conor Dooley
2024-07-15 11:13 ` [PATCH v1 1/6] spi: microchip-core: fix the issues in the isr Conor Dooley
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Conor Dooley @ 2024-07-15 11:13 UTC (permalink / raw)
To: linux-spi
Cc: conor, conor.dooley, Steve Wilkins, Daire McNamara, Mark Brown,
linux-kernel
Hey Mark,
Got some fixes here for the spi-microchip-core driver, that I am passing
on.. The author of the first patch is no longer at Microchip, so there's
probably gonna be some bounces on the series. The remainder of the
patches got sent in by a user, and, other than one patch, I just wrote
commit messages for those that were missing them and rebased the series
on top of mainline.
There was one other patch in the series submitted by the user to us, that
I opted to drop, adding locking around accesses to tx FIFO in the
interrupt handler and in the transfer_one implementation. I think that
patch is not needed after the first patch in this series since there'll
be no contention any more.
Cheers,
Conor.
CC: Steve Wilkins <steve.wilkins@raymarine.com>
CC: Conor Dooley <conor.dooley@microchip.com>
CC: Daire McNamara <daire.mcnamara@microchip.com>
CC: Mark Brown <broonie@kernel.org>
CC: linux-spi@vger.kernel.org
CC: linux-kernel@vger.kernel.org
Naga Sureshkumar Relli (1):
spi: microchip-core: fix the issues in the isr
Steve Wilkins (5):
spi: microchip-core: defer asserting chip select until just before
write to TX FIFO
spi: microchip-core: only disable SPI controller when register value
change requires it
spi: microchip-core: fix init function not setting the master and
motorola modes
spi: microchip-core: ensure TX and RX FIFOs are empty at start of a
transfer
spi: microchip-core: add support for word sizes of 1 to 32 bits
drivers/spi/spi-microchip-core.c | 190 ++++++++++++++++++-------------
1 file changed, 110 insertions(+), 80 deletions(-)
--
2.43.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v1 1/6] spi: microchip-core: fix the issues in the isr
2024-07-15 11:13 [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Conor Dooley
@ 2024-07-15 11:13 ` Conor Dooley
2024-07-15 11:13 ` [PATCH v1 2/6] spi: microchip-core: defer asserting chip select until just before write to TX FIFO Conor Dooley
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Conor Dooley @ 2024-07-15 11:13 UTC (permalink / raw)
To: linux-spi
Cc: conor, conor.dooley, Steve Wilkins, Daire McNamara, Mark Brown,
linux-kernel, Naga Sureshkumar Relli
From: Naga Sureshkumar Relli <nagasuresh.relli@microchip.com>
It is possible for the TXDONE interrupt be raised if the tx FIFO becomes
temporarily empty while transmitting, resulting in recursive calls to
mchp_corespi_write_fifo() and therefore a garbage message might be
transmitted depending on when the interrupt is triggered. Moving all of
the tx FIFO writes out of the TXDONE portion of the interrupt handler
avoids this problem.
Most of rest of the TXDONE portion of the handler is problematic too.
Only reading the rx FIFO (and finalising the transfer) when the TXDONE
interrupt is raised can cause the transfer to stall, if the final bytes
of rx data are not available in the rx FIFO when the final TXDONE
interrupt is raised. The transfer should be finalised regardless of
which interrupt is raised, provided that all tx data has been set and
all rx data received.
The first issue was encountered "in the wild", the second is
theoretical.
Fixes: 9ac8d17694b6 ("spi: add support for microchip fpga spi controllers")
Signed-off-by: Naga Sureshkumar Relli <nagasuresh.relli@microchip.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/spi/spi-microchip-core.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c
index 634364c7cfe61..a81e1317d52e6 100644
--- a/drivers/spi/spi-microchip-core.c
+++ b/drivers/spi/spi-microchip-core.c
@@ -380,21 +380,18 @@ static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id)
if (intfield == 0)
return IRQ_NONE;
- if (intfield & INT_TXDONE) {
+ if (intfield & INT_TXDONE)
mchp_corespi_write(spi, REG_INT_CLEAR, INT_TXDONE);
+ if (intfield & INT_RXRDY) {
+ mchp_corespi_write(spi, REG_INT_CLEAR, INT_RXRDY);
+
if (spi->rx_len)
mchp_corespi_read_fifo(spi);
-
- if (spi->tx_len)
- mchp_corespi_write_fifo(spi);
-
- if (!spi->rx_len)
- finalise = true;
}
- if (intfield & INT_RXRDY)
- mchp_corespi_write(spi, REG_INT_CLEAR, INT_RXRDY);
+ if (!spi->rx_len && !spi->tx_len)
+ finalise = true;
if (intfield & INT_RX_CHANNEL_OVERFLOW) {
mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW);
@@ -479,8 +476,9 @@ static int mchp_corespi_transfer_one(struct spi_controller *host,
mchp_corespi_set_xfer_size(spi, (spi->tx_len > FIFO_DEPTH)
? FIFO_DEPTH : spi->tx_len);
- if (spi->tx_len)
+ while (spi->tx_len)
mchp_corespi_write_fifo(spi);
+
return 1;
}
--
2.43.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 2/6] spi: microchip-core: defer asserting chip select until just before write to TX FIFO
2024-07-15 11:13 [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Conor Dooley
2024-07-15 11:13 ` [PATCH v1 1/6] spi: microchip-core: fix the issues in the isr Conor Dooley
@ 2024-07-15 11:13 ` Conor Dooley
2024-07-15 11:13 ` [PATCH v1 3/6] spi: microchip-core: only disable SPI controller when register value change requires it Conor Dooley
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Conor Dooley @ 2024-07-15 11:13 UTC (permalink / raw)
To: linux-spi
Cc: conor, conor.dooley, Steve Wilkins, Daire McNamara, Mark Brown,
linux-kernel
From: Steve Wilkins <steve.wilkins@raymarine.com>
Setting up many of the registers for a new SPI transfer requires the
SPI controller to be disabled after set_cs() has been called to assert
the chip select line. However, disabling the controller results in the
SCLK and MOSI output pins being tristate, which can cause clock
transitions to be seen by a slave device whilst SS is active. To fix
this, the CS is only set to inactive inline, whilst setting it active
is deferred until all registers are set up and the any controller
disables have been completed.
Fixes: 9ac8d17694b6 ("spi: add support for microchip fpga spi controllers")
Signed-off-by: Steve Wilkins <steve.wilkins@raymarine.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/spi/spi-microchip-core.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c
index a81e1317d52e6..b042160bd8811 100644
--- a/drivers/spi/spi-microchip-core.c
+++ b/drivers/spi/spi-microchip-core.c
@@ -103,6 +103,7 @@ struct mchp_corespi {
u8 *rx_buf;
u32 clk_gen; /* divider for spi output clock generated by the controller */
u32 clk_mode;
+ u32 pending_slave_select;
int irq;
int tx_len;
int rx_len;
@@ -249,8 +250,18 @@ static void mchp_corespi_set_cs(struct spi_device *spi, bool disable)
reg = mchp_corespi_read(corespi, REG_SLAVE_SELECT);
reg &= ~BIT(spi_get_chipselect(spi, 0));
reg |= !disable << spi_get_chipselect(spi, 0);
+ corespi->pending_slave_select = reg;
- mchp_corespi_write(corespi, REG_SLAVE_SELECT, reg);
+ /*
+ * Only deassert chip select immediately. Writing to some registers
+ * requires the controller to be disabled, which results in the
+ * output pins being tristated and can cause the SCLK and MOSI lines
+ * to transition. Therefore asserting the chip select is deferred
+ * until just before writing to the TX FIFO, to ensure the device
+ * doesn't see any spurious clock transitions whilst CS is enabled.
+ */
+ if (((spi->mode & SPI_CS_HIGH) == 0) == disable)
+ mchp_corespi_write(corespi, REG_SLAVE_SELECT, reg);
}
static int mchp_corespi_setup(struct spi_device *spi)
@@ -266,6 +277,7 @@ static int mchp_corespi_setup(struct spi_device *spi)
if (spi->mode & SPI_CS_HIGH) {
reg = mchp_corespi_read(corespi, REG_SLAVE_SELECT);
reg |= BIT(spi_get_chipselect(spi, 0));
+ corespi->pending_slave_select = reg;
mchp_corespi_write(corespi, REG_SLAVE_SELECT, reg);
}
return 0;
@@ -307,7 +319,8 @@ static void mchp_corespi_init(struct spi_controller *host, struct mchp_corespi *
* select is relinquished to the hardware. SSELOUT is enabled too so we
* can deal with active high targets.
*/
- mchp_corespi_write(spi, REG_SLAVE_SELECT, SSELOUT | SSEL_DIRECT);
+ spi->pending_slave_select = SSELOUT | SSEL_DIRECT;
+ mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select);
control = mchp_corespi_read(spi, REG_CONTROL);
@@ -476,6 +489,8 @@ static int mchp_corespi_transfer_one(struct spi_controller *host,
mchp_corespi_set_xfer_size(spi, (spi->tx_len > FIFO_DEPTH)
? FIFO_DEPTH : spi->tx_len);
+ mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select);
+
while (spi->tx_len)
mchp_corespi_write_fifo(spi);
--
2.43.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 3/6] spi: microchip-core: only disable SPI controller when register value change requires it
2024-07-15 11:13 [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Conor Dooley
2024-07-15 11:13 ` [PATCH v1 1/6] spi: microchip-core: fix the issues in the isr Conor Dooley
2024-07-15 11:13 ` [PATCH v1 2/6] spi: microchip-core: defer asserting chip select until just before write to TX FIFO Conor Dooley
@ 2024-07-15 11:13 ` Conor Dooley
2024-07-15 11:13 ` [PATCH v1 4/6] spi: microchip-core: fix init function not setting the master and motorola modes Conor Dooley
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Conor Dooley @ 2024-07-15 11:13 UTC (permalink / raw)
To: linux-spi
Cc: conor, conor.dooley, Steve Wilkins, Daire McNamara, Mark Brown,
linux-kernel
From: Steve Wilkins <steve.wilkins@raymarine.com>
Setting up many of the registers for a new SPI transfer involves
unconditionally disabling the SPI controller, writing the register
value and re-enabling the controller. This is being done for registers
even when the value is unchanged and is also done for registers that
don't require the controller to be disabled for the change to take
effect. Make an effort to detect changes to the register values, and
only disables the controller if the new register value is different
and disabling the controller is required. This stops the controller
being repeated disabled and the bus going tristate before every
transfer.
Fixes: 9ac8d17694b6 ("spi: add support for microchip fpga spi controllers")
Signed-off-by: Steve Wilkins <steve.wilkins@raymarine.com>
Co-developed-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/spi/spi-microchip-core.c | 79 +++++++++++++++++---------------
1 file changed, 41 insertions(+), 38 deletions(-)
diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c
index b042160bd8811..24a728bde8fda 100644
--- a/drivers/spi/spi-microchip-core.c
+++ b/drivers/spi/spi-microchip-core.c
@@ -75,6 +75,7 @@
#define REG_CONTROL (0x00)
#define REG_FRAME_SIZE (0x04)
+#define FRAME_SIZE_MASK GENMASK(5, 0)
#define REG_STATUS (0x08)
#define REG_INT_CLEAR (0x0c)
#define REG_RX_DATA (0x10)
@@ -89,6 +90,7 @@
#define REG_RIS (0x24)
#define REG_CONTROL2 (0x28)
#define REG_COMMAND (0x2c)
+#define COMMAND_CLRFRAMECNT BIT(4)
#define REG_PKTSIZE (0x30)
#define REG_CMD_SIZE (0x34)
#define REG_HWSTATUS (0x38)
@@ -149,62 +151,59 @@ static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi)
static void mchp_corespi_enable_ints(struct mchp_corespi *spi)
{
- u32 control, mask = INT_ENABLE_MASK;
+ u32 control = mchp_corespi_read(spi, REG_CONTROL);
- mchp_corespi_disable(spi);
-
- control = mchp_corespi_read(spi, REG_CONTROL);
-
- control |= mask;
- mchp_corespi_write(spi, REG_CONTROL, control);
-
- control |= CONTROL_ENABLE;
+ control |= INT_ENABLE_MASK;
mchp_corespi_write(spi, REG_CONTROL, control);
}
static void mchp_corespi_disable_ints(struct mchp_corespi *spi)
{
- u32 control, mask = INT_ENABLE_MASK;
+ u32 control = mchp_corespi_read(spi, REG_CONTROL);
- mchp_corespi_disable(spi);
-
- control = mchp_corespi_read(spi, REG_CONTROL);
- control &= ~mask;
- mchp_corespi_write(spi, REG_CONTROL, control);
-
- control |= CONTROL_ENABLE;
+ control &= ~INT_ENABLE_MASK;
mchp_corespi_write(spi, REG_CONTROL, control);
}
static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len)
{
u32 control;
- u16 lenpart;
+ u32 lenpart;
+ u32 frames = mchp_corespi_read(spi, REG_FRAMESUP);
/*
- * Disable the SPI controller. Writes to transfer length have
- * no effect when the controller is enabled.
+ * Writing to FRAMECNT in REG_CONTROL will reset the frame count, taking
+ * a shortcut requires an explicit clear.
*/
- mchp_corespi_disable(spi);
+ if (frames == len) {
+ mchp_corespi_write(spi, REG_COMMAND, COMMAND_CLRFRAMECNT);
+ return;
+ }
/*
* The lower 16 bits of the frame count are stored in the control reg
* for legacy reasons, but the upper 16 written to a different register:
* FRAMESUP. While both the upper and lower bits can be *READ* from the
- * FRAMESUP register, writing to the lower 16 bits is a NOP
+ * FRAMESUP register, writing to the lower 16 bits is (supposedly) a NOP.
+ *
+ * The driver used to disable the controller while modifying the frame
+ * count, and mask off the lower 16 bits of len while writing to
+ * FRAMES_UP. When the driver was changed to disable the controller as
+ * infrequently as possible, it was discovered that the logic of
+ * lenpart = len & 0xffff_0000
+ * write(REG_FRAMESUP, lenpart)
+ * would actually write zeros into the lower 16 bits on an mpfs250t-es,
+ * despite documentation stating these bits were read-only.
+ * Writing len unmasked into FRAMES_UP ensures those bits aren't zeroed
+ * on an mpfs250t-es and will be a NOP for the lower 16 bits on hardware
+ * that matches the documentation.
*/
lenpart = len & 0xffff;
-
control = mchp_corespi_read(spi, REG_CONTROL);
control &= ~CONTROL_FRAMECNT_MASK;
control |= lenpart << CONTROL_FRAMECNT_SHIFT;
mchp_corespi_write(spi, REG_CONTROL, control);
-
- lenpart = len & 0xffff0000;
- mchp_corespi_write(spi, REG_FRAMESUP, lenpart);
-
- control |= CONTROL_ENABLE;
- mchp_corespi_write(spi, REG_CONTROL, control);
+ mchp_corespi_write(spi, REG_FRAMESUP, len);
}
static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi)
@@ -227,17 +226,22 @@ static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi)
static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt)
{
+ u32 frame_size = mchp_corespi_read(spi, REG_FRAME_SIZE);
u32 control;
+ if ((frame_size & FRAME_SIZE_MASK) == bt)
+ return;
+
/*
* Disable the SPI controller. Writes to the frame size have
* no effect when the controller is enabled.
*/
- mchp_corespi_disable(spi);
+ control = mchp_corespi_read(spi, REG_CONTROL);
+ control &= ~CONTROL_ENABLE;
+ mchp_corespi_write(spi, REG_CONTROL, control);
mchp_corespi_write(spi, REG_FRAME_SIZE, bt);
- control = mchp_corespi_read(spi, REG_CONTROL);
control |= CONTROL_ENABLE;
mchp_corespi_write(spi, REG_CONTROL, control);
}
@@ -334,8 +338,6 @@ static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi)
{
u32 control;
- mchp_corespi_disable(spi);
-
control = mchp_corespi_read(spi, REG_CONTROL);
if (spi->clk_mode)
control |= CONTROL_CLKMODE;
@@ -344,12 +346,12 @@ static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi)
mchp_corespi_write(spi, REG_CLK_GEN, spi->clk_gen);
mchp_corespi_write(spi, REG_CONTROL, control);
- mchp_corespi_write(spi, REG_CONTROL, control | CONTROL_ENABLE);
}
static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int mode)
{
- u32 control, mode_val;
+ u32 mode_val;
+ u32 control = mchp_corespi_read(spi, REG_CONTROL);
switch (mode & SPI_MODE_X_MASK) {
case SPI_MODE_0:
@@ -367,12 +369,13 @@ static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int
}
/*
- * Disable the SPI controller. Writes to the frame size have
+ * Disable the SPI controller. Writes to the frame protocol have
* no effect when the controller is enabled.
*/
- mchp_corespi_disable(spi);
- control = mchp_corespi_read(spi, REG_CONTROL);
+ control &= ~CONTROL_ENABLE;
+ mchp_corespi_write(spi, REG_CONTROL, control);
+
control &= ~(SPI_MODE_X_MASK << MODE_X_MASK_SHIFT);
control |= mode_val;
--
2.43.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 4/6] spi: microchip-core: fix init function not setting the master and motorola modes
2024-07-15 11:13 [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Conor Dooley
` (2 preceding siblings ...)
2024-07-15 11:13 ` [PATCH v1 3/6] spi: microchip-core: only disable SPI controller when register value change requires it Conor Dooley
@ 2024-07-15 11:13 ` Conor Dooley
2024-07-15 11:13 ` [PATCH v1 5/6] spi: microchip-core: ensure TX and RX FIFOs are empty at start of a transfer Conor Dooley
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Conor Dooley @ 2024-07-15 11:13 UTC (permalink / raw)
To: linux-spi
Cc: conor, conor.dooley, Steve Wilkins, Daire McNamara, Mark Brown,
linux-kernel
From: Steve Wilkins <steve.wilkins@raymarine.com>
mchp_corespi_init() reads the CONTROL register, sets the master and
motorola bits, but doesn't write the value back to the register. The
function also doesn't ensure the controller is disabled at the start,
which may present a problem if the controller was used by an
earlier boot stage as some settings (including the mode) can only be
modified while the controller is disabled.
Fixes: 9ac8d17694b6 ("spi: add support for microchip fpga spi controllers")
Signed-off-by: Steve Wilkins <steve.wilkins@raymarine.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/spi/spi-microchip-core.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c
index 24a728bde8fda..3d17018cedb08 100644
--- a/drivers/spi/spi-microchip-core.c
+++ b/drivers/spi/spi-microchip-core.c
@@ -292,17 +292,13 @@ static void mchp_corespi_init(struct spi_controller *host, struct mchp_corespi *
unsigned long clk_hz;
u32 control = mchp_corespi_read(spi, REG_CONTROL);
- control |= CONTROL_MASTER;
+ control &= ~CONTROL_ENABLE;
+ mchp_corespi_write(spi, REG_CONTROL, control);
+ control |= CONTROL_MASTER;
control &= ~CONTROL_MODE_MASK;
control |= MOTOROLA_MODE;
- mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE);
-
- /* max. possible spi clock rate is the apb clock rate */
- clk_hz = clk_get_rate(spi->clk);
- host->max_speed_hz = clk_hz;
-
/*
* The controller must be configured so that it doesn't remove Chip
* Select until the entire message has been transferred, even if at
@@ -311,11 +307,16 @@ static void mchp_corespi_init(struct spi_controller *host, struct mchp_corespi *
* BIGFIFO mode is also enabled, which sets the fifo depth to 32 frames
* for the 8 bit transfers that this driver uses.
*/
- control = mchp_corespi_read(spi, REG_CONTROL);
control |= CONTROL_SPS | CONTROL_BIGFIFO;
mchp_corespi_write(spi, REG_CONTROL, control);
+ mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE);
+
+ /* max. possible spi clock rate is the apb clock rate */
+ clk_hz = clk_get_rate(spi->clk);
+ host->max_speed_hz = clk_hz;
+
mchp_corespi_enable_ints(spi);
/*
--
2.43.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 5/6] spi: microchip-core: ensure TX and RX FIFOs are empty at start of a transfer
2024-07-15 11:13 [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Conor Dooley
` (3 preceding siblings ...)
2024-07-15 11:13 ` [PATCH v1 4/6] spi: microchip-core: fix init function not setting the master and motorola modes Conor Dooley
@ 2024-07-15 11:13 ` Conor Dooley
2024-07-15 11:13 ` [PATCH v1 6/6] spi: microchip-core: add support for word sizes of 1 to 32 bits Conor Dooley
2024-07-16 13:26 ` [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Mark Brown
6 siblings, 0 replies; 8+ messages in thread
From: Conor Dooley @ 2024-07-15 11:13 UTC (permalink / raw)
To: linux-spi
Cc: conor, conor.dooley, Steve Wilkins, Daire McNamara, Mark Brown,
linux-kernel
From: Steve Wilkins <steve.wilkins@raymarine.com>
While transmitting with rx_len == 0, the RX FIFO is not going to be
emptied in the interrupt handler. A subsequent transfer could then
read crap from the previous transfer out of the RX FIFO into the
start RX buffer. The core provides a register that will empty the RX and
TX FIFOs, so do that before each transfer.
Fixes: 9ac8d17694b6 ("spi: add support for microchip fpga spi controllers")
Signed-off-by: Steve Wilkins <steve.wilkins@raymarine.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/spi/spi-microchip-core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c
index 3d17018cedb08..9f37603ccf10a 100644
--- a/drivers/spi/spi-microchip-core.c
+++ b/drivers/spi/spi-microchip-core.c
@@ -91,6 +91,8 @@
#define REG_CONTROL2 (0x28)
#define REG_COMMAND (0x2c)
#define COMMAND_CLRFRAMECNT BIT(4)
+#define COMMAND_TXFIFORST BIT(3)
+#define COMMAND_RXFIFORST BIT(2)
#define REG_PKTSIZE (0x30)
#define REG_CMD_SIZE (0x34)
#define REG_HWSTATUS (0x38)
@@ -493,6 +495,8 @@ static int mchp_corespi_transfer_one(struct spi_controller *host,
mchp_corespi_set_xfer_size(spi, (spi->tx_len > FIFO_DEPTH)
? FIFO_DEPTH : spi->tx_len);
+ mchp_corespi_write(spi, REG_COMMAND, COMMAND_RXFIFORST | COMMAND_TXFIFORST);
+
mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select);
while (spi->tx_len)
--
2.43.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 6/6] spi: microchip-core: add support for word sizes of 1 to 32 bits
2024-07-15 11:13 [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Conor Dooley
` (4 preceding siblings ...)
2024-07-15 11:13 ` [PATCH v1 5/6] spi: microchip-core: ensure TX and RX FIFOs are empty at start of a transfer Conor Dooley
@ 2024-07-15 11:13 ` Conor Dooley
2024-07-16 13:26 ` [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Mark Brown
6 siblings, 0 replies; 8+ messages in thread
From: Conor Dooley @ 2024-07-15 11:13 UTC (permalink / raw)
To: linux-spi
Cc: conor, conor.dooley, Steve Wilkins, Daire McNamara, Mark Brown,
linux-kernel
From: Steve Wilkins <steve.wilkins@raymarine.com>
The current implementation only supports a word size of 8 bits,
which limits the devices it can be used with. Add support for any
word size between 1 and 32 bits, as supported by the hardware.
Signed-off-by: Steve Wilkins <steve.wilkins@raymarine.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/spi/spi-microchip-core.c | 53 +++++++++++++++++++-------------
1 file changed, 31 insertions(+), 22 deletions(-)
diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c
index 9f37603ccf10a..856bcbf0292d4 100644
--- a/drivers/spi/spi-microchip-core.c
+++ b/drivers/spi/spi-microchip-core.c
@@ -111,7 +111,7 @@ struct mchp_corespi {
int irq;
int tx_len;
int rx_len;
- int pending;
+ int n_bytes;
};
static inline u32 mchp_corespi_read(struct mchp_corespi *spi, unsigned int reg)
@@ -135,20 +135,23 @@ static inline void mchp_corespi_disable(struct mchp_corespi *spi)
static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi)
{
- u8 data;
- int fifo_max, i = 0;
+ while (spi->rx_len >= spi->n_bytes && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)) {
+ u32 data = mchp_corespi_read(spi, REG_RX_DATA);
- fifo_max = min(spi->rx_len, FIFO_DEPTH);
+ spi->rx_len -= spi->n_bytes;
- while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)) {
- data = mchp_corespi_read(spi, REG_RX_DATA);
+ if (!spi->rx_buf)
+ continue;
- if (spi->rx_buf)
- *spi->rx_buf++ = data;
- i++;
+ if (spi->n_bytes == 4)
+ *((u32 *)spi->rx_buf) = data;
+ else if (spi->n_bytes == 2)
+ *((u16 *)spi->rx_buf) = data;
+ else
+ *spi->rx_buf = data;
+
+ spi->rx_buf += spi->n_bytes;
}
- spi->rx_len -= i;
- spi->pending -= i;
}
static void mchp_corespi_enable_ints(struct mchp_corespi *spi)
@@ -210,20 +213,28 @@ static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len)
static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi)
{
- u8 byte;
int fifo_max, i = 0;
- fifo_max = min(spi->tx_len, FIFO_DEPTH);
+ fifo_max = DIV_ROUND_UP(min(spi->tx_len, FIFO_DEPTH), spi->n_bytes);
mchp_corespi_set_xfer_size(spi, fifo_max);
while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_TXFIFO_FULL)) {
- byte = spi->tx_buf ? *spi->tx_buf++ : 0xaa;
- mchp_corespi_write(spi, REG_TX_DATA, byte);
+ u32 word;
+
+ if (spi->n_bytes == 4)
+ word = spi->tx_buf ? *((u32 *)spi->tx_buf) : 0xaa;
+ else if (spi->n_bytes == 2)
+ word = spi->tx_buf ? *((u16 *)spi->tx_buf) : 0xaa;
+ else
+ word = spi->tx_buf ? *spi->tx_buf : 0xaa;
+
+ mchp_corespi_write(spi, REG_TX_DATA, word);
+ if (spi->tx_buf)
+ spi->tx_buf += spi->n_bytes;
i++;
}
- spi->tx_len -= i;
- spi->pending += i;
+ spi->tx_len -= i * spi->n_bytes;
}
static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt)
@@ -490,10 +501,9 @@ static int mchp_corespi_transfer_one(struct spi_controller *host,
spi->rx_buf = xfer->rx_buf;
spi->tx_len = xfer->len;
spi->rx_len = xfer->len;
- spi->pending = 0;
+ spi->n_bytes = roundup_pow_of_two(DIV_ROUND_UP(xfer->bits_per_word, BITS_PER_BYTE));
- mchp_corespi_set_xfer_size(spi, (spi->tx_len > FIFO_DEPTH)
- ? FIFO_DEPTH : spi->tx_len);
+ mchp_corespi_set_framesize(spi, xfer->bits_per_word);
mchp_corespi_write(spi, REG_COMMAND, COMMAND_RXFIFORST | COMMAND_TXFIFORST);
@@ -511,7 +521,6 @@ static int mchp_corespi_prepare_message(struct spi_controller *host,
struct spi_device *spi_dev = msg->spi;
struct mchp_corespi *spi = spi_controller_get_devdata(host);
- mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE);
mchp_corespi_set_mode(spi, spi_dev->mode);
return 0;
@@ -538,7 +547,7 @@ static int mchp_corespi_probe(struct platform_device *pdev)
host->num_chipselect = num_cs;
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
host->setup = mchp_corespi_setup;
- host->bits_per_word_mask = SPI_BPW_MASK(8);
+ host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
host->transfer_one = mchp_corespi_transfer_one;
host->prepare_message = mchp_corespi_prepare_message;
host->set_cs = mchp_corespi_set_cs;
--
2.43.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v1 0/6] spi-microchip-core fixes & variable word size support
2024-07-15 11:13 [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Conor Dooley
` (5 preceding siblings ...)
2024-07-15 11:13 ` [PATCH v1 6/6] spi: microchip-core: add support for word sizes of 1 to 32 bits Conor Dooley
@ 2024-07-16 13:26 ` Mark Brown
6 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2024-07-16 13:26 UTC (permalink / raw)
To: linux-spi, Conor Dooley
Cc: conor, Steve Wilkins, Daire McNamara, linux-kernel
On Mon, 15 Jul 2024 12:13:51 +0100, Conor Dooley wrote:
> Hey Mark,
>
> Got some fixes here for the spi-microchip-core driver, that I am passing
> on.. The author of the first patch is no longer at Microchip, so there's
> probably gonna be some bounces on the series. The remainder of the
> patches got sent in by a user, and, other than one patch, I just wrote
> commit messages for those that were missing them and rebased the series
> on top of mainline.
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
Thanks!
[1/6] spi: microchip-core: fix the issues in the isr
commit: 502a582b8dd897d9282db47c0911d5320ef2e6b9
[2/6] spi: microchip-core: defer asserting chip select until just before write to TX FIFO
commit: 22fd98c107c792e35db7abe45298bc3a29bf4723
[3/6] spi: microchip-core: only disable SPI controller when register value change requires it
commit: de9850b5c606b754dd7861678d6e2874b96b04f8
[4/6] spi: microchip-core: fix init function not setting the master and motorola modes
commit: 3a5e76283672efddf47cea39ccfe9f5735cc91d5
[5/6] spi: microchip-core: ensure TX and RX FIFOs are empty at start of a transfer
commit: 9cf71eb0faef4bff01df4264841b8465382d7927
[6/6] spi: microchip-core: add support for word sizes of 1 to 32 bits
commit: 87232ea8a5caf8d050f8ea7acd210a2cfcbe6309
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-07-16 13:26 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-15 11:13 [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Conor Dooley
2024-07-15 11:13 ` [PATCH v1 1/6] spi: microchip-core: fix the issues in the isr Conor Dooley
2024-07-15 11:13 ` [PATCH v1 2/6] spi: microchip-core: defer asserting chip select until just before write to TX FIFO Conor Dooley
2024-07-15 11:13 ` [PATCH v1 3/6] spi: microchip-core: only disable SPI controller when register value change requires it Conor Dooley
2024-07-15 11:13 ` [PATCH v1 4/6] spi: microchip-core: fix init function not setting the master and motorola modes Conor Dooley
2024-07-15 11:13 ` [PATCH v1 5/6] spi: microchip-core: ensure TX and RX FIFOs are empty at start of a transfer Conor Dooley
2024-07-15 11:13 ` [PATCH v1 6/6] spi: microchip-core: add support for word sizes of 1 to 32 bits Conor Dooley
2024-07-16 13:26 ` [PATCH v1 0/6] spi-microchip-core fixes & variable word size support Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).