@@ -457,6 +457,229 @@ int thc_tic_pio_write_and_read(struct thc_device *dev, const u32 address,
457457}
458458EXPORT_SYMBOL_NS_GPL (thc_tic_pio_write_and_read , "INTEL_THC" );
459459
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+
460683MODULE_AUTHOR (
"Xinpeng Sun <[email protected] >" );
461684MODULE_AUTHOR (
"Even Xu <[email protected] >" );
462685
0 commit comments