@@ -427,6 +427,142 @@ static int register_device_clock(struct acpi_device *adev,
427
427
return 0 ;
428
428
}
429
429
430
+ struct lpss_device_links {
431
+ const char * supplier_hid ;
432
+ const char * supplier_uid ;
433
+ const char * consumer_hid ;
434
+ const char * consumer_uid ;
435
+ u32 flags ;
436
+ };
437
+
438
+ /*
439
+ * The _DEP method is used to identify dependencies but instead of creating
440
+ * device links for every handle in _DEP, only links in the following list are
441
+ * created. That is necessary because, in the general case, _DEP can refer to
442
+ * devices that might not have drivers, or that are on different buses, or where
443
+ * the supplier is not enumerated until after the consumer is probed.
444
+ */
445
+ static const struct lpss_device_links lpss_device_links [] = {
446
+ {"808622C1" , "7" , "80860F14" , "3" , DL_FLAG_PM_RUNTIME },
447
+ };
448
+
449
+ static bool hid_uid_match (const char * hid1 , const char * uid1 ,
450
+ const char * hid2 , const char * uid2 )
451
+ {
452
+ return !strcmp (hid1 , hid2 ) && uid1 && uid2 && !strcmp (uid1 , uid2 );
453
+ }
454
+
455
+ static bool acpi_lpss_is_supplier (struct acpi_device * adev ,
456
+ const struct lpss_device_links * link )
457
+ {
458
+ return hid_uid_match (acpi_device_hid (adev ), acpi_device_uid (adev ),
459
+ link -> supplier_hid , link -> supplier_uid );
460
+ }
461
+
462
+ static bool acpi_lpss_is_consumer (struct acpi_device * adev ,
463
+ const struct lpss_device_links * link )
464
+ {
465
+ return hid_uid_match (acpi_device_hid (adev ), acpi_device_uid (adev ),
466
+ link -> consumer_hid , link -> consumer_uid );
467
+ }
468
+
469
+ struct hid_uid {
470
+ const char * hid ;
471
+ const char * uid ;
472
+ };
473
+
474
+ static int match_hid_uid (struct device * dev , void * data )
475
+ {
476
+ struct acpi_device * adev = ACPI_COMPANION (dev );
477
+ struct hid_uid * id = data ;
478
+
479
+ if (!adev )
480
+ return 0 ;
481
+
482
+ return hid_uid_match (acpi_device_hid (adev ), acpi_device_uid (adev ),
483
+ id -> hid , id -> uid );
484
+ }
485
+
486
+ static struct device * acpi_lpss_find_device (const char * hid , const char * uid )
487
+ {
488
+ struct hid_uid data = {
489
+ .hid = hid ,
490
+ .uid = uid ,
491
+ };
492
+
493
+ return bus_find_device (& platform_bus_type , NULL , & data , match_hid_uid );
494
+ }
495
+
496
+ static bool acpi_lpss_dep (struct acpi_device * adev , acpi_handle handle )
497
+ {
498
+ struct acpi_handle_list dep_devices ;
499
+ acpi_status status ;
500
+ int i ;
501
+
502
+ if (!acpi_has_method (adev -> handle , "_DEP" ))
503
+ return false;
504
+
505
+ status = acpi_evaluate_reference (adev -> handle , "_DEP" , NULL ,
506
+ & dep_devices );
507
+ if (ACPI_FAILURE (status )) {
508
+ dev_dbg (& adev -> dev , "Failed to evaluate _DEP.\n" );
509
+ return false;
510
+ }
511
+
512
+ for (i = 0 ; i < dep_devices .count ; i ++ ) {
513
+ if (dep_devices .handles [i ] == handle )
514
+ return true;
515
+ }
516
+
517
+ return false;
518
+ }
519
+
520
+ static void acpi_lpss_link_consumer (struct device * dev1 ,
521
+ const struct lpss_device_links * link )
522
+ {
523
+ struct device * dev2 ;
524
+
525
+ dev2 = acpi_lpss_find_device (link -> consumer_hid , link -> consumer_uid );
526
+ if (!dev2 )
527
+ return ;
528
+
529
+ if (acpi_lpss_dep (ACPI_COMPANION (dev2 ), ACPI_HANDLE (dev1 )))
530
+ device_link_add (dev2 , dev1 , link -> flags );
531
+
532
+ put_device (dev2 );
533
+ }
534
+
535
+ static void acpi_lpss_link_supplier (struct device * dev1 ,
536
+ const struct lpss_device_links * link )
537
+ {
538
+ struct device * dev2 ;
539
+
540
+ dev2 = acpi_lpss_find_device (link -> supplier_hid , link -> supplier_uid );
541
+ if (!dev2 )
542
+ return ;
543
+
544
+ if (acpi_lpss_dep (ACPI_COMPANION (dev1 ), ACPI_HANDLE (dev2 )))
545
+ device_link_add (dev1 , dev2 , link -> flags );
546
+
547
+ put_device (dev2 );
548
+ }
549
+
550
+ static void acpi_lpss_create_device_links (struct acpi_device * adev ,
551
+ struct platform_device * pdev )
552
+ {
553
+ int i ;
554
+
555
+ for (i = 0 ; i < ARRAY_SIZE (lpss_device_links ); i ++ ) {
556
+ const struct lpss_device_links * link = & lpss_device_links [i ];
557
+
558
+ if (acpi_lpss_is_supplier (adev , link ))
559
+ acpi_lpss_link_consumer (& pdev -> dev , link );
560
+
561
+ if (acpi_lpss_is_consumer (adev , link ))
562
+ acpi_lpss_link_supplier (& pdev -> dev , link );
563
+ }
564
+ }
565
+
430
566
static int acpi_lpss_create_device (struct acpi_device * adev ,
431
567
const struct acpi_device_id * id )
432
568
{
@@ -500,6 +636,7 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
500
636
adev -> driver_data = pdata ;
501
637
pdev = acpi_create_platform_device (adev , dev_desc -> properties );
502
638
if (!IS_ERR_OR_NULL (pdev )) {
639
+ acpi_lpss_create_device_links (adev , pdev );
503
640
return 1 ;
504
641
}
505
642
0 commit comments