Skip to content

Commit 86f5f4a

Browse files
sunxinpengJiri Kosina
authored andcommitted
HID: intel-thc-hid: intel-thc: Add APIs for interrupt
Add THC interrupt operation interfaces, such as interrupt configure, global interrupt enable/disable, external touch device GPIO interrupt quiesce and unquiesce. Co-developed-by: Even Xu <[email protected]> Signed-off-by: Even Xu <[email protected]> Signed-off-by: Xinpeng Sun <[email protected]> Tested-by: Rui Zhang <[email protected]> Tested-by: Mark Pearson <[email protected]> Reviewed-by: Srinivas Pandruvada <[email protected]> Reviewed-by: Mark Pearson <[email protected]> Tested-by: Aaron Ma <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent e584b13 commit 86f5f4a

File tree

3 files changed

+245
-0
lines changed

3 files changed

+245
-0
lines changed

drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,229 @@ int thc_tic_pio_write_and_read(struct thc_device *dev, const u32 address,
457457
}
458458
EXPORT_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+
460683
MODULE_AUTHOR("Xinpeng Sun <[email protected]>");
461684
MODULE_AUTHOR("Even Xu <[email protected]>");
462685

drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,10 @@ int thc_tic_pio_write(struct thc_device *dev, const u32 address,
4545
int thc_tic_pio_write_and_read(struct thc_device *dev, const u32 address,
4646
const u32 write_size, const u32 *write_buffer,
4747
const u32 read_size, u32 *actual_size, u32 *read_buffer);
48+
void thc_interrupt_config(struct thc_device *dev);
49+
void thc_int_trigger_type_select(struct thc_device *dev, bool edge_trigger);
50+
void thc_interrupt_enable(struct thc_device *dev, bool int_enable);
51+
void thc_set_pio_interrupt_support(struct thc_device *dev, bool supported);
52+
int thc_interrupt_quiesce(const struct thc_device *dev, bool int_quiesce);
4853

4954
#endif /* _INTEL_THC_DEV_H_ */

drivers/hid/intel-thc-hid/intel-thc/intel-thc-hw.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,23 @@
639639
#define THC_REGMAP_POLLING_INTERVAL_US 10 /* 10us */
640640
#define THC_PIO_DONE_TIMEOUT_US USEC_PER_SEC /* 1s */
641641

642+
/* Default configures for HIDSPI */
643+
#define THC_BIT_OFFSET_INTERRUPT_TYPE 4
644+
/* input_report_type is 4 bits for HIDSPI */
645+
#define THC_BIT_LENGTH_INTERRUPT_TYPE 4
646+
/* Last fragment indicator is bit 15 for HIDSPI */
647+
#define THC_BIT_OFFSET_LAST_FRAGMENT_FLAG 22
648+
#define THC_BIT_OFFSET_MICROFRAME_SIZE 8
649+
/* input_report_length is 14 bits for HIDSPI */
650+
#define THC_BIT_LENGTH_MICROFRAME_SIZE 14
651+
/* MFS unit in power of 2 */
652+
#define THC_UNIT_MICROFRAME_SIZE 2
653+
#define THC_BITMASK_INTERRUPT_TYPE_DATA 1
654+
#define THC_BITMASK_INVALID_TYPE_DATA 2
655+
656+
/* Interrupt Quiesce default timeout value */
657+
#define THC_QUIESCE_EN_TIMEOUT_US USEC_PER_SEC /* 1s */
658+
642659
/*
643660
* THC PIO opcode default value
644661
* @THC_PIO_OP_SPI_TIC_READ: THC opcode for SPI PIO read

0 commit comments

Comments
 (0)