xref: /linux/drivers/net/wireless/ath/ath12k/thermal.c (revision 91a4855d6c03e770e42f17c798a36a3c46e63de2)
1*151322bcSMaharaja Kennadyrajan // SPDX-License-Identifier: BSD-3-Clause-Clear
2*151322bcSMaharaja Kennadyrajan /*
3*151322bcSMaharaja Kennadyrajan  * Copyright (c) 2020 The Linux Foundation. All rights reserved.
4*151322bcSMaharaja Kennadyrajan  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5*151322bcSMaharaja Kennadyrajan  */
6*151322bcSMaharaja Kennadyrajan 
7*151322bcSMaharaja Kennadyrajan #include <linux/device.h>
8*151322bcSMaharaja Kennadyrajan #include <linux/hwmon.h>
9*151322bcSMaharaja Kennadyrajan #include <linux/hwmon-sysfs.h>
10*151322bcSMaharaja Kennadyrajan #include <linux/sysfs.h>
11*151322bcSMaharaja Kennadyrajan #include <linux/thermal.h>
12*151322bcSMaharaja Kennadyrajan #include "core.h"
13*151322bcSMaharaja Kennadyrajan #include "debug.h"
14*151322bcSMaharaja Kennadyrajan 
15*151322bcSMaharaja Kennadyrajan static ssize_t ath12k_thermal_temp_show(struct device *dev,
16*151322bcSMaharaja Kennadyrajan 					struct device_attribute *attr,
17*151322bcSMaharaja Kennadyrajan 					char *buf)
18*151322bcSMaharaja Kennadyrajan {
19*151322bcSMaharaja Kennadyrajan 	struct ath12k *ar = dev_get_drvdata(dev);
20*151322bcSMaharaja Kennadyrajan 	unsigned long time_left;
21*151322bcSMaharaja Kennadyrajan 	int ret, temperature;
22*151322bcSMaharaja Kennadyrajan 
23*151322bcSMaharaja Kennadyrajan 	guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
24*151322bcSMaharaja Kennadyrajan 
25*151322bcSMaharaja Kennadyrajan 	if (ar->ah->state != ATH12K_HW_STATE_ON)
26*151322bcSMaharaja Kennadyrajan 		return -ENETDOWN;
27*151322bcSMaharaja Kennadyrajan 
28*151322bcSMaharaja Kennadyrajan 	reinit_completion(&ar->thermal.wmi_sync);
29*151322bcSMaharaja Kennadyrajan 	ret = ath12k_wmi_send_pdev_temperature_cmd(ar);
30*151322bcSMaharaja Kennadyrajan 	if (ret) {
31*151322bcSMaharaja Kennadyrajan 		ath12k_warn(ar->ab, "failed to read temperature %d\n", ret);
32*151322bcSMaharaja Kennadyrajan 		return ret;
33*151322bcSMaharaja Kennadyrajan 	}
34*151322bcSMaharaja Kennadyrajan 
35*151322bcSMaharaja Kennadyrajan 	if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
36*151322bcSMaharaja Kennadyrajan 		return -ESHUTDOWN;
37*151322bcSMaharaja Kennadyrajan 
38*151322bcSMaharaja Kennadyrajan 	time_left = wait_for_completion_timeout(&ar->thermal.wmi_sync,
39*151322bcSMaharaja Kennadyrajan 						ATH12K_THERMAL_SYNC_TIMEOUT_HZ);
40*151322bcSMaharaja Kennadyrajan 	if (!time_left) {
41*151322bcSMaharaja Kennadyrajan 		ath12k_warn(ar->ab, "failed to synchronize thermal read\n");
42*151322bcSMaharaja Kennadyrajan 		return -ETIMEDOUT;
43*151322bcSMaharaja Kennadyrajan 	}
44*151322bcSMaharaja Kennadyrajan 
45*151322bcSMaharaja Kennadyrajan 	spin_lock_bh(&ar->data_lock);
46*151322bcSMaharaja Kennadyrajan 	temperature = ar->thermal.temperature;
47*151322bcSMaharaja Kennadyrajan 	spin_unlock_bh(&ar->data_lock);
48*151322bcSMaharaja Kennadyrajan 
49*151322bcSMaharaja Kennadyrajan 	/* display in millidegree celsius */
50*151322bcSMaharaja Kennadyrajan 	return sysfs_emit(buf, "%d\n", temperature * 1000);
51*151322bcSMaharaja Kennadyrajan }
52*151322bcSMaharaja Kennadyrajan 
53*151322bcSMaharaja Kennadyrajan void ath12k_thermal_event_temperature(struct ath12k *ar, int temperature)
54*151322bcSMaharaja Kennadyrajan {
55*151322bcSMaharaja Kennadyrajan 	spin_lock_bh(&ar->data_lock);
56*151322bcSMaharaja Kennadyrajan 	ar->thermal.temperature = temperature;
57*151322bcSMaharaja Kennadyrajan 	spin_unlock_bh(&ar->data_lock);
58*151322bcSMaharaja Kennadyrajan 	complete_all(&ar->thermal.wmi_sync);
59*151322bcSMaharaja Kennadyrajan }
60*151322bcSMaharaja Kennadyrajan 
61*151322bcSMaharaja Kennadyrajan static SENSOR_DEVICE_ATTR_RO(temp1_input, ath12k_thermal_temp, 0);
62*151322bcSMaharaja Kennadyrajan 
63*151322bcSMaharaja Kennadyrajan static struct attribute *ath12k_hwmon_attrs[] = {
64*151322bcSMaharaja Kennadyrajan 	&sensor_dev_attr_temp1_input.dev_attr.attr,
65*151322bcSMaharaja Kennadyrajan 	NULL,
66*151322bcSMaharaja Kennadyrajan };
67*151322bcSMaharaja Kennadyrajan ATTRIBUTE_GROUPS(ath12k_hwmon);
68*151322bcSMaharaja Kennadyrajan 
69*151322bcSMaharaja Kennadyrajan int ath12k_thermal_register(struct ath12k_base *ab)
70*151322bcSMaharaja Kennadyrajan {
71*151322bcSMaharaja Kennadyrajan 	struct ath12k *ar;
72*151322bcSMaharaja Kennadyrajan 	int i, j, ret;
73*151322bcSMaharaja Kennadyrajan 
74*151322bcSMaharaja Kennadyrajan 	if (!IS_REACHABLE(CONFIG_HWMON))
75*151322bcSMaharaja Kennadyrajan 		return 0;
76*151322bcSMaharaja Kennadyrajan 
77*151322bcSMaharaja Kennadyrajan 	for (i = 0; i < ab->num_radios; i++) {
78*151322bcSMaharaja Kennadyrajan 		ar = ab->pdevs[i].ar;
79*151322bcSMaharaja Kennadyrajan 		if (!ar)
80*151322bcSMaharaja Kennadyrajan 			continue;
81*151322bcSMaharaja Kennadyrajan 
82*151322bcSMaharaja Kennadyrajan 		ar->thermal.hwmon_dev =
83*151322bcSMaharaja Kennadyrajan 			hwmon_device_register_with_groups(&ar->ah->hw->wiphy->dev,
84*151322bcSMaharaja Kennadyrajan 							  "ath12k_hwmon", ar,
85*151322bcSMaharaja Kennadyrajan 							  ath12k_hwmon_groups);
86*151322bcSMaharaja Kennadyrajan 		if (IS_ERR(ar->thermal.hwmon_dev)) {
87*151322bcSMaharaja Kennadyrajan 			ret = PTR_ERR(ar->thermal.hwmon_dev);
88*151322bcSMaharaja Kennadyrajan 			ar->thermal.hwmon_dev = NULL;
89*151322bcSMaharaja Kennadyrajan 			ath12k_err(ar->ab, "failed to register hwmon device: %d\n",
90*151322bcSMaharaja Kennadyrajan 				   ret);
91*151322bcSMaharaja Kennadyrajan 			for (j = i - 1; j >= 0; j--) {
92*151322bcSMaharaja Kennadyrajan 				ar = ab->pdevs[j].ar;
93*151322bcSMaharaja Kennadyrajan 				if (!ar)
94*151322bcSMaharaja Kennadyrajan 					continue;
95*151322bcSMaharaja Kennadyrajan 
96*151322bcSMaharaja Kennadyrajan 				hwmon_device_unregister(ar->thermal.hwmon_dev);
97*151322bcSMaharaja Kennadyrajan 				ar->thermal.hwmon_dev = NULL;
98*151322bcSMaharaja Kennadyrajan 			}
99*151322bcSMaharaja Kennadyrajan 			return ret;
100*151322bcSMaharaja Kennadyrajan 		}
101*151322bcSMaharaja Kennadyrajan 	}
102*151322bcSMaharaja Kennadyrajan 
103*151322bcSMaharaja Kennadyrajan 	return 0;
104*151322bcSMaharaja Kennadyrajan }
105*151322bcSMaharaja Kennadyrajan 
106*151322bcSMaharaja Kennadyrajan void ath12k_thermal_unregister(struct ath12k_base *ab)
107*151322bcSMaharaja Kennadyrajan {
108*151322bcSMaharaja Kennadyrajan 	struct ath12k *ar;
109*151322bcSMaharaja Kennadyrajan 	int i;
110*151322bcSMaharaja Kennadyrajan 
111*151322bcSMaharaja Kennadyrajan 	if (!IS_REACHABLE(CONFIG_HWMON))
112*151322bcSMaharaja Kennadyrajan 		return;
113*151322bcSMaharaja Kennadyrajan 
114*151322bcSMaharaja Kennadyrajan 	for (i = 0; i < ab->num_radios; i++) {
115*151322bcSMaharaja Kennadyrajan 		ar = ab->pdevs[i].ar;
116*151322bcSMaharaja Kennadyrajan 		if (!ar)
117*151322bcSMaharaja Kennadyrajan 			continue;
118*151322bcSMaharaja Kennadyrajan 
119*151322bcSMaharaja Kennadyrajan 		if (ar->thermal.hwmon_dev) {
120*151322bcSMaharaja Kennadyrajan 			hwmon_device_unregister(ar->thermal.hwmon_dev);
121*151322bcSMaharaja Kennadyrajan 			ar->thermal.hwmon_dev = NULL;
122*151322bcSMaharaja Kennadyrajan 		}
123*151322bcSMaharaja Kennadyrajan 	}
124*151322bcSMaharaja Kennadyrajan }
125