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