1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2020 The Linux Foundation. All rights reserved.
6 #include <linux/device.h>
7 #include <linux/sysfs.h>
8 #include <linux/thermal.h>
9 #include <linux/hwmon.h>
10 #include <linux/hwmon-sysfs.h>
15 ath11k_thermal_get_max_throttle_state(struct thermal_cooling_device
*cdev
,
18 *state
= ATH11K_THERMAL_THROTTLE_MAX
;
24 ath11k_thermal_get_cur_throttle_state(struct thermal_cooling_device
*cdev
,
27 struct ath11k
*ar
= cdev
->devdata
;
29 mutex_lock(&ar
->conf_mutex
);
30 *state
= ar
->thermal
.throttle_state
;
31 mutex_unlock(&ar
->conf_mutex
);
37 ath11k_thermal_set_cur_throttle_state(struct thermal_cooling_device
*cdev
,
38 unsigned long throttle_state
)
40 struct ath11k
*ar
= cdev
->devdata
;
43 if (throttle_state
> ATH11K_THERMAL_THROTTLE_MAX
) {
44 ath11k_warn(ar
->ab
, "throttle state %ld is exceeding the limit %d\n",
45 throttle_state
, ATH11K_THERMAL_THROTTLE_MAX
);
48 mutex_lock(&ar
->conf_mutex
);
49 ret
= ath11k_thermal_set_throttling(ar
, throttle_state
);
51 ar
->thermal
.throttle_state
= throttle_state
;
52 mutex_unlock(&ar
->conf_mutex
);
56 static const struct thermal_cooling_device_ops ath11k_thermal_ops
= {
57 .get_max_state
= ath11k_thermal_get_max_throttle_state
,
58 .get_cur_state
= ath11k_thermal_get_cur_throttle_state
,
59 .set_cur_state
= ath11k_thermal_set_cur_throttle_state
,
62 static ssize_t
ath11k_thermal_show_temp(struct device
*dev
,
63 struct device_attribute
*attr
,
66 struct ath11k
*ar
= dev_get_drvdata(dev
);
68 unsigned long time_left
;
70 mutex_lock(&ar
->conf_mutex
);
72 /* Can't get temperature when the card is off */
73 if (ar
->state
!= ATH11K_STATE_ON
) {
78 reinit_completion(&ar
->thermal
.wmi_sync
);
79 ret
= ath11k_wmi_send_pdev_temperature_cmd(ar
);
81 ath11k_warn(ar
->ab
, "failed to read temperature %d\n", ret
);
85 if (test_bit(ATH11K_FLAG_CRASH_FLUSH
, &ar
->ab
->dev_flags
)) {
90 time_left
= wait_for_completion_timeout(&ar
->thermal
.wmi_sync
,
91 ATH11K_THERMAL_SYNC_TIMEOUT_HZ
);
93 ath11k_warn(ar
->ab
, "failed to synchronize thermal read\n");
98 spin_lock_bh(&ar
->data_lock
);
99 temperature
= ar
->thermal
.temperature
;
100 spin_unlock_bh(&ar
->data_lock
);
102 /* display in millidegree celcius */
103 ret
= snprintf(buf
, PAGE_SIZE
, "%d\n", temperature
* 1000);
105 mutex_unlock(&ar
->conf_mutex
);
109 void ath11k_thermal_event_temperature(struct ath11k
*ar
, int temperature
)
111 spin_lock_bh(&ar
->data_lock
);
112 ar
->thermal
.temperature
= temperature
;
113 spin_unlock_bh(&ar
->data_lock
);
114 complete(&ar
->thermal
.wmi_sync
);
117 static SENSOR_DEVICE_ATTR(temp1_input
, 0444, ath11k_thermal_show_temp
,
120 static struct attribute
*ath11k_hwmon_attrs
[] = {
121 &sensor_dev_attr_temp1_input
.dev_attr
.attr
,
124 ATTRIBUTE_GROUPS(ath11k_hwmon
);
126 int ath11k_thermal_set_throttling(struct ath11k
*ar
, u32 throttle_state
)
128 struct ath11k_base
*sc
= ar
->ab
;
129 struct thermal_mitigation_params param
;
132 lockdep_assert_held(&ar
->conf_mutex
);
134 if (ar
->state
!= ATH11K_STATE_ON
)
137 memset(¶m
, 0, sizeof(param
));
138 param
.pdev_id
= ar
->pdev
->pdev_id
;
139 param
.enable
= throttle_state
? 1 : 0;
140 param
.dc
= ATH11K_THERMAL_DEFAULT_DUTY_CYCLE
;
141 param
.dc_per_event
= 0xFFFFFFFF;
143 param
.levelconf
[0].tmplwm
= ATH11K_THERMAL_TEMP_LOW_MARK
;
144 param
.levelconf
[0].tmphwm
= ATH11K_THERMAL_TEMP_HIGH_MARK
;
145 param
.levelconf
[0].dcoffpercent
= throttle_state
;
146 param
.levelconf
[0].priority
= 0; /* disable all data tx queues */
148 ret
= ath11k_wmi_send_thermal_mitigation_param_cmd(ar
, ¶m
);
150 ath11k_warn(sc
, "failed to send thermal mitigation duty cycle %u ret %d\n",
151 throttle_state
, ret
);
157 int ath11k_thermal_register(struct ath11k_base
*sc
)
159 struct thermal_cooling_device
*cdev
;
160 struct device
*hwmon_dev
;
162 struct ath11k_pdev
*pdev
;
165 for (i
= 0; i
< sc
->num_radios
; i
++) {
166 pdev
= &sc
->pdevs
[i
];
171 cdev
= thermal_cooling_device_register("ath11k_thermal", ar
,
172 &ath11k_thermal_ops
);
175 ath11k_err(sc
, "failed to setup thermal device result: %ld\n",
178 goto err_thermal_destroy
;
181 ar
->thermal
.cdev
= cdev
;
183 ret
= sysfs_create_link(&ar
->hw
->wiphy
->dev
.kobj
, &cdev
->device
.kobj
,
186 ath11k_err(sc
, "failed to create cooling device symlink\n");
187 goto err_thermal_destroy
;
190 if (!IS_REACHABLE(CONFIG_HWMON
))
193 hwmon_dev
= devm_hwmon_device_register_with_groups(&ar
->hw
->wiphy
->dev
,
195 ath11k_hwmon_groups
);
196 if (IS_ERR(hwmon_dev
)) {
197 ath11k_err(ar
->ab
, "failed to register hwmon device: %ld\n",
200 goto err_thermal_destroy
;
207 ath11k_thermal_unregister(sc
);
211 void ath11k_thermal_unregister(struct ath11k_base
*sc
)
214 struct ath11k_pdev
*pdev
;
217 for (i
= 0; i
< sc
->num_radios
; i
++) {
218 pdev
= &sc
->pdevs
[i
];
223 sysfs_remove_link(&ar
->hw
->wiphy
->dev
.kobj
, "cooling_device");
224 thermal_cooling_device_unregister(ar
->thermal
.cdev
);