Skip to content

Commit de9850b

Browse files
swilkins-raymarinebroonie
authored andcommitted
spi: microchip-core: only disable SPI controller when register value change requires it
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: 9ac8d17 ("spi: add support for microchip fpga spi controllers") Signed-off-by: Steve Wilkins <[email protected]> Co-developed-by: Conor Dooley <[email protected]> Signed-off-by: Conor Dooley <[email protected]> Link: https://patch.msgid.link/20240715-depict-twirl-7e592eeabaad@wendy Signed-off-by: Mark Brown <[email protected]>
1 parent 22fd98c commit de9850b

File tree

1 file changed

+41
-38
lines changed

1 file changed

+41
-38
lines changed

drivers/spi/spi-microchip-core.c

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575

7676
#define REG_CONTROL (0x00)
7777
#define REG_FRAME_SIZE (0x04)
78+
#define FRAME_SIZE_MASK GENMASK(5, 0)
7879
#define REG_STATUS (0x08)
7980
#define REG_INT_CLEAR (0x0c)
8081
#define REG_RX_DATA (0x10)
@@ -89,6 +90,7 @@
8990
#define REG_RIS (0x24)
9091
#define REG_CONTROL2 (0x28)
9192
#define REG_COMMAND (0x2c)
93+
#define COMMAND_CLRFRAMECNT BIT(4)
9294
#define REG_PKTSIZE (0x30)
9395
#define REG_CMD_SIZE (0x34)
9496
#define REG_HWSTATUS (0x38)
@@ -149,62 +151,59 @@ static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi)
149151

150152
static void mchp_corespi_enable_ints(struct mchp_corespi *spi)
151153
{
152-
u32 control, mask = INT_ENABLE_MASK;
153-
154-
mchp_corespi_disable(spi);
155-
156-
control = mchp_corespi_read(spi, REG_CONTROL);
157-
158-
control |= mask;
159-
mchp_corespi_write(spi, REG_CONTROL, control);
154+
u32 control = mchp_corespi_read(spi, REG_CONTROL);
160155

161-
control |= CONTROL_ENABLE;
156+
control |= INT_ENABLE_MASK;
162157
mchp_corespi_write(spi, REG_CONTROL, control);
163158
}
164159

165160
static void mchp_corespi_disable_ints(struct mchp_corespi *spi)
166161
{
167-
u32 control, mask = INT_ENABLE_MASK;
168-
169-
mchp_corespi_disable(spi);
170-
171-
control = mchp_corespi_read(spi, REG_CONTROL);
172-
control &= ~mask;
173-
mchp_corespi_write(spi, REG_CONTROL, control);
162+
u32 control = mchp_corespi_read(spi, REG_CONTROL);
174163

175-
control |= CONTROL_ENABLE;
164+
control &= ~INT_ENABLE_MASK;
176165
mchp_corespi_write(spi, REG_CONTROL, control);
177166
}
178167

