@@ -13,6 +13,7 @@ LOG_MODULE_DECLARE(spi_lpspi, CONFIG_SPI_LOG_LEVEL);
13
13
14
14
struct lpspi_driver_data {
15
15
uint8_t word_size_bytes ;
16
+ uint8_t lpspi_op_mode ;
16
17
};
17
18
18
19
static inline uint8_t rx_fifo_cur_len (LPSPI_Type * base )
@@ -192,10 +193,20 @@ static inline void lpspi_handle_tx_irq(const struct device *dev)
192
193
{
193
194
LPSPI_Type * base = (LPSPI_Type * )DEVICE_MMIO_NAMED_GET (dev , reg_base );
194
195
struct lpspi_data * data = dev -> data ;
196
+ struct lpspi_driver_data * lpspi_data = (struct lpspi_driver_data * )data -> driver_data ;
197
+ uint8_t op_mode = lpspi_data -> lpspi_op_mode ;
195
198
struct spi_context * ctx = & data -> ctx ;
199
+ uint32_t status_flags = base -> SR ;
196
200
197
201
base -> SR = LPSPI_SR_TDF_MASK ;
198
202
203
+ if (op_mode == SPI_OP_MODE_SLAVE && (status_flags & LPSPI_SR_TEF_MASK )) {
204
+ /* handling err051588 */
205
+ base -> SR = LPSPI_SR_TEF_MASK ;
206
+ /* workaround is to reset the transmit fifo before writing any new data */
207
+ base -> CR |= LPSPI_CR_RTF_MASK ;
208
+ }
209
+
199
210
/* If we receive a TX interrupt but no more data is available,
200
211
* we can be sure that all data has been written to the fifo.
201
212
* Disable the interrupt to signal that we are done.
@@ -219,8 +230,8 @@ static inline void lpspi_end_xfer(const struct device *dev)
219
230
NVIC_ClearPendingIRQ (config -> irqn );
220
231
if (!(ctx -> config -> operation & SPI_HOLD_ON_CS )) {
221
232
base -> TCR &= ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK );
233
+ /* don't need to wait for TCR since we are at end of xfer + in IRQ context */
222
234
}
223
- lpspi_wait_tx_fifo_empty (dev );
224
235
spi_context_cs_control (ctx , false);
225
236
spi_context_release (& data -> ctx , 0 );
226
237
}
@@ -232,6 +243,7 @@ static void lpspi_isr(const struct device *dev)
232
243
struct lpspi_data * data = dev -> data ;
233
244
struct lpspi_driver_data * lpspi_data = (struct lpspi_driver_data * )data -> driver_data ;
234
245
uint8_t word_size_bytes = lpspi_data -> word_size_bytes ;
246
+ uint8_t op_mode = lpspi_data -> lpspi_op_mode ;
235
247
struct spi_context * ctx = & data -> ctx ;
236
248
uint32_t status_flags = base -> SR ;
237
249
@@ -253,9 +265,9 @@ static void lpspi_isr(const struct device *dev)
253
265
}
254
266
255
267
/* the lpspi v1 has an errata where it doesn't clock the last bit
256
- * in continuous mode until you write the TCR
268
+ * in continuous master mode until you write the TCR
257
269
*/
258
- bool likely_stalling_v1 = data -> major_version < 2 &&
270
+ bool likely_stalling_v1 = ( data -> major_version < 2 ) && ( op_mode == SPI_OP_MODE_MASTER ) &&
259
271
(DIV_ROUND_UP (spi_context_rx_len_left (ctx , word_size_bytes ), word_size_bytes ) == 1 );
260
272
261
273
if (spi_context_rx_on (ctx )) {
@@ -313,14 +325,35 @@ static void lpspi_isr(const struct device *dev)
313
325
}
314
326
}
315
327
328
+ static void lpspi_master_setup_native_cs (const struct device * dev , const struct spi_config * spi_cfg )
329
+ {
330
+ LPSPI_Type * base = (LPSPI_Type * )DEVICE_MMIO_NAMED_GET (dev , reg_base );
331
+
332
+ /* keep the chip select asserted until the end of the zephyr xfer by using
333
+ * continunous transfer mode. If SPI_HOLD_ON_CS is requested, we need
334
+ * to also set CONTC in order to continue the previous command to keep CS
335
+ * asserted.
336
+ */
337
+ if (spi_cfg -> operation & SPI_HOLD_ON_CS || base -> TCR & LPSPI_TCR_CONTC_MASK ) {
338
+ base -> TCR |= LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK ;
339
+ } else {
340
+ base -> TCR |= LPSPI_TCR_CONT_MASK ;
341
+ }
342
+
343
+ /* tcr is written to tx fifo */
344
+ lpspi_wait_tx_fifo_empty (dev );
345
+ }
346
+
316
347
static int transceive (const struct device * dev , const struct spi_config * spi_cfg ,
317
348
const struct spi_buf_set * tx_bufs , const struct spi_buf_set * rx_bufs ,
318
349
bool asynchronous , spi_callback_t cb , void * userdata )
319
350
{
320
351
LPSPI_Type * base = (LPSPI_Type * )DEVICE_MMIO_NAMED_GET (dev , reg_base );
352
+ const struct lpspi_config * config = dev -> config ;
321
353
struct lpspi_data * data = dev -> data ;
322
354
struct lpspi_driver_data * lpspi_data = (struct lpspi_driver_data * )data -> driver_data ;
323
355
struct spi_context * ctx = & data -> ctx ;
356
+ uint8_t op_mode = SPI_OP_MODE_GET (spi_cfg -> operation );
324
357
int ret = 0 ;
325
358
326
359
spi_context_lock (& data -> ctx , asynchronous , cb , userdata , spi_cfg );
@@ -333,37 +366,47 @@ static int transceive(const struct device *dev, const struct spi_config *spi_cfg
333
366
goto error ;
334
367
}
335
368
369
+ if (op_mode == SPI_OP_MODE_SLAVE && !(spi_cfg -> operation & SPI_MODE_CPHA )) {
370
+ LOG_ERR ("CPHA=0 not supported with LPSPI peripheral mode" );
371
+ ret = - ENOTSUP ;
372
+ goto error ;
373
+ }
374
+
336
375
spi_context_buffers_setup (ctx , tx_bufs , rx_bufs , lpspi_data -> word_size_bytes );
376
+ lpspi_data -> lpspi_op_mode = op_mode ;
337
377
338
378
ret = lpspi_configure (dev , spi_cfg );
339
379
if (ret ) {
340
380
goto error ;
341
381
}
342
382
343
- base -> CR |= LPSPI_CR_RTF_MASK | LPSPI_CR_RRF_MASK ; /* flush fifos */
344
- base -> IER = 0 ; /* disable all interrupts */
345
- base -> FCR = 0 ; /* set watermarks to 0 */
383
+ base -> CR |= LPSPI_CR_RRF_MASK ;
384
+ base -> IER = 0 ;
346
385
base -> SR |= LPSPI_INTERRUPT_BITS ;
347
386
348
387
LOG_DBG ("Starting LPSPI transfer" );
349
388
spi_context_cs_control (ctx , true);
350
389
351
- base -> CR |= LPSPI_CR_MEN_MASK ;
352
-
353
- /* keep the chip select asserted until the end of the zephyr xfer by using
354
- * continunous transfer mode. If SPI_HOLD_ON_CS is requested, we need
355
- * to also set CONTC in order to continue the previous command to keep CS
356
- * asserted.
357
- */
358
- if (spi_cfg -> operation & SPI_HOLD_ON_CS || base -> TCR & LPSPI_TCR_CONTC_MASK ) {
359
- base -> TCR |= LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK ;
390
+ if (op_mode == SPI_OP_MODE_MASTER ) {
391
+ /* set watermarks to 0 so get tx interrupt when fifo empty
392
+ * and rx interrupt when any data received
393
+ */
394
+ base -> FCR = 0 ;
360
395
} else {
361
- base -> TCR |= LPSPI_TCR_CONT_MASK ;
396
+ /* set watermarks so that we are as responsive to master as possible and don't
397
+ * miss any communication. This means RX interrupt at 0 so that if we ever
398
+ * get any data, we get interrupt and handle immediately, and TX interrupt
399
+ * to one less than the max of the fifo (-2 of size) so that we have as much
400
+ * data ready to send to master as possible at any time
401
+ */
402
+ base -> FCR = LPSPI_FCR_TXWATER (config -> tx_fifo_size - 1 );
403
+ base -> CFGR1 |= LPSPI_CFGR1_AUTOPCS_MASK ;
362
404
}
363
- /* tcr is written to tx fifo */
364
- ret = lpspi_wait_tx_fifo_empty (dev );
365
- if (ret ) {
366
- return ret ;
405
+
406
+ base -> CR |= LPSPI_CR_MEN_MASK ;
407
+
408
+ if (op_mode == SPI_OP_MODE_MASTER ) {
409
+ lpspi_master_setup_native_cs (dev , spi_cfg );
367
410
}
368
411
369
412
/* start the transfer sequence which are handled by irqs */
0 commit comments