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)
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
150152static 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
165160static 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
179168static 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
210209static 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
228227static 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
353354static 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