179168
static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len)
180169
{
181170
u32 control;
182-
u16 lenpart;
171+
u32 lenpart;
172+
u32 frames = mchp_corespi_read(spi, REG_FRAMESUP);
183173

184174
/*
185-
* Disable the SPI controller. Writes to transfer length have
186-
* no effect when the controller is enabled.
175+
* Writing to FRAMECNT in REG_CONTROL will reset the frame count, taking
176+
* a shortcut requires an explicit clear.
187177
*/
188-
mchp_corespi_disable(spi);
178+
if (frames == len) {
179+
mchp_corespi_write(spi, REG_COMMAND, COMMAND_CLRFRAMECNT);
180+
return;
181+
}
189182

190183
/*
191184
* The lower 16 bits of the frame count are stored in the control reg
192185
* for legacy reasons, but the upper 16 written to a different register:
193186
* FRAMESUP. While both the upper and lower bits can be *READ* from the
194-
* FRAMESUP register, writing to the lower 16 bits is a NOP
187+
* FRAMESUP register, writing to the lower 16 bits is (supposedly) a NOP.
188+
*
189+
* The driver used to disable the controller while modifying the frame
190+
* count, and mask off the lower 16 bits of len while writing to
191+
* FRAMES_UP. When the driver was changed to disable the controller as
192+
* infrequently as possible, it was discovered that the logic of
193+
* lenpart = len & 0xffff_0000
194+
* write(REG_FRAMESUP, lenpart)
195+
* would actually write zeros into the lower 16 bits on an mpfs250t-es,
196+
* despite documentation stating these bits were read-only.
197+
* Writing len unmasked into FRAMES_UP ensures those bits aren't zeroed
198+
* on an mpfs250t-es and will be a NOP for the lower 16 bits on hardware
199+
* that matches the documentation.
195200
*/
196201
lenpart = len & 0xffff;
197-
198202
control = mchp_corespi_read(spi, REG_CONTROL);
199203
control &= ~CONTROL_FRAMECNT_MASK;
200204
control |= lenpart << CONTROL_FRAMECNT_SHIFT;
201205
mchp_corespi_write(spi, REG_CONTROL, control);
202-
203-
lenpart = len & 0xffff0000;
204-
mchp_corespi_write(spi, REG_FRAMESUP, lenpart);
205-
206-
control |= CONTROL_ENABLE;
207-
mchp_corespi_write(spi, REG_CONTROL, control);
206+
mchp_corespi_write(spi, REG_FRAMESUP, len);
208207
}
209208

210209
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)
227226

228227
static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt)
229228
{
229+
u32 frame_size = mchp_corespi_read(spi, REG_FRAME_SIZE);
230230
u32 control;
231231

232+
if ((frame_size & FRAME_SIZE_MASK) == bt)
233+
return;
234+
232235
/*
233236
* Disable the SPI controller. Writes to the frame size have
234237
* no effect when the controller is enabled.
235238
*/
236-
mchp_corespi_disable(spi);
239+
control = mchp_corespi_read(spi, REG_CONTROL);
240+
control &= ~CONTROL_ENABLE;
241+
mchp_corespi_write(spi, REG_CONTROL, control);
237242

238243
mchp_corespi_write(spi, REG_FRAME_SIZE, bt);
239244

240-
control = mchp_corespi_read(spi, REG_CONTROL);
241245
control |= CONTROL_ENABLE;
242246
mchp_corespi_write(spi, REG_CONTROL, control);
243247
}
@@ -337,8 +341,6 @@ static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi)
337341
{
338342
u32 control;
339343

340-
mchp_corespi_disable(spi);
341-
342344
control = mchp_corespi_read(spi, REG_CONTROL);
343345
if (spi->clk_mode)
344346
control |= CONTROL_CLKMODE;
@@ -347,12 +349,12 @@ static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi)
347349

348350
mchp_corespi_write(spi, REG_CLK_GEN, spi->clk_gen);
349351
mchp_corespi_write(spi, REG_CONTROL, control);
350-
mchp_corespi_write(spi, REG_CONTROL, control | CONTROL_ENABLE);
351352
}
352353

353354
static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int mode)
354355
{
355-
u32 control, mode_val;
356+
u32 mode_val;
357+
u32 control = mchp_corespi_read(spi, REG_CONTROL);
356358

357359
switch (mode & SPI_MODE_X_MASK) {
358360
case SPI_MODE_0:
@@ -370,12 +372,13 @@ static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int
370372
}
371373

372374
/*
373-
* Disable the SPI controller. Writes to the frame size have
375+
* Disable the SPI controller. Writes to the frame protocol have
374376
* no effect when the controller is enabled.
375377
*/
376-
mchp_corespi_disable(spi);
377378

378-
control = mchp_corespi_read(spi, REG_CONTROL);
379+
control &= ~CONTROL_ENABLE;
380+
mchp_corespi_write(spi, REG_CONTROL, control);
381+
379382
control &= ~(SPI_MODE_X_MASK << MODE_X_MASK_SHIFT);
380383
control |= mode_val;
381384

0 commit comments

Comments
 (0)