8
8
#include <linux/interrupt.h>
9
9
#include <linux/irqreturn.h>
10
10
#include <linux/pci.h>
11
+ #include <linux/sizes.h>
11
12
12
13
#include "intel-thc-dev.h"
13
14
#include "intel-thc-hw.h"
14
15
15
16
#include "quicki2c-dev.h"
17
+ #include "quicki2c-hid.h"
18
+ #include "quicki2c-protocol.h"
16
19
17
20
/* THC QuickI2C ACPI method to get device properties */
18
21
/* HIDI2C device method */
@@ -210,6 +213,69 @@ static irqreturn_t quicki2c_irq_quick_handler(int irq, void *dev_id)
210
213
return IRQ_WAKE_THREAD ;
211
214
}
212
215
216
+ /**
217
+ * try_recover - Try to recovery THC and Device
218
+ * @qcdev: pointer to quicki2c device
219
+ *
220
+ * This function is a error handler, called when fatal error happens.
221
+ * It try to reset Touch Device and re-configure THC to recovery
222
+ * transferring between Device and THC.
223
+ *
224
+ * Return: 0 if successful or error code on failed
225
+ */
226
+ static int try_recover (struct quicki2c_device * qcdev )
227
+ {
228
+ int ret ;
229
+
230
+ thc_dma_unconfigure (qcdev -> thc_hw );
231
+
232
+ ret = thc_dma_configure (qcdev -> thc_hw );
233
+ if (ret ) {
234
+ dev_err (qcdev -> dev , "Reconfig DMA failed\n" );
235
+ return ret ;
236
+ }
237
+
238
+ return 0 ;
239
+ }
240
+
241
+ static int handle_input_report (struct quicki2c_device * qcdev )
242
+ {
243
+ struct hidi2c_report_packet * pkt = (struct hidi2c_report_packet * )qcdev -> input_buf ;
244
+ int rx_dma_finished = 0 ;
245
+ size_t report_len ;
246
+ int ret ;
247
+
248
+ while (!rx_dma_finished ) {
249
+ ret = thc_rxdma_read (qcdev -> thc_hw , THC_RXDMA2 ,
250
+ (u8 * )pkt , & report_len ,
251
+ & rx_dma_finished );
252
+ if (ret )
253
+ return ret ;
254
+
255
+ if (!pkt -> len ) {
256
+ if (qcdev -> state == QUICKI2C_RESETING ) {
257
+ qcdev -> reset_ack = true;
258
+ wake_up (& qcdev -> reset_ack_wq );
259
+
260
+ qcdev -> state = QUICKI2C_RESETED ;
261
+ } else {
262
+ dev_warn (qcdev -> dev , "unexpected DIR happen\n" );
263
+ }
264
+
265
+ continue ;
266
+ }
267
+
268
+ /* discard samples before driver probe complete */
269
+ if (qcdev -> state != QUICKI2C_ENABLED )
270
+ continue ;
271
+
272
+ quicki2c_hid_send_report (qcdev , pkt -> data ,
273
+ HIDI2C_DATA_LEN (le16_to_cpu (pkt -> len )));
274
+ }
275
+
276
+ return 0 ;
277
+ }
278
+
213
279
/**
214
280
* quicki2c_irq_thread_handler - IRQ thread handler of quicki2c driver
215
281
*
@@ -221,15 +287,33 @@ static irqreturn_t quicki2c_irq_quick_handler(int irq, void *dev_id)
221
287
static irqreturn_t quicki2c_irq_thread_handler (int irq , void * dev_id )
222
288
{
223
289
struct quicki2c_device * qcdev = dev_id ;
290
+ int err_recover = 0 ;
224
291
int int_mask ;
225
292
226
293
if (qcdev -> state == QUICKI2C_DISABLED )
227
294
return IRQ_HANDLED ;
228
295
229
296
int_mask = thc_interrupt_handler (qcdev -> thc_hw );
230
297
298
+ if (int_mask & BIT (THC_FATAL_ERR_INT ) || int_mask & BIT (THC_TXN_ERR_INT ) ||
299
+ int_mask & BIT (THC_UNKNOWN_INT )) {
300
+ err_recover = 1 ;
301
+ goto exit ;
302
+ }
303
+
304
+ if (int_mask & BIT (THC_RXDMA2_INT )) {
305
+ err_recover = handle_input_report (qcdev );
306
+ if (err_recover )
307
+ goto exit ;
308
+ }
309
+
310
+ exit :
231
311
thc_interrupt_enable (qcdev -> thc_hw , true);
232
312
313
+ if (err_recover )
314
+ if (try_recover (qcdev ))
315
+ qcdev -> state = QUICKI2C_DISABLED ;
316
+
233
317
return IRQ_HANDLED ;
234
318
}
235
319
@@ -260,6 +344,9 @@ static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __io
260
344
qcdev -> pdev = pdev ;
261
345
qcdev -> dev = dev ;
262
346
qcdev -> mem_addr = mem_addr ;
347
+ qcdev -> state = QUICKI2C_DISABLED ;
348
+
349
+ init_waitqueue_head (& qcdev -> reset_ack_wq );
263
350
264
351
/* thc hw init */
265
352
qcdev -> thc_hw = thc_dev_init (qcdev -> dev , qcdev -> mem_addr );
@@ -275,6 +362,10 @@ static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __io
275
362
return ERR_PTR (ret );
276
363
}
277
364
365
+ ret = thc_interrupt_quiesce (qcdev -> thc_hw , true);
366
+ if (ret )
367
+ return ERR_PTR (ret );
368
+
278
369
ret = thc_port_select (qcdev -> thc_hw , THC_PORT_TYPE_I2C );
279
370
if (ret ) {
280
371
dev_err_once (dev , "Failed to select THC port, ret = %d.\n" , ret );
@@ -288,10 +379,14 @@ static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __io
288
379
if (ret )
289
380
return ERR_PTR (ret );
290
381
382
+ thc_int_trigger_type_select (qcdev -> thc_hw , false);
383
+
291
384
thc_interrupt_config (qcdev -> thc_hw );
292
385
293
386
thc_interrupt_enable (qcdev -> thc_hw , true);
294
387
388
+ qcdev -> state = QUICKI2C_INITED ;
389
+
295
390
return qcdev ;
296
391
}
297
392
@@ -305,6 +400,114 @@ static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __io
305
400
static void quicki2c_dev_deinit (struct quicki2c_device * qcdev )
306
401
{
307
402
thc_interrupt_enable (qcdev -> thc_hw , false);
403
+ thc_ltr_unconfig (qcdev -> thc_hw );
404
+
405
+ qcdev -> state = QUICKI2C_DISABLED ;
406
+ }
407
+
408
+ /**
409
+ * quicki2c_dma_init - Configure THC DMA for quicki2c device
410
+ * @qcdev: pointer to the quicki2c device structure
411
+ *
412
+ * This function uses TIC's parameters(such as max input length, max output
413
+ * length) to allocate THC DMA buffers and configure THC DMA engines.
414
+ *
415
+ * Return: 0 if success or error code on failed.
416
+ */
417
+ static int quicki2c_dma_init (struct quicki2c_device * qcdev )
418
+ {
419
+ size_t swdma_max_len ;
420
+ int ret ;
421
+
422
+ swdma_max_len = max (le16_to_cpu (qcdev -> dev_desc .max_input_len ),
423
+ le16_to_cpu (qcdev -> dev_desc .report_desc_len ));
424
+
425
+ ret = thc_dma_set_max_packet_sizes (qcdev -> thc_hw , 0 ,
426
+ le16_to_cpu (qcdev -> dev_desc .max_input_len ),
427
+ le16_to_cpu (qcdev -> dev_desc .max_output_len ),
428
+ swdma_max_len );
429
+ if (ret )
430
+ return ret ;
431
+
432
+ ret = thc_dma_allocate (qcdev -> thc_hw );
433
+ if (ret ) {
434
+ dev_err (qcdev -> dev , "Allocate THC DMA buffer failed, ret = %d\n" , ret );
435
+ return ret ;
436
+ }
437
+
438
+ /* Enable RxDMA */
439
+ ret = thc_dma_configure (qcdev -> thc_hw );
440
+ if (ret ) {
441
+ dev_err (qcdev -> dev , "Configure THC DMA failed, ret = %d\n" , ret );
442
+ thc_dma_unconfigure (qcdev -> thc_hw );
443
+ thc_dma_release (qcdev -> thc_hw );
444
+ return ret ;
445
+ }
446
+
447
+ return ret ;
448
+ }
449
+
450
+ /**
451
+ * quicki2c_dma_deinit - Release THC DMA for quicki2c device
452
+ * @qcdev: pointer to the quicki2c device structure
453
+ *
454
+ * Stop THC DMA engines and release all DMA buffers.
455
+ *
456
+ */
457
+ static void quicki2c_dma_deinit (struct quicki2c_device * qcdev )
458
+ {
459
+ thc_dma_unconfigure (qcdev -> thc_hw );
460
+ thc_dma_release (qcdev -> thc_hw );
461
+ }
462
+
463
+ /**
464
+ * quicki2c_alloc_report_buf - Alloc report buffers
465
+ * @qcdev: pointer to the quicki2c device structure
466
+ *
467
+ * Allocate report descriptor buffer, it will be used for restore TIC HID
468
+ * report descriptor.
469
+ *
470
+ * Allocate input report buffer, it will be used for receive HID input report
471
+ * data from TIC.
472
+ *
473
+ * Allocate output report buffer, it will be used for store HID output report,
474
+ * such as set feature.
475
+ *
476
+ * Return: 0 if success or error code on failed.
477
+ */
478
+ static int quicki2c_alloc_report_buf (struct quicki2c_device * qcdev )
479
+ {
480
+ size_t max_report_len ;
481
+
482
+ qcdev -> report_descriptor = devm_kzalloc (qcdev -> dev ,
483
+ le16_to_cpu (qcdev -> dev_desc .report_desc_len ),
484
+ GFP_KERNEL );
485
+ if (!qcdev -> report_descriptor )
486
+ return - ENOMEM ;
487
+
488
+ /*
489
+ * Some HIDI2C devices don't declare input/output max length correctly,
490
+ * give default 4K buffer to avoid DMA buffer overrun.
491
+ */
492
+ max_report_len = max (le16_to_cpu (qcdev -> dev_desc .max_input_len ), SZ_4K );
493
+
494
+ qcdev -> input_buf = devm_kzalloc (qcdev -> dev , max_report_len , GFP_KERNEL );
495
+ if (!qcdev -> input_buf )
496
+ return - ENOMEM ;
497
+
498
+ if (!le16_to_cpu (qcdev -> dev_desc .max_output_len ))
499
+ qcdev -> dev_desc .max_output_len = cpu_to_le16 (SZ_4K );
500
+
501
+ max_report_len = max (le16_to_cpu (qcdev -> dev_desc .max_output_len ),
502
+ max_report_len );
503
+
504
+ qcdev -> report_buf = devm_kzalloc (qcdev -> dev , max_report_len , GFP_KERNEL );
505
+ if (!qcdev -> report_buf )
506
+ return - ENOMEM ;
507
+
508
+ qcdev -> report_len = max_report_len ;
509
+
510
+ return 0 ;
308
511
}
309
512
310
513
/*
@@ -313,6 +516,18 @@ static void quicki2c_dev_deinit(struct quicki2c_device *qcdev)
313
516
* @pdev: point to pci device
314
517
* @id: point to pci_device_id structure
315
518
*
519
+ * This function initializes THC and HIDI2C device, the flow is:
520
+ * - do THC pci device initialization
521
+ * - query HIDI2C ACPI parameters
522
+ * - configure THC to HIDI2C mode
523
+ * - go through HIDI2C enumeration flow
524
+ * |- read device descriptor
525
+ * |- reset HIDI2C device
526
+ * - enable THC interrupt and DMA
527
+ * - read report descriptor
528
+ * - register HID device
529
+ * - enable runtime power management
530
+ *
316
531
* Return 0 if success or error code on failed.
317
532
*/
318
533
static int quicki2c_probe (struct pci_dev * pdev ,
@@ -376,8 +591,60 @@ static int quicki2c_probe(struct pci_dev *pdev,
376
591
goto dev_deinit ;
377
592
}
378
593
594
+ ret = quicki2c_get_device_descriptor (qcdev );
595
+ if (ret ) {
596
+ dev_err (& pdev -> dev , "Get device descriptor failed, ret = %d\n" , ret );
597
+ goto dev_deinit ;
598
+ }
599
+
600
+ ret = quicki2c_alloc_report_buf (qcdev );
601
+ if (ret ) {
602
+ dev_err (& pdev -> dev , "Alloc report buffers failed, ret= %d\n" , ret );
603
+ goto dev_deinit ;
604
+ }
605
+
606
+ ret = quicki2c_dma_init (qcdev );
607
+ if (ret ) {
608
+ dev_err (& pdev -> dev , "Setup THC DMA failed, ret= %d\n" , ret );
609
+ goto dev_deinit ;
610
+ }
611
+
612
+ ret = thc_interrupt_quiesce (qcdev -> thc_hw , false);
613
+ if (ret )
614
+ goto dev_deinit ;
615
+
616
+ ret = quicki2c_set_power (qcdev , HIDI2C_ON );
617
+ if (ret ) {
618
+ dev_err (& pdev -> dev , "Set Power On command failed, ret= %d\n" , ret );
619
+ goto dev_deinit ;
620
+ }
621
+
622
+ ret = quicki2c_reset (qcdev );
623
+ if (ret ) {
624
+ dev_err (& pdev -> dev , "Reset HIDI2C device failed, ret= %d\n" , ret );
625
+ goto dev_deinit ;
626
+ }
627
+
628
+ ret = quicki2c_get_report_descriptor (qcdev );
629
+ if (ret ) {
630
+ dev_err (& pdev -> dev , "Get report descriptor failed, ret = %d\n" , ret );
631
+ goto dma_deinit ;
632
+ }
633
+
634
+ ret = quicki2c_hid_probe (qcdev );
635
+ if (ret ) {
636
+ dev_err (& pdev -> dev , "Failed to register HID device, ret = %d\n" , ret );
637
+ goto dma_deinit ;
638
+ }
639
+
640
+ qcdev -> state = QUICKI2C_ENABLED ;
641
+
642
+ dev_dbg (& pdev -> dev , "QuickI2C probe success\n" );
643
+
379
644
return 0 ;
380
645
646
+ dma_deinit :
647
+ quicki2c_dma_deinit (qcdev );
381
648
dev_deinit :
382
649
quicki2c_dev_deinit (qcdev );
383
650
unmap_io_region :
@@ -404,6 +671,9 @@ static void quicki2c_remove(struct pci_dev *pdev)
404
671
if (!qcdev )
405
672
return ;
406
673
674
+ quicki2c_hid_remove (qcdev );
675
+ quicki2c_dma_deinit (qcdev );
676
+
407
677
quicki2c_dev_deinit (qcdev );
408
678
409
679
pcim_iounmap_regions (pdev , BIT (0 ));
@@ -427,6 +697,9 @@ static void quicki2c_shutdown(struct pci_dev *pdev)
427
697
if (!qcdev )
428
698
return ;
429
699
700
+ /* Must stop DMA before reboot to avoid DMA entering into unknown state */
701
+ quicki2c_dma_deinit (qcdev );
702
+
430
703
quicki2c_dev_deinit (qcdev );
431
704
}
432
705
0 commit comments