blob: ee5b28398e996d3a4c6d2b00b40509d499002e05 [file] [log] [blame]
developerec4ebe42022-04-12 11:17:45 +08001From b6c6afbe347c8cd3ab43d4cab07e840ecf5d3ad6 Mon Sep 17 00:00:00 2001
2From: Shayne Chen <shayne.chen@mediatek.com>
3Date: Tue, 29 Jun 2021 14:30:44 +0800
4Subject: [PATCH 1100/1112] mt76: testmode: support eeprom handle
5
6Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
7---
8 drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
9 .../net/wireless/mediatek/mt76/mt7915/init.c | 2 +-
10 .../net/wireless/mediatek/mt76/mt7915/mcu.c | 5 +-
11 .../wireless/mediatek/mt76/mt7915/mt7915.h | 2 +-
12 .../wireless/mediatek/mt76/mt7915/testmode.c | 54 +++++++++++++++++++
13 drivers/net/wireless/mediatek/mt76/testmode.c | 46 +++++++++++++++-
14 drivers/net/wireless/mediatek/mt76/testmode.h | 30 +++++++++++
15 7 files changed, 133 insertions(+), 7 deletions(-)
16
17diff --git a/mt76.h b/mt76.h
18index 58b324c..8ad7674 100644
19--- a/mt76.h
20+++ b/mt76.h
21@@ -581,6 +581,7 @@ struct mt76_testmode_ops {
22 int (*set_params)(struct mt76_phy *phy, struct nlattr **tb,
23 enum mt76_testmode_state new_state);
24 int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
25+ int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
26 };
27
28 #define MT_TM_FW_RX_COUNT BIT(0)
29diff --git a/mt7915/init.c b/mt7915/init.c
30index cd69174..92d57f9 100644
31--- a/mt7915/init.c
32+++ b/mt7915/init.c
33@@ -569,7 +569,7 @@ static void mt7915_init_work(struct work_struct *work)
34 struct mt7915_dev *dev = container_of(work, struct mt7915_dev,
35 init_work);
36
37- mt7915_mcu_set_eeprom(dev);
38+ mt7915_mcu_set_eeprom(dev, dev->flash_mode);
39 mt7915_mac_init(dev);
40 mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
41 mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
42diff --git a/mt7915/mcu.c b/mt7915/mcu.c
43index d55e9d0..2b57459 100644
44--- a/mt7915/mcu.c
45+++ b/mt7915/mcu.c
46@@ -289,7 +289,6 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
47 if (mcu_txd->ext_cid) {
48 mcu_txd->ext_cid_ack = 1;
49
50- /* do not use Q_SET for efuse */
51 if (cmd & __MCU_CMD_FIELD_QUERY)
52 mcu_txd->set_query = MCU_Q_QUERY;
53 else
54@@ -2913,14 +2912,14 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
55 return 0;
56 }
57
58-int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)
59+int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode)
60 {
61 struct mt7915_mcu_eeprom req = {
62 .buffer_mode = EE_MODE_EFUSE,
63 .format = EE_FORMAT_WHOLE,
64 };
65
66- if (dev->flash_mode)
67+ if (flash_mode)
68 return mt7915_mcu_set_eeprom_flash(dev);
69
70 return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),
71diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
72index a8726fe..274afff 100644
73--- a/mt7915/mt7915.h
74+++ b/mt7915/mt7915.h
75@@ -539,7 +539,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
76 struct ieee80211_vif *vif,
77 struct ieee80211_sta *sta,
78 void *data, u32 field);
79-int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
80+int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode);
81 int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
82 int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
83 int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
84diff --git a/mt7915/testmode.c b/mt7915/testmode.c
85index e8bf616..2c859f6 100644
86--- a/mt7915/testmode.c
87+++ b/mt7915/testmode.c
88@@ -848,8 +848,62 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
89 return mt7915_tm_get_rx_stats(phy, false);
90 }
91
92+static int
93+mt7915_tm_write_back_to_efuse(struct mt7915_dev *dev)
94+{
95+ struct mt7915_mcu_eeprom_info req = {};
96+ u8 *eeprom = dev->mt76.eeprom.data;
97+ int i, ret = -EINVAL;
98+
99+ /* prevent from damaging chip id in efuse */
100+ if (mt76_chip(&dev->mt76) != get_unaligned_le16(eeprom))
101+ goto out;
102+
103+ for (i = 0; i < MT7915_EEPROM_SIZE; i += MT76_TM_EEPROM_BLOCK_SIZE) {
104+ req.addr = cpu_to_le32(i);
105+ memcpy(&req.data, eeprom + i, MT76_TM_EEPROM_BLOCK_SIZE);
106+
107+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_ACCESS),
108+ &req, sizeof(req), true);
109+ if (ret)
110+ return ret;
111+ }
112+
113+out:
114+ return ret;
115+}
116+
117+static int
118+mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
119+{
120+ struct mt7915_phy *phy = mphy->priv;
121+ struct mt7915_dev *dev = phy->dev;
122+ u8 *eeprom = dev->mt76.eeprom.data;
123+ int ret = 0;
124+
125+ if (offset >= MT7915_EEPROM_SIZE)
126+ return -EINVAL;
127+
128+ switch (action) {
129+ case MT76_TM_EEPROM_ACTION_UPDATE_DATA:
130+ memcpy(eeprom + offset, val, MT76_TM_EEPROM_BLOCK_SIZE);
131+ break;
132+ case MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE:
133+ ret = mt7915_mcu_set_eeprom(dev, true);
134+ break;
135+ case MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE:
136+ ret = mt7915_tm_write_back_to_efuse(dev);
137+ break;
138+ default:
139+ break;
140+ }
141+
142+ return ret;
143+}
144+
145 const struct mt76_testmode_ops mt7915_testmode_ops = {
146 .set_state = mt7915_tm_set_state,
147 .set_params = mt7915_tm_set_params,
148 .dump_stats = mt7915_tm_dump_stats,
149+ .set_eeprom = mt7915_tm_set_eeprom,
150 };
151diff --git a/testmode.c b/testmode.c
152index e6d1f70..1fbca66 100644
153--- a/testmode.c
154+++ b/testmode.c
155@@ -402,6 +402,44 @@ mt76_tm_get_u8(struct nlattr *attr, u8 *dest, u8 min, u8 max)
156 return 0;
157 }
158
159+static int
160+mt76_testmode_set_eeprom(struct mt76_phy *phy, struct nlattr **tb)
161+{
162+ struct mt76_dev *dev = phy->dev;
163+ u8 action, val[MT76_TM_EEPROM_BLOCK_SIZE];
164+ u32 offset = 0;
165+ int err = -EINVAL;
166+
167+ if (!dev->test_ops->set_eeprom)
168+ return -EOPNOTSUPP;
169+
170+ if (mt76_tm_get_u8(tb[MT76_TM_ATTR_EEPROM_ACTION], &action,
171+ 0, MT76_TM_EEPROM_ACTION_MAX))
172+ goto out;
173+
174+ if (tb[MT76_TM_ATTR_EEPROM_OFFSET]) {
175+ struct nlattr *cur;
176+ int rem, idx = 0;
177+
178+ offset = nla_get_u32(tb[MT76_TM_ATTR_EEPROM_OFFSET]);
179+ if (!!(offset % MT76_TM_EEPROM_BLOCK_SIZE) ||
180+ !tb[MT76_TM_ATTR_EEPROM_VAL])
181+ goto out;
182+
183+ nla_for_each_nested(cur, tb[MT76_TM_ATTR_EEPROM_VAL], rem) {
184+ if (nla_len(cur) != 1 || idx >= ARRAY_SIZE(val))
185+ goto out;
186+
187+ val[idx++] = nla_get_u8(cur);
188+ }
189+ }
190+
191+ err = dev->test_ops->set_eeprom(phy, offset, val, action);
192+
193+out:
194+ return err;
195+}
196+
197 int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
198 void *data, int len)
199 {
200@@ -425,6 +463,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
201
202 mutex_lock(&dev->mutex);
203
204+ if (tb[MT76_TM_ATTR_EEPROM_ACTION]) {
205+ err = mt76_testmode_set_eeprom(phy, tb);
206+ goto out;
207+ }
208+
209 if (tb[MT76_TM_ATTR_RESET]) {
210 mt76_testmode_set_state(phy, MT76_TM_STATE_OFF);
211 memset(td, 0, sizeof(*td));
212@@ -484,8 +527,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
213
214 if (tb[MT76_TM_ATTR_TX_POWER]) {
215 struct nlattr *cur;
216- int idx = 0;
217- int rem;
218+ int rem, idx = 0;
219
220 nla_for_each_nested(cur, tb[MT76_TM_ATTR_TX_POWER], rem) {
221 if (nla_len(cur) != 1 ||
222diff --git a/testmode.h b/testmode.h
223index 8961326..5900c76 100644
224--- a/testmode.h
225+++ b/testmode.h
226@@ -6,6 +6,7 @@
227 #define __MT76_TESTMODE_H
228
229 #define MT76_TM_TIMEOUT 10
230+#define MT76_TM_EEPROM_BLOCK_SIZE 16
231
232 /**
233 * enum mt76_testmode_attr - testmode attributes inside NL80211_ATTR_TESTDATA
234@@ -47,6 +48,13 @@
235 * @MT76_TM_ATTR_DRV_DATA: driver specific netlink attrs (nested)
236 *
237 * @MT76_TM_ATTR_MAC_ADDRS: array of nested MAC addresses (nested)
238+ *
239+ * @MT76_TM_ATTR_EEPROM_ACTION: eeprom setting actions
240+ * (u8, see &enum mt76_testmode_eeprom_action)
241+ * @MT76_TM_ATTR_EEPROM_OFFSET: offset of eeprom data block for writing (u32)
242+ * @MT76_TM_ATTR_EEPROM_VAL: values for writing into a 16-byte data block
243+ * (nested, u8 attrs)
244+ *
245 */
246 enum mt76_testmode_attr {
247 MT76_TM_ATTR_UNSPEC,
248@@ -85,6 +93,10 @@ enum mt76_testmode_attr {
249
250 MT76_TM_ATTR_MAC_ADDRS,
251
252+ MT76_TM_ATTR_EEPROM_ACTION,
253+ MT76_TM_ATTR_EEPROM_OFFSET,
254+ MT76_TM_ATTR_EEPROM_VAL,
255+
256 /* keep last */
257 NUM_MT76_TM_ATTRS,
258 MT76_TM_ATTR_MAX = NUM_MT76_TM_ATTRS - 1,
259@@ -198,4 +210,22 @@ enum mt76_testmode_tx_mode {
260
261 extern const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS];
262
263+/**
264+ * enum mt76_testmode_eeprom_action - eeprom setting actions
265+ *
266+ * @MT76_TM_EEPROM_ACTION_UPDATE_DATA: update rf values to specific
267+ * eeprom data block
268+ * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
269+ * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
270+ */
271+enum mt76_testmode_eeprom_action {
272+ MT76_TM_EEPROM_ACTION_UPDATE_DATA,
273+ MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE,
274+ MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE,
275+
276+ /* keep last */
277+ NUM_MT76_TM_EEPROM_ACTION,
278+ MT76_TM_EEPROM_ACTION_MAX = NUM_MT76_TM_EEPROM_ACTION - 1,
279+};
280+
281 #endif
282--
2832.25.1
284