@@ -89,12 +89,18 @@ struct pcc_chan_reg {
8989 * @db: PCC register bundle for the doorbell register
9090 * @plat_irq_ack: PCC register bundle for the platform interrupt acknowledge
9191 * register
92+ * @cmd_complete: PCC register bundle for the command complete check register
93+ * @cmd_update: PCC register bundle for the command complete update register
94+ * @error: PCC register bundle for the error status register
9295 * @plat_irq: platform interrupt
9396 */
9497struct pcc_chan_info {
9598 struct pcc_mbox_chan chan ;
9699 struct pcc_chan_reg db ;
97100 struct pcc_chan_reg plat_irq_ack ;
101+ struct pcc_chan_reg cmd_complete ;
102+ struct pcc_chan_reg cmd_update ;
103+ struct pcc_chan_reg error ;
98104 int plat_irq ;
99105};
100106
@@ -228,9 +234,29 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
228234{
229235 struct pcc_chan_info * pchan ;
230236 struct mbox_chan * chan = p ;
237+ u64 val ;
238+ int ret ;
231239
232240 pchan = chan -> con_priv ;
233241
242+ ret = pcc_chan_reg_read (& pchan -> cmd_complete , & val );
243+ if (ret )
244+ return IRQ_NONE ;
245+
246+ val &= pchan -> cmd_complete .status_mask ;
247+ if (!val )
248+ return IRQ_NONE ;
249+
250+ ret = pcc_chan_reg_read (& pchan -> error , & val );
251+ if (ret )
252+ return IRQ_NONE ;
253+ val &= pchan -> error .status_mask ;
254+ if (val ) {
255+ val &= ~pchan -> error .status_mask ;
256+ pcc_chan_reg_write (& pchan -> error , val );
257+ return IRQ_NONE ;
258+ }
259+
234260 if (pcc_chan_reg_read_modify_write (& pchan -> plat_irq_ack ))
235261 return IRQ_NONE ;
236262
@@ -340,8 +366,13 @@ EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
340366 */
341367static int pcc_send_data (struct mbox_chan * chan , void * data )
342368{
369+ int ret ;
343370 struct pcc_chan_info * pchan = chan -> con_priv ;
344371
372+ ret = pcc_chan_reg_read_modify_write (& pchan -> cmd_update );
373+ if (ret )
374+ return ret ;
375+
345376 return pcc_chan_reg_read_modify_write (& pchan -> db );
346377}
347378
@@ -434,6 +465,16 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
434465 pcct2_ss -> ack_preserve_mask ,
435466 pcct2_ss -> ack_write_mask , 0 ,
436467 "PLAT IRQ ACK" );
468+
469+ } else if (pcct_ss -> header .type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE ||
470+ pcct_ss -> header .type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE ) {
471+ struct acpi_pcct_ext_pcc_master * pcct_ext = (void * )pcct_ss ;
472+
473+ ret = pcc_chan_reg_init (& pchan -> plat_irq_ack ,
474+ & pcct_ext -> platform_ack_register ,
475+ pcct_ext -> ack_preserve_mask ,
476+ pcct_ext -> ack_set_mask , 0 ,
477+ "PLAT IRQ ACK" );
437478 }
438479
439480 return ret ;
@@ -452,14 +493,48 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
452493{
453494 int ret = 0 ;
454495
455- struct acpi_pcct_subspace * pcct_ss ;
456-
457- pcct_ss = (struct acpi_pcct_subspace * )pcct_entry ;
458-
459- ret = pcc_chan_reg_init (& pchan -> db ,
460- & pcct_ss -> doorbell_register ,
461- pcct_ss -> preserve_mask ,
462- pcct_ss -> write_mask , 0 , "Doorbell" );
496+ if (pcct_entry -> type <= ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2 ) {
497+ struct acpi_pcct_subspace * pcct_ss ;
498+
499+ pcct_ss = (struct acpi_pcct_subspace * )pcct_entry ;
500+
501+ ret = pcc_chan_reg_init (& pchan -> db ,
502+ & pcct_ss -> doorbell_register ,
503+ pcct_ss -> preserve_mask ,
504+ pcct_ss -> write_mask , 0 , "Doorbell" );
505+
506+ } else {
507+ struct acpi_pcct_ext_pcc_master * pcct_ext ;
508+
509+ pcct_ext = (struct acpi_pcct_ext_pcc_master * )pcct_entry ;
510+
511+ ret = pcc_chan_reg_init (& pchan -> db ,
512+ & pcct_ext -> doorbell_register ,
513+ pcct_ext -> preserve_mask ,
514+ pcct_ext -> write_mask , 0 , "Doorbell" );
515+ if (ret )
516+ return ret ;
517+
518+ ret = pcc_chan_reg_init (& pchan -> cmd_complete ,
519+ & pcct_ext -> cmd_complete_register ,
520+ 0 , 0 , pcct_ext -> cmd_complete_mask ,
521+ "Command Complete Check" );
522+ if (ret )
523+ return ret ;
524+
525+ ret = pcc_chan_reg_init (& pchan -> cmd_update ,
526+ & pcct_ext -> cmd_update_register ,
527+ pcct_ext -> cmd_update_preserve_mask ,
528+ pcct_ext -> cmd_update_set_mask , 0 ,
529+ "Command Complete Update" );
530+ if (ret )
531+ return ret ;
532+
533+ ret = pcc_chan_reg_init (& pchan -> error ,
534+ & pcct_ext -> error_status_register ,
535+ 0 , 0 , pcct_ext -> error_status_mask ,
536+ "Error Status" );
537+ }
463538 return ret ;
464539}
465540
@@ -473,15 +548,25 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
473548static void pcc_parse_subspace_shmem (struct pcc_chan_info * pchan ,
474549 struct acpi_subtable_header * pcct_entry )
475550{
476- struct acpi_pcct_subspace * pcct_ss ;
477-
478- pcct_ss = (struct acpi_pcct_subspace * )pcct_entry ;
479-
480- pchan -> chan .shmem_base_addr = pcct_ss -> base_address ;
481- pchan -> chan .shmem_size = pcct_ss -> length ;
482- pchan -> chan .latency = pcct_ss -> latency ;
483- pchan -> chan .max_access_rate = pcct_ss -> max_access_rate ;
484- pchan -> chan .min_turnaround_time = pcct_ss -> min_turnaround_time ;
551+ if (pcct_entry -> type <= ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2 ) {
552+ struct acpi_pcct_subspace * pcct_ss =
553+ (struct acpi_pcct_subspace * )pcct_entry ;
554+
555+ pchan -> chan .shmem_base_addr = pcct_ss -> base_address ;
556+ pchan -> chan .shmem_size = pcct_ss -> length ;
557+ pchan -> chan .latency = pcct_ss -> latency ;
558+ pchan -> chan .max_access_rate = pcct_ss -> max_access_rate ;
559+ pchan -> chan .min_turnaround_time = pcct_ss -> min_turnaround_time ;
560+ } else {
561+ struct acpi_pcct_ext_pcc_master * pcct_ext =
562+ (struct acpi_pcct_ext_pcc_master * )pcct_entry ;
563+
564+ pchan -> chan .shmem_base_addr = pcct_ext -> base_address ;
565+ pchan -> chan .shmem_size = pcct_ext -> length ;
566+ pchan -> chan .latency = pcct_ext -> latency ;
567+ pchan -> chan .max_access_rate = pcct_ext -> max_access_rate ;
568+ pchan -> chan .min_turnaround_time = pcct_ext -> min_turnaround_time ;
569+ }
485570}
486571
487572/**
@@ -553,6 +638,13 @@ static int __init acpi_pcc_probe(void)
553638 pcc_mbox_channels [i ].con_priv = pchan ;
554639 pchan -> chan .mchan = & pcc_mbox_channels [i ];
555640
641+ if (pcct_entry -> type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE &&
642+ !pcc_mbox_ctrl .txdone_irq ) {
643+ pr_err ("Plaform Interrupt flag must be set to 1" );
644+ rc = - EINVAL ;
645+ goto err ;
646+ }
647+
556648 if (pcc_mbox_ctrl .txdone_irq ) {
557649 rc = pcc_parse_subspace_irq (pchan , pcct_entry );
558650 if (rc < 0 )
0 commit comments