diff options
author | Zhang Rui <rui.zhang@intel.com> | 2014-03-23 11:37:32 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2014-10-10 01:57:10 -0400 |
commit | 0ab15365ff38c8433f4d0cc2d11a1184e2c991cf (patch) | |
tree | 6617ca1a0190d4b3552ecd61630e1dc3e8137190 | |
parent | c5738dddc01be49cf6712f886371177e8df36291 (diff) |
Thermal: int3400 thermal: register to thermal framework
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
-rw-r--r-- | drivers/thermal/Kconfig | 1 | ||||
-rw-r--r-- | drivers/thermal/int340x_thermal/int3400_thermal.c | 103 |
2 files changed, 104 insertions, 0 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 6f5a87a8f19f..b34c5f54fc83 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
@@ -237,6 +237,7 @@ config INTEL_SOC_DTS_THERMAL | |||
237 | config INT340X_THERMAL | 237 | config INT340X_THERMAL |
238 | tristate "ACPI INT340X thermal drivers" | 238 | tristate "ACPI INT340X thermal drivers" |
239 | depends on X86 && ACPI | 239 | depends on X86 && ACPI |
240 | select THERMAL_GOV_USER_SPACE | ||
240 | help | 241 | help |
241 | Newer laptops and tablets that use ACPI may have thermal sensors and | 242 | Newer laptops and tablets that use ACPI may have thermal sensors and |
242 | other devices with thermal control capabilities outside the core | 243 | other devices with thermal control capabilities outside the core |
diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c index 65c63ba8b314..9104b4f9381b 100644 --- a/drivers/thermal/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/int340x_thermal/int3400_thermal.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/acpi.h> | 15 | #include <linux/acpi.h> |
16 | #include <linux/thermal.h> | ||
16 | 17 | ||
17 | struct art { | 18 | struct art { |
18 | acpi_handle source; | 19 | acpi_handle source; |
@@ -60,6 +61,8 @@ static u8 *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = { | |||
60 | 61 | ||
61 | struct int3400_thermal_priv { | 62 | struct int3400_thermal_priv { |
62 | struct acpi_device *adev; | 63 | struct acpi_device *adev; |
64 | struct thermal_zone_device *thermal; | ||
65 | int mode; | ||
63 | int art_count; | 66 | int art_count; |
64 | struct art *arts; | 67 | struct art *arts; |
65 | int trt_count; | 68 | int trt_count; |
@@ -114,6 +117,36 @@ end: | |||
114 | return result; | 117 | return result; |
115 | } | 118 | } |
116 | 119 | ||
120 | static int int3400_thermal_run_osc(acpi_handle handle, | ||
121 | enum int3400_thermal_uuid uuid, bool enable) | ||
122 | { | ||
123 | u32 ret, buf[2]; | ||
124 | acpi_status status; | ||
125 | int result = 0; | ||
126 | struct acpi_osc_context context = { | ||
127 | .uuid_str = int3400_thermal_uuids[uuid], | ||
128 | .rev = 1, | ||
129 | .cap.length = 8, | ||
130 | }; | ||
131 | |||
132 | buf[OSC_QUERY_DWORD] = 0; | ||
133 | buf[OSC_SUPPORT_DWORD] = enable; | ||
134 | |||
135 | context.cap.pointer = buf; | ||
136 | |||
137 | status = acpi_run_osc(handle, &context); | ||
138 | if (ACPI_SUCCESS(status)) { | ||
139 | ret = *((u32 *)(context.ret.pointer + 4)); | ||
140 | if (ret != enable) | ||
141 | result = -EPERM; | ||
142 | } else | ||
143 | result = -EPERM; | ||
144 | |||
145 | kfree(context.ret.pointer); | ||
146 | return result; | ||
147 | } | ||
148 | |||
149 | |||
117 | static int parse_art(struct int3400_thermal_priv *priv) | 150 | static int parse_art(struct int3400_thermal_priv *priv) |
118 | { | 151 | { |
119 | acpi_handle handle = priv->adev->handle; | 152 | acpi_handle handle = priv->adev->handle; |
@@ -243,6 +276,61 @@ end: | |||
243 | return result; | 276 | return result; |
244 | } | 277 | } |
245 | 278 | ||
279 | static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, | ||
280 | unsigned long *temp) | ||
281 | { | ||
282 | *temp = 20 * 1000; /* faked temp sensor with 20C */ | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int int3400_thermal_get_mode(struct thermal_zone_device *thermal, | ||
287 | enum thermal_device_mode *mode) | ||
288 | { | ||
289 | struct int3400_thermal_priv *priv = thermal->devdata; | ||
290 | |||
291 | if (!priv) | ||
292 | return -EINVAL; | ||
293 | |||
294 | *mode = priv->mode; | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, | ||
300 | enum thermal_device_mode mode) | ||
301 | { | ||
302 | struct int3400_thermal_priv *priv = thermal->devdata; | ||
303 | bool enable; | ||
304 | int result = 0; | ||
305 | |||
306 | if (!priv) | ||
307 | return -EINVAL; | ||
308 | |||
309 | if (mode == THERMAL_DEVICE_ENABLED) | ||
310 | enable = true; | ||
311 | else if (mode == THERMAL_DEVICE_DISABLED) | ||
312 | enable = false; | ||
313 | else | ||
314 | return -EINVAL; | ||
315 | |||
316 | if (enable != priv->mode) { | ||
317 | priv->mode = enable; | ||
318 | /* currently, only PASSIVE COOLING is supported */ | ||
319 | result = int3400_thermal_run_osc(priv->adev->handle, | ||
320 | INT3400_THERMAL_PASSIVE_1, enable); | ||
321 | } | ||
322 | return result; | ||
323 | } | ||
324 | |||
325 | static struct thermal_zone_device_ops int3400_thermal_ops = { | ||
326 | .get_temp = int3400_thermal_get_temp, | ||
327 | }; | ||
328 | |||
329 | static struct thermal_zone_params int3400_thermal_params = { | ||
330 | .governor_name = "user_space", | ||
331 | .no_hwmon = true, | ||
332 | }; | ||
333 | |||
246 | static int int3400_thermal_probe(struct platform_device *pdev) | 334 | static int int3400_thermal_probe(struct platform_device *pdev) |
247 | { | 335 | { |
248 | struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); | 336 | struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); |
@@ -272,7 +360,21 @@ static int int3400_thermal_probe(struct platform_device *pdev) | |||
272 | 360 | ||
273 | platform_set_drvdata(pdev, priv); | 361 | platform_set_drvdata(pdev, priv); |
274 | 362 | ||
363 | if (priv->uuid_bitmap & 1 << INT3400_THERMAL_PASSIVE_1) { | ||
364 | int3400_thermal_ops.get_mode = int3400_thermal_get_mode; | ||
365 | int3400_thermal_ops.set_mode = int3400_thermal_set_mode; | ||
366 | } | ||
367 | priv->thermal = thermal_zone_device_register("INT3400 Thermal", 0, 0, | ||
368 | priv, &int3400_thermal_ops, | ||
369 | &int3400_thermal_params, 0, 0); | ||
370 | if (IS_ERR(priv->thermal)) { | ||
371 | result = PTR_ERR(priv->thermal); | ||
372 | goto free_trt; | ||
373 | } | ||
374 | |||
275 | return 0; | 375 | return 0; |
376 | free_trt: | ||
377 | kfree(priv->trts); | ||
276 | free_art: | 378 | free_art: |
277 | kfree(priv->arts); | 379 | kfree(priv->arts); |
278 | free_priv: | 380 | free_priv: |
@@ -284,6 +386,7 @@ static int int3400_thermal_remove(struct platform_device *pdev) | |||
284 | { | 386 | { |
285 | struct int3400_thermal_priv *priv = platform_get_drvdata(pdev); | 387 | struct int3400_thermal_priv *priv = platform_get_drvdata(pdev); |
286 | 388 | ||
389 | thermal_zone_device_unregister(priv->thermal); | ||
287 | kfree(priv->trts); | 390 | kfree(priv->trts); |
288 | kfree(priv->arts); | 391 | kfree(priv->arts); |
289 | kfree(priv); | 392 | kfree(priv); |