@@ -802,6 +802,265 @@ void thc_ltr_unconfig(struct thc_device *dev)
802802}
803803EXPORT_SYMBOL_NS_GPL (thc_ltr_unconfig , "INTEL_THC" );
804804
805+ /**
806+ * thc_int_cause_read - Read interrupt cause register value
807+ *
808+ * @dev: The pointer of THC private device context
809+ *
810+ * Return: The interrupt cause register value
811+ */
812+ u32 thc_int_cause_read (struct thc_device * dev )
813+ {
814+ u32 int_cause ;
815+
816+ regmap_read (dev -> thc_regmap ,
817+ THC_M_PRT_DEV_INT_CAUSE_REG_VAL_OFFSET , & int_cause );
818+
819+ return int_cause ;
820+ }
821+ EXPORT_SYMBOL_NS_GPL (thc_int_cause_read , "INTEL_THC" );
822+
823+ static void thc_print_txn_error_cause (const struct thc_device * dev )
824+ {
825+ bool known_error = false;
826+ u32 cause = 0 ;
827+
828+ regmap_read (dev -> thc_regmap , THC_M_PRT_ERR_CAUSE_OFFSET , & cause );
829+
830+ if (cause & THC_M_PRT_ERR_CAUSE_PRD_ENTRY_ERR ) {
831+ dev_err (dev -> dev , "TXN Error: Invalid PRD Entry\n" );
832+ known_error = true;
833+ }
834+ if (cause & THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR ) {
835+ dev_err (dev -> dev , "TXN Error: THC Buffer Overrun\n" );
836+ known_error = true;
837+ }
838+ if (cause & THC_M_PRT_ERR_CAUSE_FRAME_BABBLE_ERR ) {
839+ dev_err (dev -> dev , "TXN Error: Frame Babble\n" );
840+ known_error = true;
841+ }
842+ if (cause & THC_M_PRT_ERR_CAUSE_INVLD_DEV_ENTRY ) {
843+ dev_err (dev -> dev , "TXN Error: Invalid Device Register Setting\n" );
844+ known_error = true;
845+ }
846+
847+ /* Clear interrupt status bits */
848+ regmap_write (dev -> thc_regmap , THC_M_PRT_ERR_CAUSE_OFFSET , cause );
849+
850+ if (!known_error )
851+ dev_err (dev -> dev , "TXN Error does not match any known value: 0x%X\n" ,
852+ cause );
853+ }
854+
855+ /**
856+ * thc_interrupt_handler - Handle THC interrupts
857+ *
858+ * THC interrupts include several types: external touch device (TIC) non-DMA
859+ * interrupts, PIO completion interrupts, DMA interrtups, I2C subIP raw
860+ * interrupts and error interrupts.
861+ *
862+ * This is a help function for interrupt processing, it detects interrupt
863+ * type, clear the interrupt status bit and return the interrupt type to caller
864+ * for future processing.
865+ *
866+ * @dev: The pointer of THC private device context
867+ *
868+ * Return: The combined flag for interrupt type
869+ */
870+ int thc_interrupt_handler (struct thc_device * dev )
871+ {
872+ u32 read_sts_1 , read_sts_2 , read_sts_sw , write_sts ;
873+ u32 int_sts , err_cause , seq_cntrl , seq_sts ;
874+ int interrupt_type = 0 ;
875+
876+ regmap_read (dev -> thc_regmap ,
877+ THC_M_PRT_READ_DMA_INT_STS_1_OFFSET , & read_sts_1 );
878+
879+ if (read_sts_1 & THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS ) {
880+ dev_dbg (dev -> dev , "THC non-DMA device interrupt\n" );
881+
882+ regmap_write (dev -> thc_regmap , THC_M_PRT_READ_DMA_INT_STS_1_OFFSET ,
883+ NONDMA_INT_STS_BIT );
884+
885+ interrupt_type |= BIT (THC_NONDMA_INT );
886+
887+ return interrupt_type ;
888+ }
889+
890+ regmap_read (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET , & int_sts );
891+
892+ if (int_sts & THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS ) {
893+ dev_err (dev -> dev , "THC transaction error, int_sts: 0x%08X\n" , int_sts );
894+ thc_print_txn_error_cause (dev );
895+
896+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
897+ TXN_ERR_INT_STS_BIT );
898+
899+ interrupt_type |= BIT (THC_TXN_ERR_INT );
900+
901+ return interrupt_type ;
902+ }
903+
904+ regmap_read (dev -> thc_regmap , THC_M_PRT_ERR_CAUSE_OFFSET , & err_cause );
905+ regmap_read (dev -> thc_regmap ,
906+ THC_M_PRT_READ_DMA_INT_STS_2_OFFSET , & read_sts_2 );
907+
908+ if (err_cause & THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR ||
909+ read_sts_1 & THC_M_PRT_READ_DMA_INT_STS_STALL_STS ||
910+ read_sts_2 & THC_M_PRT_READ_DMA_INT_STS_STALL_STS ) {
911+ dev_err (dev -> dev , "Buffer overrun or RxDMA engine stalled!\n" );
912+ thc_print_txn_error_cause (dev );
913+
914+ regmap_write (dev -> thc_regmap , THC_M_PRT_READ_DMA_INT_STS_2_OFFSET ,
915+ THC_M_PRT_READ_DMA_INT_STS_STALL_STS );
916+ regmap_write (dev -> thc_regmap , THC_M_PRT_READ_DMA_INT_STS_1_OFFSET ,
917+ THC_M_PRT_READ_DMA_INT_STS_STALL_STS );
918+ regmap_write (dev -> thc_regmap , THC_M_PRT_ERR_CAUSE_OFFSET ,
919+ THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR );
920+
921+ interrupt_type |= BIT (THC_TXN_ERR_INT );
922+
923+ return interrupt_type ;
924+ }
925+
926+ if (int_sts & THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS ) {
927+ dev_err_once (dev -> dev , "THC FATAL error, int_sts: 0x%08X\n" , int_sts );
928+
929+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
930+ TXN_FATAL_INT_STS_BIT );
931+
932+ interrupt_type |= BIT (THC_FATAL_ERR_INT );
933+
934+ return interrupt_type ;
935+ }
936+
937+ regmap_read (dev -> thc_regmap ,
938+ THC_M_PRT_SW_SEQ_CNTRL_OFFSET , & seq_cntrl );
939+ regmap_read (dev -> thc_regmap ,
940+ THC_M_PRT_SW_SEQ_STS_OFFSET , & seq_sts );
941+
942+ if (seq_cntrl & THC_M_PRT_SW_SEQ_CNTRL_THC_SS_CD_IE &&
943+ seq_sts & THC_M_PRT_SW_SEQ_STS_TSSDONE ) {
944+ dev_dbg (dev -> dev , "THC_SS_CD_IE and TSSDONE are set\n" );
945+ interrupt_type |= BIT (THC_PIO_DONE_INT );
946+ }
947+
948+ if (read_sts_1 & THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS ) {
949+ dev_dbg (dev -> dev , "Got RxDMA1 Read Interrupt\n" );
950+
951+ regmap_write (dev -> thc_regmap ,
952+ THC_M_PRT_READ_DMA_INT_STS_1_OFFSET , read_sts_1 );
953+
954+ interrupt_type |= BIT (THC_RXDMA1_INT );
955+ }
956+
957+ if (read_sts_2 & THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS ) {
958+ dev_dbg (dev -> dev , "Got RxDMA2 Read Interrupt\n" );
959+
960+ regmap_write (dev -> thc_regmap ,
961+ THC_M_PRT_READ_DMA_INT_STS_2_OFFSET , read_sts_2 );
962+
963+ interrupt_type |= BIT (THC_RXDMA2_INT );
964+ }
965+
966+ regmap_read (dev -> thc_regmap ,
967+ THC_M_PRT_READ_DMA_INT_STS_SW_OFFSET , & read_sts_sw );
968+
969+ if (read_sts_sw & THC_M_PRT_READ_DMA_INT_STS_DMACPL_STS ) {
970+ dev_dbg (dev -> dev , "Got SwDMA Read Interrupt\n" );
971+
972+ regmap_write (dev -> thc_regmap ,
973+ THC_M_PRT_READ_DMA_INT_STS_SW_OFFSET , read_sts_sw );
974+
975+ dev -> swdma_done = true;
976+ wake_up_interruptible (& dev -> swdma_complete_wait );
977+
978+ interrupt_type |= BIT (THC_SWDMA_INT );
979+ }
980+
981+ regmap_read (dev -> thc_regmap ,
982+ THC_M_PRT_WRITE_INT_STS_OFFSET , & write_sts );
983+
984+ if (write_sts & THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS ) {
985+ dev_dbg (dev -> dev , "Got TxDMA Write complete Interrupt\n" );
986+
987+ regmap_write (dev -> thc_regmap ,
988+ THC_M_PRT_WRITE_INT_STS_OFFSET , write_sts );
989+
990+ dev -> write_done = true;
991+ wake_up_interruptible (& dev -> write_complete_wait );
992+
993+ interrupt_type |= BIT (THC_TXDMA_INT );
994+ }
995+
996+ if (int_sts & THC_M_PRT_INT_STATUS_DEV_RAW_INT_STS ) {
997+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
998+ THC_M_PRT_INT_STATUS_DEV_RAW_INT_STS );
999+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1000+ }
1001+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_UNDER_INT_STS ) {
1002+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1003+ THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_UNDER_INT_STS );
1004+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1005+ }
1006+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_OVER_INT_STS ) {
1007+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1008+ THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_OVER_INT_STS );
1009+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1010+ }
1011+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_FULL_INT_STS ) {
1012+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1013+ THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_FULL_INT_STS );
1014+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1015+ }
1016+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_OVER_INT_STS ) {
1017+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1018+ THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_OVER_INT_STS );
1019+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1020+ }
1021+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_EMPTY_INT_STS ) {
1022+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1023+ THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_EMPTY_INT_STS );
1024+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1025+ }
1026+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_ABRT_INT_STS ) {
1027+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1028+ THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_ABRT_INT_STS );
1029+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1030+ }
1031+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_ACTIVITY_INT_STS ) {
1032+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1033+ THC_M_PRT_INT_STATUS_THC_I2C_IC_ACTIVITY_INT_STS );
1034+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1035+ }
1036+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_SCL_STUCK_AT_LOW_INT_STS ) {
1037+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1038+ THC_M_PRT_INT_STATUS_THC_I2C_IC_SCL_STUCK_AT_LOW_INT_STS );
1039+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1040+ }
1041+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_STOP_DET_INT_STS ) {
1042+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1043+ THC_M_PRT_INT_STATUS_THC_I2C_IC_STOP_DET_INT_STS );
1044+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1045+ }
1046+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_START_DET_INT_STS ) {
1047+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1048+ THC_M_PRT_INT_STATUS_THC_I2C_IC_START_DET_INT_STS );
1049+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1050+ }
1051+ if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_MST_ON_HOLD_INT_STS ) {
1052+ regmap_write (dev -> thc_regmap , THC_M_PRT_INT_STATUS_OFFSET ,
1053+ THC_M_PRT_INT_STATUS_THC_I2C_IC_MST_ON_HOLD_INT_STS );
1054+ interrupt_type |= BIT (THC_I2CSUBIP_INT );
1055+ }
1056+
1057+ if (!interrupt_type )
1058+ interrupt_type |= BIT (THC_UNKNOWN_INT );
1059+
1060+ return interrupt_type ;
1061+ }
1062+ EXPORT_SYMBOL_NS_GPL (thc_interrupt_handler , "INTEL_THC" );
1063+
8051064MODULE_AUTHOR (
"Xinpeng Sun <[email protected] >" );
8061065MODULE_AUTHOR (
"Even Xu <[email protected] >" );
8071066
0 commit comments