diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/devfreq/devfreq.c | 153 | ||||
| -rw-r--r-- | drivers/power/avs/smartreflex.c | 39 |
2 files changed, 123 insertions, 69 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 141413067b5c..0ae3de76833b 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -285,6 +285,44 @@ static int devfreq_notify_transition(struct devfreq *devfreq, return 0; } +static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq, + u32 flags) +{ + struct devfreq_freqs freqs; + unsigned long cur_freq; + int err = 0; + + if (devfreq->profile->get_cur_freq) + devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq); + else + cur_freq = devfreq->previous_freq; + + freqs.old = cur_freq; + freqs.new = new_freq; + devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE); + + err = devfreq->profile->target(devfreq->dev.parent, &new_freq, flags); + if (err) { + freqs.new = cur_freq; + devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE); + return err; + } + + freqs.new = new_freq; + devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE); + + if (devfreq_update_status(devfreq, new_freq)) + dev_err(&devfreq->dev, + "Couldn't update frequency transition information.\n"); + + devfreq->previous_freq = new_freq; + + if (devfreq->suspend_freq) + devfreq->resume_freq = cur_freq; + + return err; +} + /* Load monitoring helper functions for governors use */ /** @@ -296,8 +334,7 @@ static int devfreq_notify_transition(struct devfreq *devfreq, */ int update_devfreq(struct devfreq *devfreq) { - struct devfreq_freqs freqs; - unsigned long freq, cur_freq, min_freq, max_freq; + unsigned long freq, min_freq, max_freq; int err = 0; u32 flags = 0; @@ -333,31 +370,8 @@ int update_devfreq(struct devfreq *devfreq) flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */ } - if (devfreq->profile->get_cur_freq) - devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq); - else - cur_freq = devfreq->previous_freq; + return devfreq_set_target(devfreq, freq, flags); - freqs.old = cur_freq; - freqs.new = freq; - devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE); - - err = devfreq->profile->target(devfreq->dev.parent, &freq, flags); - if (err) { - freqs.new = cur_freq; - devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE); - return err; - } - - freqs.new = freq; - devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE); - - if (devfreq_update_status(devfreq, freq)) - dev_err(&devfreq->dev, - "Couldn't update frequency transition information.\n"); - - devfreq->previous_freq = freq; - return err; } EXPORT_SYMBOL(update_devfreq); @@ -657,6 +671,9 @@ struct devfreq *devfreq_add_device(struct device *dev, } devfreq->max_freq = devfreq->scaling_max_freq; + devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev); + atomic_set(&devfreq->suspend_count, 0); + dev_set_name(&devfreq->dev, "devfreq%d", atomic_inc_return(&devfreq_no)); err = device_register(&devfreq->dev); @@ -857,14 +874,28 @@ EXPORT_SYMBOL(devm_devfreq_remove_device); */ int devfreq_suspend_device(struct devfreq *devfreq) { + int ret; + if (!devfreq) return -EINVAL; - if (!devfreq->governor) + if (atomic_inc_return(&devfreq->suspend_count) > 1) return 0; - return devfreq->governor->event_handler(devfreq, - DEVFREQ_GOV_SUSPEND, NULL); + if (devfreq->governor) { + ret = devfreq->governor->event_handler(devfreq, + DEVFREQ_GOV_SUSPEND, NULL); + if (ret) + return ret; + } + + if (devfreq->suspend_freq) { + ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0); + if (ret) + return ret; + } + + return 0; } EXPORT_SYMBOL(devfreq_suspend_device); @@ -878,18 +909,76 @@ EXPORT_SYMBOL(devfreq_suspend_device); */ int devfreq_resume_device(struct devfreq *devfreq) { + int ret; + if (!devfreq) return -EINVAL; - if (!devfreq->governor) + if (atomic_dec_return(&devfreq->suspend_count) >= 1) return 0; - return devfreq->governor->event_handler(devfreq, - DEVFREQ_GOV_RESUME, NULL); + if (devfreq->resume_freq) { + ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0); + if (ret) + return ret; + } + + if (devfreq->governor) { + ret = devfreq->governor->event_handler(devfreq, + DEVFREQ_GOV_RESUME, NULL); + if (ret) + return ret; + } + + return 0; } EXPORT_SYMBOL(devfreq_resume_device); /** + * devfreq_suspend() - Suspend devfreq governors and devices + * + * Called during system wide Suspend/Hibernate cycles for suspending governors + * and devices preserving the state for resume. On some platforms the devfreq + * device must have precise state (frequency) after resume in order to provide + * fully operating setup. + */ +void devfreq_suspend(void) +{ + struct devfreq *devfreq; + int ret; + + mutex_lock(&devfreq_list_lock); + list_for_each_entry(devfreq, &devfreq_list, node) { + ret = devfreq_suspend_device(devfreq); + if (ret) + dev_err(&devfreq->dev, + "failed to suspend devfreq device\n"); + } + mutex_unlock(&devfreq_list_lock); +} + +/** + * devfreq_resume() - Resume devfreq governors and devices + * + * Called during system wide Suspend/Hibernate cycle for resuming governors and + * devices that are suspended with devfreq_suspend(). + */ +void devfreq_resume(void) +{ + struct devfreq *devfreq; + int ret; + + mutex_lock(&devfreq_list_lock); + list_for_each_entry(devfreq, &devfreq_list, node) { + ret = devfreq_resume_device(devfreq); + if (ret) + dev_warn(&devfreq->dev, + "failed to resume devfreq device\n"); + } + mutex_unlock(&devfreq_list_lock); +} + +/** * devfreq_add_governor() - Add devfreq governor * @governor: the devfreq governor to be added */ diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c index 1360a7fa542c..c96c01e09740 100644 --- a/drivers/power/avs/smartreflex.c +++ b/drivers/power/avs/smartreflex.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * OMAP SmartReflex Voltage Control * @@ -11,10 +12,6 @@ * * Copyright (C) 2007 Texas Instruments, Inc. * Lesly A M <x0080970@ti.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/module.h> @@ -37,7 +34,6 @@ static LIST_HEAD(sr_list); static struct omap_sr_class_data *sr_class; -static struct omap_sr_pmic_data *sr_pmic_data; static struct dentry *sr_dbg_dir; static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value) @@ -780,25 +776,6 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) sr_class->disable(sr, 1); } -/** - * omap_sr_register_pmic() - API to register pmic specific info. - * @pmic_data: The structure containing pmic specific data. - * - * This API is to be called from the PMIC specific code to register with - * smartreflex driver pmic specific info. Currently the only info required - * is the smartreflex init on the PMIC side. - */ -void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data) -{ - if (!pmic_data) { - pr_warn("%s: Trying to register NULL PMIC data structure with smartreflex\n", - __func__); - return; - } - - sr_pmic_data = pmic_data; -} - /* PM Debug FS entries to enable and disable smartreflex. */ static int omap_sr_autocomp_show(void *data, u64 *val) { @@ -1010,8 +987,7 @@ static int omap_sr_remove(struct platform_device *pdev) if (sr_info->autocomp_active) sr_stop_vddautocomp(sr_info); - if (sr_info->dbg_dir) - debugfs_remove_recursive(sr_info->dbg_dir); + debugfs_remove_recursive(sr_info->dbg_dir); pm_runtime_disable(&pdev->dev); list_del(&sr_info->node); @@ -1065,17 +1041,6 @@ static int __init sr_init(void) { int ret = 0; - /* - * sr_init is a late init. If by then a pmic specific API is not - * registered either there is no need for anything to be done on - * the PMIC side or somebody has forgotten to register a PMIC - * handler. Warn for the second condition. - */ - if (sr_pmic_data && sr_pmic_data->sr_pmic_init) - sr_pmic_data->sr_pmic_init(); - else - pr_warn("%s: No PMIC hook to init smartreflex\n", __func__); - ret = platform_driver_register(&smartreflex_driver); if (ret) { pr_err("%s: platform driver register failed for SR\n", |
