diff options
| -rw-r--r-- | drivers/acpi/acpi_lpss.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 93d160661f4c..f6b71afb80ea 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
| @@ -499,14 +499,15 @@ static void acpi_lpss_set_ltr(struct device *dev, s32 val) | |||
| 499 | /** | 499 | /** |
| 500 | * acpi_lpss_save_ctx() - Save the private registers of LPSS device | 500 | * acpi_lpss_save_ctx() - Save the private registers of LPSS device |
| 501 | * @dev: LPSS device | 501 | * @dev: LPSS device |
| 502 | * @pdata: pointer to the private data of the LPSS device | ||
| 502 | * | 503 | * |
| 503 | * Most LPSS devices have private registers which may loose their context when | 504 | * Most LPSS devices have private registers which may loose their context when |
| 504 | * the device is powered down. acpi_lpss_save_ctx() saves those registers into | 505 | * the device is powered down. acpi_lpss_save_ctx() saves those registers into |
| 505 | * prv_reg_ctx array. | 506 | * prv_reg_ctx array. |
| 506 | */ | 507 | */ |
| 507 | static void acpi_lpss_save_ctx(struct device *dev) | 508 | static void acpi_lpss_save_ctx(struct device *dev, |
| 509 | struct lpss_private_data *pdata) | ||
| 508 | { | 510 | { |
| 509 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | ||
| 510 | unsigned int i; | 511 | unsigned int i; |
| 511 | 512 | ||
| 512 | for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { | 513 | for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { |
| @@ -521,12 +522,13 @@ static void acpi_lpss_save_ctx(struct device *dev) | |||
| 521 | /** | 522 | /** |
| 522 | * acpi_lpss_restore_ctx() - Restore the private registers of LPSS device | 523 | * acpi_lpss_restore_ctx() - Restore the private registers of LPSS device |
| 523 | * @dev: LPSS device | 524 | * @dev: LPSS device |
| 525 | * @pdata: pointer to the private data of the LPSS device | ||
| 524 | * | 526 | * |
| 525 | * Restores the registers that were previously stored with acpi_lpss_save_ctx(). | 527 | * Restores the registers that were previously stored with acpi_lpss_save_ctx(). |
| 526 | */ | 528 | */ |
| 527 | static void acpi_lpss_restore_ctx(struct device *dev) | 529 | static void acpi_lpss_restore_ctx(struct device *dev, |
| 530 | struct lpss_private_data *pdata) | ||
| 528 | { | 531 | { |
| 529 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | ||
| 530 | unsigned int i; | 532 | unsigned int i; |
| 531 | 533 | ||
| 532 | /* | 534 | /* |
| @@ -549,23 +551,31 @@ static void acpi_lpss_restore_ctx(struct device *dev) | |||
| 549 | #ifdef CONFIG_PM_SLEEP | 551 | #ifdef CONFIG_PM_SLEEP |
| 550 | static int acpi_lpss_suspend_late(struct device *dev) | 552 | static int acpi_lpss_suspend_late(struct device *dev) |
| 551 | { | 553 | { |
| 552 | int ret = pm_generic_suspend_late(dev); | 554 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
| 555 | int ret; | ||
| 553 | 556 | ||
| 557 | ret = pm_generic_suspend_late(dev); | ||
| 554 | if (ret) | 558 | if (ret) |
| 555 | return ret; | 559 | return ret; |
| 556 | 560 | ||
| 557 | acpi_lpss_save_ctx(dev); | 561 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
| 562 | acpi_lpss_save_ctx(dev, pdata); | ||
| 563 | |||
| 558 | return acpi_dev_suspend_late(dev); | 564 | return acpi_dev_suspend_late(dev); |
| 559 | } | 565 | } |
| 560 | 566 | ||
| 561 | static int acpi_lpss_resume_early(struct device *dev) | 567 | static int acpi_lpss_resume_early(struct device *dev) |
| 562 | { | 568 | { |
| 563 | int ret = acpi_dev_resume_early(dev); | 569 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
| 570 | int ret; | ||
| 564 | 571 | ||
| 572 | ret = acpi_dev_resume_early(dev); | ||
| 565 | if (ret) | 573 | if (ret) |
| 566 | return ret; | 574 | return ret; |
| 567 | 575 | ||
| 568 | acpi_lpss_restore_ctx(dev); | 576 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
| 577 | acpi_lpss_restore_ctx(dev, pdata); | ||
| 578 | |||
| 569 | return pm_generic_resume_early(dev); | 579 | return pm_generic_resume_early(dev); |
| 570 | } | 580 | } |
| 571 | #endif /* CONFIG_PM_SLEEP */ | 581 | #endif /* CONFIG_PM_SLEEP */ |
| @@ -573,23 +583,31 @@ static int acpi_lpss_resume_early(struct device *dev) | |||
| 573 | #ifdef CONFIG_PM_RUNTIME | 583 | #ifdef CONFIG_PM_RUNTIME |
| 574 | static int acpi_lpss_runtime_suspend(struct device *dev) | 584 | static int acpi_lpss_runtime_suspend(struct device *dev) |
| 575 | { | 585 | { |
| 576 | int ret = pm_generic_runtime_suspend(dev); | 586 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
| 587 | int ret; | ||
| 577 | 588 | ||
| 589 | ret = pm_generic_runtime_suspend(dev); | ||
| 578 | if (ret) | 590 | if (ret) |
| 579 | return ret; | 591 | return ret; |
| 580 | 592 | ||
| 581 | acpi_lpss_save_ctx(dev); | 593 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
| 594 | acpi_lpss_save_ctx(dev, pdata); | ||
| 595 | |||
| 582 | return acpi_dev_runtime_suspend(dev); | 596 | return acpi_dev_runtime_suspend(dev); |
| 583 | } | 597 | } |
| 584 | 598 | ||
| 585 | static int acpi_lpss_runtime_resume(struct device *dev) | 599 | static int acpi_lpss_runtime_resume(struct device *dev) |
| 586 | { | 600 | { |
| 587 | int ret = acpi_dev_runtime_resume(dev); | 601 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
| 602 | int ret; | ||
| 588 | 603 | ||
| 604 | ret = acpi_dev_runtime_resume(dev); | ||
| 589 | if (ret) | 605 | if (ret) |
| 590 | return ret; | 606 | return ret; |
| 591 | 607 | ||
| 592 | acpi_lpss_restore_ctx(dev); | 608 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
| 609 | acpi_lpss_restore_ctx(dev, pdata); | ||
| 610 | |||
| 593 | return pm_generic_runtime_resume(dev); | 611 | return pm_generic_runtime_resume(dev); |
| 594 | } | 612 | } |
| 595 | #endif /* CONFIG_PM_RUNTIME */ | 613 | #endif /* CONFIG_PM_RUNTIME */ |
| @@ -631,22 +649,21 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, | |||
| 631 | return 0; | 649 | return 0; |
| 632 | 650 | ||
| 633 | pdata = acpi_driver_data(adev); | 651 | pdata = acpi_driver_data(adev); |
| 634 | if (!pdata || !pdata->mmio_base) | 652 | if (!pdata) |
| 635 | return 0; | 653 | return 0; |
| 636 | 654 | ||
| 637 | if (pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { | 655 | if (pdata->mmio_base && |
| 656 | pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { | ||
| 638 | dev_err(&pdev->dev, "MMIO size insufficient to access LTR\n"); | 657 | dev_err(&pdev->dev, "MMIO size insufficient to access LTR\n"); |
| 639 | return 0; | 658 | return 0; |
| 640 | } | 659 | } |
| 641 | 660 | ||
| 642 | switch (action) { | 661 | switch (action) { |
| 643 | case BUS_NOTIFY_BOUND_DRIVER: | 662 | case BUS_NOTIFY_BOUND_DRIVER: |
| 644 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) | 663 | pdev->dev.pm_domain = &acpi_lpss_pm_domain; |
| 645 | pdev->dev.pm_domain = &acpi_lpss_pm_domain; | ||
| 646 | break; | 664 | break; |
| 647 | case BUS_NOTIFY_UNBOUND_DRIVER: | 665 | case BUS_NOTIFY_UNBOUND_DRIVER: |
| 648 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) | 666 | pdev->dev.pm_domain = NULL; |
| 649 | pdev->dev.pm_domain = NULL; | ||
| 650 | break; | 667 | break; |
| 651 | case BUS_NOTIFY_ADD_DEVICE: | 668 | case BUS_NOTIFY_ADD_DEVICE: |
| 652 | if (pdata->dev_desc->flags & LPSS_LTR) | 669 | if (pdata->dev_desc->flags & LPSS_LTR) |
