@@ -316,26 +316,44 @@ static void bcm_iproc_i2c_slave_init(
316316 iproc_i2c_wr_reg (iproc_i2c , IE_OFFSET , val );
317317}
318318
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 )
321321{
322322 u32 val ;
323+ bool recover = false;
323324
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+ }
328348
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 ) {
334350 /* re-initialize i2c for recovery */
335351 bcm_iproc_i2c_enable_disable (iproc_i2c , false);
336352 bcm_iproc_i2c_slave_init (iproc_i2c , true);
337353 bcm_iproc_i2c_enable_disable (iproc_i2c , true);
338354 }
355+
356+ return recover ;
339357}
340358
341359static 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,
420438 u32 val ;
421439 u8 value ;
422440
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- }
465441
466442 if (status & BIT (IS_S_TX_UNDERRUN_SHIFT )) {
467443 iproc_i2c -> tx_underrun ++ ;
@@ -493,8 +469,9 @@ static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
493469 * less than PKT_LENGTH bytes were output on the SMBUS
494470 */
495471 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 );
498475
499476 /* End of SMBUS for Master Read */
500477 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,
515492 BIT (IS_S_START_BUSY_SHIFT ));
516493 }
517494
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+ }
521538
522539 return true;
523540}
0 commit comments