@@ -316,26 +316,44 @@ static void bcm_iproc_i2c_slave_init(
316
316
iproc_i2c_wr_reg (iproc_i2c , IE_OFFSET , val );
317
317
}
318
318
319
- static void bcm_iproc_i2c_check_slave_status (
320
- struct bcm_iproc_i2c_dev * iproc_i2c )
319
+ static bool bcm_iproc_i2c_check_slave_status
320
+ ( struct bcm_iproc_i2c_dev * iproc_i2c , u32 status )
321
321
{
322
322
u32 val ;
323
+ bool recover = false;
323
324
324
- val = iproc_i2c_rd_reg (iproc_i2c , S_CMD_OFFSET );
325
- /* status is valid only when START_BUSY is cleared after it was set */
326
- if (val & BIT (S_CMD_START_BUSY_SHIFT ))
327
- return ;
325
+ /* check slave transmit status only if slave is transmitting */
326
+ if (!iproc_i2c -> slave_rx_only ) {
327
+ val = iproc_i2c_rd_reg (iproc_i2c , S_CMD_OFFSET );
328
+ /* status is valid only when START_BUSY is cleared */
329
+ if (!(val & BIT (S_CMD_START_BUSY_SHIFT ))) {
330
+ val = (val >> S_CMD_STATUS_SHIFT ) & S_CMD_STATUS_MASK ;
331
+ if (val == S_CMD_STATUS_TIMEOUT ||
332
+ val == S_CMD_STATUS_MASTER_ABORT ) {
333
+ dev_warn (iproc_i2c -> device ,
334
+ (val == S_CMD_STATUS_TIMEOUT ) ?
335
+ "slave random stretch time timeout\n" :
336
+ "Master aborted read transaction\n" );
337
+ recover = true;
338
+ }
339
+ }
340
+ }
341
+
342
+ /* RX_EVENT is not valid when START_BUSY is set */
343
+ if ((status & BIT (IS_S_RX_EVENT_SHIFT )) &&
344
+ (status & BIT (IS_S_START_BUSY_SHIFT ))) {
345
+ dev_warn (iproc_i2c -> device , "Slave aborted read transaction\n" );
346
+ recover = true;
347
+ }
328
348
329
- val = (val >> S_CMD_STATUS_SHIFT ) & S_CMD_STATUS_MASK ;
330
- if (val == S_CMD_STATUS_TIMEOUT || val == S_CMD_STATUS_MASTER_ABORT ) {
331
- dev_err (iproc_i2c -> device , (val == S_CMD_STATUS_TIMEOUT ) ?
332
- "slave random stretch time timeout\n" :
333
- "Master aborted read transaction\n" );
349
+ if (recover ) {
334
350
/* re-initialize i2c for recovery */
335
351
bcm_iproc_i2c_enable_disable (iproc_i2c , false);
336
352
bcm_iproc_i2c_slave_init (iproc_i2c , true);
337
353
bcm_iproc_i2c_enable_disable (iproc_i2c , true);
338
354
}
355
+
356
+ return recover ;
339
357
}
340
358
341
359
static void bcm_iproc_i2c_slave_read (struct bcm_iproc_i2c_dev * iproc_i2c )
@@ -420,48 +438,6 @@ static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
420
438
u32 val ;
421
439
u8 value ;
422
440
423
- /*
424
- * Slave events in case of master-write, master-write-read and,
425
- * master-read
426
- *
427
- * Master-write : only IS_S_RX_EVENT_SHIFT event
428
- * Master-write-read: both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT
429
- * events
430
- * Master-read : both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT
431
- * events or only IS_S_RD_EVENT_SHIFT
432
- *
433
- * iproc has a slave rx fifo size of 64 bytes. Rx fifo full interrupt
434
- * (IS_S_RX_FIFO_FULL_SHIFT) will be generated when RX fifo becomes
435
- * full. This can happen if Master issues write requests of more than
436
- * 64 bytes.
437
- */
438
- if (status & BIT (IS_S_RX_EVENT_SHIFT ) ||
439
- status & BIT (IS_S_RD_EVENT_SHIFT ) ||
440
- status & BIT (IS_S_RX_FIFO_FULL_SHIFT )) {
441
- /* disable slave interrupts */
442
- val = iproc_i2c_rd_reg (iproc_i2c , IE_OFFSET );
443
- val &= ~iproc_i2c -> slave_int_mask ;
444
- iproc_i2c_wr_reg (iproc_i2c , IE_OFFSET , val );
445
-
446
- if (status & BIT (IS_S_RD_EVENT_SHIFT ))
447
- /* Master-write-read request */
448
- iproc_i2c -> slave_rx_only = false;
449
- else
450
- /* Master-write request only */
451
- iproc_i2c -> slave_rx_only = true;
452
-
453
- /* schedule tasklet to read data later */
454
- tasklet_schedule (& iproc_i2c -> slave_rx_tasklet );
455
-
456
- /*
457
- * clear only IS_S_RX_EVENT_SHIFT and
458
- * IS_S_RX_FIFO_FULL_SHIFT interrupt.
459
- */
460
- val = BIT (IS_S_RX_EVENT_SHIFT );
461
- if (status & BIT (IS_S_RX_FIFO_FULL_SHIFT ))
462
- val |= BIT (IS_S_RX_FIFO_FULL_SHIFT );
463
- iproc_i2c_wr_reg (iproc_i2c , IS_OFFSET , val );
464
- }
465
441
466
442
if (status & BIT (IS_S_TX_UNDERRUN_SHIFT )) {
467
443
iproc_i2c -> tx_underrun ++ ;
@@ -493,8 +469,9 @@ static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
493
469
* less than PKT_LENGTH bytes were output on the SMBUS
494
470
*/
495
471
iproc_i2c -> slave_int_mask &= ~BIT (IE_S_TX_UNDERRUN_SHIFT );
496
- iproc_i2c_wr_reg (iproc_i2c , IE_OFFSET ,
497
- iproc_i2c -> slave_int_mask );
472
+ val = iproc_i2c_rd_reg (iproc_i2c , IE_OFFSET );
473
+ val &= ~BIT (IE_S_TX_UNDERRUN_SHIFT );
474
+ iproc_i2c_wr_reg (iproc_i2c , IE_OFFSET , val );
498
475
499
476
/* End of SMBUS for Master Read */
500
477
val = BIT (S_TX_WR_STATUS_SHIFT );
@@ -515,9 +492,49 @@ static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
515
492
BIT (IS_S_START_BUSY_SHIFT ));
516
493
}
517
494
518
- /* check slave transmit status only if slave is transmitting */
519
- if (!iproc_i2c -> slave_rx_only )
520
- bcm_iproc_i2c_check_slave_status (iproc_i2c );
495
+ /* if the controller has been reset, immediately return from the ISR */
496
+ if (bcm_iproc_i2c_check_slave_status (iproc_i2c , status ))
497
+ return true;
498
+
499
+ /*
500
+ * Slave events in case of master-write, master-write-read and,
501
+ * master-read
502
+ *
503
+ * Master-write : only IS_S_RX_EVENT_SHIFT event
504
+ * Master-write-read: both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT
505
+ * events
506
+ * Master-read : both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT
507
+ * events or only IS_S_RD_EVENT_SHIFT
508
+ *
509
+ * iproc has a slave rx fifo size of 64 bytes. Rx fifo full interrupt
510
+ * (IS_S_RX_FIFO_FULL_SHIFT) will be generated when RX fifo becomes
511
+ * full. This can happen if Master issues write requests of more than
512
+ * 64 bytes.
513
+ */
514
+ if (status & BIT (IS_S_RX_EVENT_SHIFT ) ||
515
+ status & BIT (IS_S_RD_EVENT_SHIFT ) ||
516
+ status & BIT (IS_S_RX_FIFO_FULL_SHIFT )) {
517
+ /* disable slave interrupts */
518
+ val = iproc_i2c_rd_reg (iproc_i2c , IE_OFFSET );
519
+ val &= ~iproc_i2c -> slave_int_mask ;
520
+ iproc_i2c_wr_reg (iproc_i2c , IE_OFFSET , val );
521
+
522
+ if (status & BIT (IS_S_RD_EVENT_SHIFT ))
523
+ /* Master-write-read request */
524
+ iproc_i2c -> slave_rx_only = false;
525
+ else
526
+ /* Master-write request only */
527
+ iproc_i2c -> slave_rx_only = true;
528
+
529
+ /* schedule tasklet to read data later */
530
+ tasklet_schedule (& iproc_i2c -> slave_rx_tasklet );
531
+
532
+ /* clear IS_S_RX_FIFO_FULL_SHIFT interrupt */
533
+ if (status & BIT (IS_S_RX_FIFO_FULL_SHIFT )) {
534
+ val = BIT (IS_S_RX_FIFO_FULL_SHIFT );
535
+ iproc_i2c_wr_reg (iproc_i2c , IS_OFFSET , val );
536
+ }
537
+ }
521
538
522
539
return true;
523
540
}
0 commit comments