93
93
* @base: pointer to register struct
94
94
* @dev: device reference
95
95
* @i2c_clk: clock reference for i2c input clock
96
+ * @msg_queue: pointer to the messages requiring sending
96
97
* @buf: pointer to msg buffer for easier use
97
98
* @msg_complete: xfer completion object
98
99
* @adapter: core i2c abstraction
99
100
* @msg_err: error code for completed message
100
101
* @bus_clk_rate: current i2c bus clock rate
101
102
* @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
102
105
* @msg_len: number of bytes transferred in msg
103
106
* @addr: address of the current slave
107
+ * @restart_needed: whether or not a repeated start is required after current message
104
108
*/
105
109
struct mchp_corei2c_dev {
106
110
void __iomem * base ;
107
111
struct device * dev ;
108
112
struct clk * i2c_clk ;
113
+ struct i2c_msg * msg_queue ;
109
114
u8 * buf ;
110
115
struct completion msg_complete ;
111
116
struct i2c_adapter adapter ;
112
117
int msg_err ;
118
+ int total_num ;
119
+ int current_num ;
113
120
u32 bus_clk_rate ;
114
121
u32 isr_status ;
115
122
u16 msg_len ;
116
123
u8 addr ;
124
+ bool restart_needed ;
117
125
};
118
126
119
127
static 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)
222
230
return 0 ;
223
231
}
224
232
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
+
225
274
static irqreturn_t mchp_corei2c_handle_isr (struct mchp_corei2c_dev * idev )
226
275
{
227
276
u32 status = idev -> isr_status ;
@@ -238,19 +287,21 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
238
287
ctrl &= ~CTRL_STA ;
239
288
writeb (idev -> addr , idev -> base + CORE_I2C_DATA );
240
289
writeb (ctrl , idev -> base + CORE_I2C_CTRL );
241
- if (idev -> msg_len == 0 )
242
- finished = true;
243
290
break ;
244
291
case STATUS_M_ARB_LOST :
245
292
idev -> msg_err = - EAGAIN ;
246
293
finished = true;
247
294
break ;
248
295
case STATUS_M_SLAW_ACK :
249
296
case STATUS_M_TX_DATA_ACK :
250
- if (idev -> msg_len > 0 )
297
+ if (idev -> msg_len > 0 ) {
251
298
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
+ }
254
305
break ;
255
306
case STATUS_M_TX_DATA_NACK :
256
307
case STATUS_M_SLAR_NACK :
@@ -287,7 +338,7 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
287
338
mchp_corei2c_stop (idev );
288
339
289
340
if (last_byte || finished )
290
- complete ( & idev -> msg_complete );
341
+ mchp_corei2c_next_msg ( idev );
291
342
292
343
return IRQ_HANDLED ;
293
344
}
@@ -311,21 +362,48 @@ static irqreturn_t mchp_corei2c_isr(int irq, void *_dev)
311
362
return ret ;
312
363
}
313
364
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 )
316
367
{
317
- u8 ctrl ;
368
+ struct mchp_corei2c_dev * idev = i2c_get_adapdata (adap );
369
+ struct i2c_msg * this_msg = msgs ;
318
370
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 ;
319
383
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 ;
323
391
idev -> msg_err = 0 ;
324
392
325
- reinit_completion (& idev -> msg_complete );
393
+ if (idev -> total_num > 1 ) {
394
+ struct i2c_msg * next_msg = msgs + 1 ;
326
395
327
- mchp_corei2c_core_enable (idev );
396
+ idev -> restart_needed = next_msg -> flags & I2C_M_RD ;
397
+ }
328
398
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
+ */
329
407
ctrl = readb (idev -> base + CORE_I2C_CTRL );
330
408
ctrl |= CTRL_STA ;
331
409
writeb (ctrl , idev -> base + CORE_I2C_CTRL );
@@ -335,20 +413,8 @@ static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev,
335
413
if (!time_left )
336
414
return - ETIMEDOUT ;
337
415
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 ;
352
418
353
419
return num ;
354
420
}
0 commit comments