blob: a4338f3378b5a7d35f2b09f532761dbcc0a90fff [file] [log] [blame]
developer7e2761e2023-10-12 08:11:13 +08001From 3bf4da3eba0f082ec3be1c0ee603cbae3e9d9fbb Mon Sep 17 00:00:00 2001
developer483388c2023-03-08 13:52:15 +08002From: Howard Hsu <howard-yh.hsu@mediatek.com>
3Date: Thu, 2 Feb 2023 20:53:42 +0800
developer7e2761e2023-10-12 08:11:13 +08004Subject: [PATCH 06/98] wifi: mt76: mt7996: add thermal sensor device support
developer483388c2023-03-08 13:52:15 +08005
6---
developer7e2761e2023-10-12 08:11:13 +08007 mt7996/init.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++
developer483388c2023-03-08 13:52:15 +08008 mt7996/mcu.c | 41 ++++++++++++++++++++++++
developer7e2761e2023-10-12 08:11:13 +08009 2 files changed, 129 insertions(+)
developer483388c2023-03-08 13:52:15 +080010
11diff --git a/mt7996/init.c b/mt7996/init.c
developer7e2761e2023-10-12 08:11:13 +080012index 610d80e..de4a5f7 100644
developer483388c2023-03-08 13:52:15 +080013--- a/mt7996/init.c
14+++ b/mt7996/init.c
15@@ -4,6 +4,8 @@
16 */
17
18 #include <linux/etherdevice.h>
19+#include <linux/hwmon.h>
20+#include <linux/hwmon-sysfs.h>
21 #include <linux/thermal.h>
22 #include "mt7996.h"
23 #include "mac.h"
developer7e2761e2023-10-12 08:11:13 +080024@@ -42,6 +44,82 @@ static const struct ieee80211_iface_combination if_comb[] = {
developer483388c2023-03-08 13:52:15 +080025 }
26 };
27
28+static ssize_t mt7996_thermal_temp_show(struct device *dev,
29+ struct device_attribute *attr,
30+ char *buf)
31+{
32+ struct mt7996_phy *phy = dev_get_drvdata(dev);
33+ int i = to_sensor_dev_attr(attr)->index;
34+ int temperature;
35+
36+ switch (i) {
37+ case 0:
38+ temperature = mt7996_mcu_get_temperature(phy);
39+ if (temperature < 0)
40+ return temperature;
41+ /* display in millidegree celcius */
42+ return sprintf(buf, "%u\n", temperature * 1000);
43+ case 1:
44+ case 2:
45+ return sprintf(buf, "%u\n",
46+ phy->throttle_temp[i - 1] * 1000);
47+ case 3:
48+ return sprintf(buf, "%hhu\n", phy->throttle_state);
49+ default:
50+ return -EINVAL;
51+ }
52+}
53+
54+static ssize_t mt7996_thermal_temp_store(struct device *dev,
55+ struct device_attribute *attr,
56+ const char *buf, size_t count)
57+{
58+ struct mt7996_phy *phy = dev_get_drvdata(dev);
59+ int ret, i = to_sensor_dev_attr(attr)->index;
60+ long val;
61+
62+ ret = kstrtol(buf, 10, &val);
63+ if (ret < 0)
64+ return ret;
65+
66+ mutex_lock(&phy->dev->mt76.mutex);
67+ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 40, 130);
68+
developer7e2761e2023-10-12 08:11:13 +080069+ /* add a safety margin ~10 */
developer483388c2023-03-08 13:52:15 +080070+ if ((i - 1 == MT7996_CRIT_TEMP_IDX &&
developer7e2761e2023-10-12 08:11:13 +080071+ val > phy->throttle_temp[MT7996_MAX_TEMP_IDX] - 10) ||
developer483388c2023-03-08 13:52:15 +080072+ (i - 1 == MT7996_MAX_TEMP_IDX &&
developer7e2761e2023-10-12 08:11:13 +080073+ val - 10 < phy->throttle_temp[MT7996_CRIT_TEMP_IDX])) {
developer483388c2023-03-08 13:52:15 +080074+ dev_err(phy->dev->mt76.dev,
developer7e2761e2023-10-12 08:11:13 +080075+ "temp1_max shall be 10 degrees higher than temp1_crit.");
developer483388c2023-03-08 13:52:15 +080076+ mutex_unlock(&phy->dev->mt76.mutex);
77+ return -EINVAL;
78+ }
79+
80+ phy->throttle_temp[i - 1] = val;
81+ mutex_unlock(&phy->dev->mt76.mutex);
82+
developerc2cfe0f2023-09-22 04:11:09 +080083+ ret = mt7996_mcu_set_thermal_protect(phy, true);
developer483388c2023-03-08 13:52:15 +080084+ if (ret)
85+ return ret;
86+
87+ return count;
88+}
89+
90+static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7996_thermal_temp, 0);
91+static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7996_thermal_temp, 1);
92+static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7996_thermal_temp, 2);
93+static SENSOR_DEVICE_ATTR_RO(throttle1, mt7996_thermal_temp, 3);
94+
95+static struct attribute *mt7996_hwmon_attrs[] = {
96+ &sensor_dev_attr_temp1_input.dev_attr.attr,
97+ &sensor_dev_attr_temp1_crit.dev_attr.attr,
98+ &sensor_dev_attr_temp1_max.dev_attr.attr,
99+ &sensor_dev_attr_throttle1.dev_attr.attr,
100+ NULL,
101+};
102+ATTRIBUTE_GROUPS(mt7996_hwmon);
103+
104 static int
105 mt7996_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
106 unsigned long *state)
developer7e2761e2023-10-12 08:11:13 +0800107@@ -113,6 +191,7 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
developer483388c2023-03-08 13:52:15 +0800108 {
109 struct wiphy *wiphy = phy->mt76->hw->wiphy;
110 struct thermal_cooling_device *cdev;
111+ struct device *hwmon;
112 const char *name;
113
114 name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
developer7e2761e2023-10-12 08:11:13 +0800115@@ -131,6 +210,15 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
developer483388c2023-03-08 13:52:15 +0800116 phy->throttle_temp[MT7996_CRIT_TEMP_IDX] = MT7996_CRIT_TEMP;
117 phy->throttle_temp[MT7996_MAX_TEMP_IDX] = MT7996_MAX_TEMP;
118
119+ if (!IS_REACHABLE(CONFIG_HWMON))
120+ return 0;
121+
122+ hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
123+ mt7996_hwmon_groups);
124+
125+ if (IS_ERR(hwmon))
126+ return PTR_ERR(hwmon);
127+
128 return 0;
129 }
130
131diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer7e2761e2023-10-12 08:11:13 +0800132index 5310f9b..8320c8c 100644
developer483388c2023-03-08 13:52:15 +0800133--- a/mt7996/mcu.c
134+++ b/mt7996/mcu.c
developer7e2761e2023-10-12 08:11:13 +0800135@@ -3481,6 +3481,47 @@ out:
developer483388c2023-03-08 13:52:15 +0800136 return 0;
137 }
138
139+int mt7996_mcu_get_temperature(struct mt7996_phy *phy)
140+{
141+#define TEMPERATURE_QUERY 0
142+#define GET_TEMPERATURE 0
143+ struct {
144+ u8 _rsv[4];
145+
146+ __le16 tag;
147+ __le16 len;
148+
149+ u8 rsv1;
150+ u8 action;
151+ u8 band_idx;
152+ u8 rsv2;
153+ } req = {
154+ .tag = cpu_to_le16(TEMPERATURE_QUERY),
155+ .len = cpu_to_le16(sizeof(req) - 4),
156+ .action = GET_TEMPERATURE,
157+ .band_idx = phy->mt76->band_idx,
158+ };
159+ struct mt7996_mcu_thermal {
160+ u8 _rsv[4];
161+
162+ __le16 tag;
163+ __le16 len;
164+
165+ __le32 rsv;
166+ __le32 temperature;
167+ } __packed *res;
168+ struct sk_buff *skb;
169+ int ret;
170+
171+ ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
172+ &req, sizeof(req), true, &skb);
173+ if (ret)
174+ return ret;
175+
176+ res = (void *)skb->data;
177+
178+ return le32_to_cpu(res->temperature);
179+}
180
181 int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
182 {
183--
developer7e2761e2023-10-12 08:11:13 +08001842.18.0
developer483388c2023-03-08 13:52:15 +0800185