75
75
76
76
#define REG_CONTROL (0x00)
77
77
#define REG_FRAME_SIZE (0x04)
78
+ #define FRAME_SIZE_MASK GENMASK(5, 0)
78
79
#define REG_STATUS (0x08)
79
80
#define REG_INT_CLEAR (0x0c)
80
81
#define REG_RX_DATA (0x10)
89
90
#define REG_RIS (0x24)
90
91
#define REG_CONTROL2 (0x28)
91
92
#define REG_COMMAND (0x2c)
93
+ #define COMMAND_CLRFRAMECNT BIT(4)
92
94
#define REG_PKTSIZE (0x30)
93
95
#define REG_CMD_SIZE (0x34)
94
96
#define REG_HWSTATUS (0x38)
@@ -149,62 +151,59 @@ static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi)
149
151
150
152
static void mchp_corespi_enable_ints (struct mchp_corespi * spi )
151
153
{
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 );
160
155
161
- control |= CONTROL_ENABLE ;
156
+ control |= INT_ENABLE_MASK ;
162
157
mchp_corespi_write (spi , REG_CONTROL , control );
163
158
}
164
159
165
160
static void mchp_corespi_disable_ints (struct mchp_corespi * spi )
166
161
{
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 );
174
163
175
- control |= CONTROL_ENABLE ;
164
+ control &= ~ INT_ENABLE_MASK ;
176
165
mchp_corespi_write (spi , REG_CONTROL , control );
177
166
}
178
167
179
168
static inline void mchp_corespi_set_xfer_size (struct mchp_corespi * spi , int len )
180
169
{
181
170
u32 control ;
182
- u16 lenpart ;
171
+ u32 lenpart ;
172
+ u32 frames = mchp_corespi_read (spi , REG_FRAMESUP );
183
173
184
174
/*
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 .
187
177
*/
188
- mchp_corespi_disable (spi );
178
+ if (frames == len ) {
179
+ mchp_corespi_write (spi , REG_COMMAND , COMMAND_CLRFRAMECNT );
180
+ return ;
181
+ }
189
182
190
183
/*
191
184
* The lower 16 bits of the frame count are stored in the control reg
192
185
* for legacy reasons, but the upper 16 written to a different register:
193
186
* 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.
195
200
*/
196
201
lenpart = len & 0xffff ;
197
-
198
202
control = mchp_corespi_read (spi , REG_CONTROL );
199
203
control &= ~CONTROL_FRAMECNT_MASK ;
200
204
control |= lenpart << CONTROL_FRAMECNT_SHIFT ;
201
205
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 );
208
207
}
209
208
210
209
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)
227
226
228
227
static inline void mchp_corespi_set_framesize (struct mchp_corespi * spi , int bt )
229
228
{
229
+ u32 frame_size = mchp_corespi_read (spi , REG_FRAME_SIZE );
230
230
u32 control ;
231
231
232
+ if ((frame_size & FRAME_SIZE_MASK ) == bt )
233
+ return ;
234
+
232
235
/*
233
236
* Disable the SPI controller. Writes to the frame size have
234
237
* no effect when the controller is enabled.
235
238
*/
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 );
237
242
238
243
mchp_corespi_write (spi , REG_FRAME_SIZE , bt );
239
244
240
- control = mchp_corespi_read (spi , REG_CONTROL );
241
245
control |= CONTROL_ENABLE ;
242
246
mchp_corespi_write (spi , REG_CONTROL , control );
243
247
}
@@ -337,8 +341,6 @@ static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi)
337
341
{
338
342
u32 control ;
339
343
340
- mchp_corespi_disable (spi );
341
-
342
344
control = mchp_corespi_read (spi , REG_CONTROL );
343
345
if (spi -> clk_mode )
344
346
control |= CONTROL_CLKMODE ;
@@ -347,12 +349,12 @@ static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi)
347
349
348
350
mchp_corespi_write (spi , REG_CLK_GEN , spi -> clk_gen );
349
351
mchp_corespi_write (spi , REG_CONTROL , control );
350
- mchp_corespi_write (spi , REG_CONTROL , control | CONTROL_ENABLE );
351
352
}
352
353
353
354
static inline void mchp_corespi_set_mode (struct mchp_corespi * spi , unsigned int mode )
354
355
{
355
- u32 control , mode_val ;
356
+ u32 mode_val ;
357
+ u32 control = mchp_corespi_read (spi , REG_CONTROL );
356
358
357
359
switch (mode & SPI_MODE_X_MASK ) {
358
360
case SPI_MODE_0 :
@@ -370,12 +372,13 @@ static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int
370
372
}
371
373
372
374
/*
373
- * Disable the SPI controller. Writes to the frame size have
375
+ * Disable the SPI controller. Writes to the frame protocol have
374
376
* no effect when the controller is enabled.
375
377
*/
376
- mchp_corespi_disable (spi );
377
378
378
- control = mchp_corespi_read (spi , REG_CONTROL );
379
+ control &= ~CONTROL_ENABLE ;
380
+ mchp_corespi_write (spi , REG_CONTROL , control );
381
+
379
382
control &= ~(SPI_MODE_X_MASK << MODE_X_MASK_SHIFT );
380
383
control |= mode_val ;
381
384
0 commit comments