aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhang Rui <rui.zhang@intel.com>2014-03-23 11:37:32 -0400
committerZhang Rui <rui.zhang@intel.com>2014-10-10 01:57:10 -0400
commit0ab15365ff38c8433f4d0cc2d11a1184e2c991cf (patch)
tree6617ca1a0190d4b3552ecd61630e1dc3e8137190
parentc5738dddc01be49cf6712f886371177e8df36291 (diff)
Thermal: int3400 thermal: register to thermal framework
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
-rw-r--r--drivers/thermal/Kconfig1
-rw-r--r--drivers/thermal/int340x_thermal/int3400_thermal.c103
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
237config INT340X_THERMAL 237config 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
17struct art { 18struct art {
18 acpi_handle source; 19 acpi_handle source;
@@ -60,6 +61,8 @@ static u8 *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = {
60 61
61struct int3400_thermal_priv { 62struct 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
120static 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
117static int parse_art(struct int3400_thermal_priv *priv) 150static 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
279static 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
286static 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
299static 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
325static struct thermal_zone_device_ops int3400_thermal_ops = {
326 .get_temp = int3400_thermal_get_temp,
327};
328
329static struct thermal_zone_params int3400_thermal_params = {
330 .governor_name = "user_space",
331 .no_hwmon = true,
332};
333
246static int int3400_thermal_probe(struct platform_device *pdev) 334static 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;
376free_trt:
377 kfree(priv->trts);
276free_art: 378free_art:
277 kfree(priv->arts); 379 kfree(priv->arts);
278free_priv: 380free_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);