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}
@@ -334,8 +338,6 @@ static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi)
334338{
335339 u32 control ;
336340
337- mchp_corespi_disable (spi );
338-
339341 control = mchp_corespi_read (spi , REG_CONTROL );
340342 if (spi -> clk_mode )
341343 control |= CONTROL_CLKMODE ;
@@ -344,12 +346,12 @@ static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi)
344346
345347 mchp_corespi_write (spi , REG_CLK_GEN , spi -> clk_gen );
346348 mchp_corespi_write (spi , REG_CONTROL , control );
347- mchp_corespi_write (spi , REG_CONTROL , control | CONTROL_ENABLE );
348349}
349350
350351static inline void mchp_corespi_set_mode (struct mchp_corespi * spi , unsigned int mode )
351352{
352- u32 control , mode_val ;
353+ u32 mode_val ;
354+ u32 control = mchp_corespi_read (spi , REG_CONTROL );
353355
354356 switch (mode & SPI_MODE_X_MASK ) {
355357 case SPI_MODE_0 :
@@ -367,12 +369,13 @@ static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int
367369 }
368370
369371 /*
370- * Disable the SPI controller. Writes to the frame size have
372+ * Disable the SPI controller. Writes to the frame protocol have
371373 * no effect when the controller is enabled.
372374 */
373- mchp_corespi_disable (spi );
374375
375- control = mchp_corespi_read (spi , REG_CONTROL );
376+ control &= ~CONTROL_ENABLE ;
377+ mchp_corespi_write (spi , REG_CONTROL , control );
378+
376379 control &= ~(SPI_MODE_X_MASK << MODE_X_MASK_SHIFT );
377380 control |= mode_val ;
378381
0 commit comments