xref: /freebsd/sys/dev/aq/aq_fw2x.c (revision 6dbf809bafe1421fbf3cdd952748b15437b7c72a)
1 /**
2  * aQuantia Corporation Network Driver
3  * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *   (1) Redistributions of source code must retain the above
10  *   copyright notice, this list of conditions and the following
11  *   disclaimer.
12  *
13  *   (2) Redistributions in binary form must reproduce the above
14  *   copyright notice, this list of conditions and the following
15  *   disclaimer in the documentation and/or other materials provided
16  *   with the distribution.
17  *
18  *   (3) The name of the author may not be used to endorse or promote
19  *   products derived from this software without specific prior
20  *   written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * @file aq_fw2x.c
35  * Firmware v2.x specific functions.
36  * @date 2017.12.11  @author roman.agafonov@aquantia.com
37  */
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40 
41 #include <sys/errno.h>
42 
43 #include "aq_common.h"
44 
45 
46 #include "aq_hw.h"
47 #include "aq_hw_llh.h"
48 #include "aq_hw_llh_internal.h"
49 
50 #include "aq_fw.h"
51 
52 #include "aq_dbg.h"
53 
54 enum aq_fw2x_caps_lo {
55 	CAPS_LO_10BASET_HD = 0x00,
56 	CAPS_LO_10BASET_FD,
57 	CAPS_LO_100BASETX_HD,
58 	CAPS_LO_100BASET4_HD,
59 	CAPS_LO_100BASET2_HD,
60 	CAPS_LO_100BASETX_FD,
61 	CAPS_LO_100BASET2_FD,
62 	CAPS_LO_1000BASET_HD,
63 	CAPS_LO_1000BASET_FD,
64 	CAPS_LO_2P5GBASET_FD,
65 	CAPS_LO_5GBASET_FD,
66 	CAPS_LO_10GBASET_FD,
67 };
68 
69 enum aq_fw2x_caps_hi {
70 	CAPS_HI_RESERVED1 = 0x00,
71 	CAPS_HI_10BASET_EEE,
72 	CAPS_HI_RESERVED2,
73 	CAPS_HI_PAUSE,
74 	CAPS_HI_ASYMMETRIC_PAUSE,
75 	CAPS_HI_100BASETX_EEE,
76 	CAPS_HI_RESERVED3,
77 	CAPS_HI_RESERVED4,
78 	CAPS_HI_1000BASET_FD_EEE,
79 	CAPS_HI_2P5GBASET_FD_EEE,
80 	CAPS_HI_5GBASET_FD_EEE,
81 	CAPS_HI_10GBASET_FD_EEE,
82 	CAPS_HI_RESERVED5,
83 	CAPS_HI_RESERVED6,
84 	CAPS_HI_RESERVED7,
85 	CAPS_HI_RESERVED8,
86 	CAPS_HI_RESERVED9,
87 	CAPS_HI_CABLE_DIAG,
88 	CAPS_HI_TEMPERATURE,
89 	CAPS_HI_DOWNSHIFT,
90 	CAPS_HI_PTP_AVB_EN,
91 	CAPS_HI_THERMAL_SHUTDOWN,
92 	CAPS_HI_LINK_DROP,
93 	CAPS_HI_SLEEP_PROXY,
94 	CAPS_HI_WOL,
95 	CAPS_HI_MAC_STOP,
96 	CAPS_HI_EXT_LOOPBACK,
97 	CAPS_HI_INT_LOOPBACK,
98 	CAPS_HI_EFUSE_AGENT,
99 	CAPS_HI_WOL_TIMER,
100 	CAPS_HI_STATISTICS,
101 	CAPS_HI_TRANSACTION_ID,
102 };
103 
104 enum aq_fw2x_rate
105 {
106 	FW2X_RATE_100M = 0x20,
107 	FW2X_RATE_1G = 0x100,
108 	FW2X_RATE_2G5 = 0x200,
109 	FW2X_RATE_5G = 0x400,
110 	FW2X_RATE_10G = 0x800,
111 };
112 
113 
114 struct aq_fw2x_msm_statistics
115 {
116 	uint32_t uprc;
117 	uint32_t mprc;
118 	uint32_t bprc;
119 	uint32_t erpt;
120 	uint32_t uptc;
121 	uint32_t mptc;
122 	uint32_t bptc;
123 	uint32_t erpr;
124 	uint32_t mbtc;
125 	uint32_t bbtc;
126 	uint32_t mbrc;
127 	uint32_t bbrc;
128 	uint32_t ubrc;
129 	uint32_t ubtc;
130 	uint32_t ptc;
131 	uint32_t prc;
132 };
133 
134 struct aq_fw2x_phy_cable_diag_data
135 {
136 	uint32_t lane_data[4];
137 };
138 
139 struct aq_fw2x_capabilities {
140 	uint32_t caps_lo;
141 	uint32_t caps_hi;
142 };
143 
144 struct aq_fw2x_mailbox // struct fwHostInterface
145 {
146 	uint32_t version;
147 	uint32_t transaction_id;
148 	int32_t error;
149 	struct aq_fw2x_msm_statistics msm; // msmStatistics_t msm;
150 	uint16_t phy_h_bit;
151 	uint16_t phy_fault_code;
152 	int16_t phy_temperature;
153 	uint8_t cable_len;
154 	uint8_t reserved1;
155 	struct aq_fw2x_phy_cable_diag_data diag_data;
156 	uint32_t reserved[8];
157 
158 	struct aq_fw2x_capabilities caps;
159 
160 	/* ... */
161 };
162 
163 
164 // EEE caps
165 #define FW2X_FW_CAP_EEE_100M (1ULL << (32 + CAPS_HI_100BASETX_EEE))
166 #define FW2X_FW_CAP_EEE_1G   (1ULL << (32 + CAPS_HI_1000BASET_FD_EEE))
167 #define FW2X_FW_CAP_EEE_2G5  (1ULL << (32 + CAPS_HI_2P5GBASET_FD_EEE))
168 #define FW2X_FW_CAP_EEE_5G   (1ULL << (32 + CAPS_HI_5GBASET_FD_EEE))
169 #define FW2X_FW_CAP_EEE_10G  (1ULL << (32 + CAPS_HI_10GBASET_FD_EEE))
170 
171 // Flow Control
172 #define FW2X_FW_CAP_PAUSE      (1ULL << (32 + CAPS_HI_PAUSE))
173 #define FW2X_FW_CAP_ASYM_PAUSE (1ULL << (32 + CAPS_HI_ASYMMETRIC_PAUSE))
174 
175 // Link Drop
176 #define FW2X_CAP_LINK_DROP  (1ull << (32 + CAPS_HI_LINK_DROP))
177 
178 // MSM Statistics
179 #define FW2X_CAP_STATISTICS (1ull << (32 + CAPS_HI_STATISTICS))
180 #define FW2X_CAP_TEMPERATURE (1ull << (32 + CAPS_HI_TEMPERATURE))
181 
182 
183 #define FW2X_RATE_MASK  (FW2X_RATE_100M | FW2X_RATE_1G | FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G)
184 #define FW2X_EEE_MASK  (FW2X_FW_CAP_EEE_100M | FW2X_FW_CAP_EEE_1G | FW2X_FW_CAP_EEE_2G5 | FW2X_FW_CAP_EEE_5G | FW2X_FW_CAP_EEE_10G)
185 
186 
187 #define FW2X_MPI_LED_ADDR           0x31c
188 #define FW2X_MPI_CONTROL_ADDR       0x368
189 #define FW2X_MPI_STATE_ADDR         0x370
190 
191 #define FW2X_FW_MIN_VER_LED 0x03010026U
192 
193 #define FW2X_LED_BLINK    0x2U
194 #define FW2X_LED_DEFAULT  0x0U
195 
196 // Firmware v2-3.x specific functions.
197 static int aq_fw2x_reset(struct aq_hw* hw);
198 
199 static int aq_fw2x_set_mode(struct aq_hw* hw, enum aq_hw_fw_mpi_state mode,
200     enum aq_fw_link_speed speed);
201 static int aq_fw2x_get_mode(struct aq_hw* hw, enum aq_hw_fw_mpi_state* mode,
202     enum aq_fw_link_speed* speed, enum aq_fw_link_fc* fc);
203 
204 static int aq_fw2x_get_mac_addr(struct aq_hw* hw, uint8_t* mac);
205 static int aq_fw2x_get_stats(struct aq_hw* hw, struct aq_hw_stats* stats);
206 
207 
208 static uint64_t
read64(struct aq_hw * hw,uint32_t addr)209 read64(struct aq_hw* hw, uint32_t addr)
210 {
211 	uint64_t lo, hi, hi2;
212 
213 	hi = AQ_READ_REG(hw, addr + 4);
214 	do {
215 		hi2 = hi;
216 		lo = AQ_READ_REG(hw, addr);
217 		hi = AQ_READ_REG(hw, addr + 4);
218 	} while (hi != hi2);
219 
220 	return (lo | (hi << 32));
221 }
222 
223 static uint64_t
get_mpi_ctrl(struct aq_hw * hw)224 get_mpi_ctrl(struct aq_hw* hw)
225 {
226 	return read64(hw, FW2X_MPI_CONTROL_ADDR);
227 }
228 
229 static uint64_t
get_mpi_state(struct aq_hw * hw)230 get_mpi_state(struct aq_hw* hw)
231 {
232 	return read64(hw, FW2X_MPI_STATE_ADDR);
233 }
234 
235 static void
set_mpi_ctrl(struct aq_hw * hw,uint64_t value)236 set_mpi_ctrl(struct aq_hw* hw, uint64_t value)
237 {
238 	AQ_WRITE_REG(hw, FW2X_MPI_CONTROL_ADDR, (uint32_t)value);
239 	AQ_WRITE_REG(hw, FW2X_MPI_CONTROL_ADDR + 4, (uint32_t)(value >> 32));
240 }
241 
242 
243 static int
aq_fw2x_reset(struct aq_hw * hw)244 aq_fw2x_reset(struct aq_hw* hw)
245 {
246 	struct aq_fw2x_capabilities caps = {0};
247 	AQ_DBG_ENTER();
248 	mtx_lock(&hw->fw_mtx);
249 	int err = aq_hw_fw_downld_dwords(hw,
250 	    hw->mbox_addr + offsetof(struct aq_fw2x_mailbox, caps),
251 	    (uint32_t*)&caps, sizeof caps/sizeof(uint32_t));
252 	mtx_unlock(&hw->fw_mtx);
253 	if (err == 0) {
254 		hw->fw_caps = caps.caps_lo | ((uint64_t)caps.caps_hi << 32);
255 		trace(hw, dbg_init,
256 		     "fw2x> F/W capabilities mask = %llx",
257 		     (unsigned long long)hw->fw_caps);
258 	} else {
259 		trace_error(hw, dbg_init,
260 		     "fw2x> can't get F/W capabilities mask, error %d", err);
261 	}
262 
263 	AQ_DBG_EXIT(err);
264 	return (err);
265 }
266 
267 
268 static enum aq_fw2x_rate
link_speed_mask_to_fw2x(uint32_t speed)269 link_speed_mask_to_fw2x(uint32_t speed)
270 {
271 	uint32_t rate = 0;
272 
273 	AQ_DBG_ENTER();
274 	if (speed & aq_fw_10G)
275 		rate |= FW2X_RATE_10G;
276 
277 	if (speed & aq_fw_5G)
278 		rate |= FW2X_RATE_5G;
279 
280 	if (speed & aq_fw_2G5)
281 		rate |= FW2X_RATE_2G5;
282 
283 	if (speed & aq_fw_1G)
284 		rate |= FW2X_RATE_1G;
285 
286 	if (speed & aq_fw_100M)
287 		rate |= FW2X_RATE_100M;
288 
289 	AQ_DBG_EXIT(rate);
290 	return ((enum aq_fw2x_rate)rate);
291 }
292 
293 
294 static int
aq_fw2x_set_mode(struct aq_hw * hw,enum aq_hw_fw_mpi_state mode,enum aq_fw_link_speed speed)295 aq_fw2x_set_mode(struct aq_hw* hw, enum aq_hw_fw_mpi_state mode,
296     enum aq_fw_link_speed speed)
297 {
298 	uint64_t mpi_ctrl;
299 
300 	AQ_DBG_ENTERA("speed=%d", speed);
301 
302 	mtx_lock(&hw->fw_mtx);
303 	mpi_ctrl = get_mpi_ctrl(hw);
304 	switch (mode) {
305 	case MPI_INIT:
306 		mpi_ctrl &= ~FW2X_RATE_MASK;
307 		mpi_ctrl |= link_speed_mask_to_fw2x(speed);
308 		mpi_ctrl &= ~FW2X_CAP_LINK_DROP;
309 		mpi_ctrl &= ~(FW2X_FW_CAP_PAUSE | FW2X_FW_CAP_ASYM_PAUSE);
310 #if 0 // #todo #flowcontrol #pause #eee
311 		if (pHal->pCfg->eee)
312 			mpi_ctrl |= FW2X_EEE_MASK;
313 #endif
314 		if (hw->fc.fc_rx)
315 			mpi_ctrl |= FW2X_FW_CAP_PAUSE | FW2X_FW_CAP_ASYM_PAUSE;
316 		else if (hw->fc.fc_tx)
317 			mpi_ctrl |= FW2X_FW_CAP_ASYM_PAUSE;
318 		break;
319 
320 	case MPI_DEINIT:
321 		mpi_ctrl &= ~(FW2X_RATE_MASK | FW2X_EEE_MASK);
322 		mpi_ctrl &= ~(FW2X_FW_CAP_PAUSE | FW2X_FW_CAP_ASYM_PAUSE);
323 		break;
324 
325 	default:
326 		mtx_unlock(&hw->fw_mtx);
327 		trace_error(hw, dbg_init, "fw2x> unknown MPI state %d", mode);
328 		return (EINVAL);
329 	}
330 
331 	set_mpi_ctrl(hw, mpi_ctrl);
332 	mtx_unlock(&hw->fw_mtx);
333 
334 	AQ_DBG_EXIT(0);
335 	return (0);
336 }
337 
338 static int
aq_fw2x_get_mode(struct aq_hw * hw,enum aq_hw_fw_mpi_state * mode,enum aq_fw_link_speed * link_speed,enum aq_fw_link_fc * fc)339 aq_fw2x_get_mode(struct aq_hw* hw, enum aq_hw_fw_mpi_state* mode,
340     enum aq_fw_link_speed* link_speed, enum aq_fw_link_fc* fc)
341 {
342 	uint64_t mpi_state;
343 	uint32_t rates;
344 
345 	mtx_lock(&hw->fw_mtx);
346 	mpi_state = get_mpi_state(hw);
347 	if (mode) {
348 		uint64_t mpi_ctrl = get_mpi_ctrl(hw);
349 		if (mpi_ctrl & FW2X_RATE_MASK)
350 		*mode = MPI_INIT;
351 		else
352 		*mode = MPI_DEINIT;
353 	}
354 	mtx_unlock(&hw->fw_mtx);
355 
356 	rates = mpi_state & FW2X_RATE_MASK;
357 
358 	enum aq_fw_link_speed speed = aq_fw_none;
359 
360 	if (rates & FW2X_RATE_10G)
361 		speed = aq_fw_10G;
362 	else if (rates & FW2X_RATE_5G)
363 		speed = aq_fw_5G;
364 	else if (rates & FW2X_RATE_2G5)
365 		speed = aq_fw_2G5;
366 	else if (rates & FW2X_RATE_1G)
367 		speed = aq_fw_1G;
368 	else if (rates & FW2X_RATE_100M)
369 		speed = aq_fw_100M;
370 
371 	if (link_speed)
372 		*link_speed = speed;
373 
374 	*fc = (mpi_state & (FW2X_FW_CAP_PAUSE | FW2X_FW_CAP_ASYM_PAUSE)) >>
375 	    (32 + CAPS_HI_PAUSE);
376 
377 	return (0);
378 }
379 
380 
381 static int
aq_fw2x_get_mac_addr(struct aq_hw * hw,uint8_t * mac)382 aq_fw2x_get_mac_addr(struct aq_hw* hw, uint8_t* mac)
383 {
384 	int err = EFAULT;
385 	uint32_t mac_addr[2];
386 
387 	AQ_DBG_ENTER();
388 
389 	uint32_t efuse_shadow_addr = AQ_READ_REG(hw, 0x364);
390 	if (efuse_shadow_addr == 0) {
391 		trace_error(hw, dbg_init, "couldn't read eFUSE Shadow Address");
392 		AQ_DBG_EXIT(EFAULT);
393 		return (EFAULT);
394 	}
395 
396 	err = aq_hw_fw_downld_dwords(hw, efuse_shadow_addr + (40 * 4), mac_addr,
397 	    nitems(mac_addr));
398 	if (err != 0) {
399 		mac_addr[0] = 0;
400 		mac_addr[1] = 0;
401 		AQ_DBG_EXIT(err);
402 		return (err);
403 	}
404 
405 	mac_addr[0] = bswap32(mac_addr[0]);
406 	mac_addr[1] = bswap32(mac_addr[1]);
407 
408 	memcpy(mac, (uint8_t*)mac_addr, ETHER_ADDR_LEN);
409 
410 	AQ_DBG_EXIT(0);
411 	return (0);
412 }
413 
414 static inline void
aq_fw2x_stats_to_fw_stats(struct aq_hw_stats * dst,const struct aq_fw2x_msm_statistics * src)415 aq_fw2x_stats_to_fw_stats(struct aq_hw_stats* dst,
416     const struct aq_fw2x_msm_statistics* src)
417 {
418 	dst->uprc = src->uprc;
419 	dst->mprc = src->mprc;
420 	dst->bprc = src->bprc;
421 	dst->erpt = src->erpt;
422 	dst->uptc = src->uptc;
423 	dst->mptc = src->mptc;
424 	dst->bptc = src->bptc;
425 	dst->erpr = src->erpr;
426 	dst->mbtc = src->mbtc;
427 	dst->bbtc = src->bbtc;
428 	dst->mbrc = src->mbrc;
429 	dst->bbrc = src->bbrc;
430 	dst->ubrc = src->ubrc;
431 	dst->ubtc = src->ubtc;
432 	dst->ptc = src->ptc;
433 	dst->prc = src->prc;
434 }
435 
436 
437 static int
aq_fw2x_get_stats(struct aq_hw * hw,struct aq_hw_stats * stats)438 aq_fw2x_get_stats(struct aq_hw* hw, struct aq_hw_stats* stats)
439 {
440 	struct aq_fw2x_msm_statistics aq_fw2x_stats = {0};
441 	uint64_t mpi_ctrl;
442 	int err;
443 
444 	if ((hw->fw_caps & FW2X_CAP_STATISTICS) == 0) {
445 		trace_warn(hw, dbg_fw, "fw2x> statistics not supported by F/W");
446 		return (ENOTSUP);
447 	}
448 
449 	/* Kick-and-read: take the F/W's previous snapshot, request the next. */
450 	mtx_lock(&hw->fw_mtx);
451 	err = aq_hw_fw_downld_dwords(hw,
452 	    hw->mbox_addr + offsetof(struct aq_fw2x_mailbox, msm),
453 	    (uint32_t*)&aq_fw2x_stats, sizeof aq_fw2x_stats/sizeof(uint32_t));
454 
455 	mpi_ctrl = get_mpi_ctrl(hw);
456 	mpi_ctrl ^= FW2X_CAP_STATISTICS;
457 	set_mpi_ctrl(hw, mpi_ctrl);
458 	mtx_unlock(&hw->fw_mtx);
459 
460 	aq_fw2x_stats_to_fw_stats(stats, &aq_fw2x_stats);
461 
462 	if (err != 0)
463 		trace_error(hw, dbg_fw,
464 		    "fw2x> download statistics data FAILED, error %d", err);
465 
466 	return (err);
467 }
468 
469 static int
aq_fw2x_get_temp(struct aq_hw * hw,int * temp_mc)470 aq_fw2x_get_temp(struct aq_hw* hw, int* temp_mc)
471 {
472 	uint64_t mpi_ctrl, req_bit;
473 	uint32_t raw;
474 	int err;
475 
476 	if ((hw->fw_caps & FW2X_CAP_TEMPERATURE) == 0)
477 		return (ENOTSUP);
478 
479 	/* Toggle the request bit and wait for the F/W to echo it back. */
480 	mtx_lock(&hw->fw_mtx);
481 	mpi_ctrl = get_mpi_ctrl(hw);
482 	req_bit = mpi_ctrl & FW2X_CAP_TEMPERATURE;
483 	set_mpi_ctrl(hw, mpi_ctrl ^ FW2X_CAP_TEMPERATURE);
484 
485 	err = AQ_HW_WAIT_FOR((get_mpi_state(hw) & FW2X_CAP_TEMPERATURE) !=
486 	    req_bit, 1, 10000);
487 	if (err == 0)
488 		err = aq_hw_fw_downld_dwords(hw, hw->mbox_addr +
489 		    offsetof(struct aq_fw2x_mailbox, phy_temperature),
490 		    &raw, 1);
491 	mtx_unlock(&hw->fw_mtx);
492 
493 	if (err != 0) {
494 		trace_error(hw, dbg_fw,
495 		    "fw2x> temperature read FAILED, error %d", err);
496 		return (err);
497 	}
498 
499 	/* F/W reports 1/256 degree Celsius. */
500 	*temp_mc = (int)(int16_t)(raw & 0xffff) * 1000 / 256;
501 
502 	return (0);
503 }
504 
505 static int
aq_fw2x_get_phy_fault(struct aq_hw * hw,uint16_t * fault)506 aq_fw2x_get_phy_fault(struct aq_hw* hw, uint16_t* fault)
507 {
508 	uint32_t raw;
509 	int err;
510 
511 	mtx_lock(&hw->fw_mtx);
512 	err = aq_hw_fw_downld_dwords(hw, hw->mbox_addr +
513 	    offsetof(struct aq_fw2x_mailbox, phy_h_bit), &raw, 1);
514 	mtx_unlock(&hw->fw_mtx);
515 
516 	if (err != 0)
517 		return (err);
518 
519 	*fault = (uint16_t)(raw >> 16);
520 
521 	return (0);
522 }
523 
524 /* PHY MDIO access: MMD register read/write via the MAC's MDIO controller. */
525 #define AQ_MDIO_IFACE(n)	(0x280 + (((n) - 1) * 4))
526 #define AQ_MDIO_BUSY		0x80000000u	/* iface2 bit 31 */
527 #define AQ_MDIO_EXECUTE		0x00008000u	/* iface2 bit 15 */
528 #define AQ_MDIO_OP_S		12		/* iface2 bits 13:12 */
529 #define AQ_MDIO_OP_ADDR		3
530 #define AQ_MDIO_OP_READ		1
531 #define AQ_MDIO_OP_WRITE	2
532 #define AQ_MDIO_PHYADDR_MSK	0x3ffu
533 #define AQ_FW_SM_MDIO		0		/* cpu semaphore index */
534 
535 #define AQ_PHY_ID_MAX		32		/* MDIO port addresses to scan */
536 #define AQ_MDIO_MMD_PMAPMD	0x01		/* PMA/PMD MMD */
537 #define AQ_PHY_ID2_REG		0x0003		/* PMA/PMD Device Identifier 2 */
538 
539 #define AQ_PHY_MMD_GLOBAL	0x1e
540 #define AQ_PHY_RESET_REG	0x2681		/* 1E.2681.0 = PHY hard reset */
541 #define  AQ_PHY_RESET		0x0001
542 #define AQ_PHY_THERMAL_CTRL_REG	0xc478		/* 1E.C478 thermal control */
543 #define  AQ_PHY_THERMAL_SD_EN	0x0400		/* .A thermalShutdownEnable */
544 
545 static int
aq_fw2x_mdio_op(struct aq_hw * hw,uint16_t mmd,uint16_t addr,int write,uint16_t data,uint16_t * val)546 aq_fw2x_mdio_op(struct aq_hw* hw, uint16_t mmd, uint16_t addr, int write,
547     uint16_t data, uint16_t* val)
548 {
549 	uint32_t pa = (((uint32_t)hw->phy_id & 0x1f) << 5) | (mmd & 0x1f);
550 	int err;
551 
552 	AQ_WRITE_REG(hw, AQ_MDIO_IFACE(4), addr);
553 	AQ_WRITE_REG(hw, AQ_MDIO_IFACE(2),
554 	    AQ_MDIO_EXECUTE | (AQ_MDIO_OP_ADDR << AQ_MDIO_OP_S) | pa);
555 	err = AQ_HW_WAIT_FOR((AQ_READ_REG(hw, AQ_MDIO_IFACE(2)) &
556 	    AQ_MDIO_BUSY) == 0, 10, 10000);
557 	if (err != 0)
558 		return (err);
559 	if (write) {
560 		AQ_WRITE_REG(hw, AQ_MDIO_IFACE(3), data);
561 		AQ_WRITE_REG(hw, AQ_MDIO_IFACE(2),
562 		    AQ_MDIO_EXECUTE | (AQ_MDIO_OP_WRITE << AQ_MDIO_OP_S) | pa);
563 	} else {
564 		AQ_WRITE_REG(hw, AQ_MDIO_IFACE(2),
565 		    AQ_MDIO_EXECUTE | (AQ_MDIO_OP_READ << AQ_MDIO_OP_S) | pa);
566 	}
567 	err = AQ_HW_WAIT_FOR((AQ_READ_REG(hw, AQ_MDIO_IFACE(2)) &
568 	    AQ_MDIO_BUSY) == 0, 10, 10000);
569 	if (err != 0)
570 		return (err);
571 	if (val != NULL)
572 		*val = (uint16_t)AQ_READ_REG(hw, AQ_MDIO_IFACE(5));
573 
574 	return (0);
575 }
576 
577 /* MDIO is serialized against the F/W by cpu semaphore 0. */
578 static int
aq_fw2x_phy_write(struct aq_hw * hw,uint16_t mmd,uint16_t addr,uint16_t data)579 aq_fw2x_phy_write(struct aq_hw* hw, uint16_t mmd, uint16_t addr, uint16_t data)
580 {
581 	int err;
582 
583 	err = AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(hw, AQ_FW_SM_MDIO) == 1U,
584 	    10, 10000);
585 	if (err != 0)
586 		return (err);
587 	err = aq_fw2x_mdio_op(hw, mmd, addr, 1, data, NULL);
588 	reg_glb_cpu_sem_set(hw, 1U, AQ_FW_SM_MDIO);
589 
590 	return (err);
591 }
592 
593 static int
aq_fw2x_phy_read(struct aq_hw * hw,uint16_t mmd,uint16_t addr,uint16_t * val)594 aq_fw2x_phy_read(struct aq_hw* hw, uint16_t mmd, uint16_t addr, uint16_t* val)
595 {
596 	int err;
597 
598 	err = AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(hw, AQ_FW_SM_MDIO) == 1U,
599 	    10, 10000);
600 	if (err != 0)
601 		return (err);
602 	err = aq_fw2x_mdio_op(hw, mmd, addr, 0, 0, val);
603 	reg_glb_cpu_sem_set(hw, 1U, AQ_FW_SM_MDIO);
604 
605 	return (err);
606 }
607 
608 /* Discover the PHY's MDIO port address; it is strap-selectable, not fixed at 0. */
609 static bool
aq_fw2x_init_phy_id(struct aq_hw * hw)610 aq_fw2x_init_phy_id(struct aq_hw* hw)
611 {
612 	uint16_t val;
613 	uint8_t id;
614 	int err;
615 
616 	for (id = 0; id < AQ_PHY_ID_MAX; id++) {
617 		hw->phy_id = id;
618 		err = aq_fw2x_phy_read(hw, AQ_MDIO_MMD_PMAPMD, AQ_PHY_ID2_REG,
619 		    &val);
620 		if (err == 0 && val != 0xffff)
621 			return (true);
622 		/* A timeout means the controller is wedged, not this port. */
623 		if (err == ETIMEDOUT)
624 			break;
625 	}
626 	hw->phy_id = 0;
627 	return (false);
628 }
629 
630 /* Called with fw_mtx held; the port address is needed by every MDIO caller. */
631 static void
aq_fw2x_phy_id_probe(struct aq_hw * hw)632 aq_fw2x_phy_id_probe(struct aq_hw* hw)
633 {
634 	if (!hw->phy_id_valid && aq_fw2x_init_phy_id(hw))
635 		hw->phy_id_valid = true;
636 }
637 
638 /* PHY hard reset (1E.2681.0): clears a latched thermal shutdown a MAC reset cannot. */
639 static int
aq_fw2x_phy_reset(struct aq_hw * hw)640 aq_fw2x_phy_reset(struct aq_hw* hw)
641 {
642 	int err;
643 
644 	mtx_lock(&hw->fw_mtx);
645 	aq_fw2x_phy_id_probe(hw);
646 	err = aq_fw2x_phy_write(hw, AQ_PHY_MMD_GLOBAL, AQ_PHY_RESET_REG,
647 	    AQ_PHY_RESET);
648 	mtx_unlock(&hw->fw_mtx);
649 
650 	return (err);
651 }
652 
653 /* Arm autonomous thermal shutdown (1E.C478.A), cleared by any PHY reset. */
654 static int
aq_fw2x_thermal_arm(struct aq_hw * hw)655 aq_fw2x_thermal_arm(struct aq_hw* hw)
656 {
657 	uint16_t ctrl;
658 	int err;
659 
660 	if ((hw->fw_caps & FW2X_CAP_TEMPERATURE) == 0)
661 		return (ENOTSUP);
662 
663 	mtx_lock(&hw->fw_mtx);
664 	aq_fw2x_phy_id_probe(hw);
665 	err = aq_fw2x_phy_read(hw, AQ_PHY_MMD_GLOBAL, AQ_PHY_THERMAL_CTRL_REG,
666 	    &ctrl);
667 	if (err == 0 && ctrl == 0xffff)
668 		err = ENXIO;
669 	if (err == 0 && (ctrl & AQ_PHY_THERMAL_SD_EN) == 0)
670 		err = aq_fw2x_phy_write(hw, AQ_PHY_MMD_GLOBAL,
671 		    AQ_PHY_THERMAL_CTRL_REG, ctrl | AQ_PHY_THERMAL_SD_EN);
672 	mtx_unlock(&hw->fw_mtx);
673 
674 	return (err);
675 }
676 
677 /* 1E.C421 high-temp shutdown threshold, degrees C in Q8.8 fixed point. */
678 #define AQ_PHY_THERMAL_HIGH_REG	0xc421
679 static int
aq_fw2x_get_thermal_limit(struct aq_hw * hw,int * limit_mc)680 aq_fw2x_get_thermal_limit(struct aq_hw* hw, int* limit_mc)
681 {
682 	uint16_t raw;
683 	int err;
684 
685 	mtx_lock(&hw->fw_mtx);
686 	aq_fw2x_phy_id_probe(hw);
687 	err = aq_fw2x_phy_read(hw, AQ_PHY_MMD_GLOBAL, AQ_PHY_THERMAL_HIGH_REG,
688 	    &raw);
689 	mtx_unlock(&hw->fw_mtx);
690 	if (err != 0 || raw == 0 || raw == 0xffff)
691 		return (ENXIO);
692 	*limit_mc = (int)(int16_t)raw * 1000 / 256;
693 
694 	return (0);
695 }
696 
697 static int
aq_fw2x_led_control(struct aq_hw * hw,uint32_t onoff)698 aq_fw2x_led_control(struct aq_hw* hw, uint32_t onoff)
699 {
700 	int err = 0;
701 
702 	AQ_DBG_ENTER();
703 
704 	struct aq_hw_fw_version ver_expected = { .raw = FW2X_FW_MIN_VER_LED};
705 	if (aq_hw_ver_match(&ver_expected, &hw->fw_version))
706 		AQ_WRITE_REG(hw, FW2X_MPI_LED_ADDR,
707 		    (onoff) ? ((FW2X_LED_BLINK) | (FW2X_LED_BLINK << 2) | (FW2X_LED_BLINK << 4)):
708 		    (FW2X_LED_DEFAULT));
709 
710 	AQ_DBG_EXIT(err);
711 	return (err);
712 }
713 
714 const struct aq_firmware_ops aq_fw2x_ops =
715 {
716 	.reset = aq_fw2x_reset,
717 
718 	.set_mode = aq_fw2x_set_mode,
719 	.get_mode = aq_fw2x_get_mode,
720 
721 	.get_mac_addr = aq_fw2x_get_mac_addr,
722 	.get_stats = aq_fw2x_get_stats,
723 	.get_temp = aq_fw2x_get_temp,
724 	.get_phy_fault = aq_fw2x_get_phy_fault,
725 	.phy_reset = aq_fw2x_phy_reset,
726 	.thermal_arm = aq_fw2x_thermal_arm,
727 	.get_thermal_limit = aq_fw2x_get_thermal_limit,
728 
729 	.led_control = aq_fw2x_led_control,
730 };
731