2 * Copyright (C) 2013 Freescale Semiconductor, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
10 #include <linux/module.h>
11 #include <linux/thermal.h>
12 #include <linux/err.h>
13 #include <linux/slab.h>
15 struct devfreq_cooling_device {
17 struct thermal_cooling_device *cool_dev;
18 unsigned int devfreq_state;
21 static DEFINE_IDR(devfreq_idr);
22 static DEFINE_MUTEX(devfreq_cooling_lock);
26 static BLOCKING_NOTIFIER_HEAD(devfreq_cooling_chain_head);
28 int register_devfreq_cooling_notifier(struct notifier_block *nb)
30 return blocking_notifier_chain_register(
31 &devfreq_cooling_chain_head, nb);
33 EXPORT_SYMBOL_GPL(register_devfreq_cooling_notifier);
35 int unregister_devfreq_cooling_notifier(struct notifier_block *nb)
37 return blocking_notifier_chain_unregister(
38 &devfreq_cooling_chain_head, nb);
40 EXPORT_SYMBOL_GPL(unregister_devfreq_cooling_notifier);
42 static int devfreq_cooling_notifier_call_chain(unsigned long val)
44 return (blocking_notifier_call_chain(
45 &devfreq_cooling_chain_head, val, NULL)
46 == NOTIFY_BAD) ? -EINVAL : 0;
49 static int devfreq_set_cur_state(struct thermal_cooling_device *cdev,
52 struct devfreq_cooling_device *devfreq_device = cdev->devdata;
55 ret = devfreq_cooling_notifier_call_chain(state);
58 devfreq_device->devfreq_state = state;
63 static int devfreq_get_max_state(struct thermal_cooling_device *cdev,
71 static int devfreq_get_cur_state(struct thermal_cooling_device *cdev,
74 struct devfreq_cooling_device *devfreq_device = cdev->devdata;
76 *state = devfreq_device->devfreq_state;
81 static struct thermal_cooling_device_ops const devfreq_cooling_ops = {
82 .get_max_state = devfreq_get_max_state,
83 .get_cur_state = devfreq_get_cur_state,
84 .set_cur_state = devfreq_set_cur_state,
87 static int get_idr(struct idr *idr, int *id)
91 mutex_lock(&devfreq_cooling_lock);
92 ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
93 mutex_unlock(&devfreq_cooling_lock);
94 if (unlikely(ret < 0))
101 static void release_idr(struct idr *idr, int id)
103 mutex_lock(&devfreq_cooling_lock);
105 mutex_unlock(&devfreq_cooling_lock);
108 struct thermal_cooling_device *devfreq_cooling_register(void)
110 struct thermal_cooling_device *cool_dev;
111 struct devfreq_cooling_device *devfreq_dev = NULL;
112 char dev_name[THERMAL_NAME_LENGTH];
115 devfreq_dev = kzalloc(sizeof(struct devfreq_cooling_device),
118 return ERR_PTR(-ENOMEM);
120 ret = get_idr(&devfreq_idr, &devfreq_dev->id);
123 return ERR_PTR(-EINVAL);
126 snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d",
129 cool_dev = thermal_cooling_device_register(dev_name, devfreq_dev,
130 &devfreq_cooling_ops);
132 release_idr(&devfreq_idr, devfreq_dev->id);
134 return ERR_PTR(-EINVAL);
136 devfreq_dev->cool_dev = cool_dev;
137 devfreq_dev->devfreq_state = 0;
141 EXPORT_SYMBOL_GPL(devfreq_cooling_register);
143 void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
145 struct devfreq_cooling_device *devfreq_dev = cdev->devdata;
147 thermal_cooling_device_unregister(devfreq_dev->cool_dev);
148 release_idr(&devfreq_idr, devfreq_dev->id);
151 EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);