xref: /openbmc/linux/drivers/thermal/intel/int340x_thermal/int3402_thermal.c (revision b694e3c604e999343258c49e574abd7be012e726)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23e8c4d31SAmit Kucheria /*
33e8c4d31SAmit Kucheria  * INT3402 thermal driver for memory temperature reporting
43e8c4d31SAmit Kucheria  *
53e8c4d31SAmit Kucheria  * Copyright (C) 2014, Intel Corporation
63e8c4d31SAmit Kucheria  * Authors: Aaron Lu <aaron.lu@intel.com>
73e8c4d31SAmit Kucheria  */
83e8c4d31SAmit Kucheria 
93e8c4d31SAmit Kucheria #include <linux/module.h>
103e8c4d31SAmit Kucheria #include <linux/platform_device.h>
113e8c4d31SAmit Kucheria #include <linux/acpi.h>
123e8c4d31SAmit Kucheria #include <linux/thermal.h>
133e8c4d31SAmit Kucheria #include "int340x_thermal_zone.h"
143e8c4d31SAmit Kucheria 
153e8c4d31SAmit Kucheria #define INT3402_PERF_CHANGED_EVENT	0x80
163e8c4d31SAmit Kucheria #define INT3402_THERMAL_EVENT		0x90
173e8c4d31SAmit Kucheria 
183e8c4d31SAmit Kucheria struct int3402_thermal_data {
193e8c4d31SAmit Kucheria 	acpi_handle *handle;
203e8c4d31SAmit Kucheria 	struct int34x_thermal_zone *int340x_zone;
213e8c4d31SAmit Kucheria };
223e8c4d31SAmit Kucheria 
int3402_notify(acpi_handle handle,u32 event,void * data)233e8c4d31SAmit Kucheria static void int3402_notify(acpi_handle handle, u32 event, void *data)
243e8c4d31SAmit Kucheria {
253e8c4d31SAmit Kucheria 	struct int3402_thermal_data *priv = data;
263e8c4d31SAmit Kucheria 
273e8c4d31SAmit Kucheria 	if (!priv)
283e8c4d31SAmit Kucheria 		return;
293e8c4d31SAmit Kucheria 
303e8c4d31SAmit Kucheria 	switch (event) {
313e8c4d31SAmit Kucheria 	case INT3402_PERF_CHANGED_EVENT:
323e8c4d31SAmit Kucheria 		break;
333e8c4d31SAmit Kucheria 	case INT3402_THERMAL_EVENT:
343e8c4d31SAmit Kucheria 		int340x_thermal_zone_device_update(priv->int340x_zone,
353e8c4d31SAmit Kucheria 						   THERMAL_TRIP_VIOLATED);
363e8c4d31SAmit Kucheria 		break;
373e8c4d31SAmit Kucheria 	default:
383e8c4d31SAmit Kucheria 		break;
393e8c4d31SAmit Kucheria 	}
403e8c4d31SAmit Kucheria }
413e8c4d31SAmit Kucheria 
int3402_thermal_probe(struct platform_device * pdev)423e8c4d31SAmit Kucheria static int int3402_thermal_probe(struct platform_device *pdev)
433e8c4d31SAmit Kucheria {
443e8c4d31SAmit Kucheria 	struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
453e8c4d31SAmit Kucheria 	struct int3402_thermal_data *d;
463e8c4d31SAmit Kucheria 	int ret;
473e8c4d31SAmit Kucheria 
48*ac2eb737SChenyuan Yang 	if (!adev)
49*ac2eb737SChenyuan Yang 		return -ENODEV;
50*ac2eb737SChenyuan Yang 
513e8c4d31SAmit Kucheria 	if (!acpi_has_method(adev->handle, "_TMP"))
523e8c4d31SAmit Kucheria 		return -ENODEV;
533e8c4d31SAmit Kucheria 
543e8c4d31SAmit Kucheria 	d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
553e8c4d31SAmit Kucheria 	if (!d)
563e8c4d31SAmit Kucheria 		return -ENOMEM;
573e8c4d31SAmit Kucheria 
583e8c4d31SAmit Kucheria 	d->int340x_zone = int340x_thermal_zone_add(adev, NULL);
593e8c4d31SAmit Kucheria 	if (IS_ERR(d->int340x_zone))
603e8c4d31SAmit Kucheria 		return PTR_ERR(d->int340x_zone);
613e8c4d31SAmit Kucheria 
623e8c4d31SAmit Kucheria 	ret = acpi_install_notify_handler(adev->handle,
633e8c4d31SAmit Kucheria 					  ACPI_DEVICE_NOTIFY,
643e8c4d31SAmit Kucheria 					  int3402_notify,
653e8c4d31SAmit Kucheria 					  d);
663e8c4d31SAmit Kucheria 	if (ret) {
673e8c4d31SAmit Kucheria 		int340x_thermal_zone_remove(d->int340x_zone);
683e8c4d31SAmit Kucheria 		return ret;
693e8c4d31SAmit Kucheria 	}
703e8c4d31SAmit Kucheria 
713e8c4d31SAmit Kucheria 	d->handle = adev->handle;
723e8c4d31SAmit Kucheria 	platform_set_drvdata(pdev, d);
733e8c4d31SAmit Kucheria 
743e8c4d31SAmit Kucheria 	return 0;
753e8c4d31SAmit Kucheria }
763e8c4d31SAmit Kucheria 
773e8c4d31SAmit Kucheria static int int3402_thermal_remove(struct platform_device *pdev)
783e8c4d31SAmit Kucheria {
793e8c4d31SAmit Kucheria 	struct int3402_thermal_data *d = platform_get_drvdata(pdev);
803e8c4d31SAmit Kucheria 
813e8c4d31SAmit Kucheria 	acpi_remove_notify_handler(d->handle,
823e8c4d31SAmit Kucheria 				   ACPI_DEVICE_NOTIFY, int3402_notify);
833e8c4d31SAmit Kucheria 	int340x_thermal_zone_remove(d->int340x_zone);
843e8c4d31SAmit Kucheria 
853e8c4d31SAmit Kucheria 	return 0;
863e8c4d31SAmit Kucheria }
873e8c4d31SAmit Kucheria 
883e8c4d31SAmit Kucheria static const struct acpi_device_id int3402_thermal_match[] = {
893e8c4d31SAmit Kucheria 	{"INT3402", 0},
903e8c4d31SAmit Kucheria 	{}
913e8c4d31SAmit Kucheria };
923e8c4d31SAmit Kucheria 
933e8c4d31SAmit Kucheria MODULE_DEVICE_TABLE(acpi, int3402_thermal_match);
943e8c4d31SAmit Kucheria 
953e8c4d31SAmit Kucheria static struct platform_driver int3402_thermal_driver = {
963e8c4d31SAmit Kucheria 	.probe = int3402_thermal_probe,
973e8c4d31SAmit Kucheria 	.remove = int3402_thermal_remove,
983e8c4d31SAmit Kucheria 	.driver = {
993e8c4d31SAmit Kucheria 		   .name = "int3402 thermal",
1003e8c4d31SAmit Kucheria 		   .acpi_match_table = int3402_thermal_match,
1013e8c4d31SAmit Kucheria 		   },
1023e8c4d31SAmit Kucheria };
1033e8c4d31SAmit Kucheria 
1043e8c4d31SAmit Kucheria module_platform_driver(int3402_thermal_driver);
1053e8c4d31SAmit Kucheria 
1063e8c4d31SAmit Kucheria MODULE_DESCRIPTION("INT3402 Thermal driver");
1073e8c4d31SAmit Kucheria MODULE_LICENSE("GPL");
108