@@ -89,12 +89,18 @@ struct pcc_chan_reg {
89
89
* @db: PCC register bundle for the doorbell register
90
90
* @plat_irq_ack: PCC register bundle for the platform interrupt acknowledge
91
91
* 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
92
95
* @plat_irq: platform interrupt
93
96
*/
94
97
struct pcc_chan_info {
95
98
struct pcc_mbox_chan chan ;
96
99
struct pcc_chan_reg db ;
97
100
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 ;
98
104
int plat_irq ;
99
105
};
100
106
@@ -228,9 +234,29 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
228
234
{
229
235
struct pcc_chan_info * pchan ;
230
236
struct mbox_chan * chan = p ;
237
+ u64 val ;
238
+ int ret ;
231
239
232
240
pchan = chan -> con_priv ;
233
241
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
+
234
260
if (pcc_chan_reg_read_modify_write (& pchan -> plat_irq_ack ))
235
261
return IRQ_NONE ;
236
262
@@ -340,8 +366,13 @@ EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
340
366
*/
341
367
static int pcc_send_data (struct mbox_chan * chan , void * data )
342
368
{
369
+ int ret ;
343
370
struct pcc_chan_info * pchan = chan -> con_priv ;
344
371
372
+ ret = pcc_chan_reg_read_modify_write (& pchan -> cmd_update );
373
+ if (ret )
374
+ return ret ;
375
+
345
376
return pcc_chan_reg_read_modify_write (& pchan -> db );
346
377
}
347
378
@@ -434,6 +465,16 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
434
465
pcct2_ss -> ack_preserve_mask ,
435
466
pcct2_ss -> ack_write_mask , 0 ,
436
467
"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" );
437
478
}
438
479
439
480
return ret ;
@@ -452,14 +493,48 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
452
493
{
453
494
int ret = 0 ;
454
495
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
+ }
463
538
return ret ;
464
539
}
465
540
@@ -473,15 +548,25 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
473
548
static void pcc_parse_subspace_shmem (struct pcc_chan_info * pchan ,
474
549
struct acpi_subtable_header * pcct_entry )
475
550
{
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
+ }
485
570
}
486
571
487
572
/**
@@ -553,6 +638,13 @@ static int __init acpi_pcc_probe(void)
553
638
pcc_mbox_channels [i ].con_priv = pchan ;
554
639
pchan -> chan .mchan = & pcc_mbox_channels [i ];
555
640
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
+
556
648
if (pcc_mbox_ctrl .txdone_irq ) {
557
649
rc = pcc_parse_subspace_irq (pchan , pcct_entry );
558
650
if (rc < 0 )
0 commit comments