9393 * @base: pointer to register struct
9494 * @dev: device reference
9595 * @i2c_clk: clock reference for i2c input clock
96+ * @msg_queue: pointer to the messages requiring sending
9697 * @buf: pointer to msg buffer for easier use
9798 * @msg_complete: xfer completion object
9899 * @adapter: core i2c abstraction
99100 * @msg_err: error code for completed message
100101 * @bus_clk_rate: current i2c bus clock rate
101102 * @isr_status: cached copy of local ISR status
103+ * @total_num: total number of messages to be sent/received
104+ * @current_num: index of the current message being sent/received
102105 * @msg_len: number of bytes transferred in msg
103106 * @addr: address of the current slave
107+ * @restart_needed: whether or not a repeated start is required after current message
104108 */
105109struct mchp_corei2c_dev {
106110 void __iomem * base ;
107111 struct device * dev ;
108112 struct clk * i2c_clk ;
113+ struct i2c_msg * msg_queue ;
109114 u8 * buf ;
110115 struct completion msg_complete ;
111116 struct i2c_adapter adapter ;
112117 int msg_err ;
118+ int total_num ;
119+ int current_num ;
113120 u32 bus_clk_rate ;
114121 u32 isr_status ;
115122 u16 msg_len ;
116123 u8 addr ;
124+ bool restart_needed ;
117125};
118126
119127static void mchp_corei2c_core_disable (struct mchp_corei2c_dev * idev )
@@ -222,6 +230,47 @@ static int mchp_corei2c_fill_tx(struct mchp_corei2c_dev *idev)
222230 return 0 ;
223231}
224232
233+ static void mchp_corei2c_next_msg (struct mchp_corei2c_dev * idev )
234+ {
235+ struct i2c_msg * this_msg ;
236+ u8 ctrl ;
237+
238+ if (idev -> current_num >= idev -> total_num ) {
239+ complete (& idev -> msg_complete );
240+ return ;
241+ }
242+
243+ /*
244+ * If there's been an error, the isr needs to return control
245+ * to the "main" part of the driver, so as not to keep sending
246+ * messages once it completes and clears the SI bit.
247+ */
248+ if (idev -> msg_err ) {
249+ complete (& idev -> msg_complete );
250+ return ;
251+ }
252+
253+ this_msg = idev -> msg_queue ++ ;
254+
255+ if (idev -> current_num < (idev -> total_num - 1 )) {
256+ struct i2c_msg * next_msg = idev -> msg_queue ;
257+
258+ idev -> restart_needed = next_msg -> flags & I2C_M_RD ;
259+ } else {
260+ idev -> restart_needed = false;
261+ }
262+
263+ idev -> addr = i2c_8bit_addr_from_msg (this_msg );
264+ idev -> msg_len = this_msg -> len ;
265+ idev -> buf = this_msg -> buf ;
266+
267+ ctrl = readb (idev -> base + CORE_I2C_CTRL );
268+ ctrl |= CTRL_STA ;
269+ writeb (ctrl , idev -> base + CORE_I2C_CTRL );
270+
271+ idev -> current_num ++ ;
272+ }
273+
225274static irqreturn_t mchp_corei2c_handle_isr (struct mchp_corei2c_dev * idev )
226275{
227276 u32 status = idev -> isr_status ;
@@ -238,19 +287,21 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
238287 ctrl &= ~CTRL_STA ;
239288 writeb (idev -> addr , idev -> base + CORE_I2C_DATA );
240289 writeb (ctrl , idev -> base + CORE_I2C_CTRL );
241- if (idev -> msg_len == 0 )
242- finished = true;
243290 break ;
244291 case STATUS_M_ARB_LOST :
245292 idev -> msg_err = - EAGAIN ;
246293 finished = true;
247294 break ;
248295 case STATUS_M_SLAW_ACK :
249296 case STATUS_M_TX_DATA_ACK :
250- if (idev -> msg_len > 0 )
297+ if (idev -> msg_len > 0 ) {
251298 mchp_corei2c_fill_tx (idev );
252- else
253- last_byte = true;
299+ } else {
300+ if (idev -> restart_needed )
301+ finished = true;
302+ else
303+ last_byte = true;
304+ }
254305 break ;
255306 case STATUS_M_TX_DATA_NACK :
256307 case STATUS_M_SLAR_NACK :
@@ -287,7 +338,7 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
287338 mchp_corei2c_stop (idev );
288339
289340 if (last_byte || finished )
290- complete ( & idev -> msg_complete );
341+ mchp_corei2c_next_msg ( idev );
291342
292343 return IRQ_HANDLED ;
293344}
@@ -311,21 +362,48 @@ static irqreturn_t mchp_corei2c_isr(int irq, void *_dev)
311362 return ret ;
312363}
313364
314- static int mchp_corei2c_xfer_msg (struct mchp_corei2c_dev * idev ,
315- struct i2c_msg * msg )
365+ static int mchp_corei2c_xfer (struct i2c_adapter * adap , struct i2c_msg * msgs ,
366+ int num )
316367{
317- u8 ctrl ;
368+ struct mchp_corei2c_dev * idev = i2c_get_adapdata (adap );
369+ struct i2c_msg * this_msg = msgs ;
318370 unsigned long time_left ;
371+ u8 ctrl ;
372+
373+ mchp_corei2c_core_enable (idev );
374+
375+ /*
376+ * The isr controls the flow of a transfer, this info needs to be saved
377+ * to a location that it can access the queue information from.
378+ */
379+ idev -> restart_needed = false;
380+ idev -> msg_queue = msgs ;
381+ idev -> total_num = num ;
382+ idev -> current_num = 0 ;
319383
320- idev -> addr = i2c_8bit_addr_from_msg (msg );
321- idev -> msg_len = msg -> len ;
322- idev -> buf = msg -> buf ;
384+ /*
385+ * But the first entry to the isr is triggered by the start in this
386+ * function, so the first message needs to be "dequeued".
387+ */
388+ idev -> addr = i2c_8bit_addr_from_msg (this_msg );
389+ idev -> msg_len = this_msg -> len ;
390+ idev -> buf = this_msg -> buf ;
323391 idev -> msg_err = 0 ;
324392
325- reinit_completion (& idev -> msg_complete );
393+ if (idev -> total_num > 1 ) {
394+ struct i2c_msg * next_msg = msgs + 1 ;
326395
327- mchp_corei2c_core_enable (idev );
396+ idev -> restart_needed = next_msg -> flags & I2C_M_RD ;
397+ }
328398
399+ idev -> current_num ++ ;
400+ idev -> msg_queue ++ ;
401+
402+ reinit_completion (& idev -> msg_complete );
403+
404+ /*
405+ * Send the first start to pass control to the isr
406+ */
329407 ctrl = readb (idev -> base + CORE_I2C_CTRL );
330408 ctrl |= CTRL_STA ;
331409 writeb (ctrl , idev -> base + CORE_I2C_CTRL );
@@ -335,20 +413,8 @@ static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev,
335413 if (!time_left )
336414 return - ETIMEDOUT ;
337415
338- return idev -> msg_err ;
339- }
340-
341- static int mchp_corei2c_xfer (struct i2c_adapter * adap , struct i2c_msg * msgs ,
342- int num )
343- {
344- struct mchp_corei2c_dev * idev = i2c_get_adapdata (adap );
345- int i , ret ;
346-
347- for (i = 0 ; i < num ; i ++ ) {
348- ret = mchp_corei2c_xfer_msg (idev , msgs ++ );
349- if (ret )
350- return ret ;
351- }
416+ if (idev -> msg_err )
417+ return idev -> msg_err ;
352418
353419 return num ;
354420}
0 commit comments