1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2020 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
7 #include <linux/device.h>
8 #include <linux/sysfs.h>
9 #include <linux/thermal.h>
10 #include <linux/hwmon.h>
11 #include <linux/hwmon-sysfs.h>
16 ath11k_thermal_get_max_throttle_state(struct thermal_cooling_device
*cdev
,
19 *state
= ATH11K_THERMAL_THROTTLE_MAX
;
25 ath11k_thermal_get_cur_throttle_state(struct thermal_cooling_device
*cdev
,
28 struct ath11k
*ar
= cdev
->devdata
;
30 mutex_lock(&ar
->conf_mutex
);
31 *state
= ar
->thermal
.throttle_state
;
32 mutex_unlock(&ar
->conf_mutex
);
38 ath11k_thermal_set_cur_throttle_state(struct thermal_cooling_device
*cdev
,
39 unsigned long throttle_state
)
41 struct ath11k
*ar
= cdev
->devdata
;
44 if (throttle_state
> ATH11K_THERMAL_THROTTLE_MAX
) {
45 ath11k_warn(ar
->ab
, "throttle state %ld is exceeding the limit %d\n",
46 throttle_state
, ATH11K_THERMAL_THROTTLE_MAX
);
49 mutex_lock(&ar
->conf_mutex
);
50 ret
= ath11k_thermal_set_throttling(ar
, throttle_state
);
52 ar
->thermal
.throttle_state
= throttle_state
;
53 mutex_unlock(&ar
->conf_mutex
);
57 static const struct thermal_cooling_device_ops ath11k_thermal_ops
= {
58 .get_max_state
= ath11k_thermal_get_max_throttle_state
,
59 .get_cur_state
= ath11k_thermal_get_cur_throttle_state
,
60 .set_cur_state
= ath11k_thermal_set_cur_throttle_state
,
63 static ssize_t
ath11k_thermal_show_temp(struct device
*dev
,
64 struct device_attribute
*attr
,
67 struct ath11k
*ar
= dev_get_drvdata(dev
);
69 unsigned long time_left
;
71 mutex_lock(&ar
->conf_mutex
);
73 /* Can't get temperature when the card is off */
74 if (ar
->state
!= ATH11K_STATE_ON
) {
79 reinit_completion(&ar
->thermal
.wmi_sync
);
80 ret
= ath11k_wmi_send_pdev_temperature_cmd(ar
);
82 ath11k_warn(ar
->ab
, "failed to read temperature %d\n", ret
);
86 if (test_bit(ATH11K_FLAG_CRASH_FLUSH
, &ar
->ab
->dev_flags
)) {
91 time_left
= wait_for_completion_timeout(&ar
->thermal
.wmi_sync
,
92 ATH11K_THERMAL_SYNC_TIMEOUT_HZ
);
94 ath11k_warn(ar
->ab
, "failed to synchronize thermal read\n");
99 spin_lock_bh(&ar
->data_lock
);
100 temperature
= ar
->thermal
.temperature
;
101 spin_unlock_bh(&ar
->data_lock
);
103 /* display in millidegree Celsius */
104 ret
= sysfs_emit(buf
, "%d\n", temperature
* 1000);
106 mutex_unlock(&ar
->conf_mutex
);
110 void ath11k_thermal_event_temperature(struct ath11k
*ar
, int temperature
)
112 spin_lock_bh(&ar
->data_lock
);
113 ar
->thermal
.temperature
= temperature
;
114 spin_unlock_bh(&ar
->data_lock
);
115 complete(&ar
->thermal
.wmi_sync
);
118 static SENSOR_DEVICE_ATTR(temp1_input
, 0444, ath11k_thermal_show_temp
,
121 static struct attribute
*ath11k_hwmon_attrs
[] = {
122 &sensor_dev_attr_temp1_input
.dev_attr
.attr
,
125 ATTRIBUTE_GROUPS(ath11k_hwmon
);
127 int ath11k_thermal_set_throttling(struct ath11k
*ar
, u32 throttle_state
)
129 struct ath11k_base
*ab
= ar
->ab
;
130 struct thermal_mitigation_params param
;
133 lockdep_assert_held(&ar
->conf_mutex
);
135 if (ar
->state
!= ATH11K_STATE_ON
)
138 memset(¶m
, 0, sizeof(param
));
139 param
.pdev_id
= ar
->pdev
->pdev_id
;
140 param
.enable
= throttle_state
? 1 : 0;
141 param
.dc
= ATH11K_THERMAL_DEFAULT_DUTY_CYCLE
;
142 param
.dc_per_event
= 0xFFFFFFFF;
144 param
.levelconf
[0].tmplwm
= ATH11K_THERMAL_TEMP_LOW_MARK
;
145 param
.levelconf
[0].tmphwm
= ATH11K_THERMAL_TEMP_HIGH_MARK
;
146 param
.levelconf
[0].dcoffpercent
= throttle_state
;
147 param
.levelconf
[0].priority
= 0; /* disable all data tx queues */
149 ret
= ath11k_wmi_send_thermal_mitigation_param_cmd(ar
, ¶m
);
151 ath11k_warn(ab
, "failed to send thermal mitigation duty cycle %u ret %d\n",
152 throttle_state
, ret
);
158 int ath11k_thermal_register(struct ath11k_base
*ab
)
160 struct thermal_cooling_device
*cdev
;
161 struct device
*hwmon_dev
;
163 struct ath11k_pdev
*pdev
;
166 if (test_bit(ATH11K_FLAG_REGISTERED
, &ab
->dev_flags
))
169 for (i
= 0; i
< ab
->num_radios
; i
++) {
170 pdev
= &ab
->pdevs
[i
];
175 cdev
= thermal_cooling_device_register("ath11k_thermal", ar
,
176 &ath11k_thermal_ops
);
179 ath11k_err(ab
, "failed to setup thermal device result: %ld\n",
182 goto err_thermal_destroy
;
185 ar
->thermal
.cdev
= cdev
;
187 ret
= sysfs_create_link(&ar
->hw
->wiphy
->dev
.kobj
, &cdev
->device
.kobj
,
190 ath11k_err(ab
, "failed to create cooling device symlink\n");
191 goto err_thermal_destroy
;
194 if (!IS_REACHABLE(CONFIG_HWMON
))
197 hwmon_dev
= devm_hwmon_device_register_with_groups(&ar
->hw
->wiphy
->dev
,
199 ath11k_hwmon_groups
);
200 if (IS_ERR(hwmon_dev
)) {
201 ath11k_err(ar
->ab
, "failed to register hwmon device: %ld\n",
204 goto err_thermal_destroy
;
211 ath11k_thermal_unregister(ab
);
215 void ath11k_thermal_unregister(struct ath11k_base
*ab
)
218 struct ath11k_pdev
*pdev
;
221 for (i
= 0; i
< ab
->num_radios
; i
++) {
222 pdev
= &ab
->pdevs
[i
];
227 sysfs_remove_link(&ar
->hw
->wiphy
->dev
.kobj
, "cooling_device");
228 thermal_cooling_device_unregister(ar
->thermal
.cdev
);