diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2015-01-16 18:59:05 -0500 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2015-01-19 20:30:25 -0500 |
commit | 593df40475b719103e095aa1116653636662077e (patch) | |
tree | 92b44bfb545ede2b9bb48129daf083b846bce9db /drivers/thermal | |
parent | 820cdeba4086c74eb977088f1f9d31fd4c0aba9a (diff) |
Thermal/int340x/int3403: Use int340x thermal API
Using APIs from int340x thermal zone module to add and remove thermal
zones.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/int340x_thermal/int3403_thermal.c | 208 |
1 files changed, 10 insertions, 198 deletions
diff --git a/drivers/thermal/int340x_thermal/int3403_thermal.c b/drivers/thermal/int340x_thermal/int3403_thermal.c index 0faf500d8a77..50a7a08e3a15 100644 --- a/drivers/thermal/int340x_thermal/int3403_thermal.c +++ b/drivers/thermal/int340x_thermal/int3403_thermal.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/acpi.h> | 19 | #include <linux/acpi.h> |
20 | #include <linux/thermal.h> | 20 | #include <linux/thermal.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include "int340x_thermal_zone.h" | ||
22 | 23 | ||
23 | #define INT3403_TYPE_SENSOR 0x03 | 24 | #define INT3403_TYPE_SENSOR 0x03 |
24 | #define INT3403_TYPE_CHARGER 0x0B | 25 | #define INT3403_TYPE_CHARGER 0x0B |
@@ -26,18 +27,9 @@ | |||
26 | #define INT3403_PERF_CHANGED_EVENT 0x80 | 27 | #define INT3403_PERF_CHANGED_EVENT 0x80 |
27 | #define INT3403_THERMAL_EVENT 0x90 | 28 | #define INT3403_THERMAL_EVENT 0x90 |
28 | 29 | ||
29 | #define DECI_KELVIN_TO_MILLI_CELSIUS(t, off) (((t) - (off)) * 100) | 30 | /* Preserved structure for future expandbility */ |
30 | #define KELVIN_OFFSET 2732 | ||
31 | #define MILLI_CELSIUS_TO_DECI_KELVIN(t, off) (((t) / 100) + (off)) | ||
32 | |||
33 | struct int3403_sensor { | 31 | struct int3403_sensor { |
34 | struct thermal_zone_device *tzone; | 32 | struct int34x_thermal_zone *int340x_zone; |
35 | unsigned long *thresholds; | ||
36 | unsigned long crit_temp; | ||
37 | int crit_trip_id; | ||
38 | unsigned long psv_temp; | ||
39 | int psv_trip_id; | ||
40 | |||
41 | }; | 33 | }; |
42 | 34 | ||
43 | struct int3403_performance_state { | 35 | struct int3403_performance_state { |
@@ -63,126 +55,6 @@ struct int3403_priv { | |||
63 | void *priv; | 55 | void *priv; |
64 | }; | 56 | }; |
65 | 57 | ||
66 | static int sys_get_curr_temp(struct thermal_zone_device *tzone, | ||
67 | unsigned long *temp) | ||
68 | { | ||
69 | struct int3403_priv *priv = tzone->devdata; | ||
70 | struct acpi_device *device = priv->adev; | ||
71 | unsigned long long tmp; | ||
72 | acpi_status status; | ||
73 | |||
74 | status = acpi_evaluate_integer(device->handle, "_TMP", NULL, &tmp); | ||
75 | if (ACPI_FAILURE(status)) | ||
76 | return -EIO; | ||
77 | |||
78 | *temp = DECI_KELVIN_TO_MILLI_CELSIUS(tmp, KELVIN_OFFSET); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int sys_get_trip_hyst(struct thermal_zone_device *tzone, | ||
84 | int trip, unsigned long *temp) | ||
85 | { | ||
86 | struct int3403_priv *priv = tzone->devdata; | ||
87 | struct acpi_device *device = priv->adev; | ||
88 | unsigned long long hyst; | ||
89 | acpi_status status; | ||
90 | |||
91 | status = acpi_evaluate_integer(device->handle, "GTSH", NULL, &hyst); | ||
92 | if (ACPI_FAILURE(status)) | ||
93 | return -EIO; | ||
94 | |||
95 | /* | ||
96 | * Thermal hysteresis represents a temperature difference. | ||
97 | * Kelvin and Celsius have same degree size. So the | ||
98 | * conversion here between tenths of degree Kelvin unit | ||
99 | * and Milli-Celsius unit is just to multiply 100. | ||
100 | */ | ||
101 | *temp = hyst * 100; | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int sys_get_trip_temp(struct thermal_zone_device *tzone, | ||
107 | int trip, unsigned long *temp) | ||
108 | { | ||
109 | struct int3403_priv *priv = tzone->devdata; | ||
110 | struct int3403_sensor *obj = priv->priv; | ||
111 | |||
112 | if (priv->type != INT3403_TYPE_SENSOR || !obj) | ||
113 | return -EINVAL; | ||
114 | |||
115 | if (trip == obj->crit_trip_id) | ||
116 | *temp = obj->crit_temp; | ||
117 | else if (trip == obj->psv_trip_id) | ||
118 | *temp = obj->psv_temp; | ||
119 | else { | ||
120 | /* | ||
121 | * get_trip_temp is a mandatory callback but | ||
122 | * PATx method doesn't return any value, so return | ||
123 | * cached value, which was last set from user space | ||
124 | */ | ||
125 | *temp = obj->thresholds[trip]; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int sys_get_trip_type(struct thermal_zone_device *thermal, | ||
132 | int trip, enum thermal_trip_type *type) | ||
133 | { | ||
134 | struct int3403_priv *priv = thermal->devdata; | ||
135 | struct int3403_sensor *obj = priv->priv; | ||
136 | |||
137 | /* Mandatory callback, may not mean much here */ | ||
138 | if (trip == obj->crit_trip_id) | ||
139 | *type = THERMAL_TRIP_CRITICAL; | ||
140 | else | ||
141 | *type = THERMAL_TRIP_PASSIVE; | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | int sys_set_trip_temp(struct thermal_zone_device *tzone, int trip, | ||
147 | unsigned long temp) | ||
148 | { | ||
149 | struct int3403_priv *priv = tzone->devdata; | ||
150 | struct acpi_device *device = priv->adev; | ||
151 | struct int3403_sensor *obj = priv->priv; | ||
152 | acpi_status status; | ||
153 | char name[10]; | ||
154 | int ret = 0; | ||
155 | |||
156 | snprintf(name, sizeof(name), "PAT%d", trip); | ||
157 | if (acpi_has_method(device->handle, name)) { | ||
158 | status = acpi_execute_simple_method(device->handle, name, | ||
159 | MILLI_CELSIUS_TO_DECI_KELVIN(temp, | ||
160 | KELVIN_OFFSET)); | ||
161 | if (ACPI_FAILURE(status)) | ||
162 | ret = -EIO; | ||
163 | else | ||
164 | obj->thresholds[trip] = temp; | ||
165 | } else { | ||
166 | ret = -EIO; | ||
167 | dev_err(&device->dev, "sys_set_trip_temp: method not found\n"); | ||
168 | } | ||
169 | |||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | static struct thermal_zone_device_ops tzone_ops = { | ||
174 | .get_temp = sys_get_curr_temp, | ||
175 | .get_trip_temp = sys_get_trip_temp, | ||
176 | .get_trip_type = sys_get_trip_type, | ||
177 | .set_trip_temp = sys_set_trip_temp, | ||
178 | .get_trip_hyst = sys_get_trip_hyst, | ||
179 | }; | ||
180 | |||
181 | static struct thermal_zone_params int3403_thermal_params = { | ||
182 | .governor_name = "user_space", | ||
183 | .no_hwmon = true, | ||
184 | }; | ||
185 | |||
186 | static void int3403_notify(acpi_handle handle, | 58 | static void int3403_notify(acpi_handle handle, |
187 | u32 event, void *data) | 59 | u32 event, void *data) |
188 | { | 60 | { |
@@ -200,7 +72,7 @@ static void int3403_notify(acpi_handle handle, | |||
200 | case INT3403_PERF_CHANGED_EVENT: | 72 | case INT3403_PERF_CHANGED_EVENT: |
201 | break; | 73 | break; |
202 | case INT3403_THERMAL_EVENT: | 74 | case INT3403_THERMAL_EVENT: |
203 | thermal_zone_device_update(obj->tzone); | 75 | int340x_thermal_zone_device_update(obj->int340x_zone); |
204 | break; | 76 | break; |
205 | default: | 77 | default: |
206 | dev_err(&priv->pdev->dev, "Unsupported event [0x%x]\n", event); | 78 | dev_err(&priv->pdev->dev, "Unsupported event [0x%x]\n", event); |
@@ -208,41 +80,10 @@ static void int3403_notify(acpi_handle handle, | |||
208 | } | 80 | } |
209 | } | 81 | } |
210 | 82 | ||
211 | static int sys_get_trip_crt(struct acpi_device *device, unsigned long *temp) | ||
212 | { | ||
213 | unsigned long long crt; | ||
214 | acpi_status status; | ||
215 | |||
216 | status = acpi_evaluate_integer(device->handle, "_CRT", NULL, &crt); | ||
217 | if (ACPI_FAILURE(status)) | ||
218 | return -EIO; | ||
219 | |||
220 | *temp = DECI_KELVIN_TO_MILLI_CELSIUS(crt, KELVIN_OFFSET); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static int sys_get_trip_psv(struct acpi_device *device, unsigned long *temp) | ||
226 | { | ||
227 | unsigned long long psv; | ||
228 | acpi_status status; | ||
229 | |||
230 | status = acpi_evaluate_integer(device->handle, "_PSV", NULL, &psv); | ||
231 | if (ACPI_FAILURE(status)) | ||
232 | return -EIO; | ||
233 | |||
234 | *temp = DECI_KELVIN_TO_MILLI_CELSIUS(psv, KELVIN_OFFSET); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int int3403_sensor_add(struct int3403_priv *priv) | 83 | static int int3403_sensor_add(struct int3403_priv *priv) |
240 | { | 84 | { |
241 | int result = 0; | 85 | int result = 0; |
242 | acpi_status status; | ||
243 | struct int3403_sensor *obj; | 86 | struct int3403_sensor *obj; |
244 | unsigned long long trip_cnt; | ||
245 | int trip_mask = 0; | ||
246 | 87 | ||
247 | obj = devm_kzalloc(&priv->pdev->dev, sizeof(*obj), GFP_KERNEL); | 88 | obj = devm_kzalloc(&priv->pdev->dev, sizeof(*obj), GFP_KERNEL); |
248 | if (!obj) | 89 | if (!obj) |
@@ -250,39 +91,9 @@ static int int3403_sensor_add(struct int3403_priv *priv) | |||
250 | 91 | ||
251 | priv->priv = obj; | 92 | priv->priv = obj; |
252 | 93 | ||
253 | status = acpi_evaluate_integer(priv->adev->handle, "PATC", NULL, | 94 | obj->int340x_zone = int340x_thermal_zone_add(priv->adev, NULL); |
254 | &trip_cnt); | 95 | if (IS_ERR(obj->int340x_zone)) |
255 | if (ACPI_FAILURE(status)) | 96 | return PTR_ERR(obj->int340x_zone); |
256 | trip_cnt = 0; | ||
257 | |||
258 | if (trip_cnt) { | ||
259 | /* We have to cache, thresholds can't be readback */ | ||
260 | obj->thresholds = devm_kzalloc(&priv->pdev->dev, | ||
261 | sizeof(*obj->thresholds) * trip_cnt, | ||
262 | GFP_KERNEL); | ||
263 | if (!obj->thresholds) { | ||
264 | result = -ENOMEM; | ||
265 | goto err_free_obj; | ||
266 | } | ||
267 | trip_mask = BIT(trip_cnt) - 1; | ||
268 | } | ||
269 | |||
270 | obj->psv_trip_id = -1; | ||
271 | if (!sys_get_trip_psv(priv->adev, &obj->psv_temp)) | ||
272 | obj->psv_trip_id = trip_cnt++; | ||
273 | |||
274 | obj->crit_trip_id = -1; | ||
275 | if (!sys_get_trip_crt(priv->adev, &obj->crit_temp)) | ||
276 | obj->crit_trip_id = trip_cnt++; | ||
277 | |||
278 | obj->tzone = thermal_zone_device_register(acpi_device_bid(priv->adev), | ||
279 | trip_cnt, trip_mask, priv, &tzone_ops, | ||
280 | &int3403_thermal_params, 0, 0); | ||
281 | if (IS_ERR(obj->tzone)) { | ||
282 | result = PTR_ERR(obj->tzone); | ||
283 | obj->tzone = NULL; | ||
284 | goto err_free_obj; | ||
285 | } | ||
286 | 97 | ||
287 | result = acpi_install_notify_handler(priv->adev->handle, | 98 | result = acpi_install_notify_handler(priv->adev->handle, |
288 | ACPI_DEVICE_NOTIFY, int3403_notify, | 99 | ACPI_DEVICE_NOTIFY, int3403_notify, |
@@ -293,7 +104,7 @@ static int int3403_sensor_add(struct int3403_priv *priv) | |||
293 | return 0; | 104 | return 0; |
294 | 105 | ||
295 | err_free_obj: | 106 | err_free_obj: |
296 | thermal_zone_device_unregister(obj->tzone); | 107 | int340x_thermal_zone_remove(obj->int340x_zone); |
297 | return result; | 108 | return result; |
298 | } | 109 | } |
299 | 110 | ||
@@ -303,7 +114,8 @@ static int int3403_sensor_remove(struct int3403_priv *priv) | |||
303 | 114 | ||
304 | acpi_remove_notify_handler(priv->adev->handle, | 115 | acpi_remove_notify_handler(priv->adev->handle, |
305 | ACPI_DEVICE_NOTIFY, int3403_notify); | 116 | ACPI_DEVICE_NOTIFY, int3403_notify); |
306 | thermal_zone_device_unregister(obj->tzone); | 117 | int340x_thermal_zone_remove(obj->int340x_zone); |
118 | |||
307 | return 0; | 119 | return 0; |
308 | } | 120 | } |
309 | 121 | ||