@@ -457,6 +457,229 @@ int thc_tic_pio_write_and_read(struct thc_device *dev, const u32 address,
457
457
}
458
458
EXPORT_SYMBOL_NS_GPL (thc_tic_pio_write_and_read , "INTEL_THC" );
459
459
460
+ /**
461
+ * thc_interrupt_config - Configure THC interrupts
462
+ *
463
+ * @dev: The pointer of THC private device context
464
+ */
465
+ void thc_interrupt_config (struct thc_device * dev )
466
+ {
467
+ u32 mbits , mask , r_dma_ctrl_1 ;
468
+
469
+ /* Clear Error reporting interrupt status bits */
470
+ mbits = THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS |
471
+ THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS ;
472
+ regmap_write_bits (dev -> thc_regmap ,
473
+ THC_M_PRT_INT_STATUS_OFFSET ,
474
+ mbits , mbits );
475
+
476
+ /* Enable Error Reporting Interrupts */
477
+ mbits = THC_M_PRT_INT_EN_TXN_ERR_INT_EN |
478
+ THC_M_PRT_INT_EN_FATAL_ERR_INT_EN |
479
+ THC_M_PRT_INT_EN_BUF_OVRRUN_ERR_INT_EN ;
480
+ regmap_write_bits (dev -> thc_regmap ,
481
+ THC_M_PRT_INT_EN_OFFSET ,
482
+ mbits , mbits );
483
+
484
+ /* Clear PIO Interrupt status bits */
485
+ mbits = THC_M_PRT_SW_SEQ_STS_THC_SS_ERR |
486
+ THC_M_PRT_SW_SEQ_STS_TSSDONE ;
487
+ regmap_write_bits (dev -> thc_regmap ,
488
+ THC_M_PRT_SW_SEQ_STS_OFFSET ,
489
+ mbits , mbits );
490
+
491
+ /* Read Interrupts */
492
+ regmap_read (dev -> thc_regmap ,
493
+ THC_M_PRT_READ_DMA_CNTRL_1_OFFSET ,
494
+ & r_dma_ctrl_1 );
495
+ /* Disable RxDMA1 */
496
+ r_dma_ctrl_1 &= ~THC_M_PRT_READ_DMA_CNTRL_IE_EOF ;
497
+ regmap_write (dev -> thc_regmap ,
498
+ THC_M_PRT_READ_DMA_CNTRL_1_OFFSET ,
499
+ r_dma_ctrl_1 );
500
+
501
+ /* Ack EOF Interrupt RxDMA1 */
502
+ mbits = THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS ;
503
+ /* Ack NonDMA Interrupt */
504
+ mbits |= THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS ;
505
+ regmap_write_bits (dev -> thc_regmap ,
506
+ THC_M_PRT_READ_DMA_INT_STS_1_OFFSET ,
507
+ mbits , mbits );
508
+
509
+ /* Ack EOF Interrupt RxDMA2 */
510
+ regmap_write_bits (dev -> thc_regmap ,
511
+ THC_M_PRT_READ_DMA_INT_STS_2_OFFSET ,
512
+ THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS ,
513
+ THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS );
514
+
515
+ /* Write Interrupts */
516
+ /* Disable TxDMA */
517
+ regmap_write_bits (dev -> thc_regmap ,
518
+ THC_M_PRT_WRITE_DMA_CNTRL_OFFSET ,
519
+ THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL ,
520
+ 0 );
521
+
522
+ /* Clear TxDMA interrupt status bits */
523
+ mbits = THC_M_PRT_WRITE_INT_STS_THC_WRDMA_ERROR_STS ;
524
+ mbits |= THC_M_PRT_WRITE_INT_STS_THC_WRDMA_IOC_STS ;
525
+ regmap_write_bits (dev -> thc_regmap ,
526
+ THC_M_PRT_WRITE_INT_STS_OFFSET ,
527
+ mbits , mbits );
528
+
529
+ /* Enable Non-DMA device inband interrupt */
530
+ r_dma_ctrl_1 |= THC_M_PRT_READ_DMA_CNTRL_IE_NDDI ;
531
+ regmap_write (dev -> thc_regmap ,
532
+ THC_M_PRT_READ_DMA_CNTRL_1_OFFSET ,
533
+ r_dma_ctrl_1 );
534
+
535
+ if (dev -> port_type == THC_PORT_TYPE_SPI ) {
536
+ /* Edge triggered interrupt */
537
+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_TSEQ_CNTRL_1_OFFSET ,
538
+ THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN ,
539
+ THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN );
540
+ } else {
541
+ /* Level triggered interrupt */
542
+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_TSEQ_CNTRL_1_OFFSET ,
543
+ THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN , 0 );
544
+
545
+ mbits = THC_M_PRT_INT_EN_THC_I2C_IC_MST_ON_HOLD_INT_EN |
546
+ THC_M_PRT_INT_EN_THC_I2C_IC_SCL_STUCK_AT_LOW_DET_INT_EN |
547
+ THC_M_PRT_INT_EN_THC_I2C_IC_TX_ABRT_INT_EN |
548
+ THC_M_PRT_INT_EN_THC_I2C_IC_TX_OVER_INT_EN |
549
+ THC_M_PRT_INT_EN_THC_I2C_IC_RX_FULL_INT_EN |
550
+ THC_M_PRT_INT_EN_THC_I2C_IC_RX_OVER_INT_EN |
551
+ THC_M_PRT_INT_EN_THC_I2C_IC_RX_UNDER_INT_EN ;
552
+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_INT_EN_OFFSET ,
553
+ mbits , mbits );
554
+ }
555
+
556
+ thc_set_pio_interrupt_support (dev , false);
557
+
558
+ /* HIDSPI specific settings */
559
+ if (dev -> port_type == THC_PORT_TYPE_SPI ) {
560
+ mbits = FIELD_PREP (THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_OFFSET ,
561
+ THC_BIT_OFFSET_INTERRUPT_TYPE ) |
562
+ FIELD_PREP (THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_LEN ,
563
+ THC_BIT_LENGTH_INTERRUPT_TYPE ) |
564
+ FIELD_PREP (THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_EOF_OFFSET ,
565
+ THC_BIT_OFFSET_LAST_FRAGMENT_FLAG ) |
566
+ FIELD_PREP (THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_DATA_VAL ,
567
+ THC_BITMASK_INVALID_TYPE_DATA );
568
+ mask = THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_OFFSET |
569
+ THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_LEN |
570
+ THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_EOF_OFFSET |
571
+ THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_DATA_VAL ;
572
+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_DEVINT_CFG_1_OFFSET ,
573
+ mask , mbits );
574
+
575
+ mbits = FIELD_PREP (THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_OFFSET ,
576
+ THC_BIT_OFFSET_MICROFRAME_SIZE ) |
577
+ FIELD_PREP (THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_LEN ,
578
+ THC_BIT_LENGTH_MICROFRAME_SIZE ) |
579
+ FIELD_PREP (THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_UNIT ,
580
+ THC_UNIT_MICROFRAME_SIZE ) |
581
+ THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_IGNORE |
582
+ THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_VAL ;
583
+ mask = THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_OFFSET |
584
+ THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_LEN |
585
+ THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_UNIT |
586
+ THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_IGNORE |
587
+ THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_VAL ;
588
+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_DEVINT_CFG_2_OFFSET ,
589
+ mask , mbits );
590
+ }
591
+ }
592
+ EXPORT_SYMBOL_NS_GPL (thc_interrupt_config , "INTEL_THC" );
593
+
594
+ /**
595
+ * thc_int_trigger_type_select - Select THC interrupt trigger type
596
+ *
597
+ * @dev: the pointer of THC private device context
598
+ * @edge_trigger: determine the interrupt is edge triggered or level triggered
599
+ */
600
+ void thc_int_trigger_type_select (struct thc_device * dev , bool edge_trigger )
601
+ {
602
+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_TSEQ_CNTRL_1_OFFSET ,
603
+ THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN ,
604
+ edge_trigger ? THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN : 0 );
605
+ }
606
+ EXPORT_SYMBOL_NS_GPL (thc_int_trigger_type_select , "INTEL_THC" );
607
+
608
+ /**
609
+ * thc_interrupt_enable - Enable or disable THC interrupt
610
+ *
611
+ * @dev: the pointer of THC private device context
612
+ * @int_enable: the flag to control THC interrupt enable or disable
613
+ */
614
+ void thc_interrupt_enable (struct thc_device * dev , bool int_enable )
615
+ {
616
+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_INT_EN_OFFSET ,
617
+ THC_M_PRT_INT_EN_GBL_INT_EN ,
618
+ int_enable ? THC_M_PRT_INT_EN_GBL_INT_EN : 0 );
619
+ }
620
+ EXPORT_SYMBOL_NS_GPL (thc_interrupt_enable , "INTEL_THC" );
621
+
622
+ /**
623
+ * thc_interrupt_quiesce - Quiesce or unquiesce external touch device interrupt
624
+ *
625
+ * @dev: the pointer of THC private device context
626
+ * @int_quiesce: the flag to determine quiesce or unquiesce device interrupt
627
+ *
628
+ * Return: 0 on success, other error codes on failed
629
+ */
630
+ int thc_interrupt_quiesce (const struct thc_device * dev , bool int_quiesce )
631
+ {
632
+ u32 ctrl ;
633
+ int ret ;
634
+
635
+ regmap_read (dev -> thc_regmap , THC_M_PRT_CONTROL_OFFSET , & ctrl );
636
+ if (!(ctrl & THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN ) && !int_quiesce ) {
637
+ dev_warn (dev -> dev , "THC interrupt already unquiesce\n" );
638
+ return 0 ;
639
+ }
640
+
641
+ if ((ctrl & THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN ) && int_quiesce ) {
642
+ dev_warn (dev -> dev , "THC interrupt already quiesce\n" );
643
+ return 0 ;
644
+ }
645
+
646
+ /* Quiesce device interrupt - Set quiesce bit and waiting for THC HW to ACK */
647
+ if (int_quiesce )
648
+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_CONTROL_OFFSET ,
649
+ THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN ,
650
+ THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN );
651
+
652
+ ret = regmap_read_poll_timeout (dev -> thc_regmap , THC_M_PRT_CONTROL_OFFSET , ctrl ,
653
+ ctrl & THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_HW_STS ,
654
+ THC_REGMAP_POLLING_INTERVAL_US , THC_QUIESCE_EN_TIMEOUT_US );
655
+ if (ret ) {
656
+ dev_err_once (dev -> dev ,
657
+ "Timeout while waiting THC idle, target quiesce state = %s\n" ,
658
+ int_quiesce ? "true" : "false" );
659
+ return ret ;
660
+ }
661
+
662
+ /* Unquiesce device interrupt - Clear the quiesce bit */
663
+ if (!int_quiesce )
664
+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_CONTROL_OFFSET ,
665
+ THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN , 0 );
666
+
667
+ return 0 ;
668
+ }
669
+ EXPORT_SYMBOL_NS_GPL (thc_interrupt_quiesce , "INTEL_THC" );
670
+
671
+ /**
672
+ * thc_set_pio_interrupt_support - Determine PIO interrupt is supported or not
673
+ *
674
+ * @dev: The pointer of THC private device context
675
+ * @supported: The flag to determine enabling PIO interrupt or not
676
+ */
677
+ void thc_set_pio_interrupt_support (struct thc_device * dev , bool supported )
678
+ {
679
+ dev -> pio_int_supported = supported ;
680
+ }
681
+ EXPORT_SYMBOL_NS_GPL (thc_set_pio_interrupt_support , "INTEL_THC" );
682
+
460
683
MODULE_AUTHOR (
"Xinpeng Sun <[email protected] >" );
461
684
MODULE_AUTHOR (
"Even Xu <[email protected] >" );
462
685
0 commit comments