@@ -129,6 +129,7 @@ struct sh_mobile_i2c_data {
129129 int sr ;
130130 bool send_stop ;
131131 bool stop_after_dma ;
132+ bool atomic_xfer ;
132133
133134 struct resource * res ;
134135 struct dma_chan * dma_tx ;
@@ -330,13 +331,15 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, enum sh_mobile_i2c_op
330331 ret = iic_rd (pd , ICDR );
331332 break ;
332333 case OP_RX_STOP : /* enable DTE interrupt, issue stop */
333- iic_wr (pd , ICIC ,
334- ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE );
334+ if (!pd -> atomic_xfer )
335+ iic_wr (pd , ICIC ,
336+ ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE );
335337 iic_wr (pd , ICCR , ICCR_ICE | ICCR_RACK );
336338 break ;
337339 case OP_RX_STOP_DATA : /* enable DTE interrupt, read data, issue stop */
338- iic_wr (pd , ICIC ,
339- ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE );
340+ if (!pd -> atomic_xfer )
341+ iic_wr (pd , ICIC ,
342+ ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE );
340343 ret = iic_rd (pd , ICDR );
341344 iic_wr (pd , ICCR , ICCR_ICE | ICCR_RACK );
342345 break ;
@@ -429,7 +432,8 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
429432
430433 if (wakeup ) {
431434 pd -> sr |= SW_DONE ;
432- wake_up (& pd -> wait );
435+ if (!pd -> atomic_xfer )
436+ wake_up (& pd -> wait );
433437 }
434438
435439 /* defeat write posting to avoid spurious WAIT interrupts */
@@ -581,6 +585,9 @@ static void start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
581585 pd -> pos = -1 ;
582586 pd -> sr = 0 ;
583587
588+ if (pd -> atomic_xfer )
589+ return ;
590+
584591 pd -> dma_buf = i2c_get_dma_safe_msg_buf (pd -> msg , 8 );
585592 if (pd -> dma_buf )
586593 sh_mobile_i2c_xfer_dma (pd );
@@ -637,15 +644,13 @@ static int poll_busy(struct sh_mobile_i2c_data *pd)
637644 return i ? 0 : - ETIMEDOUT ;
638645}
639646
640- static int sh_mobile_i2c_xfer (struct i2c_adapter * adapter ,
641- struct i2c_msg * msgs ,
642- int num )
647+ static int sh_mobile_xfer (struct sh_mobile_i2c_data * pd ,
648+ struct i2c_msg * msgs , int num )
643649{
644- struct sh_mobile_i2c_data * pd = i2c_get_adapdata (adapter );
645650 struct i2c_msg * msg ;
646651 int err = 0 ;
647652 int i ;
648- long timeout ;
653+ long time_left ;
649654
650655 /* Wake up device and enable clock */
651656 pm_runtime_get_sync (pd -> dev );
@@ -662,15 +667,35 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
662667 if (do_start )
663668 i2c_op (pd , OP_START );
664669
665- /* The interrupt handler takes care of the rest... */
666- timeout = wait_event_timeout (pd -> wait ,
667- pd -> sr & (ICSR_TACK | SW_DONE ),
668- adapter -> timeout );
669-
670- /* 'stop_after_dma' tells if DMA transfer was complete */
671- i2c_put_dma_safe_msg_buf (pd -> dma_buf , pd -> msg , pd -> stop_after_dma );
670+ if (pd -> atomic_xfer ) {
671+ unsigned long j = jiffies + pd -> adap .timeout ;
672+
673+ time_left = time_before_eq (jiffies , j );
674+ while (time_left &&
675+ !(pd -> sr & (ICSR_TACK | SW_DONE ))) {
676+ unsigned char sr = iic_rd (pd , ICSR );
677+
678+ if (sr & (ICSR_AL | ICSR_TACK |
679+ ICSR_WAIT | ICSR_DTE )) {
680+ sh_mobile_i2c_isr (0 , pd );
681+ udelay (150 );
682+ } else {
683+ cpu_relax ();
684+ }
685+ time_left = time_before_eq (jiffies , j );
686+ }
687+ } else {
688+ /* The interrupt handler takes care of the rest... */
689+ time_left = wait_event_timeout (pd -> wait ,
690+ pd -> sr & (ICSR_TACK | SW_DONE ),
691+ pd -> adap .timeout );
692+
693+ /* 'stop_after_dma' tells if DMA xfer was complete */
694+ i2c_put_dma_safe_msg_buf (pd -> dma_buf , pd -> msg ,
695+ pd -> stop_after_dma );
696+ }
672697
673- if (!timeout ) {
698+ if (!time_left ) {
674699 dev_err (pd -> dev , "Transfer request timed out\n" );
675700 if (pd -> dma_direction != DMA_NONE )
676701 sh_mobile_i2c_cleanup_dma (pd );
@@ -696,14 +721,35 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
696721 return err ?: num ;
697722}
698723
724+ static int sh_mobile_i2c_xfer (struct i2c_adapter * adapter ,
725+ struct i2c_msg * msgs ,
726+ int num )
727+ {
728+ struct sh_mobile_i2c_data * pd = i2c_get_adapdata (adapter );
729+
730+ pd -> atomic_xfer = false;
731+ return sh_mobile_xfer (pd , msgs , num );
732+ }
733+
734+ static int sh_mobile_i2c_xfer_atomic (struct i2c_adapter * adapter ,
735+ struct i2c_msg * msgs ,
736+ int num )
737+ {
738+ struct sh_mobile_i2c_data * pd = i2c_get_adapdata (adapter );
739+
740+ pd -> atomic_xfer = true;
741+ return sh_mobile_xfer (pd , msgs , num );
742+ }
743+
699744static u32 sh_mobile_i2c_func (struct i2c_adapter * adapter )
700745{
701746 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING ;
702747}
703748
704749static const struct i2c_algorithm sh_mobile_i2c_algorithm = {
705- .functionality = sh_mobile_i2c_func ,
706- .master_xfer = sh_mobile_i2c_xfer ,
750+ .functionality = sh_mobile_i2c_func ,
751+ .master_xfer = sh_mobile_i2c_xfer ,
752+ .master_xfer_atomic = sh_mobile_i2c_xfer_atomic ,
707753};
708754
709755static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = {
0 commit comments