mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-21 06:01:23 +00:00
Merge branches 'pm-pci', 'acpi-pm', 'pm-sleep' and 'pm-avs'
* pm-pci: PCI / PM: Clean up outdated comments in pci_target_state() PCI / PM: Do not clear state_saved for devices that remain suspended * acpi-pm: ACPI: EC: Dispatch the EC GPE directly on s2idle wake ACPICA: Introduce acpi_dispatch_gpe() * pm-sleep: PM / hibernate: Fix oops at snapshot_write() PM / wakeup: Make s2idle_lock a RAW_SPINLOCK PM / s2idle: Make s2idle_wait_head swait based PM / wakeup: Make events_lock a RAW_SPINLOCK PM / suspend: Prevent might sleep splats * pm-avs: PM / AVS: rockchip-io: add io selectors and supplies for PX30
This commit is contained in:
commit
a24e16b131
16 changed files with 171 additions and 26 deletions
|
@ -31,6 +31,8 @@ SoC is on the same page.
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: should be one of:
|
- compatible: should be one of:
|
||||||
|
- "rockchip,px30-io-voltage-domain" for px30
|
||||||
|
- "rockchip,px30-pmu-io-voltage-domain" for px30 pmu-domains
|
||||||
- "rockchip,rk3188-io-voltage-domain" for rk3188
|
- "rockchip,rk3188-io-voltage-domain" for rk3188
|
||||||
- "rockchip,rk3228-io-voltage-domain" for rk3228
|
- "rockchip,rk3228-io-voltage-domain" for rk3228
|
||||||
- "rockchip,rk3288-io-voltage-domain" for rk3288
|
- "rockchip,rk3288-io-voltage-domain" for rk3288
|
||||||
|
@ -51,6 +53,19 @@ a phandle the relevant regulator. All specified supplies must be able
|
||||||
to report their voltage. The IO Voltage Domain for any non-specified
|
to report their voltage. The IO Voltage Domain for any non-specified
|
||||||
supplies will be not be touched.
|
supplies will be not be touched.
|
||||||
|
|
||||||
|
Possible supplies for PX30:
|
||||||
|
- vccio6-supply: The supply connected to VCCIO6.
|
||||||
|
- vccio1-supply: The supply connected to VCCIO1.
|
||||||
|
- vccio2-supply: The supply connected to VCCIO2.
|
||||||
|
- vccio3-supply: The supply connected to VCCIO3.
|
||||||
|
- vccio4-supply: The supply connected to VCCIO4.
|
||||||
|
- vccio5-supply: The supply connected to VCCIO5.
|
||||||
|
- vccio-oscgpi-supply: The supply connected to VCCIO_OSCGPI.
|
||||||
|
|
||||||
|
Possible supplies for PX30 pmu-domains:
|
||||||
|
- pmuio1-supply: The supply connected to PMUIO1.
|
||||||
|
- pmuio2-supply: The supply connected to PMUIO2.
|
||||||
|
|
||||||
Possible supplies for rk3188:
|
Possible supplies for rk3188:
|
||||||
- ap0-supply: The supply connected to AP0_VCC.
|
- ap0-supply: The supply connected to AP0_VCC.
|
||||||
- ap1-supply: The supply connected to AP1_VCC.
|
- ap1-supply: The supply connected to AP1_VCC.
|
||||||
|
|
|
@ -634,6 +634,12 @@ acpi_ev_detect_gpe(struct acpi_namespace_node *gpe_device,
|
||||||
|
|
||||||
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
|
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
|
||||||
|
|
||||||
|
if (!gpe_event_info) {
|
||||||
|
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
|
||||||
|
if (!gpe_event_info)
|
||||||
|
goto error_exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the info block for the entire GPE register */
|
/* Get the info block for the entire GPE register */
|
||||||
|
|
||||||
gpe_register_info = gpe_event_info->register_info;
|
gpe_register_info = gpe_event_info->register_info;
|
||||||
|
|
|
@ -637,6 +637,28 @@ unlock_and_exit:
|
||||||
|
|
||||||
ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
|
ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_gispatch_gpe
|
||||||
|
*
|
||||||
|
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
|
||||||
|
* gpe_number - GPE level within the GPE block
|
||||||
|
*
|
||||||
|
* RETURN: None
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
|
||||||
|
* (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)
|
||||||
|
{
|
||||||
|
ACPI_FUNCTION_TRACE(acpi_dispatch_gpe);
|
||||||
|
|
||||||
|
acpi_ev_detect_gpe(gpe_device, NULL, gpe_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe)
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* FUNCTION: acpi_finish_gpe
|
* FUNCTION: acpi_finish_gpe
|
||||||
|
|
|
@ -1034,6 +1034,12 @@ void acpi_ec_unblock_transactions(void)
|
||||||
acpi_ec_start(first_ec, true);
|
acpi_ec_start(first_ec, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void acpi_ec_dispatch_gpe(void)
|
||||||
|
{
|
||||||
|
if (first_ec)
|
||||||
|
acpi_dispatch_gpe(NULL, first_ec->gpe);
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
Event Management
|
Event Management
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
|
@ -188,6 +188,7 @@ int acpi_ec_ecdt_probe(void);
|
||||||
int acpi_ec_dsdt_probe(void);
|
int acpi_ec_dsdt_probe(void);
|
||||||
void acpi_ec_block_transactions(void);
|
void acpi_ec_block_transactions(void);
|
||||||
void acpi_ec_unblock_transactions(void);
|
void acpi_ec_unblock_transactions(void);
|
||||||
|
void acpi_ec_dispatch_gpe(void);
|
||||||
int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
||||||
acpi_handle handle, acpi_ec_query_func func,
|
acpi_handle handle, acpi_ec_query_func func,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
|
@ -989,6 +989,13 @@ static void acpi_s2idle_wake(void)
|
||||||
!irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) {
|
!irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) {
|
||||||
pm_system_cancel_wakeup();
|
pm_system_cancel_wakeup();
|
||||||
s2idle_wakeup = true;
|
s2idle_wakeup = true;
|
||||||
|
/*
|
||||||
|
* On some platforms with the LPS0 _DSM device noirq resume
|
||||||
|
* takes too much time for EC wakeup events to survive, so look
|
||||||
|
* for them now.
|
||||||
|
*/
|
||||||
|
if (lps0_device_handle)
|
||||||
|
acpi_ec_dispatch_gpe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ static void split_counters(unsigned int *cnt, unsigned int *inpr)
|
||||||
/* A preserved old value of the events counter. */
|
/* A preserved old value of the events counter. */
|
||||||
static unsigned int saved_count;
|
static unsigned int saved_count;
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(events_lock);
|
static DEFINE_RAW_SPINLOCK(events_lock);
|
||||||
|
|
||||||
static void pm_wakeup_timer_fn(struct timer_list *t);
|
static void pm_wakeup_timer_fn(struct timer_list *t);
|
||||||
|
|
||||||
|
@ -184,9 +184,9 @@ void wakeup_source_add(struct wakeup_source *ws)
|
||||||
timer_setup(&ws->timer, pm_wakeup_timer_fn, 0);
|
timer_setup(&ws->timer, pm_wakeup_timer_fn, 0);
|
||||||
ws->active = false;
|
ws->active = false;
|
||||||
|
|
||||||
spin_lock_irqsave(&events_lock, flags);
|
raw_spin_lock_irqsave(&events_lock, flags);
|
||||||
list_add_rcu(&ws->entry, &wakeup_sources);
|
list_add_rcu(&ws->entry, &wakeup_sources);
|
||||||
spin_unlock_irqrestore(&events_lock, flags);
|
raw_spin_unlock_irqrestore(&events_lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wakeup_source_add);
|
EXPORT_SYMBOL_GPL(wakeup_source_add);
|
||||||
|
|
||||||
|
@ -201,9 +201,9 @@ void wakeup_source_remove(struct wakeup_source *ws)
|
||||||
if (WARN_ON(!ws))
|
if (WARN_ON(!ws))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&events_lock, flags);
|
raw_spin_lock_irqsave(&events_lock, flags);
|
||||||
list_del_rcu(&ws->entry);
|
list_del_rcu(&ws->entry);
|
||||||
spin_unlock_irqrestore(&events_lock, flags);
|
raw_spin_unlock_irqrestore(&events_lock, flags);
|
||||||
synchronize_srcu(&wakeup_srcu);
|
synchronize_srcu(&wakeup_srcu);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wakeup_source_remove);
|
EXPORT_SYMBOL_GPL(wakeup_source_remove);
|
||||||
|
@ -842,7 +842,7 @@ bool pm_wakeup_pending(void)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
spin_lock_irqsave(&events_lock, flags);
|
raw_spin_lock_irqsave(&events_lock, flags);
|
||||||
if (events_check_enabled) {
|
if (events_check_enabled) {
|
||||||
unsigned int cnt, inpr;
|
unsigned int cnt, inpr;
|
||||||
|
|
||||||
|
@ -850,7 +850,7 @@ bool pm_wakeup_pending(void)
|
||||||
ret = (cnt != saved_count || inpr > 0);
|
ret = (cnt != saved_count || inpr > 0);
|
||||||
events_check_enabled = !ret;
|
events_check_enabled = !ret;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&events_lock, flags);
|
raw_spin_unlock_irqrestore(&events_lock, flags);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_debug("PM: Wakeup pending, aborting suspend\n");
|
pr_debug("PM: Wakeup pending, aborting suspend\n");
|
||||||
|
@ -939,13 +939,13 @@ bool pm_save_wakeup_count(unsigned int count)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
events_check_enabled = false;
|
events_check_enabled = false;
|
||||||
spin_lock_irqsave(&events_lock, flags);
|
raw_spin_lock_irqsave(&events_lock, flags);
|
||||||
split_counters(&cnt, &inpr);
|
split_counters(&cnt, &inpr);
|
||||||
if (cnt == count && inpr == 0) {
|
if (cnt == count && inpr == 0) {
|
||||||
saved_count = count;
|
saved_count = count;
|
||||||
events_check_enabled = true;
|
events_check_enabled = true;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&events_lock, flags);
|
raw_spin_unlock_irqrestore(&events_lock, flags);
|
||||||
return events_check_enabled;
|
return events_check_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -753,10 +753,11 @@ static int pci_pm_suspend(struct device *dev)
|
||||||
* better to resume the device from runtime suspend here.
|
* better to resume the device from runtime suspend here.
|
||||||
*/
|
*/
|
||||||
if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) ||
|
if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) ||
|
||||||
!pci_dev_keep_suspended(pci_dev))
|
!pci_dev_keep_suspended(pci_dev)) {
|
||||||
pm_runtime_resume(dev);
|
pm_runtime_resume(dev);
|
||||||
|
|
||||||
pci_dev->state_saved = false;
|
pci_dev->state_saved = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (pm->suspend) {
|
if (pm->suspend) {
|
||||||
pci_power_t prev = pci_dev->current_state;
|
pci_power_t prev = pci_dev->current_state;
|
||||||
int error;
|
int error;
|
||||||
|
|
|
@ -2025,8 +2025,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
|
||||||
|
|
||||||
if (platform_pci_power_manageable(dev)) {
|
if (platform_pci_power_manageable(dev)) {
|
||||||
/*
|
/*
|
||||||
* Call the platform to choose the target state of the device
|
* Call the platform to find the target state for the device.
|
||||||
* and enable wake-up from this state if supported.
|
|
||||||
*/
|
*/
|
||||||
pci_power_t state = platform_pci_choose_state(dev);
|
pci_power_t state = platform_pci_choose_state(dev);
|
||||||
|
|
||||||
|
@ -2059,8 +2058,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
|
||||||
if (wakeup) {
|
if (wakeup) {
|
||||||
/*
|
/*
|
||||||
* Find the deepest state from which the device can generate
|
* Find the deepest state from which the device can generate
|
||||||
* wake-up events, make it the target state and enable device
|
* PME#.
|
||||||
* to generate PME#.
|
|
||||||
*/
|
*/
|
||||||
if (dev->pme_support) {
|
if (dev->pme_support) {
|
||||||
while (target_state
|
while (target_state
|
||||||
|
|
|
@ -39,6 +39,10 @@
|
||||||
#define MAX_VOLTAGE_1_8 1980000
|
#define MAX_VOLTAGE_1_8 1980000
|
||||||
#define MAX_VOLTAGE_3_3 3600000
|
#define MAX_VOLTAGE_3_3 3600000
|
||||||
|
|
||||||
|
#define PX30_IO_VSEL 0x180
|
||||||
|
#define PX30_IO_VSEL_VCCIO6_SRC BIT(0)
|
||||||
|
#define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM 1
|
||||||
|
|
||||||
#define RK3288_SOC_CON2 0x24c
|
#define RK3288_SOC_CON2 0x24c
|
||||||
#define RK3288_SOC_CON2_FLASH0 BIT(7)
|
#define RK3288_SOC_CON2_FLASH0 BIT(7)
|
||||||
#define RK3288_SOC_FLASH_SUPPLY_NUM 2
|
#define RK3288_SOC_FLASH_SUPPLY_NUM 2
|
||||||
|
@ -151,6 +155,25 @@ static int rockchip_iodomain_notify(struct notifier_block *nb,
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void px30_iodomain_init(struct rockchip_iodomain *iod)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
/* if no VCCIO0 supply we should leave things alone */
|
||||||
|
if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set vccio0 iodomain to also use this framework
|
||||||
|
* instead of a special gpio.
|
||||||
|
*/
|
||||||
|
val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16);
|
||||||
|
ret = regmap_write(iod->grf, PX30_IO_VSEL, val);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_warn(iod->dev, "couldn't update vccio0 ctrl\n");
|
||||||
|
}
|
||||||
|
|
||||||
static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
|
static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -227,6 +250,43 @@ static void rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod)
|
||||||
dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
|
dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct rockchip_iodomain_soc_data soc_data_px30 = {
|
||||||
|
.grf_offset = 0x180,
|
||||||
|
.supply_names = {
|
||||||
|
NULL,
|
||||||
|
"vccio6",
|
||||||
|
"vccio1",
|
||||||
|
"vccio2",
|
||||||
|
"vccio3",
|
||||||
|
"vccio4",
|
||||||
|
"vccio5",
|
||||||
|
"vccio-oscgpi",
|
||||||
|
},
|
||||||
|
.init = px30_iodomain_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_iodomain_soc_data soc_data_px30_pmu = {
|
||||||
|
.grf_offset = 0x100,
|
||||||
|
.supply_names = {
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
"pmuio1",
|
||||||
|
"pmuio2",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On the rk3188 the io-domains are handled by a shared register with the
|
* On the rk3188 the io-domains are handled by a shared register with the
|
||||||
* lower 8 bits being still being continuing drive-strength settings.
|
* lower 8 bits being still being continuing drive-strength settings.
|
||||||
|
@ -380,6 +440,14 @@ static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id rockchip_iodomain_match[] = {
|
static const struct of_device_id rockchip_iodomain_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,px30-io-voltage-domain",
|
||||||
|
.data = (void *)&soc_data_px30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,px30-pmu-io-voltage-domain",
|
||||||
|
.data = (void *)&soc_data_px30_pmu
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.compatible = "rockchip,rk3188-io-voltage-domain",
|
.compatible = "rockchip,rk3188-io-voltage-domain",
|
||||||
.data = &soc_data_rk3188
|
.data = &soc_data_rk3188
|
||||||
|
|
|
@ -753,6 +753,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
|
||||||
u32 gpe_number,
|
u32 gpe_number,
|
||||||
acpi_event_status
|
acpi_event_status
|
||||||
*event_status))
|
*event_status))
|
||||||
|
ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number))
|
||||||
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
|
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
|
||||||
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
|
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
|
||||||
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
|
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
|
||||||
|
|
|
@ -542,6 +542,7 @@ extern enum system_states {
|
||||||
SYSTEM_HALT,
|
SYSTEM_HALT,
|
||||||
SYSTEM_POWER_OFF,
|
SYSTEM_POWER_OFF,
|
||||||
SYSTEM_RESTART,
|
SYSTEM_RESTART,
|
||||||
|
SYSTEM_SUSPEND,
|
||||||
} system_state;
|
} system_state;
|
||||||
|
|
||||||
/* This cannot be an enum because some may be used in assembly source. */
|
/* This cannot be an enum because some may be used in assembly source. */
|
||||||
|
|
|
@ -287,6 +287,8 @@ static int create_image(int platform_mode)
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
|
||||||
|
system_state = SYSTEM_SUSPEND;
|
||||||
|
|
||||||
error = syscore_suspend();
|
error = syscore_suspend();
|
||||||
if (error) {
|
if (error) {
|
||||||
pr_err("Some system devices failed to power down, aborting hibernation\n");
|
pr_err("Some system devices failed to power down, aborting hibernation\n");
|
||||||
|
@ -317,6 +319,7 @@ static int create_image(int platform_mode)
|
||||||
syscore_resume();
|
syscore_resume();
|
||||||
|
|
||||||
Enable_irqs:
|
Enable_irqs:
|
||||||
|
system_state = SYSTEM_RUNNING;
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
Enable_cpus:
|
Enable_cpus:
|
||||||
|
@ -445,6 +448,7 @@ static int resume_target_kernel(bool platform_mode)
|
||||||
goto Enable_cpus;
|
goto Enable_cpus;
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
system_state = SYSTEM_SUSPEND;
|
||||||
|
|
||||||
error = syscore_suspend();
|
error = syscore_suspend();
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -478,6 +482,7 @@ static int resume_target_kernel(bool platform_mode)
|
||||||
syscore_resume();
|
syscore_resume();
|
||||||
|
|
||||||
Enable_irqs:
|
Enable_irqs:
|
||||||
|
system_state = SYSTEM_RUNNING;
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
Enable_cpus:
|
Enable_cpus:
|
||||||
|
@ -563,6 +568,7 @@ int hibernation_platform_enter(void)
|
||||||
goto Enable_cpus;
|
goto Enable_cpus;
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
system_state = SYSTEM_SUSPEND;
|
||||||
syscore_suspend();
|
syscore_suspend();
|
||||||
if (pm_wakeup_pending()) {
|
if (pm_wakeup_pending()) {
|
||||||
error = -EAGAIN;
|
error = -EAGAIN;
|
||||||
|
@ -575,6 +581,7 @@ int hibernation_platform_enter(void)
|
||||||
|
|
||||||
Power_up:
|
Power_up:
|
||||||
syscore_resume();
|
syscore_resume();
|
||||||
|
system_state = SYSTEM_RUNNING;
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
Enable_cpus:
|
Enable_cpus:
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <linux/syscore_ops.h>
|
#include <linux/syscore_ops.h>
|
||||||
|
#include <linux/swait.h>
|
||||||
#include <linux/ftrace.h>
|
#include <linux/ftrace.h>
|
||||||
#include <trace/events/power.h>
|
#include <trace/events/power.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
@ -57,10 +58,10 @@ EXPORT_SYMBOL_GPL(pm_suspend_global_flags);
|
||||||
|
|
||||||
static const struct platform_suspend_ops *suspend_ops;
|
static const struct platform_suspend_ops *suspend_ops;
|
||||||
static const struct platform_s2idle_ops *s2idle_ops;
|
static const struct platform_s2idle_ops *s2idle_ops;
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(s2idle_wait_head);
|
static DECLARE_SWAIT_QUEUE_HEAD(s2idle_wait_head);
|
||||||
|
|
||||||
enum s2idle_states __read_mostly s2idle_state;
|
enum s2idle_states __read_mostly s2idle_state;
|
||||||
static DEFINE_SPINLOCK(s2idle_lock);
|
static DEFINE_RAW_SPINLOCK(s2idle_lock);
|
||||||
|
|
||||||
void s2idle_set_ops(const struct platform_s2idle_ops *ops)
|
void s2idle_set_ops(const struct platform_s2idle_ops *ops)
|
||||||
{
|
{
|
||||||
|
@ -78,12 +79,12 @@ static void s2idle_enter(void)
|
||||||
{
|
{
|
||||||
trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_TO_IDLE, true);
|
trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_TO_IDLE, true);
|
||||||
|
|
||||||
spin_lock_irq(&s2idle_lock);
|
raw_spin_lock_irq(&s2idle_lock);
|
||||||
if (pm_wakeup_pending())
|
if (pm_wakeup_pending())
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
s2idle_state = S2IDLE_STATE_ENTER;
|
s2idle_state = S2IDLE_STATE_ENTER;
|
||||||
spin_unlock_irq(&s2idle_lock);
|
raw_spin_unlock_irq(&s2idle_lock);
|
||||||
|
|
||||||
get_online_cpus();
|
get_online_cpus();
|
||||||
cpuidle_resume();
|
cpuidle_resume();
|
||||||
|
@ -91,17 +92,17 @@ static void s2idle_enter(void)
|
||||||
/* Push all the CPUs into the idle loop. */
|
/* Push all the CPUs into the idle loop. */
|
||||||
wake_up_all_idle_cpus();
|
wake_up_all_idle_cpus();
|
||||||
/* Make the current CPU wait so it can enter the idle loop too. */
|
/* Make the current CPU wait so it can enter the idle loop too. */
|
||||||
wait_event(s2idle_wait_head,
|
swait_event(s2idle_wait_head,
|
||||||
s2idle_state == S2IDLE_STATE_WAKE);
|
s2idle_state == S2IDLE_STATE_WAKE);
|
||||||
|
|
||||||
cpuidle_pause();
|
cpuidle_pause();
|
||||||
put_online_cpus();
|
put_online_cpus();
|
||||||
|
|
||||||
spin_lock_irq(&s2idle_lock);
|
raw_spin_lock_irq(&s2idle_lock);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
s2idle_state = S2IDLE_STATE_NONE;
|
s2idle_state = S2IDLE_STATE_NONE;
|
||||||
spin_unlock_irq(&s2idle_lock);
|
raw_spin_unlock_irq(&s2idle_lock);
|
||||||
|
|
||||||
trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_TO_IDLE, false);
|
trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_TO_IDLE, false);
|
||||||
}
|
}
|
||||||
|
@ -156,12 +157,12 @@ void s2idle_wake(void)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&s2idle_lock, flags);
|
raw_spin_lock_irqsave(&s2idle_lock, flags);
|
||||||
if (s2idle_state > S2IDLE_STATE_NONE) {
|
if (s2idle_state > S2IDLE_STATE_NONE) {
|
||||||
s2idle_state = S2IDLE_STATE_WAKE;
|
s2idle_state = S2IDLE_STATE_WAKE;
|
||||||
wake_up(&s2idle_wait_head);
|
swake_up(&s2idle_wait_head);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&s2idle_lock, flags);
|
raw_spin_unlock_irqrestore(&s2idle_lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(s2idle_wake);
|
EXPORT_SYMBOL_GPL(s2idle_wake);
|
||||||
|
|
||||||
|
@ -428,6 +429,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
|
||||||
arch_suspend_disable_irqs();
|
arch_suspend_disable_irqs();
|
||||||
BUG_ON(!irqs_disabled());
|
BUG_ON(!irqs_disabled());
|
||||||
|
|
||||||
|
system_state = SYSTEM_SUSPEND;
|
||||||
|
|
||||||
error = syscore_suspend();
|
error = syscore_suspend();
|
||||||
if (!error) {
|
if (!error) {
|
||||||
*wakeup = pm_wakeup_pending();
|
*wakeup = pm_wakeup_pending();
|
||||||
|
@ -443,6 +446,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
|
||||||
syscore_resume();
|
syscore_resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
system_state = SYSTEM_RUNNING;
|
||||||
|
|
||||||
arch_suspend_enable_irqs();
|
arch_suspend_enable_irqs();
|
||||||
BUG_ON(irqs_disabled());
|
BUG_ON(irqs_disabled());
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,11 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf,
|
||||||
res = PAGE_SIZE - pg_offp;
|
res = PAGE_SIZE - pg_offp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!data_of(data->handle)) {
|
||||||
|
res = -EINVAL;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp,
|
res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp,
|
||||||
buf, count);
|
buf, count);
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
|
|
|
@ -490,6 +490,7 @@ void tick_freeze(void)
|
||||||
if (tick_freeze_depth == num_online_cpus()) {
|
if (tick_freeze_depth == num_online_cpus()) {
|
||||||
trace_suspend_resume(TPS("timekeeping_freeze"),
|
trace_suspend_resume(TPS("timekeeping_freeze"),
|
||||||
smp_processor_id(), true);
|
smp_processor_id(), true);
|
||||||
|
system_state = SYSTEM_SUSPEND;
|
||||||
timekeeping_suspend();
|
timekeeping_suspend();
|
||||||
} else {
|
} else {
|
||||||
tick_suspend_local();
|
tick_suspend_local();
|
||||||
|
@ -513,6 +514,7 @@ void tick_unfreeze(void)
|
||||||
|
|
||||||
if (tick_freeze_depth == num_online_cpus()) {
|
if (tick_freeze_depth == num_online_cpus()) {
|
||||||
timekeeping_resume();
|
timekeeping_resume();
|
||||||
|
system_state = SYSTEM_RUNNING;
|
||||||
trace_suspend_resume(TPS("timekeeping_freeze"),
|
trace_suspend_resume(TPS("timekeeping_freeze"),
|
||||||
smp_processor_id(), false);
|
smp_processor_id(), false);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue