Last active
October 17, 2018 15:26
-
-
Save pamolloy/8640710fec0291943a257e180a66c8ca to your computer and use it in GitHub Desktop.
Disabling runtime power management does not disable autosuspend
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/module.h> | |
#include <linux/device.h> | |
#include <linux/platform_device.h> | |
#include <linux/gpio.h> | |
#include <linux/gpio/consumer.h> | |
#include <linux/of_gpio.h> | |
#include <linux/pm_runtime.h> | |
#define MODULE_NAME "device" | |
#define COMPATIBLE_STRING "company,device" | |
#define DEVICE_AUTOSUSPEND_TIMEOUT 4000 // milliseconds | |
struct device_drvdata { | |
struct gpio_desc *power_gpio; | |
}; | |
static int device_runtime_suspend(struct device *dev) | |
{ | |
struct device_drvdata *drvdata = dev_get_drvdata(dev); | |
gpiod_set_value(drvdata->power_gpio, 0); | |
return 0; | |
} | |
static int device_runtime_resume(struct device *dev) | |
{ | |
struct device_drvdata *drvdata = dev_get_drvdata(dev); | |
gpiod_set_value(drvdata->power_gpio, 1); | |
return 0; | |
} | |
static const struct dev_pm_ops device_pm_ops = { | |
SET_RUNTIME_PM_OPS(device_runtime_suspend, device_runtime_resume, NULL) | |
}; | |
static int device_probe(struct platform_device *pdev) | |
{ | |
int status; | |
struct device_drvdata *drvdata; | |
struct device *dev = &pdev->dev; | |
drvdata = devm_kzalloc(dev, sizeof(struct device_drvdata), GFP_KERNEL); | |
if (!drvdata) { | |
err("failed to allocate memory for device driver data"); | |
status = -ENOMEM; | |
goto error_alloc_drvdata; | |
} | |
drvdata->power_gpio = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); | |
if (IS_ERR(drvdata->power_gpio)) { | |
err("failed to get power GPIO from device tree"); | |
status = PTR_ERR(drvdata->power_gpio); | |
goto error_gpiod_get; | |
} | |
dev_set_drvdata(dev, drvdata); | |
pm_runtime_set_autosuspend_delay(dev, DEVICE_AUTOSUSPEND_TIMEOUT); | |
pm_runtime_use_autosuspend(dev); | |
pm_runtime_enable(dev); | |
pm_runtime_mark_last_busy(dev); | |
if (pm_runtime_put_autosuspend(dev) != 0) { | |
err("failed to autosuspend device"); | |
goto error_pm_runtime_autosuspend; | |
} | |
return 0; | |
error_pm_runtime_autosuspend: | |
error_gpiod_get: | |
error_alloc_drvdata: | |
devm_kfree(dev, drvdata); | |
return status; | |
} | |
static int device_remove(struct platform_device *pdev) | |
{ | |
struct device *dev = &pdev->dev; | |
struct device_drvdata *drvdata = platform_get_drvdata(pdev); | |
pm_runtime_autosuspend(dev); | |
pm_runtime_disable(dev); | |
return 0; | |
} | |
static const struct of_device_id device_of_match[] = { | |
{ .compatible = COMPATIBLE_STRING }, | |
{}, | |
}; | |
struct platform_driver device_platform_driver = { | |
.probe = device_probe, | |
.remove = device_remove, | |
.driver = { | |
.name = MODULE_NAME, | |
.owner = THIS_MODULE, | |
.of_match_table = device_of_match, | |
.pm = &device_pm_ops, | |
}, | |
}; | |
module_platform_driver(device_platform_driver); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ cd /sys/devices/platform/device\@0/power/ | |
$ grep "" * | |
autosuspend_delay_ms:4000 | |
control:auto | |
runtime_active_time:0 | |
runtime_status:suspended | |
runtime_suspended_time:122968 | |
$ echo on > control | |
$ grep "" * | |
autosuspend_delay_ms:4000 | |
control:on | |
runtime_active_time:16856 | |
runtime_status:active | |
runtime_suspended_time:1552912 | |
$ grep "" * | |
autosuspend_delay_ms:4000 | |
control:on | |
runtime_active_time:16928 | |
runtime_status:suspended | |
runtime_suspended_time:1555212 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment