xref: /openbmc/linux/drivers/devfreq/devfreq.c (revision 87832e937c808a7ebc41254b408362e3255c87c9)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a3c98b8bSMyungJoo Ham /*
3a3c98b8bSMyungJoo Ham  * devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework
4a3c98b8bSMyungJoo Ham  *	    for Non-CPU Devices.
5a3c98b8bSMyungJoo Ham  *
6a3c98b8bSMyungJoo Ham  * Copyright (C) 2011 Samsung Electronics
7a3c98b8bSMyungJoo Ham  *	MyungJoo Ham <myungjoo.ham@samsung.com>
8a3c98b8bSMyungJoo Ham  */
9a3c98b8bSMyungJoo Ham 
10a3c98b8bSMyungJoo Ham #include <linux/kernel.h>
1123c7b54cSEnric Balletbo i Serra #include <linux/kmod.h>
12a3c98b8bSMyungJoo Ham #include <linux/sched.h>
13490a421bSChanwoo Choi #include <linux/debugfs.h>
141224451bSDaniel Lezcano #include <linux/devfreq_cooling.h>
15a3c98b8bSMyungJoo Ham #include <linux/errno.h>
16a3c98b8bSMyungJoo Ham #include <linux/err.h>
17a3c98b8bSMyungJoo Ham #include <linux/init.h>
18417dc4bbSPaul Gortmaker #include <linux/export.h>
19a3c98b8bSMyungJoo Ham #include <linux/slab.h>
20952f6d13SMyungJoo Ham #include <linux/stat.h>
21e4db1c74SNishanth Menon #include <linux/pm_opp.h>
22a3c98b8bSMyungJoo Ham #include <linux/devfreq.h>
23a3c98b8bSMyungJoo Ham #include <linux/workqueue.h>
24a3c98b8bSMyungJoo Ham #include <linux/platform_device.h>
25a3c98b8bSMyungJoo Ham #include <linux/list.h>
26a3c98b8bSMyungJoo Ham #include <linux/printk.h>
27a3c98b8bSMyungJoo Ham #include <linux/hrtimer.h>
288f510aebSChanwoo Choi #include <linux/of.h>
2905d7ae15SLeonard Crestez #include <linux/pm_qos.h>
3004c8984aSDaniel Lezcano #include <linux/units.h>
31a3c98b8bSMyungJoo Ham #include "governor.h"
32a3c98b8bSMyungJoo Ham 
33cf451adfSLukasz Luba #define CREATE_TRACE_POINTS
34cf451adfSLukasz Luba #include <trace/events/devfreq.h>
35cf451adfSLukasz Luba 
360dd25a0dSChanwoo Choi #define IS_SUPPORTED_FLAG(f, name) ((f & DEVFREQ_GOV_FLAG_##name) ? true : false)
375f1a9066SChanwoo Choi #define IS_SUPPORTED_ATTR(f, name) ((f & DEVFREQ_GOV_ATTR_##name) ? true : false)
3805d7ae15SLeonard Crestez 
391a1357eaSNishanth Menon static struct class *devfreq_class;
40490a421bSChanwoo Choi static struct dentry *devfreq_debugfs;
41a3c98b8bSMyungJoo Ham 
42a3c98b8bSMyungJoo Ham /*
437e6fdd4bSRajagopal Venkat  * devfreq core provides delayed work based load monitoring helper
447e6fdd4bSRajagopal Venkat  * functions. Governors can use these or can implement their own
457e6fdd4bSRajagopal Venkat  * monitoring mechanism.
46a3c98b8bSMyungJoo Ham  */
47a3c98b8bSMyungJoo Ham static struct workqueue_struct *devfreq_wq;
48a3c98b8bSMyungJoo Ham 
493aa173b8SNishanth Menon /* The list of all device-devfreq governors */
503aa173b8SNishanth Menon static LIST_HEAD(devfreq_governor_list);
51a3c98b8bSMyungJoo Ham /* The list of all device-devfreq */
52a3c98b8bSMyungJoo Ham static LIST_HEAD(devfreq_list);
53a3c98b8bSMyungJoo Ham static DEFINE_MUTEX(devfreq_list_lock);
54a3c98b8bSMyungJoo Ham 
554dc3bab8SChanwoo Choi static const char timer_name[][DEVFREQ_NAME_LEN] = {
564dc3bab8SChanwoo Choi 	[DEVFREQ_TIMER_DEFERRABLE] = { "deferrable" },
574dc3bab8SChanwoo Choi 	[DEVFREQ_TIMER_DELAYED] = { "delayed" },
584dc3bab8SChanwoo Choi };
594dc3bab8SChanwoo Choi 
60a3c98b8bSMyungJoo Ham /**
61a3c98b8bSMyungJoo Ham  * find_device_devfreq() - find devfreq struct using device pointer
62a3c98b8bSMyungJoo Ham  * @dev:	device pointer used to lookup device devfreq.
63a3c98b8bSMyungJoo Ham  *
64a3c98b8bSMyungJoo Ham  * Search the list of device devfreqs and return the matched device's
65a3c98b8bSMyungJoo Ham  * devfreq info. devfreq_list_lock should be held by the caller.
66a3c98b8bSMyungJoo Ham  */
find_device_devfreq(struct device * dev)67a3c98b8bSMyungJoo Ham static struct devfreq *find_device_devfreq(struct device *dev)
68a3c98b8bSMyungJoo Ham {
69a3c98b8bSMyungJoo Ham 	struct devfreq *tmp_devfreq;
70a3c98b8bSMyungJoo Ham 
718fc0e48eSKrzysztof Kozlowski 	lockdep_assert_held(&devfreq_list_lock);
728fc0e48eSKrzysztof Kozlowski 
739348da2fSViresh Kumar 	if (IS_ERR_OR_NULL(dev)) {
74a3c98b8bSMyungJoo Ham 		pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
75a3c98b8bSMyungJoo Ham 		return ERR_PTR(-EINVAL);
76a3c98b8bSMyungJoo Ham 	}
77a3c98b8bSMyungJoo Ham 
78a3c98b8bSMyungJoo Ham 	list_for_each_entry(tmp_devfreq, &devfreq_list, node) {
79a3c98b8bSMyungJoo Ham 		if (tmp_devfreq->dev.parent == dev)
80a3c98b8bSMyungJoo Ham 			return tmp_devfreq;
81a3c98b8bSMyungJoo Ham 	}
82a3c98b8bSMyungJoo Ham 
83a3c98b8bSMyungJoo Ham 	return ERR_PTR(-ENODEV);
84a3c98b8bSMyungJoo Ham }
85a3c98b8bSMyungJoo Ham 
find_available_min_freq(struct devfreq * devfreq)86ab8f58adSChanwoo Choi static unsigned long find_available_min_freq(struct devfreq *devfreq)
87ab8f58adSChanwoo Choi {
88ab8f58adSChanwoo Choi 	struct dev_pm_opp *opp;
89ab8f58adSChanwoo Choi 	unsigned long min_freq = 0;
90ab8f58adSChanwoo Choi 
91ab8f58adSChanwoo Choi 	opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &min_freq);
92ab8f58adSChanwoo Choi 	if (IS_ERR(opp))
93ab8f58adSChanwoo Choi 		min_freq = 0;
94ab8f58adSChanwoo Choi 	else
95ab8f58adSChanwoo Choi 		dev_pm_opp_put(opp);
96ab8f58adSChanwoo Choi 
97ab8f58adSChanwoo Choi 	return min_freq;
98ab8f58adSChanwoo Choi }
99ab8f58adSChanwoo Choi 
find_available_max_freq(struct devfreq * devfreq)100ab8f58adSChanwoo Choi static unsigned long find_available_max_freq(struct devfreq *devfreq)
101ab8f58adSChanwoo Choi {
102ab8f58adSChanwoo Choi 	struct dev_pm_opp *opp;
103ab8f58adSChanwoo Choi 	unsigned long max_freq = ULONG_MAX;
104ab8f58adSChanwoo Choi 
105ab8f58adSChanwoo Choi 	opp = dev_pm_opp_find_freq_floor(devfreq->dev.parent, &max_freq);
106ab8f58adSChanwoo Choi 	if (IS_ERR(opp))
107ab8f58adSChanwoo Choi 		max_freq = 0;
108ab8f58adSChanwoo Choi 	else
109ab8f58adSChanwoo Choi 		dev_pm_opp_put(opp);
110ab8f58adSChanwoo Choi 
111ab8f58adSChanwoo Choi 	return max_freq;
112ab8f58adSChanwoo Choi }
113ab8f58adSChanwoo Choi 
114a3c98b8bSMyungJoo Ham /**
115713472e5SChanwoo Choi  * devfreq_get_freq_range() - Get the current freq range
11646cecc0bSLeonard Crestez  * @devfreq:	the devfreq instance
11746cecc0bSLeonard Crestez  * @min_freq:	the min frequency
11846cecc0bSLeonard Crestez  * @max_freq:	the max frequency
11946cecc0bSLeonard Crestez  *
12046cecc0bSLeonard Crestez  * This takes into consideration all constraints.
12146cecc0bSLeonard Crestez  */
devfreq_get_freq_range(struct devfreq * devfreq,unsigned long * min_freq,unsigned long * max_freq)122713472e5SChanwoo Choi void devfreq_get_freq_range(struct devfreq *devfreq,
12346cecc0bSLeonard Crestez 			    unsigned long *min_freq,
12446cecc0bSLeonard Crestez 			    unsigned long *max_freq)
12546cecc0bSLeonard Crestez {
126b5d281f6SChristian Marangi 	unsigned long *freq_table = devfreq->freq_table;
12705d7ae15SLeonard Crestez 	s32 qos_min_freq, qos_max_freq;
12846cecc0bSLeonard Crestez 
12946cecc0bSLeonard Crestez 	lockdep_assert_held(&devfreq->lock);
13046cecc0bSLeonard Crestez 
13146cecc0bSLeonard Crestez 	/*
13246cecc0bSLeonard Crestez 	 * Initialize minimum/maximum frequency from freq table.
13346cecc0bSLeonard Crestez 	 * The devfreq drivers can initialize this in either ascending or
13446cecc0bSLeonard Crestez 	 * descending order and devfreq core supports both.
13546cecc0bSLeonard Crestez 	 */
136b5d281f6SChristian Marangi 	if (freq_table[0] < freq_table[devfreq->max_state - 1]) {
13746cecc0bSLeonard Crestez 		*min_freq = freq_table[0];
138b5d281f6SChristian Marangi 		*max_freq = freq_table[devfreq->max_state - 1];
13946cecc0bSLeonard Crestez 	} else {
140b5d281f6SChristian Marangi 		*min_freq = freq_table[devfreq->max_state - 1];
14146cecc0bSLeonard Crestez 		*max_freq = freq_table[0];
14246cecc0bSLeonard Crestez 	}
14346cecc0bSLeonard Crestez 
14405d7ae15SLeonard Crestez 	/* Apply constraints from PM QoS */
14505d7ae15SLeonard Crestez 	qos_min_freq = dev_pm_qos_read_value(devfreq->dev.parent,
14605d7ae15SLeonard Crestez 					     DEV_PM_QOS_MIN_FREQUENCY);
14705d7ae15SLeonard Crestez 	qos_max_freq = dev_pm_qos_read_value(devfreq->dev.parent,
14805d7ae15SLeonard Crestez 					     DEV_PM_QOS_MAX_FREQUENCY);
14905d7ae15SLeonard Crestez 	*min_freq = max(*min_freq, (unsigned long)HZ_PER_KHZ * qos_min_freq);
15005d7ae15SLeonard Crestez 	if (qos_max_freq != PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE)
15105d7ae15SLeonard Crestez 		*max_freq = min(*max_freq,
15205d7ae15SLeonard Crestez 				(unsigned long)HZ_PER_KHZ * qos_max_freq);
15305d7ae15SLeonard Crestez 
15446cecc0bSLeonard Crestez 	/* Apply constraints from OPP interface */
15546cecc0bSLeonard Crestez 	*min_freq = max(*min_freq, devfreq->scaling_min_freq);
15646cecc0bSLeonard Crestez 	*max_freq = min(*max_freq, devfreq->scaling_max_freq);
15746cecc0bSLeonard Crestez 
15846cecc0bSLeonard Crestez 	if (*min_freq > *max_freq)
15946cecc0bSLeonard Crestez 		*min_freq = *max_freq;
16046cecc0bSLeonard Crestez }
161713472e5SChanwoo Choi EXPORT_SYMBOL(devfreq_get_freq_range);
16246cecc0bSLeonard Crestez 
16346cecc0bSLeonard Crestez /**
164e552bbafSJonghwa Lee  * devfreq_get_freq_level() - Lookup freq_table for the frequency
165e552bbafSJonghwa Lee  * @devfreq:	the devfreq instance
166e552bbafSJonghwa Lee  * @freq:	the target frequency
167e552bbafSJonghwa Lee  */
devfreq_get_freq_level(struct devfreq * devfreq,unsigned long freq)168e552bbafSJonghwa Lee static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
169e552bbafSJonghwa Lee {
170e552bbafSJonghwa Lee 	int lev;
171e552bbafSJonghwa Lee 
172b5d281f6SChristian Marangi 	for (lev = 0; lev < devfreq->max_state; lev++)
173b5d281f6SChristian Marangi 		if (freq == devfreq->freq_table[lev])
174e552bbafSJonghwa Lee 			return lev;
175e552bbafSJonghwa Lee 
176e552bbafSJonghwa Lee 	return -EINVAL;
177e552bbafSJonghwa Lee }
178e552bbafSJonghwa Lee 
set_freq_table(struct devfreq * devfreq)179ea572f81SChanwoo Choi static int set_freq_table(struct devfreq *devfreq)
1800ec09ac2SChanwoo Choi {
1810ec09ac2SChanwoo Choi 	struct dev_pm_opp *opp;
1820ec09ac2SChanwoo Choi 	unsigned long freq;
1830ec09ac2SChanwoo Choi 	int i, count;
1840ec09ac2SChanwoo Choi 
1850ec09ac2SChanwoo Choi 	/* Initialize the freq_table from OPP table */
1860ec09ac2SChanwoo Choi 	count = dev_pm_opp_get_opp_count(devfreq->dev.parent);
1870ec09ac2SChanwoo Choi 	if (count <= 0)
188ea572f81SChanwoo Choi 		return -EINVAL;
1890ec09ac2SChanwoo Choi 
190b5d281f6SChristian Marangi 	devfreq->max_state = count;
191b5d281f6SChristian Marangi 	devfreq->freq_table = devm_kcalloc(devfreq->dev.parent,
192b5d281f6SChristian Marangi 					   devfreq->max_state,
193b5d281f6SChristian Marangi 					   sizeof(*devfreq->freq_table),
1940ec09ac2SChanwoo Choi 					   GFP_KERNEL);
195b5d281f6SChristian Marangi 	if (!devfreq->freq_table)
196ea572f81SChanwoo Choi 		return -ENOMEM;
1970ec09ac2SChanwoo Choi 
198b5d281f6SChristian Marangi 	for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) {
1990ec09ac2SChanwoo Choi 		opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
2000ec09ac2SChanwoo Choi 		if (IS_ERR(opp)) {
201b5d281f6SChristian Marangi 			devm_kfree(devfreq->dev.parent, devfreq->freq_table);
202ea572f81SChanwoo Choi 			return PTR_ERR(opp);
2030ec09ac2SChanwoo Choi 		}
2048a31d9d9SViresh Kumar 		dev_pm_opp_put(opp);
205b5d281f6SChristian Marangi 		devfreq->freq_table[i] = freq;
2060ec09ac2SChanwoo Choi 	}
207ea572f81SChanwoo Choi 
208ea572f81SChanwoo Choi 	return 0;
2090ec09ac2SChanwoo Choi }
2100ec09ac2SChanwoo Choi 
2110ec09ac2SChanwoo Choi /**
212e552bbafSJonghwa Lee  * devfreq_update_status() - Update statistics of devfreq behavior
213e552bbafSJonghwa Lee  * @devfreq:	the devfreq instance
214e552bbafSJonghwa Lee  * @freq:	the update target frequency
215e552bbafSJonghwa Lee  */
devfreq_update_status(struct devfreq * devfreq,unsigned long freq)21630582c25SChanwoo Choi int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
217e552bbafSJonghwa Lee {
218e35d35a1SSaravana Kannan 	int lev, prev_lev, ret = 0;
219b76b3479SKamil Konieczny 	u64 cur_time;
220e552bbafSJonghwa Lee 
2212abb0d52SLeonard Crestez 	lockdep_assert_held(&devfreq->lock);
222b76b3479SKamil Konieczny 	cur_time = get_jiffies_64();
223e35d35a1SSaravana Kannan 
224d0563a03STobias Jakobi 	/* Immediately exit if previous_freq is not initialized yet. */
225d0563a03STobias Jakobi 	if (!devfreq->previous_freq)
226d0563a03STobias Jakobi 		goto out;
227d0563a03STobias Jakobi 
228e35d35a1SSaravana Kannan 	prev_lev = devfreq_get_freq_level(devfreq, devfreq->previous_freq);
229e35d35a1SSaravana Kannan 	if (prev_lev < 0) {
230e35d35a1SSaravana Kannan 		ret = prev_lev;
231e35d35a1SSaravana Kannan 		goto out;
232e35d35a1SSaravana Kannan 	}
233e35d35a1SSaravana Kannan 
2341ebd0bc0SKamil Konieczny 	devfreq->stats.time_in_state[prev_lev] +=
2351ebd0bc0SKamil Konieczny 			cur_time - devfreq->stats.last_update;
236e35d35a1SSaravana Kannan 
237e35d35a1SSaravana Kannan 	lev = devfreq_get_freq_level(devfreq, freq);
238e35d35a1SSaravana Kannan 	if (lev < 0) {
239e35d35a1SSaravana Kannan 		ret = lev;
240e35d35a1SSaravana Kannan 		goto out;
241e35d35a1SSaravana Kannan 	}
242e35d35a1SSaravana Kannan 
243e35d35a1SSaravana Kannan 	if (lev != prev_lev) {
2441ebd0bc0SKamil Konieczny 		devfreq->stats.trans_table[
245b5d281f6SChristian Marangi 			(prev_lev * devfreq->max_state) + lev]++;
2461ebd0bc0SKamil Konieczny 		devfreq->stats.total_trans++;
247e552bbafSJonghwa Lee 	}
248e552bbafSJonghwa Lee 
249e35d35a1SSaravana Kannan out:
2501ebd0bc0SKamil Konieczny 	devfreq->stats.last_update = cur_time;
251e35d35a1SSaravana Kannan 	return ret;
252e552bbafSJonghwa Lee }
25330582c25SChanwoo Choi EXPORT_SYMBOL(devfreq_update_status);
254e552bbafSJonghwa Lee 
2553aa173b8SNishanth Menon /**
2563aa173b8SNishanth Menon  * find_devfreq_governor() - find devfreq governor from name
2573aa173b8SNishanth Menon  * @name:	name of the governor
2583aa173b8SNishanth Menon  *
2593aa173b8SNishanth Menon  * Search the list of devfreq governors and return the matched
2603aa173b8SNishanth Menon  * governor's pointer. devfreq_list_lock should be held by the caller.
2613aa173b8SNishanth Menon  */
find_devfreq_governor(const char * name)2623aa173b8SNishanth Menon static struct devfreq_governor *find_devfreq_governor(const char *name)
2633aa173b8SNishanth Menon {
2643aa173b8SNishanth Menon 	struct devfreq_governor *tmp_governor;
2653aa173b8SNishanth Menon 
2668fc0e48eSKrzysztof Kozlowski 	lockdep_assert_held(&devfreq_list_lock);
2678fc0e48eSKrzysztof Kozlowski 
2689348da2fSViresh Kumar 	if (IS_ERR_OR_NULL(name)) {
2693aa173b8SNishanth Menon 		pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
2703aa173b8SNishanth Menon 		return ERR_PTR(-EINVAL);
2713aa173b8SNishanth Menon 	}
2723aa173b8SNishanth Menon 
2733aa173b8SNishanth Menon 	list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
2743aa173b8SNishanth Menon 		if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
2753aa173b8SNishanth Menon 			return tmp_governor;
2763aa173b8SNishanth Menon 	}
2773aa173b8SNishanth Menon 
2783aa173b8SNishanth Menon 	return ERR_PTR(-ENODEV);
2793aa173b8SNishanth Menon }
2803aa173b8SNishanth Menon 
28123c7b54cSEnric Balletbo i Serra /**
28223c7b54cSEnric Balletbo i Serra  * try_then_request_governor() - Try to find the governor and request the
28323c7b54cSEnric Balletbo i Serra  *                               module if is not found.
28423c7b54cSEnric Balletbo i Serra  * @name:	name of the governor
28523c7b54cSEnric Balletbo i Serra  *
28623c7b54cSEnric Balletbo i Serra  * Search the list of devfreq governors and request the module and try again
28723c7b54cSEnric Balletbo i Serra  * if is not found. This can happen when both drivers (the governor driver
28823c7b54cSEnric Balletbo i Serra  * and the driver that call devfreq_add_device) are built as modules.
28923c7b54cSEnric Balletbo i Serra  * devfreq_list_lock should be held by the caller. Returns the matched
290b53b0128SEnric Balletbo i Serra  * governor's pointer or an error pointer.
29123c7b54cSEnric Balletbo i Serra  */
try_then_request_governor(const char * name)29223c7b54cSEnric Balletbo i Serra static struct devfreq_governor *try_then_request_governor(const char *name)
29323c7b54cSEnric Balletbo i Serra {
29423c7b54cSEnric Balletbo i Serra 	struct devfreq_governor *governor;
29523c7b54cSEnric Balletbo i Serra 	int err = 0;
29623c7b54cSEnric Balletbo i Serra 
2978fc0e48eSKrzysztof Kozlowski 	lockdep_assert_held(&devfreq_list_lock);
2988fc0e48eSKrzysztof Kozlowski 
29923c7b54cSEnric Balletbo i Serra 	if (IS_ERR_OR_NULL(name)) {
30023c7b54cSEnric Balletbo i Serra 		pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
30123c7b54cSEnric Balletbo i Serra 		return ERR_PTR(-EINVAL);
30223c7b54cSEnric Balletbo i Serra 	}
30323c7b54cSEnric Balletbo i Serra 
30423c7b54cSEnric Balletbo i Serra 	governor = find_devfreq_governor(name);
30523c7b54cSEnric Balletbo i Serra 	if (IS_ERR(governor)) {
30623c7b54cSEnric Balletbo i Serra 		mutex_unlock(&devfreq_list_lock);
30723c7b54cSEnric Balletbo i Serra 
30823c7b54cSEnric Balletbo i Serra 		if (!strncmp(name, DEVFREQ_GOV_SIMPLE_ONDEMAND,
30923c7b54cSEnric Balletbo i Serra 			     DEVFREQ_NAME_LEN))
31023c7b54cSEnric Balletbo i Serra 			err = request_module("governor_%s", "simpleondemand");
31123c7b54cSEnric Balletbo i Serra 		else
31223c7b54cSEnric Balletbo i Serra 			err = request_module("governor_%s", name);
31323c7b54cSEnric Balletbo i Serra 		/* Restore previous state before return */
31423c7b54cSEnric Balletbo i Serra 		mutex_lock(&devfreq_list_lock);
31523c7b54cSEnric Balletbo i Serra 		if (err)
3167544fd7fSEzequiel Garcia 			return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL);
31723c7b54cSEnric Balletbo i Serra 
31823c7b54cSEnric Balletbo i Serra 		governor = find_devfreq_governor(name);
31923c7b54cSEnric Balletbo i Serra 	}
32023c7b54cSEnric Balletbo i Serra 
32123c7b54cSEnric Balletbo i Serra 	return governor;
32223c7b54cSEnric Balletbo i Serra }
32323c7b54cSEnric Balletbo i Serra 
devfreq_notify_transition(struct devfreq * devfreq,struct devfreq_freqs * freqs,unsigned int state)3240fe3a664SChanwoo Choi static int devfreq_notify_transition(struct devfreq *devfreq,
3250fe3a664SChanwoo Choi 		struct devfreq_freqs *freqs, unsigned int state)
3260fe3a664SChanwoo Choi {
3270fe3a664SChanwoo Choi 	if (!devfreq)
3280fe3a664SChanwoo Choi 		return -EINVAL;
3290fe3a664SChanwoo Choi 
3300fe3a664SChanwoo Choi 	switch (state) {
3310fe3a664SChanwoo Choi 	case DEVFREQ_PRECHANGE:
3320fe3a664SChanwoo Choi 		srcu_notifier_call_chain(&devfreq->transition_notifier_list,
3330fe3a664SChanwoo Choi 				DEVFREQ_PRECHANGE, freqs);
3340fe3a664SChanwoo Choi 		break;
3350fe3a664SChanwoo Choi 
3360fe3a664SChanwoo Choi 	case DEVFREQ_POSTCHANGE:
3370fe3a664SChanwoo Choi 		srcu_notifier_call_chain(&devfreq->transition_notifier_list,
3380fe3a664SChanwoo Choi 				DEVFREQ_POSTCHANGE, freqs);
3390fe3a664SChanwoo Choi 		break;
3400fe3a664SChanwoo Choi 	default:
3410fe3a664SChanwoo Choi 		return -EINVAL;
3420fe3a664SChanwoo Choi 	}
3430fe3a664SChanwoo Choi 
3440fe3a664SChanwoo Choi 	return 0;
3450fe3a664SChanwoo Choi }
3460fe3a664SChanwoo Choi 
devfreq_set_target(struct devfreq * devfreq,unsigned long new_freq,u32 flags)34763314172SLukasz Luba static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,
34863314172SLukasz Luba 			      u32 flags)
34963314172SLukasz Luba {
35063314172SLukasz Luba 	struct devfreq_freqs freqs;
35163314172SLukasz Luba 	unsigned long cur_freq;
35263314172SLukasz Luba 	int err = 0;
35363314172SLukasz Luba 
35463314172SLukasz Luba 	if (devfreq->profile->get_cur_freq)
35563314172SLukasz Luba 		devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
35663314172SLukasz Luba 	else
35763314172SLukasz Luba 		cur_freq = devfreq->previous_freq;
35863314172SLukasz Luba 
35963314172SLukasz Luba 	freqs.old = cur_freq;
36063314172SLukasz Luba 	freqs.new = new_freq;
36163314172SLukasz Luba 	devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
36263314172SLukasz Luba 
36363314172SLukasz Luba 	err = devfreq->profile->target(devfreq->dev.parent, &new_freq, flags);
36463314172SLukasz Luba 	if (err) {
36563314172SLukasz Luba 		freqs.new = cur_freq;
36663314172SLukasz Luba 		devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
36763314172SLukasz Luba 		return err;
36863314172SLukasz Luba 	}
36963314172SLukasz Luba 
370cab477d0SMatthias Kaehlcke 	/*
371cab477d0SMatthias Kaehlcke 	 * Print devfreq_frequency trace information between DEVFREQ_PRECHANGE
372cab477d0SMatthias Kaehlcke 	 * and DEVFREQ_POSTCHANGE because for showing the correct frequency
373cab477d0SMatthias Kaehlcke 	 * change order of between devfreq device and passive devfreq device.
374cab477d0SMatthias Kaehlcke 	 */
375cab477d0SMatthias Kaehlcke 	if (trace_devfreq_frequency_enabled() && new_freq != cur_freq)
376cab477d0SMatthias Kaehlcke 		trace_devfreq_frequency(devfreq, new_freq, cur_freq);
377cab477d0SMatthias Kaehlcke 
37863314172SLukasz Luba 	freqs.new = new_freq;
37963314172SLukasz Luba 	devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
38063314172SLukasz Luba 
38163314172SLukasz Luba 	if (devfreq_update_status(devfreq, new_freq))
38246674314STzung-Bi Shih 		dev_warn(&devfreq->dev,
38363314172SLukasz Luba 			 "Couldn't update frequency transition information.\n");
38463314172SLukasz Luba 
38563314172SLukasz Luba 	devfreq->previous_freq = new_freq;
38683f8ca45SLukasz Luba 
38783f8ca45SLukasz Luba 	if (devfreq->suspend_freq)
38862453f1bSDong Aisheng 		devfreq->resume_freq = new_freq;
38983f8ca45SLukasz Luba 
39063314172SLukasz Luba 	return err;
39163314172SLukasz Luba }
39263314172SLukasz Luba 
393a3c98b8bSMyungJoo Ham /**
394b4365423SChanwoo Choi  * devfreq_update_target() - Reevaluate the device and configure frequency
395b4365423SChanwoo Choi  *			   on the final stage.
396a3c98b8bSMyungJoo Ham  * @devfreq:	the devfreq instance.
397b4365423SChanwoo Choi  * @freq:	the new frequency of parent device. This argument
398b4365423SChanwoo Choi  *		is only used for devfreq device using passive governor.
399a3c98b8bSMyungJoo Ham  *
400b4365423SChanwoo Choi  * Note: Lock devfreq->lock before calling devfreq_update_target. This function
401b4365423SChanwoo Choi  *	 should be only used by both update_devfreq() and devfreq governors.
402a3c98b8bSMyungJoo Ham  */
devfreq_update_target(struct devfreq * devfreq,unsigned long freq)403b4365423SChanwoo Choi int devfreq_update_target(struct devfreq *devfreq, unsigned long freq)
404a3c98b8bSMyungJoo Ham {
405b4365423SChanwoo Choi 	unsigned long min_freq, max_freq;
406a3c98b8bSMyungJoo Ham 	int err = 0;
407ab5f299fSMyungJoo Ham 	u32 flags = 0;
408a3c98b8bSMyungJoo Ham 
4098fc0e48eSKrzysztof Kozlowski 	lockdep_assert_held(&devfreq->lock);
410a3c98b8bSMyungJoo Ham 
4111b5c1be2SNishanth Menon 	if (!devfreq->governor)
4121b5c1be2SNishanth Menon 		return -EINVAL;
4131b5c1be2SNishanth Menon 
414a3c98b8bSMyungJoo Ham 	/* Reevaluate the proper frequency */
415a3c98b8bSMyungJoo Ham 	err = devfreq->governor->get_target_freq(devfreq, &freq);
416a3c98b8bSMyungJoo Ham 	if (err)
417a3c98b8bSMyungJoo Ham 		return err;
418713472e5SChanwoo Choi 	devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
419ab5f299fSMyungJoo Ham 
420df5cf4a3SMatthias Kaehlcke 	if (freq < min_freq) {
421f1d981eaSChanwoo Choi 		freq = min_freq;
422ab5f299fSMyungJoo Ham 		flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */
423ab5f299fSMyungJoo Ham 	}
424df5cf4a3SMatthias Kaehlcke 	if (freq > max_freq) {
425f1d981eaSChanwoo Choi 		freq = max_freq;
426ab5f299fSMyungJoo Ham 		flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */
427ab5f299fSMyungJoo Ham 	}
428ab5f299fSMyungJoo Ham 
42963314172SLukasz Luba 	return devfreq_set_target(devfreq, freq, flags);
430b4365423SChanwoo Choi }
431b4365423SChanwoo Choi EXPORT_SYMBOL(devfreq_update_target);
4320fe3a664SChanwoo Choi 
433b4365423SChanwoo Choi /* Load monitoring helper functions for governors use */
434b4365423SChanwoo Choi 
435b4365423SChanwoo Choi /**
436b4365423SChanwoo Choi  * update_devfreq() - Reevaluate the device and configure frequency.
437b4365423SChanwoo Choi  * @devfreq:	the devfreq instance.
438b4365423SChanwoo Choi  *
439b4365423SChanwoo Choi  * Note: Lock devfreq->lock before calling update_devfreq
440b4365423SChanwoo Choi  *	 This function is exported for governors.
441b4365423SChanwoo Choi  */
update_devfreq(struct devfreq * devfreq)442b4365423SChanwoo Choi int update_devfreq(struct devfreq *devfreq)
443b4365423SChanwoo Choi {
444b4365423SChanwoo Choi 	return devfreq_update_target(devfreq, 0L);
445a3c98b8bSMyungJoo Ham }
4462df5021fSNishanth Menon EXPORT_SYMBOL(update_devfreq);
447a3c98b8bSMyungJoo Ham 
448a3c98b8bSMyungJoo Ham /**
4497e6fdd4bSRajagopal Venkat  * devfreq_monitor() - Periodically poll devfreq objects.
4507e6fdd4bSRajagopal Venkat  * @work:	the work struct used to run devfreq_monitor periodically.
4517e6fdd4bSRajagopal Venkat  *
4527e6fdd4bSRajagopal Venkat  */
devfreq_monitor(struct work_struct * work)4537e6fdd4bSRajagopal Venkat static void devfreq_monitor(struct work_struct *work)
4547e6fdd4bSRajagopal Venkat {
4557e6fdd4bSRajagopal Venkat 	int err;
4567e6fdd4bSRajagopal Venkat 	struct devfreq *devfreq = container_of(work,
4577e6fdd4bSRajagopal Venkat 					struct devfreq, work.work);
4587e6fdd4bSRajagopal Venkat 
4597e6fdd4bSRajagopal Venkat 	mutex_lock(&devfreq->lock);
4607e6fdd4bSRajagopal Venkat 	err = update_devfreq(devfreq);
4617e6fdd4bSRajagopal Venkat 	if (err)
4627e6fdd4bSRajagopal Venkat 		dev_err(&devfreq->dev, "dvfs failed with (%d) error\n", err);
4637e6fdd4bSRajagopal Venkat 
464*0aedb319SMukesh Ojha 	if (devfreq->stop_polling)
465*0aedb319SMukesh Ojha 		goto out;
466*0aedb319SMukesh Ojha 
4677e6fdd4bSRajagopal Venkat 	queue_delayed_work(devfreq_wq, &devfreq->work,
4687e6fdd4bSRajagopal Venkat 				msecs_to_jiffies(devfreq->profile->polling_ms));
469cf451adfSLukasz Luba 
470*0aedb319SMukesh Ojha out:
471*0aedb319SMukesh Ojha 	mutex_unlock(&devfreq->lock);
472cf451adfSLukasz Luba 	trace_devfreq_monitor(devfreq);
4737e6fdd4bSRajagopal Venkat }
4747e6fdd4bSRajagopal Venkat 
4757e6fdd4bSRajagopal Venkat /**
4767e6fdd4bSRajagopal Venkat  * devfreq_monitor_start() - Start load monitoring of devfreq instance
4777e6fdd4bSRajagopal Venkat  * @devfreq:	the devfreq instance.
4787e6fdd4bSRajagopal Venkat  *
479c46de2fbSManivannan Sadhasivam  * Helper function for starting devfreq device load monitoring. By default,
480c46de2fbSManivannan Sadhasivam  * deferrable timer is used for load monitoring. But the users can change this
481c46de2fbSManivannan Sadhasivam  * behavior using the "timer" type in devfreq_dev_profile. This function will be
482c46de2fbSManivannan Sadhasivam  * called by devfreq governor in response to the DEVFREQ_GOV_START event
483c46de2fbSManivannan Sadhasivam  * generated while adding a device to the devfreq framework.
4847e6fdd4bSRajagopal Venkat  */
devfreq_monitor_start(struct devfreq * devfreq)4857e6fdd4bSRajagopal Venkat void devfreq_monitor_start(struct devfreq *devfreq)
4867e6fdd4bSRajagopal Venkat {
4870dd25a0dSChanwoo Choi 	if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
4885c0f6c79SDmitry Osipenko 		return;
4895c0f6c79SDmitry Osipenko 
490*0aedb319SMukesh Ojha 	mutex_lock(&devfreq->lock);
491*0aedb319SMukesh Ojha 	if (delayed_work_pending(&devfreq->work))
492*0aedb319SMukesh Ojha 		goto out;
493*0aedb319SMukesh Ojha 
4944dc3bab8SChanwoo Choi 	switch (devfreq->profile->timer) {
4954dc3bab8SChanwoo Choi 	case DEVFREQ_TIMER_DEFERRABLE:
4967e6fdd4bSRajagopal Venkat 		INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
4974dc3bab8SChanwoo Choi 		break;
4984dc3bab8SChanwoo Choi 	case DEVFREQ_TIMER_DELAYED:
4994dc3bab8SChanwoo Choi 		INIT_DELAYED_WORK(&devfreq->work, devfreq_monitor);
5004dc3bab8SChanwoo Choi 		break;
5014dc3bab8SChanwoo Choi 	default:
502*0aedb319SMukesh Ojha 		goto out;
5034dc3bab8SChanwoo Choi 	}
5044dc3bab8SChanwoo Choi 
5057e6fdd4bSRajagopal Venkat 	if (devfreq->profile->polling_ms)
5067e6fdd4bSRajagopal Venkat 		queue_delayed_work(devfreq_wq, &devfreq->work,
5077e6fdd4bSRajagopal Venkat 			msecs_to_jiffies(devfreq->profile->polling_ms));
508*0aedb319SMukesh Ojha 
509*0aedb319SMukesh Ojha out:
510*0aedb319SMukesh Ojha 	devfreq->stop_polling = false;
511*0aedb319SMukesh Ojha 	mutex_unlock(&devfreq->lock);
5127e6fdd4bSRajagopal Venkat }
5136dcdd8e3SMyungJoo Ham EXPORT_SYMBOL(devfreq_monitor_start);
5147e6fdd4bSRajagopal Venkat 
5157e6fdd4bSRajagopal Venkat /**
5167e6fdd4bSRajagopal Venkat  * devfreq_monitor_stop() - Stop load monitoring of a devfreq instance
5177e6fdd4bSRajagopal Venkat  * @devfreq:	the devfreq instance.
5187e6fdd4bSRajagopal Venkat  *
5192c090832SGaël PORTAY  * Helper function to stop devfreq device load monitoring. Function
5207e6fdd4bSRajagopal Venkat  * to be called from governor in response to DEVFREQ_GOV_STOP
5217e6fdd4bSRajagopal Venkat  * event when device is removed from devfreq framework.
5227e6fdd4bSRajagopal Venkat  */
devfreq_monitor_stop(struct devfreq * devfreq)5237e6fdd4bSRajagopal Venkat void devfreq_monitor_stop(struct devfreq *devfreq)
5247e6fdd4bSRajagopal Venkat {
5250dd25a0dSChanwoo Choi 	if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
5265c0f6c79SDmitry Osipenko 		return;
5275c0f6c79SDmitry Osipenko 
528*0aedb319SMukesh Ojha 	mutex_lock(&devfreq->lock);
529*0aedb319SMukesh Ojha 	if (devfreq->stop_polling) {
530*0aedb319SMukesh Ojha 		mutex_unlock(&devfreq->lock);
531*0aedb319SMukesh Ojha 		return;
532*0aedb319SMukesh Ojha 	}
533*0aedb319SMukesh Ojha 
534*0aedb319SMukesh Ojha 	devfreq->stop_polling = true;
535*0aedb319SMukesh Ojha 	mutex_unlock(&devfreq->lock);
5367e6fdd4bSRajagopal Venkat 	cancel_delayed_work_sync(&devfreq->work);
5377e6fdd4bSRajagopal Venkat }
5386dcdd8e3SMyungJoo Ham EXPORT_SYMBOL(devfreq_monitor_stop);
5397e6fdd4bSRajagopal Venkat 
5407e6fdd4bSRajagopal Venkat /**
5417e6fdd4bSRajagopal Venkat  * devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance
5427e6fdd4bSRajagopal Venkat  * @devfreq:	the devfreq instance.
5437e6fdd4bSRajagopal Venkat  *
5442c090832SGaël PORTAY  * Helper function to suspend devfreq device load monitoring. Function
5457e6fdd4bSRajagopal Venkat  * to be called from governor in response to DEVFREQ_GOV_SUSPEND
5467e6fdd4bSRajagopal Venkat  * event or when polling interval is set to zero.
5477e6fdd4bSRajagopal Venkat  *
5487e6fdd4bSRajagopal Venkat  * Note: Though this function is same as devfreq_monitor_stop(),
5497e6fdd4bSRajagopal Venkat  * intentionally kept separate to provide hooks for collecting
5507e6fdd4bSRajagopal Venkat  * transition statistics.
5517e6fdd4bSRajagopal Venkat  */
devfreq_monitor_suspend(struct devfreq * devfreq)5527e6fdd4bSRajagopal Venkat void devfreq_monitor_suspend(struct devfreq *devfreq)
5537e6fdd4bSRajagopal Venkat {
5547e6fdd4bSRajagopal Venkat 	mutex_lock(&devfreq->lock);
5557e6fdd4bSRajagopal Venkat 	if (devfreq->stop_polling) {
5567e6fdd4bSRajagopal Venkat 		mutex_unlock(&devfreq->lock);
5577e6fdd4bSRajagopal Venkat 		return;
5587e6fdd4bSRajagopal Venkat 	}
5597e6fdd4bSRajagopal Venkat 
56039688ce6SRajagopal Venkat 	devfreq_update_status(devfreq, devfreq->previous_freq);
5617e6fdd4bSRajagopal Venkat 	devfreq->stop_polling = true;
5627e6fdd4bSRajagopal Venkat 	mutex_unlock(&devfreq->lock);
5635c0f6c79SDmitry Osipenko 
5640dd25a0dSChanwoo Choi 	if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
5655c0f6c79SDmitry Osipenko 		return;
5665c0f6c79SDmitry Osipenko 
5677e6fdd4bSRajagopal Venkat 	cancel_delayed_work_sync(&devfreq->work);
5687e6fdd4bSRajagopal Venkat }
5696dcdd8e3SMyungJoo Ham EXPORT_SYMBOL(devfreq_monitor_suspend);
5707e6fdd4bSRajagopal Venkat 
5717e6fdd4bSRajagopal Venkat /**
5727e6fdd4bSRajagopal Venkat  * devfreq_monitor_resume() - Resume load monitoring of a devfreq instance
5737e6fdd4bSRajagopal Venkat  * @devfreq:    the devfreq instance.
5747e6fdd4bSRajagopal Venkat  *
5752c090832SGaël PORTAY  * Helper function to resume devfreq device load monitoring. Function
5767e6fdd4bSRajagopal Venkat  * to be called from governor in response to DEVFREQ_GOV_RESUME
5777e6fdd4bSRajagopal Venkat  * event or when polling interval is set to non-zero.
5787e6fdd4bSRajagopal Venkat  */
devfreq_monitor_resume(struct devfreq * devfreq)5797e6fdd4bSRajagopal Venkat void devfreq_monitor_resume(struct devfreq *devfreq)
5807e6fdd4bSRajagopal Venkat {
58139688ce6SRajagopal Venkat 	unsigned long freq;
58239688ce6SRajagopal Venkat 
5837e6fdd4bSRajagopal Venkat 	mutex_lock(&devfreq->lock);
5840dd25a0dSChanwoo Choi 
5850dd25a0dSChanwoo Choi 	if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
5860dd25a0dSChanwoo Choi 		goto out_update;
5870dd25a0dSChanwoo Choi 
5887e6fdd4bSRajagopal Venkat 	if (!devfreq->stop_polling)
5897e6fdd4bSRajagopal Venkat 		goto out;
5907e6fdd4bSRajagopal Venkat 
5917e6fdd4bSRajagopal Venkat 	if (!delayed_work_pending(&devfreq->work) &&
5927e6fdd4bSRajagopal Venkat 			devfreq->profile->polling_ms)
5937e6fdd4bSRajagopal Venkat 		queue_delayed_work(devfreq_wq, &devfreq->work,
5947e6fdd4bSRajagopal Venkat 			msecs_to_jiffies(devfreq->profile->polling_ms));
59539688ce6SRajagopal Venkat 
5965c0f6c79SDmitry Osipenko out_update:
5971ebd0bc0SKamil Konieczny 	devfreq->stats.last_update = get_jiffies_64();
5987e6fdd4bSRajagopal Venkat 	devfreq->stop_polling = false;
5997e6fdd4bSRajagopal Venkat 
60039688ce6SRajagopal Venkat 	if (devfreq->profile->get_cur_freq &&
60139688ce6SRajagopal Venkat 		!devfreq->profile->get_cur_freq(devfreq->dev.parent, &freq))
60239688ce6SRajagopal Venkat 		devfreq->previous_freq = freq;
60339688ce6SRajagopal Venkat 
6047e6fdd4bSRajagopal Venkat out:
6057e6fdd4bSRajagopal Venkat 	mutex_unlock(&devfreq->lock);
6067e6fdd4bSRajagopal Venkat }
6076dcdd8e3SMyungJoo Ham EXPORT_SYMBOL(devfreq_monitor_resume);
6087e6fdd4bSRajagopal Venkat 
6097e6fdd4bSRajagopal Venkat /**
6103a1ec2e8SChanwoo Choi  * devfreq_update_interval() - Update device devfreq monitoring interval
6117e6fdd4bSRajagopal Venkat  * @devfreq:    the devfreq instance.
6127e6fdd4bSRajagopal Venkat  * @delay:      new polling interval to be set.
6137e6fdd4bSRajagopal Venkat  *
6147e6fdd4bSRajagopal Venkat  * Helper function to set new load monitoring polling interval. Function
6153a1ec2e8SChanwoo Choi  * to be called from governor in response to DEVFREQ_GOV_UPDATE_INTERVAL event.
6167e6fdd4bSRajagopal Venkat  */
devfreq_update_interval(struct devfreq * devfreq,unsigned int * delay)6173a1ec2e8SChanwoo Choi void devfreq_update_interval(struct devfreq *devfreq, unsigned int *delay)
6187e6fdd4bSRajagopal Venkat {
6197e6fdd4bSRajagopal Venkat 	unsigned int cur_delay = devfreq->profile->polling_ms;
6207e6fdd4bSRajagopal Venkat 	unsigned int new_delay = *delay;
6217e6fdd4bSRajagopal Venkat 
6227e6fdd4bSRajagopal Venkat 	mutex_lock(&devfreq->lock);
6237e6fdd4bSRajagopal Venkat 	devfreq->profile->polling_ms = new_delay;
6247e6fdd4bSRajagopal Venkat 
6250dd25a0dSChanwoo Choi 	if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
6267e6fdd4bSRajagopal Venkat 		goto out;
6277e6fdd4bSRajagopal Venkat 
6280dd25a0dSChanwoo Choi 	if (devfreq->stop_polling)
6295c0f6c79SDmitry Osipenko 		goto out;
6305c0f6c79SDmitry Osipenko 
6317e6fdd4bSRajagopal Venkat 	/* if new delay is zero, stop polling */
6327e6fdd4bSRajagopal Venkat 	if (!new_delay) {
6337e6fdd4bSRajagopal Venkat 		mutex_unlock(&devfreq->lock);
6347e6fdd4bSRajagopal Venkat 		cancel_delayed_work_sync(&devfreq->work);
6357e6fdd4bSRajagopal Venkat 		return;
6367e6fdd4bSRajagopal Venkat 	}
6377e6fdd4bSRajagopal Venkat 
6387e6fdd4bSRajagopal Venkat 	/* if current delay is zero, start polling with new delay */
6397e6fdd4bSRajagopal Venkat 	if (!cur_delay) {
6407e6fdd4bSRajagopal Venkat 		queue_delayed_work(devfreq_wq, &devfreq->work,
6417e6fdd4bSRajagopal Venkat 			msecs_to_jiffies(devfreq->profile->polling_ms));
6427e6fdd4bSRajagopal Venkat 		goto out;
6437e6fdd4bSRajagopal Venkat 	}
6447e6fdd4bSRajagopal Venkat 
6457e6fdd4bSRajagopal Venkat 	/* if current delay is greater than new delay, restart polling */
6467e6fdd4bSRajagopal Venkat 	if (cur_delay > new_delay) {
6477e6fdd4bSRajagopal Venkat 		mutex_unlock(&devfreq->lock);
6487e6fdd4bSRajagopal Venkat 		cancel_delayed_work_sync(&devfreq->work);
6497e6fdd4bSRajagopal Venkat 		mutex_lock(&devfreq->lock);
6507e6fdd4bSRajagopal Venkat 		if (!devfreq->stop_polling)
6517e6fdd4bSRajagopal Venkat 			queue_delayed_work(devfreq_wq, &devfreq->work,
6527e6fdd4bSRajagopal Venkat 				msecs_to_jiffies(devfreq->profile->polling_ms));
6537e6fdd4bSRajagopal Venkat 	}
6547e6fdd4bSRajagopal Venkat out:
6557e6fdd4bSRajagopal Venkat 	mutex_unlock(&devfreq->lock);
6567e6fdd4bSRajagopal Venkat }
6573a1ec2e8SChanwoo Choi EXPORT_SYMBOL(devfreq_update_interval);
658a3c98b8bSMyungJoo Ham 
659a3c98b8bSMyungJoo Ham /**
660a3c98b8bSMyungJoo Ham  * devfreq_notifier_call() - Notify that the device frequency requirements
661a3c98b8bSMyungJoo Ham  *			     has been changed out of devfreq framework.
662c5b4a1c1SNishanth Menon  * @nb:		the notifier_block (supposed to be devfreq->nb)
663c5b4a1c1SNishanth Menon  * @type:	not used
664c5b4a1c1SNishanth Menon  * @devp:	not used
665a3c98b8bSMyungJoo Ham  *
666a3c98b8bSMyungJoo Ham  * Called by a notifier that uses devfreq->nb.
667a3c98b8bSMyungJoo Ham  */
devfreq_notifier_call(struct notifier_block * nb,unsigned long type,void * devp)668a3c98b8bSMyungJoo Ham static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
669a3c98b8bSMyungJoo Ham 				 void *devp)
670a3c98b8bSMyungJoo Ham {
671a3c98b8bSMyungJoo Ham 	struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
672e876e710SLeonard Crestez 	int err = -EINVAL;
673a3c98b8bSMyungJoo Ham 
674a3c98b8bSMyungJoo Ham 	mutex_lock(&devfreq->lock);
675f1d981eaSChanwoo Choi 
676f1d981eaSChanwoo Choi 	devfreq->scaling_min_freq = find_available_min_freq(devfreq);
677e876e710SLeonard Crestez 	if (!devfreq->scaling_min_freq)
678e876e710SLeonard Crestez 		goto out;
679f1d981eaSChanwoo Choi 
680f1d981eaSChanwoo Choi 	devfreq->scaling_max_freq = find_available_max_freq(devfreq);
681e7cc792dSLeonard Crestez 	if (!devfreq->scaling_max_freq) {
682e7cc792dSLeonard Crestez 		devfreq->scaling_max_freq = ULONG_MAX;
683e876e710SLeonard Crestez 		goto out;
684e7cc792dSLeonard Crestez 	}
685f1d981eaSChanwoo Choi 
686e876e710SLeonard Crestez 	err = update_devfreq(devfreq);
687a3c98b8bSMyungJoo Ham 
688e876e710SLeonard Crestez out:
689e876e710SLeonard Crestez 	mutex_unlock(&devfreq->lock);
690e876e710SLeonard Crestez 	if (err)
691e876e710SLeonard Crestez 		dev_err(devfreq->dev.parent,
692e876e710SLeonard Crestez 			"failed to update frequency from OPP notifier (%d)\n",
693e876e710SLeonard Crestez 			err);
694e876e710SLeonard Crestez 
695e876e710SLeonard Crestez 	return NOTIFY_OK;
696a3c98b8bSMyungJoo Ham }
697a3c98b8bSMyungJoo Ham 
698a3c98b8bSMyungJoo Ham /**
69905d7ae15SLeonard Crestez  * qos_notifier_call() - Common handler for QoS constraints.
70005d7ae15SLeonard Crestez  * @devfreq:    the devfreq instance.
70105d7ae15SLeonard Crestez  */
qos_notifier_call(struct devfreq * devfreq)70205d7ae15SLeonard Crestez static int qos_notifier_call(struct devfreq *devfreq)
70305d7ae15SLeonard Crestez {
70405d7ae15SLeonard Crestez 	int err;
70505d7ae15SLeonard Crestez 
70605d7ae15SLeonard Crestez 	mutex_lock(&devfreq->lock);
70705d7ae15SLeonard Crestez 	err = update_devfreq(devfreq);
70805d7ae15SLeonard Crestez 	mutex_unlock(&devfreq->lock);
70905d7ae15SLeonard Crestez 	if (err)
71005d7ae15SLeonard Crestez 		dev_err(devfreq->dev.parent,
71105d7ae15SLeonard Crestez 			"failed to update frequency from PM QoS (%d)\n",
71205d7ae15SLeonard Crestez 			err);
71305d7ae15SLeonard Crestez 
71405d7ae15SLeonard Crestez 	return NOTIFY_OK;
71505d7ae15SLeonard Crestez }
71605d7ae15SLeonard Crestez 
71705d7ae15SLeonard Crestez /**
71805d7ae15SLeonard Crestez  * qos_min_notifier_call() - Callback for QoS min_freq changes.
71905d7ae15SLeonard Crestez  * @nb:		Should be devfreq->nb_min
720c9deb748SMauro Carvalho Chehab  * @val:	not used
721c9deb748SMauro Carvalho Chehab  * @ptr:	not used
72205d7ae15SLeonard Crestez  */
qos_min_notifier_call(struct notifier_block * nb,unsigned long val,void * ptr)72305d7ae15SLeonard Crestez static int qos_min_notifier_call(struct notifier_block *nb,
72405d7ae15SLeonard Crestez 					 unsigned long val, void *ptr)
72505d7ae15SLeonard Crestez {
72605d7ae15SLeonard Crestez 	return qos_notifier_call(container_of(nb, struct devfreq, nb_min));
72705d7ae15SLeonard Crestez }
72805d7ae15SLeonard Crestez 
72905d7ae15SLeonard Crestez /**
73005d7ae15SLeonard Crestez  * qos_max_notifier_call() - Callback for QoS max_freq changes.
73105d7ae15SLeonard Crestez  * @nb:		Should be devfreq->nb_max
732c9deb748SMauro Carvalho Chehab  * @val:	not used
733c9deb748SMauro Carvalho Chehab  * @ptr:	not used
73405d7ae15SLeonard Crestez  */
qos_max_notifier_call(struct notifier_block * nb,unsigned long val,void * ptr)73505d7ae15SLeonard Crestez static int qos_max_notifier_call(struct notifier_block *nb,
73605d7ae15SLeonard Crestez 					 unsigned long val, void *ptr)
73705d7ae15SLeonard Crestez {
73805d7ae15SLeonard Crestez 	return qos_notifier_call(container_of(nb, struct devfreq, nb_max));
73905d7ae15SLeonard Crestez }
74005d7ae15SLeonard Crestez 
74105d7ae15SLeonard Crestez /**
74229b6968bSChanwoo Choi  * devfreq_dev_release() - Callback for struct device to release the device.
74329b6968bSChanwoo Choi  * @dev:	the devfreq device
74429b6968bSChanwoo Choi  *
74529b6968bSChanwoo Choi  * Remove devfreq from the list and release its resources.
746a3c98b8bSMyungJoo Ham  */
devfreq_dev_release(struct device * dev)74729b6968bSChanwoo Choi static void devfreq_dev_release(struct device *dev)
748a3c98b8bSMyungJoo Ham {
74929b6968bSChanwoo Choi 	struct devfreq *devfreq = to_devfreq(dev);
75005d7ae15SLeonard Crestez 	int err;
75129b6968bSChanwoo Choi 
7527e6fdd4bSRajagopal Venkat 	mutex_lock(&devfreq_list_lock);
7537e6fdd4bSRajagopal Venkat 	list_del(&devfreq->node);
7547e6fdd4bSRajagopal Venkat 	mutex_unlock(&devfreq_list_lock);
755a3c98b8bSMyungJoo Ham 
75605d7ae15SLeonard Crestez 	err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_max,
75705d7ae15SLeonard Crestez 					 DEV_PM_QOS_MAX_FREQUENCY);
75805d7ae15SLeonard Crestez 	if (err && err != -ENOENT)
75905d7ae15SLeonard Crestez 		dev_warn(dev->parent,
76005d7ae15SLeonard Crestez 			"Failed to remove max_freq notifier: %d\n", err);
76105d7ae15SLeonard Crestez 	err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_min,
76205d7ae15SLeonard Crestez 					 DEV_PM_QOS_MIN_FREQUENCY);
76305d7ae15SLeonard Crestez 	if (err && err != -ENOENT)
76405d7ae15SLeonard Crestez 		dev_warn(dev->parent,
76505d7ae15SLeonard Crestez 			"Failed to remove min_freq notifier: %d\n", err);
76605d7ae15SLeonard Crestez 
76727dbc542SLeonard Crestez 	if (dev_pm_qos_request_active(&devfreq->user_max_freq_req)) {
76827dbc542SLeonard Crestez 		err = dev_pm_qos_remove_request(&devfreq->user_max_freq_req);
7694c6abef7SLeonard Crestez 		if (err < 0)
77027dbc542SLeonard Crestez 			dev_warn(dev->parent,
77127dbc542SLeonard Crestez 				"Failed to remove max_freq request: %d\n", err);
77227dbc542SLeonard Crestez 	}
77327dbc542SLeonard Crestez 	if (dev_pm_qos_request_active(&devfreq->user_min_freq_req)) {
77427dbc542SLeonard Crestez 		err = dev_pm_qos_remove_request(&devfreq->user_min_freq_req);
7754c6abef7SLeonard Crestez 		if (err < 0)
77627dbc542SLeonard Crestez 			dev_warn(dev->parent,
77727dbc542SLeonard Crestez 				"Failed to remove min_freq request: %d\n", err);
77827dbc542SLeonard Crestez 	}
77927dbc542SLeonard Crestez 
780a3c98b8bSMyungJoo Ham 	if (devfreq->profile->exit)
781a3c98b8bSMyungJoo Ham 		devfreq->profile->exit(devfreq->dev.parent);
782a3c98b8bSMyungJoo Ham 
78326f9c7ccSSaravana Kannan 	if (devfreq->opp_table)
78426f9c7ccSSaravana Kannan 		dev_pm_opp_put_opp_table(devfreq->opp_table);
78526f9c7ccSSaravana Kannan 
786a3c98b8bSMyungJoo Ham 	mutex_destroy(&devfreq->lock);
7875693d077SBoris Brezillon 	srcu_cleanup_notifier_head(&devfreq->transition_notifier_list);
788a3c98b8bSMyungJoo Ham 	kfree(devfreq);
789a3c98b8bSMyungJoo Ham }
790a3c98b8bSMyungJoo Ham 
7915f1a9066SChanwoo Choi static void create_sysfs_files(struct devfreq *devfreq,
7925f1a9066SChanwoo Choi 				const struct devfreq_governor *gov);
7935f1a9066SChanwoo Choi static void remove_sysfs_files(struct devfreq *devfreq,
7945f1a9066SChanwoo Choi 				const struct devfreq_governor *gov);
7955f1a9066SChanwoo Choi 
796a3c98b8bSMyungJoo Ham /**
797a3c98b8bSMyungJoo Ham  * devfreq_add_device() - Add devfreq feature to the device
798a3c98b8bSMyungJoo Ham  * @dev:	the device to add devfreq feature.
799a3c98b8bSMyungJoo Ham  * @profile:	device-specific profile to run devfreq.
8001b5c1be2SNishanth Menon  * @governor_name:	name of the policy to choose frequency.
8015fdded84SKant Fan  * @data:	devfreq driver pass to governors, governor should not change it.
802a3c98b8bSMyungJoo Ham  */
devfreq_add_device(struct device * dev,struct devfreq_dev_profile * profile,const char * governor_name,void * data)803a3c98b8bSMyungJoo Ham struct devfreq *devfreq_add_device(struct device *dev,
804a3c98b8bSMyungJoo Ham 				   struct devfreq_dev_profile *profile,
8051b5c1be2SNishanth Menon 				   const char *governor_name,
806a3c98b8bSMyungJoo Ham 				   void *data)
807a3c98b8bSMyungJoo Ham {
808a3c98b8bSMyungJoo Ham 	struct devfreq *devfreq;
8091b5c1be2SNishanth Menon 	struct devfreq_governor *governor;
810713472e5SChanwoo Choi 	unsigned long min_freq, max_freq;
811a3c98b8bSMyungJoo Ham 	int err = 0;
812a3c98b8bSMyungJoo Ham 
8131b5c1be2SNishanth Menon 	if (!dev || !profile || !governor_name) {
814a3c98b8bSMyungJoo Ham 		dev_err(dev, "%s: Invalid parameters.\n", __func__);
815a3c98b8bSMyungJoo Ham 		return ERR_PTR(-EINVAL);
816a3c98b8bSMyungJoo Ham 	}
817a3c98b8bSMyungJoo Ham 
818a3c98b8bSMyungJoo Ham 	mutex_lock(&devfreq_list_lock);
819a3c98b8bSMyungJoo Ham 	devfreq = find_device_devfreq(dev);
820a3c98b8bSMyungJoo Ham 	mutex_unlock(&devfreq_list_lock);
821a3c98b8bSMyungJoo Ham 	if (!IS_ERR(devfreq)) {
822df4d7b14SMatthias Kaehlcke 		dev_err(dev, "%s: devfreq device already exists!\n",
8239d0109beSChanwoo Choi 			__func__);
824a3c98b8bSMyungJoo Ham 		err = -EINVAL;
8253f19f08aSAxel Lin 		goto err_out;
826a3c98b8bSMyungJoo Ham 	}
827a3c98b8bSMyungJoo Ham 
828a3c98b8bSMyungJoo Ham 	devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL);
829a3c98b8bSMyungJoo Ham 	if (!devfreq) {
830a3c98b8bSMyungJoo Ham 		err = -ENOMEM;
8313f19f08aSAxel Lin 		goto err_out;
832a3c98b8bSMyungJoo Ham 	}
833a3c98b8bSMyungJoo Ham 
834a3c98b8bSMyungJoo Ham 	mutex_init(&devfreq->lock);
835a3c98b8bSMyungJoo Ham 	mutex_lock(&devfreq->lock);
836a3c98b8bSMyungJoo Ham 	devfreq->dev.parent = dev;
837a3c98b8bSMyungJoo Ham 	devfreq->dev.class = devfreq_class;
838a3c98b8bSMyungJoo Ham 	devfreq->dev.release = devfreq_dev_release;
83942a6b25eSLeonard Crestez 	INIT_LIST_HEAD(&devfreq->node);
840a3c98b8bSMyungJoo Ham 	devfreq->profile = profile;
841a3c98b8bSMyungJoo Ham 	devfreq->previous_freq = profile->initial_freq;
8428d39fc08SLukasz Luba 	devfreq->last_status.current_frequency = profile->initial_freq;
843a3c98b8bSMyungJoo Ham 	devfreq->data = data;
844a3c98b8bSMyungJoo Ham 	devfreq->nb.notifier_call = devfreq_notifier_call;
845a3c98b8bSMyungJoo Ham 
8464dc3bab8SChanwoo Choi 	if (devfreq->profile->timer < 0
8474dc3bab8SChanwoo Choi 		|| devfreq->profile->timer >= DEVFREQ_TIMER_NUM) {
8488b50a799SLukasz Luba 		mutex_unlock(&devfreq->lock);
84918b380edSYueHaibing 		err = -EINVAL;
8508b50a799SLukasz Luba 		goto err_dev;
8514dc3bab8SChanwoo Choi 	}
8524dc3bab8SChanwoo Choi 
8535cf79c29SSamuel Holland 	if (!devfreq->profile->max_state || !devfreq->profile->freq_table) {
8540ec09ac2SChanwoo Choi 		mutex_unlock(&devfreq->lock);
855ea572f81SChanwoo Choi 		err = set_freq_table(devfreq);
856ea572f81SChanwoo Choi 		if (err < 0)
857a9487917SYangtao Li 			goto err_dev;
8580ec09ac2SChanwoo Choi 		mutex_lock(&devfreq->lock);
859b5d281f6SChristian Marangi 	} else {
860b5d281f6SChristian Marangi 		devfreq->freq_table = devfreq->profile->freq_table;
861b5d281f6SChristian Marangi 		devfreq->max_state = devfreq->profile->max_state;
8620ec09ac2SChanwoo Choi 	}
8630ec09ac2SChanwoo Choi 
8642c2cb1e6SMatthias Kaehlcke 	devfreq->scaling_min_freq = find_available_min_freq(devfreq);
8652c2cb1e6SMatthias Kaehlcke 	if (!devfreq->scaling_min_freq) {
866ab8f58adSChanwoo Choi 		mutex_unlock(&devfreq->lock);
867ab8f58adSChanwoo Choi 		err = -EINVAL;
868ab8f58adSChanwoo Choi 		goto err_dev;
869ab8f58adSChanwoo Choi 	}
870ab8f58adSChanwoo Choi 
8712c2cb1e6SMatthias Kaehlcke 	devfreq->scaling_max_freq = find_available_max_freq(devfreq);
8722c2cb1e6SMatthias Kaehlcke 	if (!devfreq->scaling_max_freq) {
873ab8f58adSChanwoo Choi 		mutex_unlock(&devfreq->lock);
874ab8f58adSChanwoo Choi 		err = -EINVAL;
875ab8f58adSChanwoo Choi 		goto err_dev;
876ab8f58adSChanwoo Choi 	}
877ab8f58adSChanwoo Choi 
878713472e5SChanwoo Choi 	devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
879713472e5SChanwoo Choi 
88083f8ca45SLukasz Luba 	devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
88126f9c7ccSSaravana Kannan 	devfreq->opp_table = dev_pm_opp_get_opp_table(dev);
88226f9c7ccSSaravana Kannan 	if (IS_ERR(devfreq->opp_table))
88326f9c7ccSSaravana Kannan 		devfreq->opp_table = NULL;
88426f9c7ccSSaravana Kannan 
88583f8ca45SLukasz Luba 	atomic_set(&devfreq->suspend_count, 0);
88683f8ca45SLukasz Luba 
88766d0e797SOrson Zhai 	dev_set_name(&devfreq->dev, "%s", dev_name(dev));
888a3c98b8bSMyungJoo Ham 	err = device_register(&devfreq->dev);
889a3c98b8bSMyungJoo Ham 	if (err) {
8907e6fdd4bSRajagopal Venkat 		mutex_unlock(&devfreq->lock);
8912d803dc8SArvind Yadav 		put_device(&devfreq->dev);
8922d803dc8SArvind Yadav 		goto err_out;
893a3c98b8bSMyungJoo Ham 	}
894a3c98b8bSMyungJoo Ham 
8951ebd0bc0SKamil Konieczny 	devfreq->stats.trans_table = devm_kzalloc(&devfreq->dev,
896a86854d0SKees Cook 			array3_size(sizeof(unsigned int),
897b5d281f6SChristian Marangi 				    devfreq->max_state,
898b5d281f6SChristian Marangi 				    devfreq->max_state),
8993e1d7fb0SMyungJoo Ham 			GFP_KERNEL);
9001ebd0bc0SKamil Konieczny 	if (!devfreq->stats.trans_table) {
90125846fa1SYangtao Li 		mutex_unlock(&devfreq->lock);
90225846fa1SYangtao Li 		err = -ENOMEM;
90325846fa1SYangtao Li 		goto err_devfreq;
90425846fa1SYangtao Li 	}
90525846fa1SYangtao Li 
9061ebd0bc0SKamil Konieczny 	devfreq->stats.time_in_state = devm_kcalloc(&devfreq->dev,
907b5d281f6SChristian Marangi 			devfreq->max_state,
9081ebd0bc0SKamil Konieczny 			sizeof(*devfreq->stats.time_in_state),
9093e1d7fb0SMyungJoo Ham 			GFP_KERNEL);
9101ebd0bc0SKamil Konieczny 	if (!devfreq->stats.time_in_state) {
91125846fa1SYangtao Li 		mutex_unlock(&devfreq->lock);
91225846fa1SYangtao Li 		err = -ENOMEM;
91325846fa1SYangtao Li 		goto err_devfreq;
91425846fa1SYangtao Li 	}
91525846fa1SYangtao Li 
9161ebd0bc0SKamil Konieczny 	devfreq->stats.total_trans = 0;
9171ebd0bc0SKamil Konieczny 	devfreq->stats.last_update = get_jiffies_64();
9183e1d7fb0SMyungJoo Ham 
9190fe3a664SChanwoo Choi 	srcu_init_notifier_head(&devfreq->transition_notifier_list);
9200fe3a664SChanwoo Choi 
921a3c98b8bSMyungJoo Ham 	mutex_unlock(&devfreq->lock);
922a3c98b8bSMyungJoo Ham 
92327dbc542SLeonard Crestez 	err = dev_pm_qos_add_request(dev, &devfreq->user_min_freq_req,
92427dbc542SLeonard Crestez 				     DEV_PM_QOS_MIN_FREQUENCY, 0);
92527dbc542SLeonard Crestez 	if (err < 0)
92627dbc542SLeonard Crestez 		goto err_devfreq;
92727dbc542SLeonard Crestez 	err = dev_pm_qos_add_request(dev, &devfreq->user_max_freq_req,
92827dbc542SLeonard Crestez 				     DEV_PM_QOS_MAX_FREQUENCY,
92927dbc542SLeonard Crestez 				     PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
93027dbc542SLeonard Crestez 	if (err < 0)
93127dbc542SLeonard Crestez 		goto err_devfreq;
93227dbc542SLeonard Crestez 
93305d7ae15SLeonard Crestez 	devfreq->nb_min.notifier_call = qos_min_notifier_call;
934ec894883Spierre Kuo 	err = dev_pm_qos_add_notifier(dev, &devfreq->nb_min,
93505d7ae15SLeonard Crestez 				      DEV_PM_QOS_MIN_FREQUENCY);
93605d7ae15SLeonard Crestez 	if (err)
93705d7ae15SLeonard Crestez 		goto err_devfreq;
93805d7ae15SLeonard Crestez 
93905d7ae15SLeonard Crestez 	devfreq->nb_max.notifier_call = qos_max_notifier_call;
940ec894883Spierre Kuo 	err = dev_pm_qos_add_notifier(dev, &devfreq->nb_max,
94105d7ae15SLeonard Crestez 				      DEV_PM_QOS_MAX_FREQUENCY);
94205d7ae15SLeonard Crestez 	if (err)
94305d7ae15SLeonard Crestez 		goto err_devfreq;
94405d7ae15SLeonard Crestez 
945a3c98b8bSMyungJoo Ham 	mutex_lock(&devfreq_list_lock);
946a3c98b8bSMyungJoo Ham 
94796ffcdf2SChanwoo Choi 	governor = try_then_request_governor(governor_name);
94873613b16SChanwoo Choi 	if (IS_ERR(governor)) {
94973613b16SChanwoo Choi 		dev_err(dev, "%s: Unable to find governor for the device\n",
95073613b16SChanwoo Choi 			__func__);
95173613b16SChanwoo Choi 		err = PTR_ERR(governor);
95273613b16SChanwoo Choi 		goto err_init;
95373613b16SChanwoo Choi 	}
95473613b16SChanwoo Choi 
9551b5c1be2SNishanth Menon 	devfreq->governor = governor;
95673613b16SChanwoo Choi 	err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
95773613b16SChanwoo Choi 						NULL);
9587e6fdd4bSRajagopal Venkat 	if (err) {
959e52b045fSChristian 'Ansuel' Marangi 		dev_err_probe(dev, err,
960e52b045fSChristian 'Ansuel' Marangi 			"%s: Unable to start governor for the device\n",
9617e6fdd4bSRajagopal Venkat 			 __func__);
9627e6fdd4bSRajagopal Venkat 		goto err_init;
9637e6fdd4bSRajagopal Venkat 	}
9645f1a9066SChanwoo Choi 	create_sysfs_files(devfreq, devfreq->governor);
96523c7b54cSEnric Balletbo i Serra 
96623c7b54cSEnric Balletbo i Serra 	list_add(&devfreq->node, &devfreq_list);
96723c7b54cSEnric Balletbo i Serra 
9680f376c9cSAxel Lin 	mutex_unlock(&devfreq_list_lock);
9697e6fdd4bSRajagopal Venkat 
9701224451bSDaniel Lezcano 	if (devfreq->profile->is_cooling_device) {
9711224451bSDaniel Lezcano 		devfreq->cdev = devfreq_cooling_em_register(devfreq, NULL);
9721224451bSDaniel Lezcano 		if (IS_ERR(devfreq->cdev))
9731224451bSDaniel Lezcano 			devfreq->cdev = NULL;
9741224451bSDaniel Lezcano 	}
9751224451bSDaniel Lezcano 
9763f19f08aSAxel Lin 	return devfreq;
9773f19f08aSAxel Lin 
978a3c98b8bSMyungJoo Ham err_init:
9790f376c9cSAxel Lin 	mutex_unlock(&devfreq_list_lock);
98025846fa1SYangtao Li err_devfreq:
9812f061fd0SVincent Donnefort 	devfreq_remove_device(devfreq);
9822d803dc8SArvind Yadav 	devfreq = NULL;
9839e14de10SChanwoo Choi err_dev:
9849e14de10SChanwoo Choi 	kfree(devfreq);
9853f19f08aSAxel Lin err_out:
986a3c98b8bSMyungJoo Ham 	return ERR_PTR(err);
987a3c98b8bSMyungJoo Ham }
9887e6fdd4bSRajagopal Venkat EXPORT_SYMBOL(devfreq_add_device);
989a3c98b8bSMyungJoo Ham 
990a3c98b8bSMyungJoo Ham /**
991a3c98b8bSMyungJoo Ham  * devfreq_remove_device() - Remove devfreq feature from a device.
992c5b4a1c1SNishanth Menon  * @devfreq:	the devfreq instance to be removed
993de9c7394SMyungJoo Ham  *
994de9c7394SMyungJoo Ham  * The opposite of devfreq_add_device().
995a3c98b8bSMyungJoo Ham  */
devfreq_remove_device(struct devfreq * devfreq)996a3c98b8bSMyungJoo Ham int devfreq_remove_device(struct devfreq *devfreq)
997a3c98b8bSMyungJoo Ham {
998a3c98b8bSMyungJoo Ham 	if (!devfreq)
999a3c98b8bSMyungJoo Ham 		return -EINVAL;
1000a3c98b8bSMyungJoo Ham 
10011224451bSDaniel Lezcano 	devfreq_cooling_unregister(devfreq->cdev);
10021224451bSDaniel Lezcano 
10035f1a9066SChanwoo Choi 	if (devfreq->governor) {
10042f061fd0SVincent Donnefort 		devfreq->governor->event_handler(devfreq,
10052f061fd0SVincent Donnefort 						 DEVFREQ_GOV_STOP, NULL);
10065f1a9066SChanwoo Choi 		remove_sysfs_files(devfreq, devfreq->governor);
10075f1a9066SChanwoo Choi 	}
10085f1a9066SChanwoo Choi 
1009585fc83eSChanwoo Choi 	device_unregister(&devfreq->dev);
1010a3c98b8bSMyungJoo Ham 
1011a3c98b8bSMyungJoo Ham 	return 0;
1012a3c98b8bSMyungJoo Ham }
10137e6fdd4bSRajagopal Venkat EXPORT_SYMBOL(devfreq_remove_device);
1014a3c98b8bSMyungJoo Ham 
devm_devfreq_dev_match(struct device * dev,void * res,void * data)10158cd84092SChanwoo Choi static int devm_devfreq_dev_match(struct device *dev, void *res, void *data)
10168cd84092SChanwoo Choi {
10178cd84092SChanwoo Choi 	struct devfreq **r = res;
10188cd84092SChanwoo Choi 
10198cd84092SChanwoo Choi 	if (WARN_ON(!r || !*r))
10208cd84092SChanwoo Choi 		return 0;
10218cd84092SChanwoo Choi 
10228cd84092SChanwoo Choi 	return *r == data;
10238cd84092SChanwoo Choi }
10248cd84092SChanwoo Choi 
devm_devfreq_dev_release(struct device * dev,void * res)10258cd84092SChanwoo Choi static void devm_devfreq_dev_release(struct device *dev, void *res)
10268cd84092SChanwoo Choi {
10278cd84092SChanwoo Choi 	devfreq_remove_device(*(struct devfreq **)res);
10288cd84092SChanwoo Choi }
10298cd84092SChanwoo Choi 
10308cd84092SChanwoo Choi /**
10318cd84092SChanwoo Choi  * devm_devfreq_add_device() - Resource-managed devfreq_add_device()
10328cd84092SChanwoo Choi  * @dev:	the device to add devfreq feature.
10338cd84092SChanwoo Choi  * @profile:	device-specific profile to run devfreq.
10348cd84092SChanwoo Choi  * @governor_name:	name of the policy to choose frequency.
10355fdded84SKant Fan  * @data:	 devfreq driver pass to governors, governor should not change it.
10368cd84092SChanwoo Choi  *
10378cd84092SChanwoo Choi  * This function manages automatically the memory of devfreq device using device
10388cd84092SChanwoo Choi  * resource management and simplify the free operation for memory of devfreq
10398cd84092SChanwoo Choi  * device.
10408cd84092SChanwoo Choi  */
devm_devfreq_add_device(struct device * dev,struct devfreq_dev_profile * profile,const char * governor_name,void * data)10418cd84092SChanwoo Choi struct devfreq *devm_devfreq_add_device(struct device *dev,
10428cd84092SChanwoo Choi 					struct devfreq_dev_profile *profile,
10438cd84092SChanwoo Choi 					const char *governor_name,
10448cd84092SChanwoo Choi 					void *data)
10458cd84092SChanwoo Choi {
10468cd84092SChanwoo Choi 	struct devfreq **ptr, *devfreq;
10478cd84092SChanwoo Choi 
10488cd84092SChanwoo Choi 	ptr = devres_alloc(devm_devfreq_dev_release, sizeof(*ptr), GFP_KERNEL);
10498cd84092SChanwoo Choi 	if (!ptr)
10508cd84092SChanwoo Choi 		return ERR_PTR(-ENOMEM);
10518cd84092SChanwoo Choi 
10528cd84092SChanwoo Choi 	devfreq = devfreq_add_device(dev, profile, governor_name, data);
10538cd84092SChanwoo Choi 	if (IS_ERR(devfreq)) {
10548cd84092SChanwoo Choi 		devres_free(ptr);
1055d1bf2d30SBjorn Andersson 		return devfreq;
10568cd84092SChanwoo Choi 	}
10578cd84092SChanwoo Choi 
10588cd84092SChanwoo Choi 	*ptr = devfreq;
10598cd84092SChanwoo Choi 	devres_add(dev, ptr);
10608cd84092SChanwoo Choi 
10618cd84092SChanwoo Choi 	return devfreq;
10628cd84092SChanwoo Choi }
10638cd84092SChanwoo Choi EXPORT_SYMBOL(devm_devfreq_add_device);
10648cd84092SChanwoo Choi 
10658f510aebSChanwoo Choi #ifdef CONFIG_OF
10668f510aebSChanwoo Choi /*
10677b38b7b0SLeonard Crestez  * devfreq_get_devfreq_by_node - Get the devfreq device from devicetree
10687b38b7b0SLeonard Crestez  * @node - pointer to device_node
10697b38b7b0SLeonard Crestez  *
10707b38b7b0SLeonard Crestez  * return the instance of devfreq device
10717b38b7b0SLeonard Crestez  */
devfreq_get_devfreq_by_node(struct device_node * node)10727b38b7b0SLeonard Crestez struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
10737b38b7b0SLeonard Crestez {
10747b38b7b0SLeonard Crestez 	struct devfreq *devfreq;
10757b38b7b0SLeonard Crestez 
10767b38b7b0SLeonard Crestez 	if (!node)
10777b38b7b0SLeonard Crestez 		return ERR_PTR(-EINVAL);
10787b38b7b0SLeonard Crestez 
10797b38b7b0SLeonard Crestez 	mutex_lock(&devfreq_list_lock);
10807b38b7b0SLeonard Crestez 	list_for_each_entry(devfreq, &devfreq_list, node) {
10817b38b7b0SLeonard Crestez 		if (devfreq->dev.parent
1082fba39536Sye xingchen 			&& device_match_of_node(devfreq->dev.parent, node)) {
10837b38b7b0SLeonard Crestez 			mutex_unlock(&devfreq_list_lock);
10847b38b7b0SLeonard Crestez 			return devfreq;
10857b38b7b0SLeonard Crestez 		}
10867b38b7b0SLeonard Crestez 	}
10877b38b7b0SLeonard Crestez 	mutex_unlock(&devfreq_list_lock);
10887b38b7b0SLeonard Crestez 
10897b38b7b0SLeonard Crestez 	return ERR_PTR(-ENODEV);
10907b38b7b0SLeonard Crestez }
10917b38b7b0SLeonard Crestez 
10927b38b7b0SLeonard Crestez /*
10938f510aebSChanwoo Choi  * devfreq_get_devfreq_by_phandle - Get the devfreq device from devicetree
10948f510aebSChanwoo Choi  * @dev - instance to the given device
109586d90fd9SChanwoo Choi  * @phandle_name - name of property holding a phandle value
10968f510aebSChanwoo Choi  * @index - index into list of devfreq
10978f510aebSChanwoo Choi  *
10988f510aebSChanwoo Choi  * return the instance of devfreq device
10998f510aebSChanwoo Choi  */
devfreq_get_devfreq_by_phandle(struct device * dev,const char * phandle_name,int index)110086d90fd9SChanwoo Choi struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
110186d90fd9SChanwoo Choi 					const char *phandle_name, int index)
11028f510aebSChanwoo Choi {
11038f510aebSChanwoo Choi 	struct device_node *node;
11048f510aebSChanwoo Choi 	struct devfreq *devfreq;
11058f510aebSChanwoo Choi 
110686d90fd9SChanwoo Choi 	if (!dev || !phandle_name)
11078f510aebSChanwoo Choi 		return ERR_PTR(-EINVAL);
11088f510aebSChanwoo Choi 
11098f510aebSChanwoo Choi 	if (!dev->of_node)
11108f510aebSChanwoo Choi 		return ERR_PTR(-EINVAL);
11118f510aebSChanwoo Choi 
111286d90fd9SChanwoo Choi 	node = of_parse_phandle(dev->of_node, phandle_name, index);
11138f510aebSChanwoo Choi 	if (!node)
11148f510aebSChanwoo Choi 		return ERR_PTR(-ENODEV);
11158f510aebSChanwoo Choi 
11167b38b7b0SLeonard Crestez 	devfreq = devfreq_get_devfreq_by_node(node);
11173427c6f0SPeter Chen 	of_node_put(node);
11188f510aebSChanwoo Choi 
11197b38b7b0SLeonard Crestez 	return devfreq;
11208f510aebSChanwoo Choi }
11217b38b7b0SLeonard Crestez 
11228f510aebSChanwoo Choi #else
devfreq_get_devfreq_by_node(struct device_node * node)11237b38b7b0SLeonard Crestez struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
11247b38b7b0SLeonard Crestez {
11257b38b7b0SLeonard Crestez 	return ERR_PTR(-ENODEV);
11267b38b7b0SLeonard Crestez }
11277b38b7b0SLeonard Crestez 
devfreq_get_devfreq_by_phandle(struct device * dev,const char * phandle_name,int index)112886d90fd9SChanwoo Choi struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
112986d90fd9SChanwoo Choi 					const char *phandle_name, int index)
11308f510aebSChanwoo Choi {
11318f510aebSChanwoo Choi 	return ERR_PTR(-ENODEV);
11328f510aebSChanwoo Choi }
11338f510aebSChanwoo Choi #endif /* CONFIG_OF */
11347b38b7b0SLeonard Crestez EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_node);
11358f510aebSChanwoo Choi EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_phandle);
11368f510aebSChanwoo Choi 
11378cd84092SChanwoo Choi /**
11388cd84092SChanwoo Choi  * devm_devfreq_remove_device() - Resource-managed devfreq_remove_device()
1139e2fc1677SKrzysztof Kozlowski  * @dev:	the device from which to remove devfreq feature.
11408cd84092SChanwoo Choi  * @devfreq:	the devfreq instance to be removed
11418cd84092SChanwoo Choi  */
devm_devfreq_remove_device(struct device * dev,struct devfreq * devfreq)11428cd84092SChanwoo Choi void devm_devfreq_remove_device(struct device *dev, struct devfreq *devfreq)
11438cd84092SChanwoo Choi {
11448cd84092SChanwoo Choi 	WARN_ON(devres_release(dev, devm_devfreq_dev_release,
11458cd84092SChanwoo Choi 			       devm_devfreq_dev_match, devfreq));
11468cd84092SChanwoo Choi }
11478cd84092SChanwoo Choi EXPORT_SYMBOL(devm_devfreq_remove_device);
11488cd84092SChanwoo Choi 
1149206c30cfSRajagopal Venkat /**
1150206c30cfSRajagopal Venkat  * devfreq_suspend_device() - Suspend devfreq of a device.
1151206c30cfSRajagopal Venkat  * @devfreq: the devfreq instance to be suspended
1152de9c7394SMyungJoo Ham  *
1153de9c7394SMyungJoo Ham  * This function is intended to be called by the pm callbacks
1154de9c7394SMyungJoo Ham  * (e.g., runtime_suspend, suspend) of the device driver that
1155de9c7394SMyungJoo Ham  * holds the devfreq.
1156206c30cfSRajagopal Venkat  */
devfreq_suspend_device(struct devfreq * devfreq)1157206c30cfSRajagopal Venkat int devfreq_suspend_device(struct devfreq *devfreq)
1158206c30cfSRajagopal Venkat {
115983f8ca45SLukasz Luba 	int ret;
116083f8ca45SLukasz Luba 
1161206c30cfSRajagopal Venkat 	if (!devfreq)
1162206c30cfSRajagopal Venkat 		return -EINVAL;
1163206c30cfSRajagopal Venkat 
116483f8ca45SLukasz Luba 	if (atomic_inc_return(&devfreq->suspend_count) > 1)
11651b5c1be2SNishanth Menon 		return 0;
11661b5c1be2SNishanth Menon 
116783f8ca45SLukasz Luba 	if (devfreq->governor) {
116883f8ca45SLukasz Luba 		ret = devfreq->governor->event_handler(devfreq,
1169206c30cfSRajagopal Venkat 					DEVFREQ_GOV_SUSPEND, NULL);
117083f8ca45SLukasz Luba 		if (ret)
117183f8ca45SLukasz Luba 			return ret;
117283f8ca45SLukasz Luba 	}
117383f8ca45SLukasz Luba 
117483f8ca45SLukasz Luba 	if (devfreq->suspend_freq) {
1175e1e047acSMarek Szyprowski 		mutex_lock(&devfreq->lock);
117683f8ca45SLukasz Luba 		ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0);
1177e1e047acSMarek Szyprowski 		mutex_unlock(&devfreq->lock);
117883f8ca45SLukasz Luba 		if (ret)
117983f8ca45SLukasz Luba 			return ret;
118083f8ca45SLukasz Luba 	}
118183f8ca45SLukasz Luba 
118283f8ca45SLukasz Luba 	return 0;
1183206c30cfSRajagopal Venkat }
1184206c30cfSRajagopal Venkat EXPORT_SYMBOL(devfreq_suspend_device);
1185206c30cfSRajagopal Venkat 
1186206c30cfSRajagopal Venkat /**
1187206c30cfSRajagopal Venkat  * devfreq_resume_device() - Resume devfreq of a device.
1188206c30cfSRajagopal Venkat  * @devfreq: the devfreq instance to be resumed
1189de9c7394SMyungJoo Ham  *
1190de9c7394SMyungJoo Ham  * This function is intended to be called by the pm callbacks
1191de9c7394SMyungJoo Ham  * (e.g., runtime_resume, resume) of the device driver that
1192de9c7394SMyungJoo Ham  * holds the devfreq.
1193206c30cfSRajagopal Venkat  */
devfreq_resume_device(struct devfreq * devfreq)1194206c30cfSRajagopal Venkat int devfreq_resume_device(struct devfreq *devfreq)
1195206c30cfSRajagopal Venkat {
119683f8ca45SLukasz Luba 	int ret;
119783f8ca45SLukasz Luba 
1198206c30cfSRajagopal Venkat 	if (!devfreq)
1199206c30cfSRajagopal Venkat 		return -EINVAL;
1200206c30cfSRajagopal Venkat 
120183f8ca45SLukasz Luba 	if (atomic_dec_return(&devfreq->suspend_count) >= 1)
12021b5c1be2SNishanth Menon 		return 0;
12031b5c1be2SNishanth Menon 
120483f8ca45SLukasz Luba 	if (devfreq->resume_freq) {
1205e1e047acSMarek Szyprowski 		mutex_lock(&devfreq->lock);
120683f8ca45SLukasz Luba 		ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0);
1207e1e047acSMarek Szyprowski 		mutex_unlock(&devfreq->lock);
120883f8ca45SLukasz Luba 		if (ret)
120983f8ca45SLukasz Luba 			return ret;
121083f8ca45SLukasz Luba 	}
121183f8ca45SLukasz Luba 
121283f8ca45SLukasz Luba 	if (devfreq->governor) {
121383f8ca45SLukasz Luba 		ret = devfreq->governor->event_handler(devfreq,
1214206c30cfSRajagopal Venkat 					DEVFREQ_GOV_RESUME, NULL);
121583f8ca45SLukasz Luba 		if (ret)
121683f8ca45SLukasz Luba 			return ret;
121783f8ca45SLukasz Luba 	}
121883f8ca45SLukasz Luba 
121983f8ca45SLukasz Luba 	return 0;
1220206c30cfSRajagopal Venkat }
1221206c30cfSRajagopal Venkat EXPORT_SYMBOL(devfreq_resume_device);
1222206c30cfSRajagopal Venkat 
12233aa173b8SNishanth Menon /**
122459031956SLukasz Luba  * devfreq_suspend() - Suspend devfreq governors and devices
122559031956SLukasz Luba  *
122659031956SLukasz Luba  * Called during system wide Suspend/Hibernate cycles for suspending governors
122759031956SLukasz Luba  * and devices preserving the state for resume. On some platforms the devfreq
122859031956SLukasz Luba  * device must have precise state (frequency) after resume in order to provide
122959031956SLukasz Luba  * fully operating setup.
123059031956SLukasz Luba  */
devfreq_suspend(void)123159031956SLukasz Luba void devfreq_suspend(void)
123259031956SLukasz Luba {
123359031956SLukasz Luba 	struct devfreq *devfreq;
123459031956SLukasz Luba 	int ret;
123559031956SLukasz Luba 
123659031956SLukasz Luba 	mutex_lock(&devfreq_list_lock);
123759031956SLukasz Luba 	list_for_each_entry(devfreq, &devfreq_list, node) {
123859031956SLukasz Luba 		ret = devfreq_suspend_device(devfreq);
123959031956SLukasz Luba 		if (ret)
124059031956SLukasz Luba 			dev_err(&devfreq->dev,
124159031956SLukasz Luba 				"failed to suspend devfreq device\n");
124259031956SLukasz Luba 	}
124359031956SLukasz Luba 	mutex_unlock(&devfreq_list_lock);
124459031956SLukasz Luba }
124559031956SLukasz Luba 
124659031956SLukasz Luba /**
124759031956SLukasz Luba  * devfreq_resume() - Resume devfreq governors and devices
124859031956SLukasz Luba  *
124959031956SLukasz Luba  * Called during system wide Suspend/Hibernate cycle for resuming governors and
125059031956SLukasz Luba  * devices that are suspended with devfreq_suspend().
125159031956SLukasz Luba  */
devfreq_resume(void)125259031956SLukasz Luba void devfreq_resume(void)
125359031956SLukasz Luba {
125459031956SLukasz Luba 	struct devfreq *devfreq;
125559031956SLukasz Luba 	int ret;
125659031956SLukasz Luba 
125759031956SLukasz Luba 	mutex_lock(&devfreq_list_lock);
125859031956SLukasz Luba 	list_for_each_entry(devfreq, &devfreq_list, node) {
125959031956SLukasz Luba 		ret = devfreq_resume_device(devfreq);
126059031956SLukasz Luba 		if (ret)
126159031956SLukasz Luba 			dev_warn(&devfreq->dev,
126259031956SLukasz Luba 				 "failed to resume devfreq device\n");
126359031956SLukasz Luba 	}
126459031956SLukasz Luba 	mutex_unlock(&devfreq_list_lock);
126559031956SLukasz Luba }
126659031956SLukasz Luba 
126759031956SLukasz Luba /**
12683aa173b8SNishanth Menon  * devfreq_add_governor() - Add devfreq governor
12693aa173b8SNishanth Menon  * @governor:	the devfreq governor to be added
12703aa173b8SNishanth Menon  */
devfreq_add_governor(struct devfreq_governor * governor)12713aa173b8SNishanth Menon int devfreq_add_governor(struct devfreq_governor *governor)
12723aa173b8SNishanth Menon {
12733aa173b8SNishanth Menon 	struct devfreq_governor *g;
12741b5c1be2SNishanth Menon 	struct devfreq *devfreq;
12753aa173b8SNishanth Menon 	int err = 0;
12763aa173b8SNishanth Menon 
12773aa173b8SNishanth Menon 	if (!governor) {
12783aa173b8SNishanth Menon 		pr_err("%s: Invalid parameters.\n", __func__);
12793aa173b8SNishanth Menon 		return -EINVAL;
12803aa173b8SNishanth Menon 	}
12813aa173b8SNishanth Menon 
12823aa173b8SNishanth Menon 	mutex_lock(&devfreq_list_lock);
12833aa173b8SNishanth Menon 	g = find_devfreq_governor(governor->name);
12843aa173b8SNishanth Menon 	if (!IS_ERR(g)) {
12853aa173b8SNishanth Menon 		pr_err("%s: governor %s already registered\n", __func__,
12863aa173b8SNishanth Menon 		       g->name);
12873aa173b8SNishanth Menon 		err = -EINVAL;
12883aa173b8SNishanth Menon 		goto err_out;
12893aa173b8SNishanth Menon 	}
12903aa173b8SNishanth Menon 
12913aa173b8SNishanth Menon 	list_add(&governor->node, &devfreq_governor_list);
12923aa173b8SNishanth Menon 
12931b5c1be2SNishanth Menon 	list_for_each_entry(devfreq, &devfreq_list, node) {
12941b5c1be2SNishanth Menon 		int ret = 0;
12951b5c1be2SNishanth Menon 		struct device *dev = devfreq->dev.parent;
12961b5c1be2SNishanth Menon 
129796ffcdf2SChanwoo Choi 		if (!strncmp(devfreq->governor->name, governor->name,
12981b5c1be2SNishanth Menon 			     DEVFREQ_NAME_LEN)) {
12991b5c1be2SNishanth Menon 			/* The following should never occur */
13001b5c1be2SNishanth Menon 			if (devfreq->governor) {
13011b5c1be2SNishanth Menon 				dev_warn(dev,
13021b5c1be2SNishanth Menon 					 "%s: Governor %s already present\n",
13031b5c1be2SNishanth Menon 					 __func__, devfreq->governor->name);
13041b5c1be2SNishanth Menon 				ret = devfreq->governor->event_handler(devfreq,
13051b5c1be2SNishanth Menon 							DEVFREQ_GOV_STOP, NULL);
13061b5c1be2SNishanth Menon 				if (ret) {
13071b5c1be2SNishanth Menon 					dev_warn(dev,
13081b5c1be2SNishanth Menon 						 "%s: Governor %s stop = %d\n",
13091b5c1be2SNishanth Menon 						 __func__,
13101b5c1be2SNishanth Menon 						 devfreq->governor->name, ret);
13111b5c1be2SNishanth Menon 				}
13121b5c1be2SNishanth Menon 				/* Fall through */
13131b5c1be2SNishanth Menon 			}
13141b5c1be2SNishanth Menon 			devfreq->governor = governor;
13151b5c1be2SNishanth Menon 			ret = devfreq->governor->event_handler(devfreq,
13161b5c1be2SNishanth Menon 						DEVFREQ_GOV_START, NULL);
13171b5c1be2SNishanth Menon 			if (ret) {
13181b5c1be2SNishanth Menon 				dev_warn(dev, "%s: Governor %s start=%d\n",
13191b5c1be2SNishanth Menon 					 __func__, devfreq->governor->name,
13201b5c1be2SNishanth Menon 					 ret);
13211b5c1be2SNishanth Menon 			}
13221b5c1be2SNishanth Menon 		}
13231b5c1be2SNishanth Menon 	}
13241b5c1be2SNishanth Menon 
13253aa173b8SNishanth Menon err_out:
13263aa173b8SNishanth Menon 	mutex_unlock(&devfreq_list_lock);
13273aa173b8SNishanth Menon 
13283aa173b8SNishanth Menon 	return err;
13293aa173b8SNishanth Menon }
13303aa173b8SNishanth Menon EXPORT_SYMBOL(devfreq_add_governor);
13313aa173b8SNishanth Menon 
devm_devfreq_remove_governor(void * governor)13321cc55204SDmitry Osipenko static void devm_devfreq_remove_governor(void *governor)
13331cc55204SDmitry Osipenko {
13341cc55204SDmitry Osipenko 	WARN_ON(devfreq_remove_governor(governor));
13351cc55204SDmitry Osipenko }
13361cc55204SDmitry Osipenko 
13371cc55204SDmitry Osipenko /**
13381cc55204SDmitry Osipenko  * devm_devfreq_add_governor() - Add devfreq governor
13391cc55204SDmitry Osipenko  * @dev:	device which adds devfreq governor
13401cc55204SDmitry Osipenko  * @governor:	the devfreq governor to be added
13411cc55204SDmitry Osipenko  *
13421cc55204SDmitry Osipenko  * This is a resource-managed variant of devfreq_add_governor().
13431cc55204SDmitry Osipenko  */
devm_devfreq_add_governor(struct device * dev,struct devfreq_governor * governor)13441cc55204SDmitry Osipenko int devm_devfreq_add_governor(struct device *dev,
13451cc55204SDmitry Osipenko 			      struct devfreq_governor *governor)
13461cc55204SDmitry Osipenko {
13471cc55204SDmitry Osipenko 	int err;
13481cc55204SDmitry Osipenko 
13491cc55204SDmitry Osipenko 	err = devfreq_add_governor(governor);
13501cc55204SDmitry Osipenko 	if (err)
13511cc55204SDmitry Osipenko 		return err;
13521cc55204SDmitry Osipenko 
13531cc55204SDmitry Osipenko 	return devm_add_action_or_reset(dev, devm_devfreq_remove_governor,
13541cc55204SDmitry Osipenko 					governor);
13551cc55204SDmitry Osipenko }
13561cc55204SDmitry Osipenko EXPORT_SYMBOL(devm_devfreq_add_governor);
13571cc55204SDmitry Osipenko 
13583aa173b8SNishanth Menon /**
1359bafeb42bSMyungJoo Ham  * devfreq_remove_governor() - Remove devfreq feature from a device.
13603aa173b8SNishanth Menon  * @governor:	the devfreq governor to be removed
13613aa173b8SNishanth Menon  */
devfreq_remove_governor(struct devfreq_governor * governor)13623aa173b8SNishanth Menon int devfreq_remove_governor(struct devfreq_governor *governor)
13633aa173b8SNishanth Menon {
13643aa173b8SNishanth Menon 	struct devfreq_governor *g;
13651b5c1be2SNishanth Menon 	struct devfreq *devfreq;
13663aa173b8SNishanth Menon 	int err = 0;
13673aa173b8SNishanth Menon 
13683aa173b8SNishanth Menon 	if (!governor) {
13693aa173b8SNishanth Menon 		pr_err("%s: Invalid parameters.\n", __func__);
13703aa173b8SNishanth Menon 		return -EINVAL;
13713aa173b8SNishanth Menon 	}
13723aa173b8SNishanth Menon 
13733aa173b8SNishanth Menon 	mutex_lock(&devfreq_list_lock);
13743aa173b8SNishanth Menon 	g = find_devfreq_governor(governor->name);
13753aa173b8SNishanth Menon 	if (IS_ERR(g)) {
13763aa173b8SNishanth Menon 		pr_err("%s: governor %s not registered\n", __func__,
1377b9e1c8e8SSachin Kamat 		       governor->name);
1378f9c08e2aSSachin Kamat 		err = PTR_ERR(g);
13793aa173b8SNishanth Menon 		goto err_out;
13803aa173b8SNishanth Menon 	}
13811b5c1be2SNishanth Menon 	list_for_each_entry(devfreq, &devfreq_list, node) {
13821b5c1be2SNishanth Menon 		int ret;
13831b5c1be2SNishanth Menon 		struct device *dev = devfreq->dev.parent;
13841b5c1be2SNishanth Menon 
138596ffcdf2SChanwoo Choi 		if (!strncmp(devfreq->governor->name, governor->name,
13861b5c1be2SNishanth Menon 			     DEVFREQ_NAME_LEN)) {
13871b5c1be2SNishanth Menon 			/* we should have a devfreq governor! */
13881b5c1be2SNishanth Menon 			if (!devfreq->governor) {
13891b5c1be2SNishanth Menon 				dev_warn(dev, "%s: Governor %s NOT present\n",
13901b5c1be2SNishanth Menon 					 __func__, governor->name);
13911b5c1be2SNishanth Menon 				continue;
13921b5c1be2SNishanth Menon 				/* Fall through */
13931b5c1be2SNishanth Menon 			}
13941b5c1be2SNishanth Menon 			ret = devfreq->governor->event_handler(devfreq,
13951b5c1be2SNishanth Menon 						DEVFREQ_GOV_STOP, NULL);
13961b5c1be2SNishanth Menon 			if (ret) {
13971b5c1be2SNishanth Menon 				dev_warn(dev, "%s: Governor %s stop=%d\n",
13981b5c1be2SNishanth Menon 					 __func__, devfreq->governor->name,
13991b5c1be2SNishanth Menon 					 ret);
14001b5c1be2SNishanth Menon 			}
14011b5c1be2SNishanth Menon 			devfreq->governor = NULL;
14021b5c1be2SNishanth Menon 		}
14031b5c1be2SNishanth Menon 	}
14043aa173b8SNishanth Menon 
14053aa173b8SNishanth Menon 	list_del(&governor->node);
14063aa173b8SNishanth Menon err_out:
14073aa173b8SNishanth Menon 	mutex_unlock(&devfreq_list_lock);
14083aa173b8SNishanth Menon 
14093aa173b8SNishanth Menon 	return err;
14103aa173b8SNishanth Menon }
14113aa173b8SNishanth Menon EXPORT_SYMBOL(devfreq_remove_governor);
1412a3c98b8bSMyungJoo Ham 
name_show(struct device * dev,struct device_attribute * attr,char * buf)14132fee1a7cSChanwoo Choi static ssize_t name_show(struct device *dev,
14142fee1a7cSChanwoo Choi 			struct device_attribute *attr, char *buf)
14152fee1a7cSChanwoo Choi {
1416483d557eSChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
1417483d557eSChanwoo Choi 	return sprintf(buf, "%s\n", dev_name(df->dev.parent));
14182fee1a7cSChanwoo Choi }
14192fee1a7cSChanwoo Choi static DEVICE_ATTR_RO(name);
14202fee1a7cSChanwoo Choi 
governor_show(struct device * dev,struct device_attribute * attr,char * buf)1421a93d6b0aSGreg Kroah-Hartman static ssize_t governor_show(struct device *dev,
14229005b650SMyungJoo Ham 			     struct device_attribute *attr, char *buf)
14239005b650SMyungJoo Ham {
1424483d557eSChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
1425483d557eSChanwoo Choi 
1426483d557eSChanwoo Choi 	if (!df->governor)
14271b5c1be2SNishanth Menon 		return -EINVAL;
14281b5c1be2SNishanth Menon 
1429483d557eSChanwoo Choi 	return sprintf(buf, "%s\n", df->governor->name);
14309005b650SMyungJoo Ham }
14319005b650SMyungJoo Ham 
governor_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1432a93d6b0aSGreg Kroah-Hartman static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
14330359d1afSNishanth Menon 			      const char *buf, size_t count)
14340359d1afSNishanth Menon {
14350359d1afSNishanth Menon 	struct devfreq *df = to_devfreq(dev);
14360359d1afSNishanth Menon 	int ret;
14370359d1afSNishanth Menon 	char str_governor[DEVFREQ_NAME_LEN + 1];
1438bc658befSSaravana Kannan 	const struct devfreq_governor *governor, *prev_governor;
14390359d1afSNishanth Menon 
1440483d557eSChanwoo Choi 	if (!df->governor)
1441483d557eSChanwoo Choi 		return -EINVAL;
1442483d557eSChanwoo Choi 
14430359d1afSNishanth Menon 	ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
14440359d1afSNishanth Menon 	if (ret != 1)
14450359d1afSNishanth Menon 		return -EINVAL;
14460359d1afSNishanth Menon 
14470359d1afSNishanth Menon 	mutex_lock(&devfreq_list_lock);
144823c7b54cSEnric Balletbo i Serra 	governor = try_then_request_governor(str_governor);
14490359d1afSNishanth Menon 	if (IS_ERR(governor)) {
14500359d1afSNishanth Menon 		ret = PTR_ERR(governor);
14510359d1afSNishanth Menon 		goto out;
14520359d1afSNishanth Menon 	}
145314a21e7bSTobias Jakobi 	if (df->governor == governor) {
145414a21e7bSTobias Jakobi 		ret = 0;
14550359d1afSNishanth Menon 		goto out;
14560dd25a0dSChanwoo Choi 	} else if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)
14570dd25a0dSChanwoo Choi 		|| IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE)) {
1458bcf23c79SChanwoo Choi 		ret = -EINVAL;
1459bcf23c79SChanwoo Choi 		goto out;
146014a21e7bSTobias Jakobi 	}
14610359d1afSNishanth Menon 
14625f1a9066SChanwoo Choi 	/*
14635f1a9066SChanwoo Choi 	 * Stop the current governor and remove the specific sysfs files
14645f1a9066SChanwoo Choi 	 * which depend on current governor.
14655f1a9066SChanwoo Choi 	 */
14660359d1afSNishanth Menon 	ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
14670359d1afSNishanth Menon 	if (ret) {
14680359d1afSNishanth Menon 		dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
14690359d1afSNishanth Menon 			 __func__, df->governor->name, ret);
14700359d1afSNishanth Menon 		goto out;
14710359d1afSNishanth Menon 	}
14725f1a9066SChanwoo Choi 	remove_sysfs_files(df, df->governor);
1473483d557eSChanwoo Choi 
14745f1a9066SChanwoo Choi 	/*
14755f1a9066SChanwoo Choi 	 * Start the new governor and create the specific sysfs files
14765f1a9066SChanwoo Choi 	 * which depend on the new governor.
14775f1a9066SChanwoo Choi 	 */
1478bc658befSSaravana Kannan 	prev_governor = df->governor;
14790359d1afSNishanth Menon 	df->governor = governor;
14800359d1afSNishanth Menon 	ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
1481bc658befSSaravana Kannan 	if (ret) {
14820359d1afSNishanth Menon 		dev_warn(dev, "%s: Governor %s not started(%d)\n",
14830359d1afSNishanth Menon 			 __func__, df->governor->name, ret);
14845f1a9066SChanwoo Choi 
14855f1a9066SChanwoo Choi 		/* Restore previous governor */
1486bc658befSSaravana Kannan 		df->governor = prev_governor;
1487bc658befSSaravana Kannan 		ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
1488bc658befSSaravana Kannan 		if (ret) {
1489bc658befSSaravana Kannan 			dev_err(dev,
1490bc658befSSaravana Kannan 				"%s: reverting to Governor %s failed (%d)\n",
149196ffcdf2SChanwoo Choi 				__func__, prev_governor->name, ret);
1492bc658befSSaravana Kannan 			df->governor = NULL;
14935f1a9066SChanwoo Choi 			goto out;
1494bc658befSSaravana Kannan 		}
1495bc658befSSaravana Kannan 	}
14965f1a9066SChanwoo Choi 
14975f1a9066SChanwoo Choi 	/*
14985f1a9066SChanwoo Choi 	 * Create the sysfs files for the new governor. But if failed to start
14995f1a9066SChanwoo Choi 	 * the new governor, restore the sysfs files of previous governor.
15005f1a9066SChanwoo Choi 	 */
15015f1a9066SChanwoo Choi 	create_sysfs_files(df, df->governor);
15025f1a9066SChanwoo Choi 
15030359d1afSNishanth Menon out:
15040359d1afSNishanth Menon 	mutex_unlock(&devfreq_list_lock);
15050359d1afSNishanth Menon 
15060359d1afSNishanth Menon 	if (!ret)
15070359d1afSNishanth Menon 		ret = count;
15080359d1afSNishanth Menon 	return ret;
15090359d1afSNishanth Menon }
1510a93d6b0aSGreg Kroah-Hartman static DEVICE_ATTR_RW(governor);
1511a93d6b0aSGreg Kroah-Hartman 
available_governors_show(struct device * d,struct device_attribute * attr,char * buf)1512a93d6b0aSGreg Kroah-Hartman static ssize_t available_governors_show(struct device *d,
151350a5b33eSNishanth Menon 					struct device_attribute *attr,
151450a5b33eSNishanth Menon 					char *buf)
151550a5b33eSNishanth Menon {
1516bcf23c79SChanwoo Choi 	struct devfreq *df = to_devfreq(d);
151750a5b33eSNishanth Menon 	ssize_t count = 0;
151850a5b33eSNishanth Menon 
1519483d557eSChanwoo Choi 	if (!df->governor)
1520483d557eSChanwoo Choi 		return -EINVAL;
1521483d557eSChanwoo Choi 
152250a5b33eSNishanth Menon 	mutex_lock(&devfreq_list_lock);
1523bcf23c79SChanwoo Choi 
1524bcf23c79SChanwoo Choi 	/*
1525bcf23c79SChanwoo Choi 	 * The devfreq with immutable governor (e.g., passive) shows
1526bcf23c79SChanwoo Choi 	 * only own governor.
1527bcf23c79SChanwoo Choi 	 */
15280dd25a0dSChanwoo Choi 	if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)) {
1529bcf23c79SChanwoo Choi 		count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
153096ffcdf2SChanwoo Choi 				  "%s ", df->governor->name);
1531bcf23c79SChanwoo Choi 	/*
1532bcf23c79SChanwoo Choi 	 * The devfreq device shows the registered governor except for
1533bcf23c79SChanwoo Choi 	 * immutable governors such as passive governor .
1534bcf23c79SChanwoo Choi 	 */
1535bcf23c79SChanwoo Choi 	} else {
1536bcf23c79SChanwoo Choi 		struct devfreq_governor *governor;
1537bcf23c79SChanwoo Choi 
1538bcf23c79SChanwoo Choi 		list_for_each_entry(governor, &devfreq_governor_list, node) {
15390dd25a0dSChanwoo Choi 			if (IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE))
1540bcf23c79SChanwoo Choi 				continue;
154150a5b33eSNishanth Menon 			count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
1542bcf23c79SChanwoo Choi 					   "%s ", governor->name);
1543bcf23c79SChanwoo Choi 		}
1544bcf23c79SChanwoo Choi 	}
1545bcf23c79SChanwoo Choi 
154650a5b33eSNishanth Menon 	mutex_unlock(&devfreq_list_lock);
154750a5b33eSNishanth Menon 
154850a5b33eSNishanth Menon 	/* Truncate the trailing space */
154950a5b33eSNishanth Menon 	if (count)
155050a5b33eSNishanth Menon 		count--;
155150a5b33eSNishanth Menon 
155250a5b33eSNishanth Menon 	count += sprintf(&buf[count], "\n");
155350a5b33eSNishanth Menon 
155450a5b33eSNishanth Menon 	return count;
155550a5b33eSNishanth Menon }
1556a93d6b0aSGreg Kroah-Hartman static DEVICE_ATTR_RO(available_governors);
15570359d1afSNishanth Menon 
cur_freq_show(struct device * dev,struct device_attribute * attr,char * buf)1558a93d6b0aSGreg Kroah-Hartman static ssize_t cur_freq_show(struct device *dev, struct device_attribute *attr,
1559a93d6b0aSGreg Kroah-Hartman 			     char *buf)
15609005b650SMyungJoo Ham {
15617f98a905SRajagopal Venkat 	unsigned long freq;
1562483d557eSChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
15637f98a905SRajagopal Venkat 
1564483d557eSChanwoo Choi 	if (!df->profile)
1565483d557eSChanwoo Choi 		return -EINVAL;
1566483d557eSChanwoo Choi 
1567483d557eSChanwoo Choi 	if (df->profile->get_cur_freq &&
1568483d557eSChanwoo Choi 		!df->profile->get_cur_freq(df->dev.parent, &freq))
15697f98a905SRajagopal Venkat 		return sprintf(buf, "%lu\n", freq);
15707f98a905SRajagopal Venkat 
1571483d557eSChanwoo Choi 	return sprintf(buf, "%lu\n", df->previous_freq);
15727f98a905SRajagopal Venkat }
1573a93d6b0aSGreg Kroah-Hartman static DEVICE_ATTR_RO(cur_freq);
15747f98a905SRajagopal Venkat 
target_freq_show(struct device * dev,struct device_attribute * attr,char * buf)1575a93d6b0aSGreg Kroah-Hartman static ssize_t target_freq_show(struct device *dev,
15767f98a905SRajagopal Venkat 				struct device_attribute *attr, char *buf)
15777f98a905SRajagopal Venkat {
1578483d557eSChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
1579483d557eSChanwoo Choi 
1580483d557eSChanwoo Choi 	return sprintf(buf, "%lu\n", df->previous_freq);
15819005b650SMyungJoo Ham }
1582a93d6b0aSGreg Kroah-Hartman static DEVICE_ATTR_RO(target_freq);
15839005b650SMyungJoo Ham 
min_freq_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1584a93d6b0aSGreg Kroah-Hartman static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
15856530b9deSMyungJoo Ham 			      const char *buf, size_t count)
15866530b9deSMyungJoo Ham {
15876530b9deSMyungJoo Ham 	struct devfreq *df = to_devfreq(dev);
15886530b9deSMyungJoo Ham 	unsigned long value;
15896530b9deSMyungJoo Ham 	int ret;
15906530b9deSMyungJoo Ham 
159127dbc542SLeonard Crestez 	/*
159227dbc542SLeonard Crestez 	 * Protect against theoretical sysfs writes between
159327dbc542SLeonard Crestez 	 * device_add and dev_pm_qos_add_request
159427dbc542SLeonard Crestez 	 */
159527dbc542SLeonard Crestez 	if (!dev_pm_qos_request_active(&df->user_min_freq_req))
159627dbc542SLeonard Crestez 		return -EAGAIN;
159727dbc542SLeonard Crestez 
15986530b9deSMyungJoo Ham 	ret = sscanf(buf, "%lu", &value);
15996530b9deSMyungJoo Ham 	if (ret != 1)
160012e26265SNishanth Menon 		return -EINVAL;
16016530b9deSMyungJoo Ham 
160227dbc542SLeonard Crestez 	/* Round down to kHz for PM QoS */
160327dbc542SLeonard Crestez 	ret = dev_pm_qos_update_request(&df->user_min_freq_req,
160427dbc542SLeonard Crestez 					value / HZ_PER_KHZ);
160527dbc542SLeonard Crestez 	if (ret < 0)
160627dbc542SLeonard Crestez 		return ret;
160746cecc0bSLeonard Crestez 
160846cecc0bSLeonard Crestez 	return count;
16096530b9deSMyungJoo Ham }
16106530b9deSMyungJoo Ham 
min_freq_show(struct device * dev,struct device_attribute * attr,char * buf)16111051e2c3SChanwoo Choi static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
16121051e2c3SChanwoo Choi 			     char *buf)
16131051e2c3SChanwoo Choi {
1614f1d981eaSChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
161546cecc0bSLeonard Crestez 	unsigned long min_freq, max_freq;
1616f1d981eaSChanwoo Choi 
161746cecc0bSLeonard Crestez 	mutex_lock(&df->lock);
1618713472e5SChanwoo Choi 	devfreq_get_freq_range(df, &min_freq, &max_freq);
161946cecc0bSLeonard Crestez 	mutex_unlock(&df->lock);
162046cecc0bSLeonard Crestez 
162146cecc0bSLeonard Crestez 	return sprintf(buf, "%lu\n", min_freq);
16221051e2c3SChanwoo Choi }
1623f9002b16SKamil Konieczny static DEVICE_ATTR_RW(min_freq);
16241051e2c3SChanwoo Choi 
max_freq_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1625a93d6b0aSGreg Kroah-Hartman static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
16266530b9deSMyungJoo Ham 			      const char *buf, size_t count)
16276530b9deSMyungJoo Ham {
16286530b9deSMyungJoo Ham 	struct devfreq *df = to_devfreq(dev);
16296530b9deSMyungJoo Ham 	unsigned long value;
16306530b9deSMyungJoo Ham 	int ret;
16316530b9deSMyungJoo Ham 
163227dbc542SLeonard Crestez 	/*
163327dbc542SLeonard Crestez 	 * Protect against theoretical sysfs writes between
163427dbc542SLeonard Crestez 	 * device_add and dev_pm_qos_add_request
163527dbc542SLeonard Crestez 	 */
163627dbc542SLeonard Crestez 	if (!dev_pm_qos_request_active(&df->user_max_freq_req))
163727dbc542SLeonard Crestez 		return -EINVAL;
163827dbc542SLeonard Crestez 
16396530b9deSMyungJoo Ham 	ret = sscanf(buf, "%lu", &value);
16406530b9deSMyungJoo Ham 	if (ret != 1)
164112e26265SNishanth Menon 		return -EINVAL;
16426530b9deSMyungJoo Ham 
164327dbc542SLeonard Crestez 	/*
164427dbc542SLeonard Crestez 	 * PM QoS frequencies are in kHz so we need to convert. Convert by
164527dbc542SLeonard Crestez 	 * rounding upwards so that the acceptable interval never shrinks.
164627dbc542SLeonard Crestez 	 *
164727dbc542SLeonard Crestez 	 * For example if the user writes "666666666" to sysfs this value will
164827dbc542SLeonard Crestez 	 * be converted to 666667 kHz and back to 666667000 Hz before an OPP
164927dbc542SLeonard Crestez 	 * lookup, this ensures that an OPP of 666666666Hz is still accepted.
165027dbc542SLeonard Crestez 	 *
165127dbc542SLeonard Crestez 	 * A value of zero means "no limit".
165227dbc542SLeonard Crestez 	 */
165327dbc542SLeonard Crestez 	if (value)
165427dbc542SLeonard Crestez 		value = DIV_ROUND_UP(value, HZ_PER_KHZ);
165527dbc542SLeonard Crestez 	else
165627dbc542SLeonard Crestez 		value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
1657df5cf4a3SMatthias Kaehlcke 
165827dbc542SLeonard Crestez 	ret = dev_pm_qos_update_request(&df->user_max_freq_req, value);
165927dbc542SLeonard Crestez 	if (ret < 0)
166027dbc542SLeonard Crestez 		return ret;
166146cecc0bSLeonard Crestez 
166246cecc0bSLeonard Crestez 	return count;
16636530b9deSMyungJoo Ham }
16641051e2c3SChanwoo Choi 
max_freq_show(struct device * dev,struct device_attribute * attr,char * buf)16651051e2c3SChanwoo Choi static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
16661051e2c3SChanwoo Choi 			     char *buf)
16671051e2c3SChanwoo Choi {
1668f1d981eaSChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
166946cecc0bSLeonard Crestez 	unsigned long min_freq, max_freq;
1670f1d981eaSChanwoo Choi 
167146cecc0bSLeonard Crestez 	mutex_lock(&df->lock);
1672713472e5SChanwoo Choi 	devfreq_get_freq_range(df, &min_freq, &max_freq);
167346cecc0bSLeonard Crestez 	mutex_unlock(&df->lock);
167446cecc0bSLeonard Crestez 
167546cecc0bSLeonard Crestez 	return sprintf(buf, "%lu\n", max_freq);
16761051e2c3SChanwoo Choi }
1677a93d6b0aSGreg Kroah-Hartman static DEVICE_ATTR_RW(max_freq);
16786530b9deSMyungJoo Ham 
available_frequencies_show(struct device * d,struct device_attribute * attr,char * buf)1679a93d6b0aSGreg Kroah-Hartman static ssize_t available_frequencies_show(struct device *d,
1680d287de85SNishanth Menon 					  struct device_attribute *attr,
1681d287de85SNishanth Menon 					  char *buf)
1682d287de85SNishanth Menon {
1683d287de85SNishanth Menon 	struct devfreq *df = to_devfreq(d);
1684d287de85SNishanth Menon 	ssize_t count = 0;
1685416b46a2SChanwoo Choi 	int i;
1686d287de85SNishanth Menon 
1687483d557eSChanwoo Choi 	if (!df->profile)
1688483d557eSChanwoo Choi 		return -EINVAL;
1689483d557eSChanwoo Choi 
1690416b46a2SChanwoo Choi 	mutex_lock(&df->lock);
1691d287de85SNishanth Menon 
1692b5d281f6SChristian Marangi 	for (i = 0; i < df->max_state; i++)
1693d287de85SNishanth Menon 		count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
1694b5d281f6SChristian Marangi 				"%lu ", df->freq_table[i]);
1695d287de85SNishanth Menon 
1696416b46a2SChanwoo Choi 	mutex_unlock(&df->lock);
1697d287de85SNishanth Menon 	/* Truncate the trailing space */
1698d287de85SNishanth Menon 	if (count)
1699d287de85SNishanth Menon 		count--;
1700d287de85SNishanth Menon 
1701d287de85SNishanth Menon 	count += sprintf(&buf[count], "\n");
1702d287de85SNishanth Menon 
1703d287de85SNishanth Menon 	return count;
1704d287de85SNishanth Menon }
1705a93d6b0aSGreg Kroah-Hartman static DEVICE_ATTR_RO(available_frequencies);
1706d287de85SNishanth Menon 
trans_stat_show(struct device * dev,struct device_attribute * attr,char * buf)1707a93d6b0aSGreg Kroah-Hartman static ssize_t trans_stat_show(struct device *dev,
1708a93d6b0aSGreg Kroah-Hartman 			       struct device_attribute *attr, char *buf)
1709e552bbafSJonghwa Lee {
1710483d557eSChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
1711a979f56aSChristian Marangi 	ssize_t len = 0;
171239688ce6SRajagopal Venkat 	int i, j;
1713483d557eSChanwoo Choi 	unsigned int max_state;
1714483d557eSChanwoo Choi 
1715483d557eSChanwoo Choi 	if (!df->profile)
1716483d557eSChanwoo Choi 		return -EINVAL;
1717b5d281f6SChristian Marangi 	max_state = df->max_state;
1718e552bbafSJonghwa Lee 
171934bd3220SMyungJoo Ham 	if (max_state == 0)
1720a979f56aSChristian Marangi 		return scnprintf(buf, PAGE_SIZE, "Not Supported.\n");
1721e552bbafSJonghwa Lee 
1722483d557eSChanwoo Choi 	mutex_lock(&df->lock);
1723483d557eSChanwoo Choi 	if (!df->stop_polling &&
1724483d557eSChanwoo Choi 			devfreq_update_status(df, df->previous_freq)) {
1725483d557eSChanwoo Choi 		mutex_unlock(&df->lock);
17262abb0d52SLeonard Crestez 		return 0;
17272abb0d52SLeonard Crestez 	}
1728483d557eSChanwoo Choi 	mutex_unlock(&df->lock);
17292abb0d52SLeonard Crestez 
1730a979f56aSChristian Marangi 	len += scnprintf(buf + len, PAGE_SIZE - len, "     From  :   To\n");
1731a979f56aSChristian Marangi 	len += scnprintf(buf + len, PAGE_SIZE - len, "           :");
1732a979f56aSChristian Marangi 	for (i = 0; i < max_state; i++) {
1733a979f56aSChristian Marangi 		if (len >= PAGE_SIZE - 1)
1734a979f56aSChristian Marangi 			break;
1735a979f56aSChristian Marangi 		len += scnprintf(buf + len, PAGE_SIZE - len, "%10lu",
1736b5d281f6SChristian Marangi 				 df->freq_table[i]);
1737a979f56aSChristian Marangi 	}
1738a979f56aSChristian Marangi 	if (len >= PAGE_SIZE - 1)
1739a979f56aSChristian Marangi 		return PAGE_SIZE - 1;
1740e552bbafSJonghwa Lee 
1741a979f56aSChristian Marangi 	len += scnprintf(buf + len, PAGE_SIZE - len, "   time(ms)\n");
1742e552bbafSJonghwa Lee 
1743e552bbafSJonghwa Lee 	for (i = 0; i < max_state; i++) {
1744a979f56aSChristian Marangi 		if (len >= PAGE_SIZE - 1)
1745a979f56aSChristian Marangi 			break;
1746b5d281f6SChristian Marangi 		if (df->freq_table[i] == df->previous_freq)
1747a979f56aSChristian Marangi 			len += scnprintf(buf + len, PAGE_SIZE - len, "*");
1748b5d281f6SChristian Marangi 		else
1749a979f56aSChristian Marangi 			len += scnprintf(buf + len, PAGE_SIZE - len, " ");
1750a979f56aSChristian Marangi 		if (len >= PAGE_SIZE - 1)
1751a979f56aSChristian Marangi 			break;
1752b5d281f6SChristian Marangi 
1753a979f56aSChristian Marangi 		len += scnprintf(buf + len, PAGE_SIZE - len, "%10lu:",
1754a979f56aSChristian Marangi 				 df->freq_table[i]);
1755a979f56aSChristian Marangi 		for (j = 0; j < max_state; j++) {
1756a979f56aSChristian Marangi 			if (len >= PAGE_SIZE - 1)
1757a979f56aSChristian Marangi 				break;
1758a979f56aSChristian Marangi 			len += scnprintf(buf + len, PAGE_SIZE - len, "%10u",
1759483d557eSChanwoo Choi 					 df->stats.trans_table[(i * max_state) + j]);
1760a979f56aSChristian Marangi 		}
1761a979f56aSChristian Marangi 		if (len >= PAGE_SIZE - 1)
1762a979f56aSChristian Marangi 			break;
1763a979f56aSChristian Marangi 		len += scnprintf(buf + len, PAGE_SIZE - len, "%10llu\n", (u64)
1764483d557eSChanwoo Choi 				 jiffies64_to_msecs(df->stats.time_in_state[i]));
1765e552bbafSJonghwa Lee 	}
1766e552bbafSJonghwa Lee 
1767a979f56aSChristian Marangi 	if (len < PAGE_SIZE - 1)
1768a979f56aSChristian Marangi 		len += scnprintf(buf + len, PAGE_SIZE - len, "Total transition : %u\n",
1769483d557eSChanwoo Choi 				 df->stats.total_trans);
1770a979f56aSChristian Marangi 
1771a979f56aSChristian Marangi 	if (len >= PAGE_SIZE - 1) {
1772a979f56aSChristian Marangi 		pr_warn_once("devfreq transition table exceeds PAGE_SIZE. Disabling\n");
1773a979f56aSChristian Marangi 		return -EFBIG;
1774a979f56aSChristian Marangi 	}
1775a979f56aSChristian Marangi 
1776e552bbafSJonghwa Lee 	return len;
1777e552bbafSJonghwa Lee }
177814a34396SKamil Konieczny 
trans_stat_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)177914a34396SKamil Konieczny static ssize_t trans_stat_store(struct device *dev,
178014a34396SKamil Konieczny 				struct device_attribute *attr,
178114a34396SKamil Konieczny 				const char *buf, size_t count)
178214a34396SKamil Konieczny {
178314a34396SKamil Konieczny 	struct devfreq *df = to_devfreq(dev);
178414a34396SKamil Konieczny 	int err, value;
178514a34396SKamil Konieczny 
1786483d557eSChanwoo Choi 	if (!df->profile)
1787483d557eSChanwoo Choi 		return -EINVAL;
1788483d557eSChanwoo Choi 
1789b5d281f6SChristian Marangi 	if (df->max_state == 0)
179014a34396SKamil Konieczny 		return count;
179114a34396SKamil Konieczny 
179214a34396SKamil Konieczny 	err = kstrtoint(buf, 10, &value);
179314a34396SKamil Konieczny 	if (err || value != 0)
179414a34396SKamil Konieczny 		return -EINVAL;
179514a34396SKamil Konieczny 
179614a34396SKamil Konieczny 	mutex_lock(&df->lock);
1797b5d281f6SChristian Marangi 	memset(df->stats.time_in_state, 0, (df->max_state *
17981ebd0bc0SKamil Konieczny 					sizeof(*df->stats.time_in_state)));
17991ebd0bc0SKamil Konieczny 	memset(df->stats.trans_table, 0, array3_size(sizeof(unsigned int),
1800b5d281f6SChristian Marangi 					df->max_state,
1801b5d281f6SChristian Marangi 					df->max_state));
18021ebd0bc0SKamil Konieczny 	df->stats.total_trans = 0;
18031ebd0bc0SKamil Konieczny 	df->stats.last_update = get_jiffies_64();
180414a34396SKamil Konieczny 	mutex_unlock(&df->lock);
180514a34396SKamil Konieczny 
180614a34396SKamil Konieczny 	return count;
180714a34396SKamil Konieczny }
180814a34396SKamil Konieczny static DEVICE_ATTR_RW(trans_stat);
1809e552bbafSJonghwa Lee 
18105f1a9066SChanwoo Choi static struct attribute *devfreq_attrs[] = {
18115f1a9066SChanwoo Choi 	&dev_attr_name.attr,
18125f1a9066SChanwoo Choi 	&dev_attr_governor.attr,
18135f1a9066SChanwoo Choi 	&dev_attr_available_governors.attr,
18145f1a9066SChanwoo Choi 	&dev_attr_cur_freq.attr,
18155f1a9066SChanwoo Choi 	&dev_attr_available_frequencies.attr,
18165f1a9066SChanwoo Choi 	&dev_attr_target_freq.attr,
18175f1a9066SChanwoo Choi 	&dev_attr_min_freq.attr,
18185f1a9066SChanwoo Choi 	&dev_attr_max_freq.attr,
18195f1a9066SChanwoo Choi 	&dev_attr_trans_stat.attr,
18205f1a9066SChanwoo Choi 	NULL,
18215f1a9066SChanwoo Choi };
18225f1a9066SChanwoo Choi ATTRIBUTE_GROUPS(devfreq);
18235f1a9066SChanwoo Choi 
polling_interval_show(struct device * dev,struct device_attribute * attr,char * buf)18245f1a9066SChanwoo Choi static ssize_t polling_interval_show(struct device *dev,
18255f1a9066SChanwoo Choi 				     struct device_attribute *attr, char *buf)
18265f1a9066SChanwoo Choi {
18275f1a9066SChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
18285f1a9066SChanwoo Choi 
18295f1a9066SChanwoo Choi 	if (!df->profile)
18305f1a9066SChanwoo Choi 		return -EINVAL;
18315f1a9066SChanwoo Choi 
18325f1a9066SChanwoo Choi 	return sprintf(buf, "%d\n", df->profile->polling_ms);
18335f1a9066SChanwoo Choi }
18345f1a9066SChanwoo Choi 
polling_interval_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)18355f1a9066SChanwoo Choi static ssize_t polling_interval_store(struct device *dev,
18365f1a9066SChanwoo Choi 				      struct device_attribute *attr,
18375f1a9066SChanwoo Choi 				      const char *buf, size_t count)
18385f1a9066SChanwoo Choi {
18395f1a9066SChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
18405f1a9066SChanwoo Choi 	unsigned int value;
18415f1a9066SChanwoo Choi 	int ret;
18425f1a9066SChanwoo Choi 
18435f1a9066SChanwoo Choi 	if (!df->governor)
18445f1a9066SChanwoo Choi 		return -EINVAL;
18455f1a9066SChanwoo Choi 
18465f1a9066SChanwoo Choi 	ret = sscanf(buf, "%u", &value);
18475f1a9066SChanwoo Choi 	if (ret != 1)
18485f1a9066SChanwoo Choi 		return -EINVAL;
18495f1a9066SChanwoo Choi 
18505f1a9066SChanwoo Choi 	df->governor->event_handler(df, DEVFREQ_GOV_UPDATE_INTERVAL, &value);
18515f1a9066SChanwoo Choi 	ret = count;
18525f1a9066SChanwoo Choi 
18535f1a9066SChanwoo Choi 	return ret;
18545f1a9066SChanwoo Choi }
18555f1a9066SChanwoo Choi static DEVICE_ATTR_RW(polling_interval);
18565f1a9066SChanwoo Choi 
timer_show(struct device * dev,struct device_attribute * attr,char * buf)18574dc3bab8SChanwoo Choi static ssize_t timer_show(struct device *dev,
18584dc3bab8SChanwoo Choi 			     struct device_attribute *attr, char *buf)
18594dc3bab8SChanwoo Choi {
18604dc3bab8SChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
18614dc3bab8SChanwoo Choi 
18624dc3bab8SChanwoo Choi 	if (!df->profile)
18634dc3bab8SChanwoo Choi 		return -EINVAL;
18644dc3bab8SChanwoo Choi 
18654dc3bab8SChanwoo Choi 	return sprintf(buf, "%s\n", timer_name[df->profile->timer]);
18664dc3bab8SChanwoo Choi }
18674dc3bab8SChanwoo Choi 
timer_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)18684dc3bab8SChanwoo Choi static ssize_t timer_store(struct device *dev, struct device_attribute *attr,
18694dc3bab8SChanwoo Choi 			      const char *buf, size_t count)
18704dc3bab8SChanwoo Choi {
18714dc3bab8SChanwoo Choi 	struct devfreq *df = to_devfreq(dev);
18724dc3bab8SChanwoo Choi 	char str_timer[DEVFREQ_NAME_LEN + 1];
18734dc3bab8SChanwoo Choi 	int timer = -1;
18744dc3bab8SChanwoo Choi 	int ret = 0, i;
18754dc3bab8SChanwoo Choi 
18764dc3bab8SChanwoo Choi 	if (!df->governor || !df->profile)
18774dc3bab8SChanwoo Choi 		return -EINVAL;
18784dc3bab8SChanwoo Choi 
18794dc3bab8SChanwoo Choi 	ret = sscanf(buf, "%16s", str_timer);
18804dc3bab8SChanwoo Choi 	if (ret != 1)
18814dc3bab8SChanwoo Choi 		return -EINVAL;
18824dc3bab8SChanwoo Choi 
18834dc3bab8SChanwoo Choi 	for (i = 0; i < DEVFREQ_TIMER_NUM; i++) {
18844dc3bab8SChanwoo Choi 		if (!strncmp(timer_name[i], str_timer, DEVFREQ_NAME_LEN)) {
18854dc3bab8SChanwoo Choi 			timer = i;
18864dc3bab8SChanwoo Choi 			break;
18874dc3bab8SChanwoo Choi 		}
18884dc3bab8SChanwoo Choi 	}
18894dc3bab8SChanwoo Choi 
18904dc3bab8SChanwoo Choi 	if (timer < 0) {
18914dc3bab8SChanwoo Choi 		ret = -EINVAL;
18924dc3bab8SChanwoo Choi 		goto out;
18934dc3bab8SChanwoo Choi 	}
18944dc3bab8SChanwoo Choi 
18954dc3bab8SChanwoo Choi 	if (df->profile->timer == timer) {
18964dc3bab8SChanwoo Choi 		ret = 0;
18974dc3bab8SChanwoo Choi 		goto out;
18984dc3bab8SChanwoo Choi 	}
18994dc3bab8SChanwoo Choi 
19004dc3bab8SChanwoo Choi 	mutex_lock(&df->lock);
19014dc3bab8SChanwoo Choi 	df->profile->timer = timer;
19024dc3bab8SChanwoo Choi 	mutex_unlock(&df->lock);
19034dc3bab8SChanwoo Choi 
19044dc3bab8SChanwoo Choi 	ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
19054dc3bab8SChanwoo Choi 	if (ret) {
19064dc3bab8SChanwoo Choi 		dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
19074dc3bab8SChanwoo Choi 			 __func__, df->governor->name, ret);
19084dc3bab8SChanwoo Choi 		goto out;
19094dc3bab8SChanwoo Choi 	}
19104dc3bab8SChanwoo Choi 
19114dc3bab8SChanwoo Choi 	ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
19124dc3bab8SChanwoo Choi 	if (ret)
19134dc3bab8SChanwoo Choi 		dev_warn(dev, "%s: Governor %s not started(%d)\n",
19144dc3bab8SChanwoo Choi 			 __func__, df->governor->name, ret);
19154dc3bab8SChanwoo Choi out:
19164dc3bab8SChanwoo Choi 	return ret ? ret : count;
19174dc3bab8SChanwoo Choi }
19184dc3bab8SChanwoo Choi static DEVICE_ATTR_RW(timer);
19194dc3bab8SChanwoo Choi 
19205f1a9066SChanwoo Choi #define CREATE_SYSFS_FILE(df, name)					\
19215f1a9066SChanwoo Choi {									\
19225f1a9066SChanwoo Choi 	int ret;							\
19235f1a9066SChanwoo Choi 	ret = sysfs_create_file(&df->dev.kobj, &dev_attr_##name.attr);	\
19245f1a9066SChanwoo Choi 	if (ret < 0) {							\
19255f1a9066SChanwoo Choi 		dev_warn(&df->dev,					\
19265f1a9066SChanwoo Choi 			"Unable to create attr(%s)\n", "##name");	\
19275f1a9066SChanwoo Choi 	}								\
19285f1a9066SChanwoo Choi }									\
19295f1a9066SChanwoo Choi 
19305f1a9066SChanwoo Choi /* Create the specific sysfs files which depend on each governor. */
create_sysfs_files(struct devfreq * devfreq,const struct devfreq_governor * gov)19315f1a9066SChanwoo Choi static void create_sysfs_files(struct devfreq *devfreq,
19325f1a9066SChanwoo Choi 				const struct devfreq_governor *gov)
19335f1a9066SChanwoo Choi {
19345f1a9066SChanwoo Choi 	if (IS_SUPPORTED_ATTR(gov->attrs, POLLING_INTERVAL))
19355f1a9066SChanwoo Choi 		CREATE_SYSFS_FILE(devfreq, polling_interval);
19365f1a9066SChanwoo Choi 	if (IS_SUPPORTED_ATTR(gov->attrs, TIMER))
19375f1a9066SChanwoo Choi 		CREATE_SYSFS_FILE(devfreq, timer);
19385f1a9066SChanwoo Choi }
19395f1a9066SChanwoo Choi 
19405f1a9066SChanwoo Choi /* Remove the specific sysfs files which depend on each governor. */
remove_sysfs_files(struct devfreq * devfreq,const struct devfreq_governor * gov)19415f1a9066SChanwoo Choi static void remove_sysfs_files(struct devfreq *devfreq,
19425f1a9066SChanwoo Choi 				const struct devfreq_governor *gov)
19435f1a9066SChanwoo Choi {
19445f1a9066SChanwoo Choi 	if (IS_SUPPORTED_ATTR(gov->attrs, POLLING_INTERVAL))
19455f1a9066SChanwoo Choi 		sysfs_remove_file(&devfreq->dev.kobj,
19465f1a9066SChanwoo Choi 				&dev_attr_polling_interval.attr);
19475f1a9066SChanwoo Choi 	if (IS_SUPPORTED_ATTR(gov->attrs, TIMER))
19485f1a9066SChanwoo Choi 		sysfs_remove_file(&devfreq->dev.kobj, &dev_attr_timer.attr);
19495f1a9066SChanwoo Choi }
19509005b650SMyungJoo Ham 
1951490a421bSChanwoo Choi /**
1952490a421bSChanwoo Choi  * devfreq_summary_show() - Show the summary of the devfreq devices
1953490a421bSChanwoo Choi  * @s:		seq_file instance to show the summary of devfreq devices
1954490a421bSChanwoo Choi  * @data:	not used
1955490a421bSChanwoo Choi  *
1956490a421bSChanwoo Choi  * Show the summary of the devfreq devices via 'devfreq_summary' debugfs file.
1957490a421bSChanwoo Choi  * It helps that user can know the detailed information of the devfreq devices.
1958490a421bSChanwoo Choi  *
1959490a421bSChanwoo Choi  * Return 0 always because it shows the information without any data change.
1960490a421bSChanwoo Choi  */
devfreq_summary_show(struct seq_file * s,void * data)1961490a421bSChanwoo Choi static int devfreq_summary_show(struct seq_file *s, void *data)
1962490a421bSChanwoo Choi {
1963490a421bSChanwoo Choi 	struct devfreq *devfreq;
1964490a421bSChanwoo Choi 	struct devfreq *p_devfreq = NULL;
1965490a421bSChanwoo Choi 	unsigned long cur_freq, min_freq, max_freq;
1966490a421bSChanwoo Choi 	unsigned int polling_ms;
19670c309ed1SChanwoo Choi 	unsigned int timer;
1968490a421bSChanwoo Choi 
19690c309ed1SChanwoo Choi 	seq_printf(s, "%-30s %-30s %-15s %-10s %10s %12s %12s %12s\n",
1970490a421bSChanwoo Choi 			"dev",
1971490a421bSChanwoo Choi 			"parent_dev",
1972490a421bSChanwoo Choi 			"governor",
19730c309ed1SChanwoo Choi 			"timer",
1974490a421bSChanwoo Choi 			"polling_ms",
1975490a421bSChanwoo Choi 			"cur_freq_Hz",
1976490a421bSChanwoo Choi 			"min_freq_Hz",
1977490a421bSChanwoo Choi 			"max_freq_Hz");
19780c309ed1SChanwoo Choi 	seq_printf(s, "%30s %30s %15s %10s %10s %12s %12s %12s\n",
1979490a421bSChanwoo Choi 			"------------------------------",
19800aae11bcSChanwoo Choi 			"------------------------------",
1981490a421bSChanwoo Choi 			"---------------",
1982490a421bSChanwoo Choi 			"----------",
19830c309ed1SChanwoo Choi 			"----------",
1984490a421bSChanwoo Choi 			"------------",
1985490a421bSChanwoo Choi 			"------------",
1986490a421bSChanwoo Choi 			"------------");
1987490a421bSChanwoo Choi 
1988490a421bSChanwoo Choi 	mutex_lock(&devfreq_list_lock);
1989490a421bSChanwoo Choi 
1990490a421bSChanwoo Choi 	list_for_each_entry_reverse(devfreq, &devfreq_list, node) {
1991490a421bSChanwoo Choi #if IS_ENABLED(CONFIG_DEVFREQ_GOV_PASSIVE)
199296ffcdf2SChanwoo Choi 		if (!strncmp(devfreq->governor->name, DEVFREQ_GOV_PASSIVE,
1993490a421bSChanwoo Choi 							DEVFREQ_NAME_LEN)) {
1994490a421bSChanwoo Choi 			struct devfreq_passive_data *data = devfreq->data;
1995490a421bSChanwoo Choi 
1996490a421bSChanwoo Choi 			if (data)
1997490a421bSChanwoo Choi 				p_devfreq = data->parent;
1998490a421bSChanwoo Choi 		} else {
1999490a421bSChanwoo Choi 			p_devfreq = NULL;
2000490a421bSChanwoo Choi 		}
2001490a421bSChanwoo Choi #endif
2002490a421bSChanwoo Choi 
2003490a421bSChanwoo Choi 		mutex_lock(&devfreq->lock);
200427a69714SChanwoo Choi 		cur_freq = devfreq->previous_freq;
2005713472e5SChanwoo Choi 		devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
20060c309ed1SChanwoo Choi 		timer = devfreq->profile->timer;
20075f1a9066SChanwoo Choi 
20085f1a9066SChanwoo Choi 		if (IS_SUPPORTED_ATTR(devfreq->governor->attrs, POLLING_INTERVAL))
20095f1a9066SChanwoo Choi 			polling_ms = devfreq->profile->polling_ms;
20105f1a9066SChanwoo Choi 		else
20115f1a9066SChanwoo Choi 			polling_ms = 0;
2012490a421bSChanwoo Choi 		mutex_unlock(&devfreq->lock);
2013490a421bSChanwoo Choi 
2014490a421bSChanwoo Choi 		seq_printf(s,
20150c309ed1SChanwoo Choi 			"%-30s %-30s %-15s %-10s %10d %12ld %12ld %12ld\n",
2016490a421bSChanwoo Choi 			dev_name(&devfreq->dev),
2017490a421bSChanwoo Choi 			p_devfreq ? dev_name(&p_devfreq->dev) : "null",
201896ffcdf2SChanwoo Choi 			devfreq->governor->name,
20190c309ed1SChanwoo Choi 			polling_ms ? timer_name[timer] : "null",
2020490a421bSChanwoo Choi 			polling_ms,
2021490a421bSChanwoo Choi 			cur_freq,
2022490a421bSChanwoo Choi 			min_freq,
2023490a421bSChanwoo Choi 			max_freq);
2024490a421bSChanwoo Choi 	}
2025490a421bSChanwoo Choi 
2026490a421bSChanwoo Choi 	mutex_unlock(&devfreq_list_lock);
2027490a421bSChanwoo Choi 
2028490a421bSChanwoo Choi 	return 0;
2029490a421bSChanwoo Choi }
2030490a421bSChanwoo Choi DEFINE_SHOW_ATTRIBUTE(devfreq_summary);
2031490a421bSChanwoo Choi 
devfreq_init(void)2032a3c98b8bSMyungJoo Ham static int __init devfreq_init(void)
2033a3c98b8bSMyungJoo Ham {
20341aaba11dSGreg Kroah-Hartman 	devfreq_class = class_create("devfreq");
2035a3c98b8bSMyungJoo Ham 	if (IS_ERR(devfreq_class)) {
2036a3c98b8bSMyungJoo Ham 		pr_err("%s: couldn't create class\n", __FILE__);
2037a3c98b8bSMyungJoo Ham 		return PTR_ERR(devfreq_class);
2038a3c98b8bSMyungJoo Ham 	}
20397e6fdd4bSRajagopal Venkat 
20407e6fdd4bSRajagopal Venkat 	devfreq_wq = create_freezable_workqueue("devfreq_wq");
2041ea7f4548SDan Carpenter 	if (!devfreq_wq) {
20427e6fdd4bSRajagopal Venkat 		class_destroy(devfreq_class);
20437e6fdd4bSRajagopal Venkat 		pr_err("%s: couldn't create workqueue\n", __FILE__);
2044ea7f4548SDan Carpenter 		return -ENOMEM;
20457e6fdd4bSRajagopal Venkat 	}
2046a93d6b0aSGreg Kroah-Hartman 	devfreq_class->dev_groups = devfreq_groups;
20477e6fdd4bSRajagopal Venkat 
2048490a421bSChanwoo Choi 	devfreq_debugfs = debugfs_create_dir("devfreq", NULL);
2049490a421bSChanwoo Choi 	debugfs_create_file("devfreq_summary", 0444,
2050490a421bSChanwoo Choi 				devfreq_debugfs, NULL,
2051490a421bSChanwoo Choi 				&devfreq_summary_fops);
2052490a421bSChanwoo Choi 
2053a3c98b8bSMyungJoo Ham 	return 0;
2054a3c98b8bSMyungJoo Ham }
2055a3c98b8bSMyungJoo Ham subsys_initcall(devfreq_init);
2056a3c98b8bSMyungJoo Ham 
2057a3c98b8bSMyungJoo Ham /*
20584091fb95SMasahiro Yamada  * The following are helper functions for devfreq user device drivers with
2059a3c98b8bSMyungJoo Ham  * OPP framework.
2060a3c98b8bSMyungJoo Ham  */
2061a3c98b8bSMyungJoo Ham 
2062a3c98b8bSMyungJoo Ham /**
2063a3c98b8bSMyungJoo Ham  * devfreq_recommended_opp() - Helper function to get proper OPP for the
2064a3c98b8bSMyungJoo Ham  *			     freq value given to target callback.
2065c5b4a1c1SNishanth Menon  * @dev:	The devfreq user device. (parent of devfreq)
2066c5b4a1c1SNishanth Menon  * @freq:	The frequency given to target function
2067c5b4a1c1SNishanth Menon  * @flags:	Flags handed from devfreq framework.
2068a3c98b8bSMyungJoo Ham  *
20698a31d9d9SViresh Kumar  * The callers are required to call dev_pm_opp_put() for the returned OPP after
20708a31d9d9SViresh Kumar  * use.
2071a3c98b8bSMyungJoo Ham  */
devfreq_recommended_opp(struct device * dev,unsigned long * freq,u32 flags)207247d43ba7SNishanth Menon struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
207347d43ba7SNishanth Menon 					   unsigned long *freq,
2074ab5f299fSMyungJoo Ham 					   u32 flags)
2075a3c98b8bSMyungJoo Ham {
207647d43ba7SNishanth Menon 	struct dev_pm_opp *opp;
2077a3c98b8bSMyungJoo Ham 
2078ab5f299fSMyungJoo Ham 	if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
2079ab5f299fSMyungJoo Ham 		/* The freq is an upper bound. opp should be lower */
20805d4879cdSNishanth Menon 		opp = dev_pm_opp_find_freq_floor(dev, freq);
2081ab5f299fSMyungJoo Ham 
2082ab5f299fSMyungJoo Ham 		/* If not available, use the closest opp */
20830779726cSNishanth Menon 		if (opp == ERR_PTR(-ERANGE))
20845d4879cdSNishanth Menon 			opp = dev_pm_opp_find_freq_ceil(dev, freq);
2085ab5f299fSMyungJoo Ham 	} else {
2086ab5f299fSMyungJoo Ham 		/* The freq is an lower bound. opp should be higher */
20875d4879cdSNishanth Menon 		opp = dev_pm_opp_find_freq_ceil(dev, freq);
2088ab5f299fSMyungJoo Ham 
2089ab5f299fSMyungJoo Ham 		/* If not available, use the closest opp */
20900779726cSNishanth Menon 		if (opp == ERR_PTR(-ERANGE))
20915d4879cdSNishanth Menon 			opp = dev_pm_opp_find_freq_floor(dev, freq);
2092ab5f299fSMyungJoo Ham 	}
2093ab5f299fSMyungJoo Ham 
2094a3c98b8bSMyungJoo Ham 	return opp;
2095a3c98b8bSMyungJoo Ham }
2096bd7e9277SÃrjan Eide EXPORT_SYMBOL(devfreq_recommended_opp);
2097a3c98b8bSMyungJoo Ham 
2098a3c98b8bSMyungJoo Ham /**
2099a3c98b8bSMyungJoo Ham  * devfreq_register_opp_notifier() - Helper function to get devfreq notified
2100a3c98b8bSMyungJoo Ham  *				     for any changes in the OPP availability
2101a3c98b8bSMyungJoo Ham  *				     changes
2102c5b4a1c1SNishanth Menon  * @dev:	The devfreq user device. (parent of devfreq)
2103c5b4a1c1SNishanth Menon  * @devfreq:	The devfreq object.
2104a3c98b8bSMyungJoo Ham  */
devfreq_register_opp_notifier(struct device * dev,struct devfreq * devfreq)2105a3c98b8bSMyungJoo Ham int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
2106a3c98b8bSMyungJoo Ham {
2107dc2c9ad5SViresh Kumar 	return dev_pm_opp_register_notifier(dev, &devfreq->nb);
2108a3c98b8bSMyungJoo Ham }
2109bd7e9277SÃrjan Eide EXPORT_SYMBOL(devfreq_register_opp_notifier);
2110a3c98b8bSMyungJoo Ham 
2111a3c98b8bSMyungJoo Ham /**
2112a3c98b8bSMyungJoo Ham  * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
2113a3c98b8bSMyungJoo Ham  *				       notified for any changes in the OPP
2114a3c98b8bSMyungJoo Ham  *				       availability changes anymore.
2115c5b4a1c1SNishanth Menon  * @dev:	The devfreq user device. (parent of devfreq)
2116c5b4a1c1SNishanth Menon  * @devfreq:	The devfreq object.
2117a3c98b8bSMyungJoo Ham  *
2118a3c98b8bSMyungJoo Ham  * At exit() callback of devfreq_dev_profile, this must be included if
2119a3c98b8bSMyungJoo Ham  * devfreq_recommended_opp is used.
2120a3c98b8bSMyungJoo Ham  */
devfreq_unregister_opp_notifier(struct device * dev,struct devfreq * devfreq)2121a3c98b8bSMyungJoo Ham int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
2122a3c98b8bSMyungJoo Ham {
2123dc2c9ad5SViresh Kumar 	return dev_pm_opp_unregister_notifier(dev, &devfreq->nb);
2124a3c98b8bSMyungJoo Ham }
2125bd7e9277SÃrjan Eide EXPORT_SYMBOL(devfreq_unregister_opp_notifier);
2126a3c98b8bSMyungJoo Ham 
devm_devfreq_opp_release(struct device * dev,void * res)2127d5b040d0SChanwoo Choi static void devm_devfreq_opp_release(struct device *dev, void *res)
2128d5b040d0SChanwoo Choi {
2129d5b040d0SChanwoo Choi 	devfreq_unregister_opp_notifier(dev, *(struct devfreq **)res);
2130d5b040d0SChanwoo Choi }
2131d5b040d0SChanwoo Choi 
2132d5b040d0SChanwoo Choi /**
21336d690f77SMyungJoo Ham  * devm_devfreq_register_opp_notifier() - Resource-managed
21346d690f77SMyungJoo Ham  *					  devfreq_register_opp_notifier()
2135d5b040d0SChanwoo Choi  * @dev:	The devfreq user device. (parent of devfreq)
2136d5b040d0SChanwoo Choi  * @devfreq:	The devfreq object.
2137d5b040d0SChanwoo Choi  */
devm_devfreq_register_opp_notifier(struct device * dev,struct devfreq * devfreq)2138d5b040d0SChanwoo Choi int devm_devfreq_register_opp_notifier(struct device *dev,
2139d5b040d0SChanwoo Choi 				       struct devfreq *devfreq)
2140d5b040d0SChanwoo Choi {
2141d5b040d0SChanwoo Choi 	struct devfreq **ptr;
2142d5b040d0SChanwoo Choi 	int ret;
2143d5b040d0SChanwoo Choi 
2144d5b040d0SChanwoo Choi 	ptr = devres_alloc(devm_devfreq_opp_release, sizeof(*ptr), GFP_KERNEL);
2145d5b040d0SChanwoo Choi 	if (!ptr)
2146d5b040d0SChanwoo Choi 		return -ENOMEM;
2147d5b040d0SChanwoo Choi 
2148d5b040d0SChanwoo Choi 	ret = devfreq_register_opp_notifier(dev, devfreq);
2149d5b040d0SChanwoo Choi 	if (ret) {
2150d5b040d0SChanwoo Choi 		devres_free(ptr);
2151d5b040d0SChanwoo Choi 		return ret;
2152d5b040d0SChanwoo Choi 	}
2153d5b040d0SChanwoo Choi 
2154d5b040d0SChanwoo Choi 	*ptr = devfreq;
2155d5b040d0SChanwoo Choi 	devres_add(dev, ptr);
2156d5b040d0SChanwoo Choi 
2157d5b040d0SChanwoo Choi 	return 0;
2158d5b040d0SChanwoo Choi }
2159d5b040d0SChanwoo Choi EXPORT_SYMBOL(devm_devfreq_register_opp_notifier);
2160d5b040d0SChanwoo Choi 
2161d5b040d0SChanwoo Choi /**
21626d690f77SMyungJoo Ham  * devm_devfreq_unregister_opp_notifier() - Resource-managed
21636d690f77SMyungJoo Ham  *					    devfreq_unregister_opp_notifier()
2164d5b040d0SChanwoo Choi  * @dev:	The devfreq user device. (parent of devfreq)
2165d5b040d0SChanwoo Choi  * @devfreq:	The devfreq object.
2166d5b040d0SChanwoo Choi  */
devm_devfreq_unregister_opp_notifier(struct device * dev,struct devfreq * devfreq)2167d5b040d0SChanwoo Choi void devm_devfreq_unregister_opp_notifier(struct device *dev,
2168d5b040d0SChanwoo Choi 					 struct devfreq *devfreq)
2169d5b040d0SChanwoo Choi {
2170d5b040d0SChanwoo Choi 	WARN_ON(devres_release(dev, devm_devfreq_opp_release,
2171d5b040d0SChanwoo Choi 			       devm_devfreq_dev_match, devfreq));
2172d5b040d0SChanwoo Choi }
2173d5b040d0SChanwoo Choi EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier);
2174d5b040d0SChanwoo Choi 
21750fe3a664SChanwoo Choi /**
21760fe3a664SChanwoo Choi  * devfreq_register_notifier() - Register a driver with devfreq
21770fe3a664SChanwoo Choi  * @devfreq:	The devfreq object.
21780fe3a664SChanwoo Choi  * @nb:		The notifier block to register.
21790fe3a664SChanwoo Choi  * @list:	DEVFREQ_TRANSITION_NOTIFIER.
21800fe3a664SChanwoo Choi  */
devfreq_register_notifier(struct devfreq * devfreq,struct notifier_block * nb,unsigned int list)21810fe3a664SChanwoo Choi int devfreq_register_notifier(struct devfreq *devfreq,
21820fe3a664SChanwoo Choi 			      struct notifier_block *nb,
21830fe3a664SChanwoo Choi 			      unsigned int list)
21840fe3a664SChanwoo Choi {
21850fe3a664SChanwoo Choi 	int ret = 0;
21860fe3a664SChanwoo Choi 
21870fe3a664SChanwoo Choi 	if (!devfreq)
21880fe3a664SChanwoo Choi 		return -EINVAL;
21890fe3a664SChanwoo Choi 
21900fe3a664SChanwoo Choi 	switch (list) {
21910fe3a664SChanwoo Choi 	case DEVFREQ_TRANSITION_NOTIFIER:
21920fe3a664SChanwoo Choi 		ret = srcu_notifier_chain_register(
21930fe3a664SChanwoo Choi 				&devfreq->transition_notifier_list, nb);
21940fe3a664SChanwoo Choi 		break;
21950fe3a664SChanwoo Choi 	default:
21960fe3a664SChanwoo Choi 		ret = -EINVAL;
21970fe3a664SChanwoo Choi 	}
21980fe3a664SChanwoo Choi 
21990fe3a664SChanwoo Choi 	return ret;
22000fe3a664SChanwoo Choi }
22010fe3a664SChanwoo Choi EXPORT_SYMBOL(devfreq_register_notifier);
22020fe3a664SChanwoo Choi 
22030fe3a664SChanwoo Choi /*
22040fe3a664SChanwoo Choi  * devfreq_unregister_notifier() - Unregister a driver with devfreq
22050fe3a664SChanwoo Choi  * @devfreq:	The devfreq object.
22060fe3a664SChanwoo Choi  * @nb:		The notifier block to be unregistered.
22070fe3a664SChanwoo Choi  * @list:	DEVFREQ_TRANSITION_NOTIFIER.
22080fe3a664SChanwoo Choi  */
devfreq_unregister_notifier(struct devfreq * devfreq,struct notifier_block * nb,unsigned int list)22090fe3a664SChanwoo Choi int devfreq_unregister_notifier(struct devfreq *devfreq,
22100fe3a664SChanwoo Choi 				struct notifier_block *nb,
22110fe3a664SChanwoo Choi 				unsigned int list)
22120fe3a664SChanwoo Choi {
22130fe3a664SChanwoo Choi 	int ret = 0;
22140fe3a664SChanwoo Choi 
22150fe3a664SChanwoo Choi 	if (!devfreq)
22160fe3a664SChanwoo Choi 		return -EINVAL;
22170fe3a664SChanwoo Choi 
22180fe3a664SChanwoo Choi 	switch (list) {
22190fe3a664SChanwoo Choi 	case DEVFREQ_TRANSITION_NOTIFIER:
22200fe3a664SChanwoo Choi 		ret = srcu_notifier_chain_unregister(
22210fe3a664SChanwoo Choi 				&devfreq->transition_notifier_list, nb);
22220fe3a664SChanwoo Choi 		break;
22230fe3a664SChanwoo Choi 	default:
22240fe3a664SChanwoo Choi 		ret = -EINVAL;
22250fe3a664SChanwoo Choi 	}
22260fe3a664SChanwoo Choi 
22270fe3a664SChanwoo Choi 	return ret;
22280fe3a664SChanwoo Choi }
22290fe3a664SChanwoo Choi EXPORT_SYMBOL(devfreq_unregister_notifier);
22300fe3a664SChanwoo Choi 
22310fe3a664SChanwoo Choi struct devfreq_notifier_devres {
22320fe3a664SChanwoo Choi 	struct devfreq *devfreq;
22330fe3a664SChanwoo Choi 	struct notifier_block *nb;
22340fe3a664SChanwoo Choi 	unsigned int list;
22350fe3a664SChanwoo Choi };
22360fe3a664SChanwoo Choi 
devm_devfreq_notifier_release(struct device * dev,void * res)22370fe3a664SChanwoo Choi static void devm_devfreq_notifier_release(struct device *dev, void *res)
22380fe3a664SChanwoo Choi {
22390fe3a664SChanwoo Choi 	struct devfreq_notifier_devres *this = res;
22400fe3a664SChanwoo Choi 
22410fe3a664SChanwoo Choi 	devfreq_unregister_notifier(this->devfreq, this->nb, this->list);
22420fe3a664SChanwoo Choi }
22430fe3a664SChanwoo Choi 
22440fe3a664SChanwoo Choi /**
22450fe3a664SChanwoo Choi  * devm_devfreq_register_notifier()
224654cb5740SRandy Dunlap  *	- Resource-managed devfreq_register_notifier()
22470fe3a664SChanwoo Choi  * @dev:	The devfreq user device. (parent of devfreq)
22480fe3a664SChanwoo Choi  * @devfreq:	The devfreq object.
22490fe3a664SChanwoo Choi  * @nb:		The notifier block to be unregistered.
22500fe3a664SChanwoo Choi  * @list:	DEVFREQ_TRANSITION_NOTIFIER.
22510fe3a664SChanwoo Choi  */
devm_devfreq_register_notifier(struct device * dev,struct devfreq * devfreq,struct notifier_block * nb,unsigned int list)22520fe3a664SChanwoo Choi int devm_devfreq_register_notifier(struct device *dev,
22530fe3a664SChanwoo Choi 				struct devfreq *devfreq,
22540fe3a664SChanwoo Choi 				struct notifier_block *nb,
22550fe3a664SChanwoo Choi 				unsigned int list)
22560fe3a664SChanwoo Choi {
22570fe3a664SChanwoo Choi 	struct devfreq_notifier_devres *ptr;
22580fe3a664SChanwoo Choi 	int ret;
22590fe3a664SChanwoo Choi 
22600fe3a664SChanwoo Choi 	ptr = devres_alloc(devm_devfreq_notifier_release, sizeof(*ptr),
22610fe3a664SChanwoo Choi 				GFP_KERNEL);
22620fe3a664SChanwoo Choi 	if (!ptr)
22630fe3a664SChanwoo Choi 		return -ENOMEM;
22640fe3a664SChanwoo Choi 
22650fe3a664SChanwoo Choi 	ret = devfreq_register_notifier(devfreq, nb, list);
22660fe3a664SChanwoo Choi 	if (ret) {
22670fe3a664SChanwoo Choi 		devres_free(ptr);
22680fe3a664SChanwoo Choi 		return ret;
22690fe3a664SChanwoo Choi 	}
22700fe3a664SChanwoo Choi 
22710fe3a664SChanwoo Choi 	ptr->devfreq = devfreq;
22720fe3a664SChanwoo Choi 	ptr->nb = nb;
22730fe3a664SChanwoo Choi 	ptr->list = list;
22740fe3a664SChanwoo Choi 	devres_add(dev, ptr);
22750fe3a664SChanwoo Choi 
22760fe3a664SChanwoo Choi 	return 0;
22770fe3a664SChanwoo Choi }
22780fe3a664SChanwoo Choi EXPORT_SYMBOL(devm_devfreq_register_notifier);
22790fe3a664SChanwoo Choi 
22800fe3a664SChanwoo Choi /**
22810fe3a664SChanwoo Choi  * devm_devfreq_unregister_notifier()
228254cb5740SRandy Dunlap  *	- Resource-managed devfreq_unregister_notifier()
22830fe3a664SChanwoo Choi  * @dev:	The devfreq user device. (parent of devfreq)
22840fe3a664SChanwoo Choi  * @devfreq:	The devfreq object.
22850fe3a664SChanwoo Choi  * @nb:		The notifier block to be unregistered.
22860fe3a664SChanwoo Choi  * @list:	DEVFREQ_TRANSITION_NOTIFIER.
22870fe3a664SChanwoo Choi  */
devm_devfreq_unregister_notifier(struct device * dev,struct devfreq * devfreq,struct notifier_block * nb,unsigned int list)22880fe3a664SChanwoo Choi void devm_devfreq_unregister_notifier(struct device *dev,
22890fe3a664SChanwoo Choi 				      struct devfreq *devfreq,
22900fe3a664SChanwoo Choi 				      struct notifier_block *nb,
22910fe3a664SChanwoo Choi 				      unsigned int list)
22920fe3a664SChanwoo Choi {
22930fe3a664SChanwoo Choi 	WARN_ON(devres_release(dev, devm_devfreq_notifier_release,
22940fe3a664SChanwoo Choi 			       devm_devfreq_dev_match, devfreq));
22950fe3a664SChanwoo Choi }
22960fe3a664SChanwoo Choi EXPORT_SYMBOL(devm_devfreq_unregister_notifier);
2297