linux/drivers/thermal/intel/int340x_thermal/int3402_thermal.c
<<
>>
Prefs
   1/*
   2 * INT3402 thermal driver for memory temperature reporting
   3 *
   4 * Copyright (C) 2014, Intel Corporation
   5 * Authors: Aaron Lu <aaron.lu@intel.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/platform_device.h>
  15#include <linux/acpi.h>
  16#include <linux/thermal.h>
  17#include "int340x_thermal_zone.h"
  18
  19#define INT3402_PERF_CHANGED_EVENT      0x80
  20#define INT3402_THERMAL_EVENT           0x90
  21
  22struct int3402_thermal_data {
  23        acpi_handle *handle;
  24        struct int34x_thermal_zone *int340x_zone;
  25};
  26
  27static void int3402_notify(acpi_handle handle, u32 event, void *data)
  28{
  29        struct int3402_thermal_data *priv = data;
  30
  31        if (!priv)
  32                return;
  33
  34        switch (event) {
  35        case INT3402_PERF_CHANGED_EVENT:
  36                break;
  37        case INT3402_THERMAL_EVENT:
  38                int340x_thermal_zone_device_update(priv->int340x_zone,
  39                                                   THERMAL_TRIP_VIOLATED);
  40                break;
  41        default:
  42                break;
  43        }
  44}
  45
  46static int int3402_thermal_probe(struct platform_device *pdev)
  47{
  48        struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
  49        struct int3402_thermal_data *d;
  50        int ret;
  51
  52        if (!acpi_has_method(adev->handle, "_TMP"))
  53                return -ENODEV;
  54
  55        d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
  56        if (!d)
  57                return -ENOMEM;
  58
  59        d->int340x_zone = int340x_thermal_zone_add(adev, NULL);
  60        if (IS_ERR(d->int340x_zone))
  61                return PTR_ERR(d->int340x_zone);
  62
  63        ret = acpi_install_notify_handler(adev->handle,
  64                                          ACPI_DEVICE_NOTIFY,
  65                                          int3402_notify,
  66                                          d);
  67        if (ret) {
  68                int340x_thermal_zone_remove(d->int340x_zone);
  69                return ret;
  70        }
  71
  72        d->handle = adev->handle;
  73        platform_set_drvdata(pdev, d);
  74
  75        return 0;
  76}
  77
  78static int int3402_thermal_remove(struct platform_device *pdev)
  79{
  80        struct int3402_thermal_data *d = platform_get_drvdata(pdev);
  81
  82        acpi_remove_notify_handler(d->handle,
  83                                   ACPI_DEVICE_NOTIFY, int3402_notify);
  84        int340x_thermal_zone_remove(d->int340x_zone);
  85
  86        return 0;
  87}
  88
  89static const struct acpi_device_id int3402_thermal_match[] = {
  90        {"INT3402", 0},
  91        {}
  92};
  93
  94MODULE_DEVICE_TABLE(acpi, int3402_thermal_match);
  95
  96static struct platform_driver int3402_thermal_driver = {
  97        .probe = int3402_thermal_probe,
  98        .remove = int3402_thermal_remove,
  99        .driver = {
 100                   .name = "int3402 thermal",
 101                   .acpi_match_table = int3402_thermal_match,
 102                   },
 103};
 104
 105module_platform_driver(int3402_thermal_driver);
 106
 107MODULE_DESCRIPTION("INT3402 Thermal driver");
 108MODULE_LICENSE("GPL");
 109