Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
Loading...
v3.15
 
  1/*
  2 * OMAP thermal driver interface
  3 *
  4 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
  5 * Contact:
  6 *   Eduardo Valentin <eduardo.valentin@ti.com>
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * version 2 as published by the Free Software Foundation.
 11 *
 12 * This program is distributed in the hope that it will be useful, but
 13 * WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15 * General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU General Public License
 18 * along with this program; if not, write to the Free Software
 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 20 * 02110-1301 USA
 21 *
 22 */
 23
 24#include <linux/device.h>
 25#include <linux/err.h>
 26#include <linux/mutex.h>
 27#include <linux/gfp.h>
 28#include <linux/kernel.h>
 29#include <linux/workqueue.h>
 30#include <linux/thermal.h>
 31#include <linux/cpufreq.h>
 32#include <linux/cpumask.h>
 33#include <linux/cpu_cooling.h>
 34#include <linux/of.h>
 35
 36#include "ti-thermal.h"
 37#include "ti-bandgap.h"
 
 
 
 38
 39/* common data structures */
 40struct ti_thermal_data {
 
 41	struct thermal_zone_device *ti_thermal;
 42	struct thermal_zone_device *pcb_tz;
 43	struct thermal_cooling_device *cool_dev;
 44	struct ti_bandgap *bgp;
 45	enum thermal_device_mode mode;
 46	struct work_struct thermal_wq;
 47	int sensor_id;
 48	bool our_zone;
 49};
 50
 51static void ti_thermal_work(struct work_struct *work)
 52{
 53	struct ti_thermal_data *data = container_of(work,
 54					struct ti_thermal_data, thermal_wq);
 55
 56	thermal_zone_device_update(data->ti_thermal);
 57
 58	dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n",
 59		data->ti_thermal->type);
 60}
 61
 62/**
 63 * ti_thermal_hotspot_temperature - returns sensor extrapolated temperature
 64 * @t:	omap sensor temperature
 65 * @s:	omap sensor slope value
 66 * @c:	omap sensor const value
 67 */
 68static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
 69{
 70	int delta = t * s / 1000 + c;
 71
 72	if (delta < 0)
 73		delta = 0;
 74
 75	return t + delta;
 76}
 77
 78/* thermal zone ops */
 79/* Get temperature callback function for thermal zone*/
 80static inline int __ti_thermal_get_temp(void *devdata, long *temp)
 81{
 82	struct thermal_zone_device *pcb_tz = NULL;
 83	struct ti_thermal_data *data = devdata;
 84	struct ti_bandgap *bgp;
 85	const struct ti_temp_sensor *s;
 86	int ret, tmp, slope, constant;
 87	unsigned long pcb_temp;
 88
 89	if (!data)
 90		return 0;
 91
 92	bgp = data->bgp;
 93	s = &bgp->conf->sensors[data->sensor_id];
 94
 95	ret = ti_bandgap_read_temperature(bgp, data->sensor_id, &tmp);
 96	if (ret)
 97		return ret;
 98
 99	/* Default constants */
100	slope = s->slope;
101	constant = s->constant;
102
103	pcb_tz = data->pcb_tz;
104	/* In case pcb zone is available, use the extrapolation rule with it */
105	if (!IS_ERR(pcb_tz)) {
106		ret = thermal_zone_get_temp(pcb_tz, &pcb_temp);
107		if (!ret) {
108			tmp -= pcb_temp; /* got a valid PCB temp */
109			slope = s->slope_pcb;
110			constant = s->constant_pcb;
111		} else {
112			dev_err(bgp->dev,
113				"Failed to read PCB state. Using defaults\n");
114			ret = 0;
115		}
116	}
117	*temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
118
119	return ret;
120}
121
122static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
123				      unsigned long *temp)
124{
125	struct ti_thermal_data *data = thermal->devdata;
126
127	return __ti_thermal_get_temp(data, temp);
128}
129
130/* Bind callback functions for thermal zone */
131static int ti_thermal_bind(struct thermal_zone_device *thermal,
132			   struct thermal_cooling_device *cdev)
133{
134	struct ti_thermal_data *data = thermal->devdata;
135	int id;
136
137	if (!data || IS_ERR(data))
138		return -ENODEV;
139
140	/* check if this is the cooling device we registered */
141	if (data->cool_dev != cdev)
142		return 0;
143
144	id = data->sensor_id;
145
146	/* Simple thing, two trips, one passive another critical */
147	return thermal_zone_bind_cooling_device(thermal, 0, cdev,
148	/* bind with min and max states defined by cpu_cooling */
149						THERMAL_NO_LIMIT,
150						THERMAL_NO_LIMIT);
151}
152
153/* Unbind callback functions for thermal zone */
154static int ti_thermal_unbind(struct thermal_zone_device *thermal,
155			     struct thermal_cooling_device *cdev)
156{
157	struct ti_thermal_data *data = thermal->devdata;
158
159	if (!data || IS_ERR(data))
160		return -ENODEV;
161
162	/* check if this is the cooling device we registered */
163	if (data->cool_dev != cdev)
164		return 0;
165
166	/* Simple thing, two trips, one passive another critical */
167	return thermal_zone_unbind_cooling_device(thermal, 0, cdev);
168}
169
170/* Get mode callback functions for thermal zone */
171static int ti_thermal_get_mode(struct thermal_zone_device *thermal,
172			       enum thermal_device_mode *mode)
173{
174	struct ti_thermal_data *data = thermal->devdata;
175
176	if (data)
177		*mode = data->mode;
178
179	return 0;
180}
181
182/* Set mode callback functions for thermal zone */
183static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
184			       enum thermal_device_mode mode)
185{
186	struct ti_thermal_data *data = thermal->devdata;
187	struct ti_bandgap *bgp;
188
189	bgp = data->bgp;
190
191	if (!data->ti_thermal) {
192		dev_notice(&thermal->device, "thermal zone not registered\n");
193		return 0;
194	}
195
196	mutex_lock(&data->ti_thermal->lock);
197
198	if (mode == THERMAL_DEVICE_ENABLED)
199		data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
200	else
201		data->ti_thermal->polling_delay = 0;
202
203	mutex_unlock(&data->ti_thermal->lock);
204
205	data->mode = mode;
206	ti_bandgap_write_update_interval(bgp, data->sensor_id,
207					data->ti_thermal->polling_delay);
208	thermal_zone_device_update(data->ti_thermal);
209	dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
210		data->ti_thermal->polling_delay);
211
212	return 0;
213}
214
215/* Get trip type callback functions for thermal zone */
216static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
217				    int trip, enum thermal_trip_type *type)
218{
219	if (!ti_thermal_is_valid_trip(trip))
220		return -EINVAL;
221
222	if (trip + 1 == OMAP_TRIP_NUMBER)
223		*type = THERMAL_TRIP_CRITICAL;
224	else
225		*type = THERMAL_TRIP_PASSIVE;
226
227	return 0;
228}
229
230/* Get trip temperature callback functions for thermal zone */
231static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
232				    int trip, unsigned long *temp)
233{
234	if (!ti_thermal_is_valid_trip(trip))
235		return -EINVAL;
236
237	*temp = ti_thermal_get_trip_value(trip);
238
239	return 0;
240}
241
242static int __ti_thermal_get_trend(void *p, long *trend)
243{
244	struct ti_thermal_data *data = p;
245	struct ti_bandgap *bgp;
246	int id, tr, ret = 0;
247
248	bgp = data->bgp;
249	id = data->sensor_id;
250
251	ret = ti_bandgap_get_trend(bgp, id, &tr);
252	if (ret)
253		return ret;
254
255	*trend = tr;
256
257	return 0;
258}
259
260/* Get the temperature trend callback functions for thermal zone */
261static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
262				int trip, enum thermal_trend *trend)
263{
264	int ret;
265	long tr;
266
267	ret = __ti_thermal_get_trend(thermal->devdata, &tr);
268	if (ret)
269		return ret;
270
271	if (tr > 0)
272		*trend = THERMAL_TREND_RAISING;
273	else if (tr < 0)
274		*trend = THERMAL_TREND_DROPPING;
275	else
276		*trend = THERMAL_TREND_STABLE;
277
278	return 0;
279}
280
281/* Get critical temperature callback functions for thermal zone */
282static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
283				    unsigned long *temp)
284{
285	/* shutdown zone */
286	return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
287}
288
289static struct thermal_zone_device_ops ti_thermal_ops = {
290	.get_temp = ti_thermal_get_temp,
291	.get_trend = ti_thermal_get_trend,
292	.bind = ti_thermal_bind,
293	.unbind = ti_thermal_unbind,
294	.get_mode = ti_thermal_get_mode,
295	.set_mode = ti_thermal_set_mode,
296	.get_trip_type = ti_thermal_get_trip_type,
297	.get_trip_temp = ti_thermal_get_trip_temp,
298	.get_crit_temp = ti_thermal_get_crit_temp,
299};
300
301static struct ti_thermal_data
302*ti_thermal_build_data(struct ti_bandgap *bgp, int id)
303{
304	struct ti_thermal_data *data;
305
306	data = devm_kzalloc(bgp->dev, sizeof(*data), GFP_KERNEL);
307	if (!data) {
308		dev_err(bgp->dev, "kzalloc fail\n");
309		return NULL;
310	}
311	data->sensor_id = id;
312	data->bgp = bgp;
313	data->mode = THERMAL_DEVICE_ENABLED;
314	/* pcb_tz will be either valid or PTR_ERR() */
315	data->pcb_tz = thermal_zone_get_zone_by_name("pcb");
316	INIT_WORK(&data->thermal_wq, ti_thermal_work);
317
318	return data;
319}
320
321int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
322			     char *domain)
323{
324	struct ti_thermal_data *data;
325
326	data = ti_bandgap_get_sensor_data(bgp, id);
327
328	if (!data || IS_ERR(data))
329		data = ti_thermal_build_data(bgp, id);
330
331	if (!data)
332		return -EINVAL;
333
334	/* in case this is specified by DT */
335	data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id,
336					data, __ti_thermal_get_temp,
337					__ti_thermal_get_trend);
338	if (IS_ERR(data->ti_thermal)) {
339		/* Create thermal zone */
340		data->ti_thermal = thermal_zone_device_register(domain,
341				OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
342				NULL, FAST_TEMP_MONITORING_RATE,
343				FAST_TEMP_MONITORING_RATE);
344		if (IS_ERR(data->ti_thermal)) {
345			dev_err(bgp->dev, "thermal zone device is NULL\n");
346			return PTR_ERR(data->ti_thermal);
347		}
348		data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
349		data->our_zone = true;
350	}
 
