88#include <linux/interrupt.h>
99#include <linux/irqreturn.h>
1010#include <linux/pci.h>
11+ #include <linux/sizes.h>
1112
1213#include "intel-thc-dev.h"
1314#include "intel-thc-hw.h"
1415
1516#include "quicki2c-dev.h"
17+ #include "quicki2c-hid.h"
18+ #include "quicki2c-protocol.h"
1619
1720/* THC QuickI2C ACPI method to get device properties */
1821/* HIDI2C device method */
@@ -210,6 +213,69 @@ static irqreturn_t quicki2c_irq_quick_handler(int irq, void *dev_id)
210213 return IRQ_WAKE_THREAD ;
211214}
212215
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+
213279/**
214280 * quicki2c_irq_thread_handler - IRQ thread handler of quicki2c driver
215281 *
@@ -221,15 +287,33 @@ static irqreturn_t quicki2c_irq_quick_handler(int irq, void *dev_id)
221287static irqreturn_t quicki2c_irq_thread_handler (int irq , void * dev_id )
222288{
223289 struct quicki2c_device * qcdev = dev_id ;
290+ int err_recover = 0 ;
224291 int int_mask ;
225292
226293 if (qcdev -> state == QUICKI2C_DISABLED )
227294 return IRQ_HANDLED ;
228295
229296 int_mask = thc_interrupt_handler (qcdev -> thc_hw );
230297
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 :
231311 thc_interrupt_enable (qcdev -> thc_hw , true);
232312
313+ if (err_recover )
314+ if (try_recover (qcdev ))
315+ qcdev -> state = QUICKI2C_DISABLED ;
316+
233317 return IRQ_HANDLED ;
234318}
235319
@@ -260,6 +344,9 @@ static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __io
260344 qcdev -> pdev = pdev ;
261345 qcdev -> dev = dev ;
262346 qcdev -> mem_addr = mem_addr ;
347+ qcdev -> state = QUICKI2C_DISABLED ;
348+
349+ init_waitqueue_head (& qcdev -> reset_ack_wq );
263350
264351 /* thc hw init */
265352 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
275362 return ERR_PTR (ret );
276363 }
277364
365+ ret = thc_interrupt_quiesce (qcdev -> thc_hw , true);
366+ if (ret )
367+ return ERR_PTR (ret );
368+
278369 ret = thc_port_select (qcdev -> thc_hw , THC_PORT_TYPE_I2C );
279370 if (ret ) {
280371 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
288379 if (ret )
289380 return ERR_PTR (ret );
290381
382+ thc_int_trigger_type_select (qcdev -> thc_hw , false);
383+
291384 thc_interrupt_config (qcdev -> thc_hw );
292385
293386 thc_interrupt_enable (qcdev -> thc_hw , true);
294387
388+ qcdev -> state = QUICKI2C_INITED ;
389+
295390 return qcdev ;
296391}
297392
@@ -305,6 +400,114 @@ static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __io
305400static void quicki2c_dev_deinit (struct quicki2c_device * qcdev )
306401{
307402 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 ;
308511}
309512
310513/*
@@ -313,6 +516,18 @@ static void quicki2c_dev_deinit(struct quicki2c_device *qcdev)
313516 * @pdev: point to pci device
314517 * @id: point to pci_device_id structure
315518 *
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+ *
316531 * Return 0 if success or error code on failed.
317532 */
318533static int quicki2c_probe (struct pci_dev * pdev ,
@@ -376,8 +591,60 @@ static int quicki2c_probe(struct pci_dev *pdev,
376591 goto dev_deinit ;
377592 }
378593
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+
379644 return 0 ;
380645
646+ dma_deinit :
647+ quicki2c_dma_deinit (qcdev );
381648dev_deinit :
382649 quicki2c_dev_deinit (qcdev );
383650unmap_io_region :
@@ -404,6 +671,9 @@ static void quicki2c_remove(struct pci_dev *pdev)
404671 if (!qcdev )
405672 return ;
406673
674+ quicki2c_hid_remove (qcdev );
675+ quicki2c_dma_deinit (qcdev );
676+
407677 quicki2c_dev_deinit (qcdev );
408678
409679 pcim_iounmap_regions (pdev , BIT (0 ));
@@ -427,6 +697,9 @@ static void quicki2c_shutdown(struct pci_dev *pdev)
427697 if (!qcdev )
428698 return ;
429699
700+ /* Must stop DMA before reboot to avoid DMA entering into unknown state */
701+ quicki2c_dma_deinit (qcdev );
702+
430703 quicki2c_dev_deinit (qcdev );
431704}
432705
0 commit comments