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
@ -31,6 +31,8 @@ SoC is on the same page.
|
||||
|
||||
Required properties:
|
||||
- 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,rk3228-io-voltage-domain" for rk3228
|
||||
- "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
|
||||
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:
|
||||
- ap0-supply: The supply connected to AP0_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);
|
||||
|
||||
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 */
|
||||
|
||||
gpe_register_info = gpe_event_info->register_info;
|
||||
|
@ -637,6 +637,28 @@ acpi_get_gpe_status(acpi_handle gpe_device,
|
||||
|
||||
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
|
||||
|
@ -1034,6 +1034,12 @@ void acpi_ec_unblock_transactions(void)
|
||||
acpi_ec_start(first_ec, true);
|
||||
}
|
||||
|
||||
void acpi_ec_dispatch_gpe(void)
|
||||
{
|
||||
if (first_ec)
|
||||
acpi_dispatch_gpe(NULL, first_ec->gpe);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Event Management
|
||||
-------------------------------------------------------------------------- */
|
||||
|
@ -188,6 +188,7 @@ int acpi_ec_ecdt_probe(void);
|
||||
int acpi_ec_dsdt_probe(void);
|
||||
void acpi_ec_block_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,
|
||||
acpi_handle handle, acpi_ec_query_func func,
|
||||
void *data);
|
||||
|
@ -989,6 +989,13 @@ static void acpi_s2idle_wake(void)
|
||||
!irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) {
|
||||
pm_system_cancel_wakeup();
|
||||
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. */
|
||||
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);
|
||||
|
||||
@ -184,9 +184,9 @@ void wakeup_source_add(struct wakeup_source *ws)
|
||||
timer_setup(&ws->timer, pm_wakeup_timer_fn, 0);
|
||||
ws->active = false;
|
||||
|
||||
spin_lock_irqsave(&events_lock, flags);
|
||||
raw_spin_lock_irqsave(&events_lock, flags);
|
||||
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);
|
||||
|
||||
@ -201,9 +201,9 @@ void wakeup_source_remove(struct wakeup_source *ws)
|
||||
if (WARN_ON(!ws))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&events_lock, flags);
|
||||
raw_spin_lock_irqsave(&events_lock, flags);
|
||||
list_del_rcu(&ws->entry);
|
||||
spin_unlock_irqrestore(&events_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&events_lock, flags);
|
||||
synchronize_srcu(&wakeup_srcu);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wakeup_source_remove);
|
||||
@ -842,7 +842,7 @@ bool pm_wakeup_pending(void)
|
||||
unsigned long flags;
|
||||
bool ret = false;
|
||||
|
||||
spin_lock_irqsave(&events_lock, flags);
|
||||
raw_spin_lock_irqsave(&events_lock, flags);
|
||||
if (events_check_enabled) {
|
||||
unsigned int cnt, inpr;
|
||||
|
||||
@ -850,7 +850,7 @@ bool pm_wakeup_pending(void)
|
||||
ret = (cnt != saved_count || inpr > 0);
|
||||
events_check_enabled = !ret;
|
||||
}
|
||||
spin_unlock_irqrestore(&events_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&events_lock, flags);
|
||||
|
||||
if (ret) {
|
||||
pr_debug("PM: Wakeup pending, aborting suspend\n");
|
||||
@ -939,13 +939,13 @@ bool pm_save_wakeup_count(unsigned int count)
|
||||
unsigned long flags;
|
||||
|
||||
events_check_enabled = false;
|
||||
spin_lock_irqsave(&events_lock, flags);
|
||||
raw_spin_lock_irqsave(&events_lock, flags);
|
||||
split_counters(&cnt, &inpr);
|
||||
if (cnt == count && inpr == 0) {
|
||||
saved_count = count;
|
||||
events_check_enabled = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&events_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&events_lock, flags);
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
pci_dev->state_saved = false;
|
||||
}
|
||||
|
||||
pci_dev->state_saved = false;
|
||||
if (pm->suspend) {
|
||||
pci_power_t prev = pci_dev->current_state;
|
||||
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)) {
|
||||
/*
|
||||
* Call the platform to choose the target state of the device
|
||||
* and enable wake-up from this state if supported.
|
||||
* Call the platform to find the target state for the device.
|
||||
*/
|
||||
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) {
|
||||
/*
|
||||
* Find the deepest state from which the device can generate
|
||||
* wake-up events, make it the target state and enable device
|
||||
* to generate PME#.
|
||||
* PME#.
|
||||
*/
|
||||
if (dev->pme_support) {
|
||||
while (target_state
|
||||
|
@ -39,6 +39,10 @@
|
||||
#define MAX_VOLTAGE_1_8 1980000
|
||||
#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_FLASH0 BIT(7)
|
||||
#define RK3288_SOC_FLASH_SUPPLY_NUM 2
|
||||
@ -151,6 +155,25 @@ static int rockchip_iodomain_notify(struct notifier_block *nb,
|
||||
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)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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
|
||||
* 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[] = {
|
||||
{
|
||||
.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",
|
||||
.data = &soc_data_rk3188
|
||||
|
@ -753,6 +753,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
|
||||
u32 gpe_number,
|
||||
acpi_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_enable_all_runtime_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_POWER_OFF,
|
||||
SYSTEM_RESTART,
|
||||
SYSTEM_SUSPEND,
|
||||
} system_state;
|
||||
|
||||
/* 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();
|
||||
|
||||
system_state = SYSTEM_SUSPEND;
|
||||
|
||||
error = syscore_suspend();
|
||||
if (error) {
|
||||
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();
|
||||
|
||||
Enable_irqs:
|
||||
system_state = SYSTEM_RUNNING;
|
||||
local_irq_enable();
|
||||
|
||||
Enable_cpus:
|
||||
@ -445,6 +448,7 @@ static int resume_target_kernel(bool platform_mode)
|
||||
goto Enable_cpus;
|
||||
|
||||
local_irq_disable();
|
||||
system_state = SYSTEM_SUSPEND;
|
||||
|
||||
error = syscore_suspend();
|
||||
if (error)
|
||||
@ -478,6 +482,7 @@ static int resume_target_kernel(bool platform_mode)
|
||||
syscore_resume();
|
||||
|
||||
Enable_irqs:
|
||||
system_state = SYSTEM_RUNNING;
|
||||
local_irq_enable();
|
||||
|
||||
Enable_cpus:
|
||||
@ -563,6 +568,7 @@ int hibernation_platform_enter(void)
|
||||
goto Enable_cpus;
|
||||
|
||||
local_irq_disable();
|
||||
system_state = SYSTEM_SUSPEND;
|
||||
syscore_suspend();
|
||||
if (pm_wakeup_pending()) {
|
||||
error = -EAGAIN;
|
||||
@ -575,6 +581,7 @@ int hibernation_platform_enter(void)
|
||||
|
||||
Power_up:
|
||||
syscore_resume();
|
||||
system_state = SYSTEM_RUNNING;
|
||||
local_irq_enable();
|
||||
|
||||
Enable_cpus:
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <linux/swait.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <trace/events/power.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_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;
|
||||
static DEFINE_SPINLOCK(s2idle_lock);
|
||||
static DEFINE_RAW_SPINLOCK(s2idle_lock);
|
||||
|
||||
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);
|
||||
|
||||
spin_lock_irq(&s2idle_lock);
|
||||
raw_spin_lock_irq(&s2idle_lock);
|
||||
if (pm_wakeup_pending())
|
||||
goto out;
|
||||
|
||||
s2idle_state = S2IDLE_STATE_ENTER;
|
||||
spin_unlock_irq(&s2idle_lock);
|
||||
raw_spin_unlock_irq(&s2idle_lock);
|
||||
|
||||
get_online_cpus();
|
||||
cpuidle_resume();
|
||||
@ -91,17 +92,17 @@ static void s2idle_enter(void)
|
||||
/* Push all the CPUs into the idle loop. */
|
||||
wake_up_all_idle_cpus();
|
||||
/* Make the current CPU wait so it can enter the idle loop too. */
|
||||
wait_event(s2idle_wait_head,
|
||||
s2idle_state == S2IDLE_STATE_WAKE);
|
||||
swait_event(s2idle_wait_head,
|
||||
s2idle_state == S2IDLE_STATE_WAKE);
|
||||
|
||||
cpuidle_pause();
|
||||
put_online_cpus();
|
||||
|
||||
spin_lock_irq(&s2idle_lock);
|
||||
raw_spin_lock_irq(&s2idle_lock);
|
||||
|
||||
out:
|
||||
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);
|
||||
}
|
||||
@ -156,12 +157,12 @@ void s2idle_wake(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&s2idle_lock, flags);
|
||||
raw_spin_lock_irqsave(&s2idle_lock, flags);
|
||||
if (s2idle_state > S2IDLE_STATE_NONE) {
|
||||
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);
|
||||
|
||||
@ -428,6 +429,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
|
||||
arch_suspend_disable_irqs();
|
||||
BUG_ON(!irqs_disabled());
|
||||
|
||||
system_state = SYSTEM_SUSPEND;
|
||||
|
||||
error = syscore_suspend();
|
||||
if (!error) {
|
||||
*wakeup = pm_wakeup_pending();
|
||||
@ -443,6 +446,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
|
||||
syscore_resume();
|
||||
}
|
||||
|
||||
system_state = SYSTEM_RUNNING;
|
||||
|
||||
arch_suspend_enable_irqs();
|
||||
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;
|
||||
}
|
||||
|
||||
if (!data_of(data->handle)) {
|
||||
res = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp,
|
||||
buf, count);
|
||||
if (res > 0)
|
||||
|
@ -490,6 +490,7 @@ void tick_freeze(void)
|
||||
if (tick_freeze_depth == num_online_cpus()) {
|
||||
trace_suspend_resume(TPS("timekeeping_freeze"),
|
||||
smp_processor_id(), true);
|
||||
system_state = SYSTEM_SUSPEND;
|
||||
timekeeping_suspend();
|
||||
} else {
|
||||
tick_suspend_local();
|
||||
@ -513,6 +514,7 @@ void tick_unfreeze(void)
|
||||
|
||||
if (tick_freeze_depth == num_online_cpus()) {
|
||||
timekeeping_resume();
|
||||
system_state = SYSTEM_RUNNING;
|
||||
trace_suspend_resume(TPS("timekeeping_freeze"),
|
||||
smp_processor_id(), false);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user