351	ti_bandgap_set_sensor_data(bgp, id, data);
352	ti_bandgap_write_update_interval(bgp, data->sensor_id,
353					data->ti_thermal->polling_delay);
 
 
354
355	return 0;
356}
357
358int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
359{
360	struct ti_thermal_data *data;
361
362	data = ti_bandgap_get_sensor_data(bgp, id);
363
364	if (data && data->ti_thermal) {
365		if (data->our_zone)
366			thermal_zone_device_unregister(data->ti_thermal);
367		else
368			thermal_zone_of_sensor_unregister(bgp->dev,
369							  data->ti_thermal);
370	}
371
372	return 0;
373}
374
375int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
376{
377	struct ti_thermal_data *data;
378
379	data = ti_bandgap_get_sensor_data(bgp, id);
380
381	schedule_work(&data->thermal_wq);
382
383	return 0;
384}
385
386int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
387{
388	struct ti_thermal_data *data;
389	struct device_node *np = bgp->dev->of_node;
390
391	/*
392	 * We are assuming here that if one deploys the zone
393	 * using DT, then it must be aware that the cooling device
394	 * loading has to happen via cpufreq driver.
395	 */
396	if (of_find_property(np, "#thermal-sensor-cells", NULL))
397		return 0;
398
399	data = ti_bandgap_get_sensor_data(bgp, id);
400	if (!data || IS_ERR(data))
401		data = ti_thermal_build_data(bgp, id);
402
403	if (!data)
404		return -EINVAL;
405
406	if (!cpufreq_get_current_driver()) {
407		dev_dbg(bgp->dev, "no cpufreq driver yet\n");
 
408		return -EPROBE_DEFER;
409	}
410
411	/* Register cooling device */
412	data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
413	if (IS_ERR(data->cool_dev)) {
414		dev_err(bgp->dev,
415			"Failed to register cpufreq cooling device\n");
416		return PTR_ERR(data->cool_dev);
 
 
 
417	}
418	ti_bandgap_set_sensor_data(bgp, id, data);
419
420	return 0;
421}
422
423int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
424{
425	struct ti_thermal_data *data;
426
427	data = ti_bandgap_get_sensor_data(bgp, id);
428
429	if (data && data->cool_dev)
430		cpufreq_cooling_unregister(data->cool_dev);
 
 
 
431
432	return 0;
433}
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * OMAP thermal driver interface
  4 *
  5 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
  6 * Contact:
  7 *   Eduardo Valentin <eduardo.valentin@ti.com>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  8 */
  9
 10#include <linux/device.h>
 11#include <linux/err.h>
 12#include <linux/mutex.h>
 13#include <linux/gfp.h>
 14#include <linux/kernel.h>
 15#include <linux/workqueue.h>
 16#include <linux/thermal.h>
 17#include <linux/cpufreq.h>
 18#include <linux/cpumask.h>
 19#include <linux/cpu_cooling.h>
 20#include <linux/of.h>
 21
 22#include "ti-thermal.h"
 23#include "ti-bandgap.h"
 24#include "../thermal_hwmon.h"
 25
 26#define TI_BANDGAP_UPDATE_INTERVAL_MS 250
 27
 28/* common data structures */
 29struct ti_thermal_data {
 30	struct cpufreq_policy *policy;
 31	struct thermal_zone_device *ti_thermal;
 32	struct thermal_zone_device *pcb_tz;
 33	struct thermal_cooling_device *cool_dev;
 34	struct ti_bandgap *bgp;
 35	enum thermal_device_mode mode;
 36	struct work_struct thermal_wq;
 37	int sensor_id;
 38	bool our_zone;
 39};
 40
 41static void ti_thermal_work(struct work_struct *work)
 42{
 43	struct ti_thermal_data *data = container_of(work,
 44					struct ti_thermal_data, thermal_wq);
 45
 46	thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
 47
 48	dev_dbg(data->bgp->dev, "updated thermal zone %s\n",
 49		thermal_zone_device_type(data->ti_thermal));
 50}
 51
 52/**
 53 * ti_thermal_hotspot_temperature - returns sensor extrapolated temperature
 54 * @t:	omap sensor temperature
 55 * @s:	omap sensor slope value
 56 * @c:	omap sensor const value
 57 */
 58static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
 59{
 60	int delta = t * s / 1000 + c;
 61
 62	if (delta < 0)
 63		delta = 0;
 64
 65	return t + delta;
 66}
 67
 68/* thermal zone ops */
 69/* Get temperature callback function for thermal zone */
 70static inline int __ti_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 71{
 72	struct thermal_zone_device *pcb_tz = NULL;
 73	struct ti_thermal_data *data = thermal_zone_device_priv(tz);
 74	struct ti_bandgap *bgp;
 75	const struct ti_temp_sensor *s;
 76	int ret, tmp, slope, constant;
 77	int pcb_temp;
 78
 79	if (!data)
 80		return 0;
 81
 82	bgp = data->bgp;
 83	s = &bgp->conf->sensors[data->sensor_id];
 84
 85	ret = ti_bandgap_read_temperature(bgp, data->sensor_id, &tmp);
 86	if (ret)
 87		return ret;
 88
 89	/* Default constants */
 90	slope = thermal_zone_get_slope(tz);
 91	constant = thermal_zone_get_offset(tz);
 92
 93	pcb_tz = data->pcb_tz;
 94	/* In case pcb zone is available, use the extrapolation rule with it */
 95	if (!IS_ERR(pcb_tz)) {
 96		ret = thermal_zone_get_temp(pcb_tz, &pcb_temp);
 97		if (!ret) {
 98			tmp -= pcb_temp; /* got a valid PCB temp */
 99			slope = s->slope_pcb;
100			constant = s->constant_pcb;
101		} else {
102			dev_err(bgp->dev,
103				"Failed to read PCB state. Using defaults\n");
104			ret = 0;
105		}
106	}
107	*temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
108
109	return ret;
110}
111
112static int __ti_thermal_get_trend(struct thermal_zone_device *tz,
113				  const struct thermal_trip *trip,
114				  enum thermal_trend *trend)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115{
116	struct ti_thermal_data *data = thermal_zone_device_priv(tz);
117	struct ti_bandgap *bgp;
118	int id, tr, ret = 0;
119
120	bgp = data->bgp;
121	id = data->sensor_id;
122
123	ret = ti_bandgap_get_trend(bgp, id, &tr);
124	if (ret)
125		return ret;
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127	if (tr > 0)
128		*trend = THERMAL_TREND_RAISING;
129	else if (tr < 0)
130		*trend = THERMAL_TREND_DROPPING;
131	else
132		*trend = THERMAL_TREND_STABLE;
133
134	return 0;
135}
136
137static const struct thermal_zone_device_ops ti_of_thermal_ops = {
138	.get_temp = __ti_thermal_get_temp,
139	.get_trend = __ti_thermal_get_trend,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140};
141
142static struct ti_thermal_data
143*ti_thermal_build_data(struct ti_bandgap *bgp, int id)
144{
145	struct ti_thermal_data *data;
146
147	data = devm_kzalloc(bgp->dev, sizeof(*data), GFP_KERNEL);
148	if (!data) {
149		dev_err(bgp->dev, "kzalloc fail\n");
150		return NULL;
151	}
152	data->sensor_id = id;
153	data->bgp = bgp;
154	data->mode = THERMAL_DEVICE_ENABLED;
155	/* pcb_tz will be either valid or PTR_ERR() */
156	data->pcb_tz = thermal_zone_get_zone_by_name("pcb");
157	INIT_WORK(&data->thermal_wq, ti_thermal_work);
158
159	return data;
160}
161
162int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
163			     char *domain)
164{
165	struct ti_thermal_data *data;
166
167	data = ti_bandgap_get_sensor_data(bgp, id);
168
169	if (IS_ERR_OR_NULL(data))
170		data = ti_thermal_build_data(bgp, id);
171
172	if (!data)
173		return -EINVAL;
174
175	/* in case this is specified by DT */
176	data->ti_thermal = devm_thermal_of_zone_register(bgp->dev, id,
177					data, &ti_of_thermal_ops);
 
178	if (IS_ERR(data->ti_thermal)) {
179		dev_err(bgp->dev, "thermal zone device is NULL\n");
180		return PTR_ERR(data->ti_thermal);
 
 
 
 
 
 
 
 
 
181	}
182
183	ti_bandgap_set_sensor_data(bgp, id, data);
184	ti_bandgap_write_update_interval(bgp, data->sensor_id,
185					 TI_BANDGAP_UPDATE_INTERVAL_MS);
186
187	devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal);
188
189	return 0;
190}
191
192int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
193{
194	struct ti_thermal_data *data;
195
196	data = ti_bandgap_get_sensor_data(bgp, id);
197
198	if (!IS_ERR_OR_NULL(data) && data->ti_thermal) {
199		if (data->our_zone)
200			thermal_zone_device_unregister(data->ti_thermal);
 
 
 
201	}
202
203	return 0;
204}
205
206int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
207{
208	struct ti_thermal_data *data;
209
210	data = ti_bandgap_get_sensor_data(bgp, id);
211
212	schedule_work(&data->thermal_wq);
213
214	return 0;
215}
216
217int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
218{
219	struct ti_thermal_data *data;
220	struct device_node *np = bgp->dev->of_node;
221
222	/*
223	 * We are assuming here that if one deploys the zone
224	 * using DT, then it must be aware that the cooling device
225	 * loading has to happen via cpufreq driver.
226	 */
227	if (of_property_present(np, "#thermal-sensor-cells"))
228		return 0;
229
230	data = ti_bandgap_get_sensor_data(bgp, id);
231	if (!data || IS_ERR(data))
232		data = ti_thermal_build_data(bgp, id);
233
234	if (!data)
235		return -EINVAL;
236
237	data->policy = cpufreq_cpu_get(0);
238	if (!data->policy) {
239		pr_debug("%s: CPUFreq policy not found\n", __func__);
240		return -EPROBE_DEFER;
241	}
242
243	/* Register cooling device */
244	data->cool_dev = cpufreq_cooling_register(data->policy);
245	if (IS_ERR(data->cool_dev)) {
246		int ret = PTR_ERR(data->cool_dev);
247		dev_err(bgp->dev, "Failed to register cpu cooling device %d\n",
248			ret);
249		cpufreq_cpu_put(data->policy);
250
251		return ret;
252	}
253	ti_bandgap_set_sensor_data(bgp, id, data);
254
255	return 0;
256}
257
258int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
259{
260	struct ti_thermal_data *data;
261
262	data = ti_bandgap_get_sensor_data(bgp, id);
263
264	if (!IS_ERR_OR_NULL(data)) {
265		cpufreq_cooling_unregister(data->cool_dev);
266		if (data->policy)
267			cpufreq_cpu_put(data->policy);
268	}
269
270	return 0;
271}