Commit 56963d99 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'pm-sleep', 'pm-domains' and 'pm-avs'

* pm-sleep:
  PM / suspend: make sync() on suspend-to-RAM build-time optional
  PM / sleep: Allow devices without runtime PM to do direct-complete
  PM / autosleep: Use workqueue for user space wakeup sources garbage collector

* pm-domains:
  PM / Domains: Fix typo in description of genpd_dev_pm_detach()
  PM / Domains: Remove unusable governor dummies
  PM / Domains: Make pm_genpd_init() available to modules
  PM / domains: Align column headers and data in pm_genpd_summary output
  PM / Domains: Return -EPROBE_DEFER if we fail to init or turn-on domain
  PM / Domains: Correct unit address in power-controller example
  PM / Domains: Remove intermediate states from the power off sequence

* pm-avs:
  PM / AVS: rockchip-io: add io selectors and supplies for rk3368
  PM / AVS: rockchip-io: depend on CONFIG_POWER_AVS
...@@ -48,7 +48,7 @@ Example 2: ...@@ -48,7 +48,7 @@ Example 2:
#power-domain-cells = <1>; #power-domain-cells = <1>;
}; };
child: power-controller@12340000 { child: power-controller@12341000 {
compatible = "foo,power-controller"; compatible = "foo,power-controller";
reg = <0x12341000 0x1000>; reg = <0x12341000 0x1000>;
power-domains = <&parent 0>; power-domains = <&parent 0>;
......
...@@ -33,6 +33,8 @@ Required properties: ...@@ -33,6 +33,8 @@ Required properties:
- compatible: should be one of: - compatible: should be one of:
- "rockchip,rk3188-io-voltage-domain" for rk3188 - "rockchip,rk3188-io-voltage-domain" for rk3188
- "rockchip,rk3288-io-voltage-domain" for rk3288 - "rockchip,rk3288-io-voltage-domain" for rk3288
- "rockchip,rk3368-io-voltage-domain" for rk3368
- "rockchip,rk3368-pmu-io-voltage-domain" for rk3368 pmu-domains
- rockchip,grf: phandle to the syscon managing the "general register files" - rockchip,grf: phandle to the syscon managing the "general register files"
...@@ -64,6 +66,18 @@ Possible supplies for rk3288: ...@@ -64,6 +66,18 @@ Possible supplies for rk3288:
- sdcard-supply: The supply connected to SDMMC0_VDD. - sdcard-supply: The supply connected to SDMMC0_VDD.
- wifi-supply: The supply connected to APIO3_VDD. Also known as SDIO0. - wifi-supply: The supply connected to APIO3_VDD. Also known as SDIO0.
Possible supplies for rk3368:
- audio-supply: The supply connected to APIO3_VDD.
- dvp-supply: The supply connected to DVPIO_VDD.
- flash0-supply: The supply connected to FLASH0_VDD. Typically for eMMC
- gpio30-supply: The supply connected to APIO1_VDD.
- gpio1830 The supply connected to APIO4_VDD.
- sdcard-supply: The supply connected to SDMMC0_VDD.
- wifi-supply: The supply connected to APIO2_VDD. Also known as SDIO0.
Possible supplies for rk3368 pmu-domains:
- pmu-supply: The supply connected to PMUIO_VDD.
- vop-supply: The supply connected to LCDC_VDD.
Example: Example:
......
...@@ -341,6 +341,13 @@ the phases are: ...@@ -341,6 +341,13 @@ the phases are:
and is entirely responsible for bringing the device back to the and is entirely responsible for bringing the device back to the
functional state as appropriate. functional state as appropriate.
Note that this direct-complete procedure applies even if the device is
disabled for runtime PM; only the runtime-PM status matters. It follows
that if a device has system-sleep callbacks but does not support runtime
PM, then its prepare callback must never return a positive value. This
is because all devices are initially set to runtime-suspended with
runtime PM disabled.
2. The suspend methods should quiesce the device to stop it from performing 2. The suspend methods should quiesce the device to stop it from performing
I/O. They also may save the device registers and put it into the I/O. They also may save the device registers and put it into the
appropriate low-power state, depending on the bus type the device is on, appropriate low-power state, depending on the bus type the device is on,
......
...@@ -445,10 +445,6 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: ...@@ -445,10 +445,6 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
bool pm_runtime_status_suspended(struct device *dev); bool pm_runtime_status_suspended(struct device *dev);
- return true if the device's runtime PM status is 'suspended' - return true if the device's runtime PM status is 'suspended'
bool pm_runtime_suspended_if_enabled(struct device *dev);
- return true if the device's runtime PM status is 'suspended' and its
'power.disable_depth' field is equal to 1
void pm_runtime_allow(struct device *dev); void pm_runtime_allow(struct device *dev);
- set the power.runtime_auto flag for the device and decrease its usage - set the power.runtime_auto flag for the device and decrease its usage
counter (used by the /sys/devices/.../power/control interface to counter (used by the /sys/devices/.../power/control interface to
......
This diff is collapsed.
...@@ -1377,7 +1377,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) ...@@ -1377,7 +1377,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
if (dev->power.direct_complete) { if (dev->power.direct_complete) {
if (pm_runtime_status_suspended(dev)) { if (pm_runtime_status_suspended(dev)) {
pm_runtime_disable(dev); pm_runtime_disable(dev);
if (pm_runtime_suspended_if_enabled(dev)) if (pm_runtime_status_suspended(dev))
goto Complete; goto Complete;
pm_runtime_enable(dev); pm_runtime_enable(dev);
......
...@@ -13,7 +13,7 @@ menuconfig POWER_AVS ...@@ -13,7 +13,7 @@ menuconfig POWER_AVS
config ROCKCHIP_IODOMAIN config ROCKCHIP_IODOMAIN
tristate "Rockchip IO domain support" tristate "Rockchip IO domain support"
depends on ARCH_ROCKCHIP && OF depends on POWER_AVS && ARCH_ROCKCHIP && OF
help help
Say y here to enable support io domains on Rockchip SoCs. It is Say y here to enable support io domains on Rockchip SoCs. It is
necessary for the io domain setting of the SoC to match the necessary for the io domain setting of the SoC to match the
......
...@@ -43,6 +43,10 @@ ...@@ -43,6 +43,10 @@
#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
#define RK3368_SOC_CON15 0x43c
#define RK3368_SOC_CON15_FLASH0 BIT(14)
#define RK3368_SOC_FLASH_SUPPLY_NUM 2
struct rockchip_iodomain; struct rockchip_iodomain;
/** /**
...@@ -158,6 +162,25 @@ static void rk3288_iodomain_init(struct rockchip_iodomain *iod) ...@@ -158,6 +162,25 @@ static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
dev_warn(iod->dev, "couldn't update flash0 ctrl\n"); dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
} }
static void rk3368_iodomain_init(struct rockchip_iodomain *iod)
{
int ret;
u32 val;
/* if no flash supply we should leave things alone */
if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg)
return;
/*
* set flash0 iodomain to also use this framework
* instead of a special gpio.
*/
val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
ret = regmap_write(iod->grf, RK3368_SOC_CON15, val);
if (ret < 0)
dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
}
/* /*
* 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.
...@@ -201,6 +224,34 @@ static const struct rockchip_iodomain_soc_data soc_data_rk3288 = { ...@@ -201,6 +224,34 @@ static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
.init = rk3288_iodomain_init, .init = rk3288_iodomain_init,
}; };
static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
.grf_offset = 0x900,
.supply_names = {
NULL, /* reserved */
"dvp", /* DVPIO_VDD */
"flash0", /* FLASH0_VDD (emmc) */
"wifi", /* APIO2_VDD (sdio0) */
NULL,
"audio", /* APIO3_VDD */
"sdcard", /* SDMMC0_VDD (sdmmc) */
"gpio30", /* APIO1_VDD */
"gpio1830", /* APIO4_VDD (gpujtag) */
},
.init = rk3368_iodomain_init,
};
static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
.grf_offset = 0x100,
.supply_names = {
NULL,
NULL,
NULL,
NULL,
"pmu", /*PMU IO domain*/
"vop", /*LCDC IO domain*/
},
};
static const struct of_device_id rockchip_iodomain_match[] = { static const struct of_device_id rockchip_iodomain_match[] = {
{ {
.compatible = "rockchip,rk3188-io-voltage-domain", .compatible = "rockchip,rk3188-io-voltage-domain",
...@@ -210,6 +261,14 @@ static const struct of_device_id rockchip_iodomain_match[] = { ...@@ -210,6 +261,14 @@ static const struct of_device_id rockchip_iodomain_match[] = {
.compatible = "rockchip,rk3288-io-voltage-domain", .compatible = "rockchip,rk3288-io-voltage-domain",
.data = (void *)&soc_data_rk3288 .data = (void *)&soc_data_rk3288
}, },
{
.compatible = "rockchip,rk3368-io-voltage-domain",
.data = (void *)&soc_data_rk3368
},
{
.compatible = "rockchip,rk3368-pmu-io-voltage-domain",
.data = (void *)&soc_data_rk3368_pmu
},
{ /* sentinel */ }, { /* sentinel */ },
}; };
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
enum gpd_status { enum gpd_status {
GPD_STATE_ACTIVE = 0, /* PM domain is active */ GPD_STATE_ACTIVE = 0, /* PM domain is active */
GPD_STATE_WAIT_MASTER, /* PM domain's master is being waited for */
GPD_STATE_BUSY, /* Something is happening to the PM domain */
GPD_STATE_REPEAT, /* Power off in progress, to be repeated */
GPD_STATE_POWER_OFF, /* PM domain is off */ GPD_STATE_POWER_OFF, /* PM domain is off */
}; };
...@@ -59,9 +56,6 @@ struct generic_pm_domain { ...@@ -59,9 +56,6 @@ struct generic_pm_domain {
unsigned int in_progress; /* Number of devices being suspended now */ unsigned int in_progress; /* Number of devices being suspended now */
atomic_t sd_count; /* Number of subdomains with power "on" */ atomic_t sd_count; /* Number of subdomains with power "on" */
enum gpd_status status; /* Current state of the domain */ enum gpd_status status; /* Current state of the domain */
wait_queue_head_t status_wait_queue;
struct task_struct *poweroff_task; /* Powering off task */
unsigned int resume_count; /* Number of devices being resumed */
unsigned int device_count; /* Number of devices */ unsigned int device_count; /* Number of devices */
unsigned int suspended_count; /* System suspend device counter */ unsigned int suspended_count; /* System suspend device counter */
unsigned int prepared_count; /* Suspend counter of prepared devices */ unsigned int prepared_count; /* Suspend counter of prepared devices */
...@@ -113,7 +107,6 @@ struct generic_pm_domain_data { ...@@ -113,7 +107,6 @@ struct generic_pm_domain_data {
struct pm_domain_data base; struct pm_domain_data base;
struct gpd_timing_data td; struct gpd_timing_data td;
struct notifier_block nb; struct notifier_block nb;
int need_restore;
}; };
#ifdef CONFIG_PM_GENERIC_DOMAINS #ifdef CONFIG_PM_GENERIC_DOMAINS
...@@ -228,8 +221,6 @@ static inline int pm_genpd_name_poweron(const char *domain_name) ...@@ -228,8 +221,6 @@ static inline int pm_genpd_name_poweron(const char *domain_name)
return -ENOSYS; return -ENOSYS;
} }
static inline void pm_genpd_poweroff_unused(void) {} static inline void pm_genpd_poweroff_unused(void) {}
#define simple_qos_governor NULL
#define pm_domain_always_on_gov NULL
#endif #endif
static inline int pm_genpd_add_device(struct generic_pm_domain *genpd, static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
......
...@@ -98,11 +98,6 @@ static inline bool pm_runtime_status_suspended(struct device *dev) ...@@ -98,11 +98,6 @@ static inline bool pm_runtime_status_suspended(struct device *dev)
return dev->power.runtime_status == RPM_SUSPENDED; return dev->power.runtime_status == RPM_SUSPENDED;
} }
static inline bool pm_runtime_suspended_if_enabled(struct device *dev)
{
return pm_runtime_status_suspended(dev) && dev->power.disable_depth == 1;
}
static inline bool pm_runtime_enabled(struct device *dev) static inline bool pm_runtime_enabled(struct device *dev)
{ {
return !dev->power.disable_depth; return !dev->power.disable_depth;
...@@ -164,7 +159,6 @@ static inline void device_set_run_wake(struct device *dev, bool enable) {} ...@@ -164,7 +159,6 @@ static inline void device_set_run_wake(struct device *dev, bool enable) {}
static inline bool pm_runtime_suspended(struct device *dev) { return false; } static inline bool pm_runtime_suspended(struct device *dev) { return false; }
static inline bool pm_runtime_active(struct device *dev) { return true; } static inline bool pm_runtime_active(struct device *dev) { return true; }
static inline bool pm_runtime_status_suspended(struct device *dev) { return false; } static inline bool pm_runtime_status_suspended(struct device *dev) { return false; }
static inline bool pm_runtime_suspended_if_enabled(struct device *dev) { return false; }
static inline bool pm_runtime_enabled(struct device *dev) { return false; } static inline bool pm_runtime_enabled(struct device *dev) { return false; }
static inline void pm_runtime_no_callbacks(struct device *dev) {} static inline void pm_runtime_no_callbacks(struct device *dev) {}
......
...@@ -18,6 +18,16 @@ config SUSPEND_FREEZER ...@@ -18,6 +18,16 @@ config SUSPEND_FREEZER
Turning OFF this setting is NOT recommended! If in doubt, say Y. Turning OFF this setting is NOT recommended! If in doubt, say Y.
config SUSPEND_SKIP_SYNC
bool "Skip kernel's sys_sync() on suspend to RAM/standby"
depends on SUSPEND
depends on EXPERT
help
Skip the kernel sys_sync() before freezing user processes.
Some systems prefer not to pay this cost on every invocation
of suspend, or they are content with invoking sync() from
user-space before invoking suspend. Say Y if that's your case.
config HIBERNATE_CALLBACKS config HIBERNATE_CALLBACKS
bool bool
......
...@@ -484,11 +484,13 @@ static int enter_state(suspend_state_t state) ...@@ -484,11 +484,13 @@ static int enter_state(suspend_state_t state)
if (state == PM_SUSPEND_FREEZE) if (state == PM_SUSPEND_FREEZE)
freeze_begin(); freeze_begin();
#ifndef CONFIG_SUSPEND_SKIP_SYNC
trace_suspend_resume(TPS("sync_filesystems"), 0, true); trace_suspend_resume(TPS("sync_filesystems"), 0, true);
printk(KERN_INFO "PM: Syncing filesystems ... "); printk(KERN_INFO "PM: Syncing filesystems ... ");
sys_sync(); sys_sync();
printk("done.\n"); printk("done.\n");
trace_suspend_resume(TPS("sync_filesystems"), 0, false); trace_suspend_resume(TPS("sync_filesystems"), 0, false);
#endif
pr_debug("PM: Preparing system for sleep (%s)\n", pm_states[state]); pr_debug("PM: Preparing system for sleep (%s)\n", pm_states[state]);
error = suspend_prepare(state); error = suspend_prepare(state);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h>
#include "power.h" #include "power.h"
...@@ -83,7 +84,9 @@ static inline void decrement_wakelocks_number(void) {} ...@@ -83,7 +84,9 @@ static inline void decrement_wakelocks_number(void) {}
#define WL_GC_COUNT_MAX 100 #define WL_GC_COUNT_MAX 100
#define WL_GC_TIME_SEC 300 #define WL_GC_TIME_SEC 300
static void __wakelocks_gc(struct work_struct *work);
static LIST_HEAD(wakelocks_lru_list); static LIST_HEAD(wakelocks_lru_list);
static DECLARE_WORK(wakelock_work, __wakelocks_gc);
static unsigned int wakelocks_gc_count; static unsigned int wakelocks_gc_count;
static inline void wakelocks_lru_add(struct wakelock *wl) static inline void wakelocks_lru_add(struct wakelock *wl)
...@@ -96,13 +99,12 @@ static inline void wakelocks_lru_most_recent(struct wakelock *wl) ...@@ -96,13 +99,12 @@ static inline void wakelocks_lru_most_recent(struct wakelock *wl)
list_move(&wl->lru, &wakelocks_lru_list); list_move(&wl->lru, &wakelocks_lru_list);
} }
static void wakelocks_gc(void) static void __wakelocks_gc(struct work_struct *work)
{ {
struct wakelock *wl, *aux; struct wakelock *wl, *aux;
ktime_t now; ktime_t now;
if (++wakelocks_gc_count <= WL_GC_COUNT_MAX) mutex_lock(&wakelocks_lock);
return;
now = ktime_get(); now = ktime_get();
list_for_each_entry_safe_reverse(wl, aux, &wakelocks_lru_list, lru) { list_for_each_entry_safe_reverse(wl, aux, &wakelocks_lru_list, lru) {
...@@ -127,6 +129,16 @@ static void wakelocks_gc(void) ...@@ -127,6 +129,16 @@ static void wakelocks_gc(void)
} }
} }
wakelocks_gc_count = 0; wakelocks_gc_count = 0;
mutex_unlock(&wakelocks_lock);
}
static void wakelocks_gc(void)
{
if (++wakelocks_gc_count <= WL_GC_COUNT_MAX)
return;
schedule_work(&wakelock_work);
} }
#else /* !CONFIG_PM_WAKELOCKS_GC */ #else /* !CONFIG_PM_WAKELOCKS_GC */
static inline void wakelocks_lru_add(struct wakelock *wl) {} static inline void wakelocks_lru_add(struct wakelock *wl) {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment