1/**************************************************************************
2
3Copyright (c) 2009 Chelsio Inc.
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
8
9 1. Redistributions of source code must retain the above copyright notice,
10    this list of conditions and the following disclaimer.
11
12 2. Neither the name of the Chelsio Corporation nor the names of its
13    contributors may be used to endorse or promote products derived from
14    this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26POSSIBILITY OF SUCH DAMAGE.
27
28***************************************************************************/
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32
33#include <cxgb_include.h>
34
35#undef msleep
36#define msleep t3_os_sleep
37
38enum {
39	/* MDIO_DEV_PMA_PMD registers */
40	AQ_LINK_STAT	= 0xe800,
41
42	/* MDIO_DEV_XGXS registers */
43	AQ_XAUI_RX_CFG	= 0xc400,
44	AQ_XAUI_KX_CFG	= 0xc440,
45	AQ_XAUI_TX_CFG	= 0xe400,
46
47	/* MDIO_DEV_ANEG registers */
48	AQ_100M_CTRL	= 0x0010,
49	AQ_10G_CTRL	= 0x0020,
50	AQ_1G_CTRL	= 0xc400,
51	AQ_ANEG_STAT	= 0xc800,
52
53	/* MDIO_DEV_VEND1 registers */
54	AQ_FW_VERSION	= 0x0020,
55	AQ_THERMAL_THR	= 0xc421,
56	AQ_THERMAL1	= 0xc820,
57	AQ_THERMAL2	= 0xc821,
58	AQ_IFLAG_GLOBAL	= 0xfc00,
59	AQ_IMASK_GLOBAL	= 0xff00,
60};
61
62#define AQBIT(x)	(1 << (0x##x))
63#define ADV_1G_FULL	AQBIT(f)
64#define ADV_1G_HALF	AQBIT(e)
65#define ADV_10G_FULL	AQBIT(c)
66
67#define AQ_WRITE_REGS(phy, regs) do { \
68	int i; \
69	for (i = 0; i < ARRAY_SIZE(regs); i++) { \
70		(void) mdio_write(phy, regs[i].mmd, regs[i].reg, regs[i].val); \
71	} \
72} while (0)
73#define AQ_READ_REGS(phy, regs) do { \
74	unsigned i, v; \
75	for (i = 0; i < ARRAY_SIZE(regs); i++) { \
76		(void) mdio_read(phy, regs[i].mmd, regs[i].reg, &v); \
77	} \
78} while (0)
79
80/*
81 * Return value is temperature in celcius, 0xffff for error or don't know.
82 */
83static int
84aq100x_temperature(struct cphy *phy)
85{
86	unsigned int v;
87
88	if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL2, &v) ||
89	    v == 0xffff || (v & 1) != 1)
90		return (0xffff);
91
92	if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL1, &v))
93		return (0xffff);
94
95	return ((int)((signed char)(v >> 8)));
96}
97
98static int
99aq100x_set_defaults(struct cphy *phy)
100{
101	return mdio_write(phy, MDIO_DEV_VEND1, AQ_THERMAL_THR, 0x6c00);
102}
103
104static int
105aq100x_reset(struct cphy *phy, int wait)
106{
107	int err;
108	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
109	if (!err)
110		err = aq100x_set_defaults(phy);
111	return (err);
112}
113
114static int
115aq100x_intr_enable(struct cphy *phy)
116{
117	struct {
118		int mmd;
119		int reg;
120		int val;
121	} imasks[] = {
122		{MDIO_DEV_VEND1, 0xd400, AQBIT(e)},
123		{MDIO_DEV_VEND1, 0xff01, AQBIT(2)},
124		{MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, AQBIT(0)}
125	};
126
127	AQ_WRITE_REGS(phy, imasks);
128
129	return (0);
130}
131
132static int
133aq100x_intr_disable(struct cphy *phy)
134{
135	struct {
136		int mmd;
137		int reg;
138		int val;
139	} imasks[] = {
140		{MDIO_DEV_VEND1, 0xd400, 0},
141		{MDIO_DEV_VEND1, 0xff01, 0},
142		{MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, 0}
143	};
144
145	AQ_WRITE_REGS(phy, imasks);
146
147	return (0);
148}
149
150static int
151aq100x_intr_clear(struct cphy *phy)
152{
153	struct {
154		int mmd;
155		int reg;
156	} iclr[] = {
157		{MDIO_DEV_VEND1, 0xcc00},
158		{MDIO_DEV_VEND1, AQ_IMASK_GLOBAL} /* needed? */
159	};
160
161	AQ_READ_REGS(phy, iclr);
162
163	return (0);
164}
165
166static int
167aq100x_vendor_intr(struct cphy *phy, int *rc)
168{
169	int err;
170	unsigned int cause, v;
171
172	err = mdio_read(phy, MDIO_DEV_VEND1, 0xfc01, &cause);
173	if (err)
174		return (err);
175
176	if (cause & AQBIT(2)) {
177		err = mdio_read(phy, MDIO_DEV_VEND1, 0xcc00, &v);
178		if (err)
179			return (err);
180
181		if (v & AQBIT(e)) {
182			CH_WARN(phy->adapter, "PHY%d: temperature is now %dC\n",
183			    phy->addr, aq100x_temperature(phy));
184
185			t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
186			    phy->addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL, 0);
187
188			*rc |= cphy_cause_alarm;
189		}
190
191		cause &= ~4;
192	}
193
194	if (cause)
195		CH_WARN(phy->adapter, "PHY%d: unhandled vendor interrupt"
196		    " (0x%x)\n", phy->addr, cause);
197
198	return (0);
199
200}
201
202static int
203aq100x_intr_handler(struct cphy *phy)
204{
205	int err, rc = 0;
206	unsigned int cause;
207
208	err = mdio_read(phy, MDIO_DEV_VEND1, AQ_IFLAG_GLOBAL, &cause);
209	if (err)
210		return (err);
211
212	if (cause & AQBIT(0)) {
213		err = aq100x_vendor_intr(phy, &rc);
214		if (err)
215			return (err);
216		cause &= ~AQBIT(0);
217	}
218
219	if (cause)
220		CH_WARN(phy->adapter, "PHY%d: unhandled interrupt (0x%x)\n",
221		    phy->addr, cause);
222
223	return (rc);
224}
225
226static int
227aq100x_power_down(struct cphy *phy, int off)
228{
229	int err, wait = 500;
230	unsigned int v;
231
232	err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, BMCR_PDOWN,
233	    off ? BMCR_PDOWN : 0);
234	if (err || off)
235		return (err);
236
237	msleep(300);
238	do {
239		err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
240		if (err)
241			return (err);
242		v &= BMCR_RESET;
243		if (v)
244			msleep(10);
245	} while (v && --wait);
246	if (v) {
247		CH_WARN(phy->adapter, "PHY%d: power-up timed out (0x%x).\n",
248		    phy->addr, v);
249		return (ETIMEDOUT);
250	}
251
252	return (0);
253}
254
255static int
256aq100x_autoneg_enable(struct cphy *phy)
257{
258	int err;
259
260	err = aq100x_power_down(phy, 0);
261	if (!err)
262		err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
263		    BMCR_RESET, BMCR_ANENABLE | BMCR_ANRESTART);
264
265	return (err);
266}
267
268static int
269aq100x_autoneg_restart(struct cphy *phy)
270{
271	return aq100x_autoneg_enable(phy);
272}
273
274static int
275aq100x_advertise(struct cphy *phy, unsigned int advertise_map)
276{
277	unsigned int adv;
278	int err;
279
280	/* 10G advertisement */
281	adv = 0;
282	if (advertise_map & ADVERTISED_10000baseT_Full)
283		adv |= ADV_10G_FULL;
284	err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_10G_CTRL,
285				  ADV_10G_FULL, adv);
286	if (err)
287		return (err);
288
289	/* 1G advertisement */
290	adv = 0;
291	if (advertise_map & ADVERTISED_1000baseT_Full)
292		adv |= ADV_1G_FULL;
293	if (advertise_map & ADVERTISED_1000baseT_Half)
294		adv |= ADV_1G_HALF;
295	err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_1G_CTRL,
296				  ADV_1G_FULL | ADV_1G_HALF, adv);
297	if (err)
298		return (err);
299
300	/* 100M, pause advertisement */
301	adv = 0;
302	if (advertise_map & ADVERTISED_100baseT_Half)
303		adv |= ADVERTISE_100HALF;
304	if (advertise_map & ADVERTISED_100baseT_Full)
305		adv |= ADVERTISE_100FULL;
306	if (advertise_map & ADVERTISED_Pause)
307		adv |= ADVERTISE_PAUSE_CAP;
308	if (advertise_map & ADVERTISED_Asym_Pause)
309		adv |= ADVERTISE_PAUSE_ASYM;
310	err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_100M_CTRL, 0xfe0, adv);
311
312	return (err);
313}
314
315static int
316aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable)
317{
318	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
319				   BMCR_LOOPBACK, enable ? BMCR_LOOPBACK : 0);
320}
321
322static int
323aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex)
324{
325	int err, set;
326
327	if (speed == SPEED_100)
328		set = BMCR_SPEED100;
329	else if (speed == SPEED_1000)
330		set = BMCR_SPEED1000;
331	else if (speed == SPEED_10000)
332		set = BMCR_SPEED1000 | BMCR_SPEED100;
333	else
334		return (EINVAL);
335
336	if (duplex != DUPLEX_FULL)
337		return (EINVAL);
338
339	err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
340	    BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART, 0);
341	if (err)
342		return (err);
343
344	err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
345	    BMCR_SPEED1000 | BMCR_SPEED100, set);
346	if (err)
347		return (err);
348
349	return (0);
350}
351
352static int
353aq100x_get_link_status(struct cphy *phy, int *link_ok, int *speed, int *duplex,
354		       int *fc)
355{
356	int err;
357	unsigned int v, link = 0;
358
359	err = mdio_read(phy, MDIO_DEV_PMA_PMD, AQ_LINK_STAT, &v);
360	if (err)
361		return (err);
362	if (v == 0xffff || !(v & 1))
363		goto done;
364
365	err = mdio_read(phy, MDIO_DEV_ANEG, MII_BMCR, &v);
366	if (err)
367		return (err);
368	if (v & 0x8000)
369		goto done;
370	if (v & BMCR_ANENABLE) {
371
372		err = mdio_read(phy, MDIO_DEV_ANEG, 1, &v);
373		if (err)
374			return (err);
375		if ((v & 0x20) == 0)
376			goto done;
377
378		err = mdio_read(phy, MDIO_DEV_ANEG, AQ_ANEG_STAT, &v);
379		if (err)
380			return (err);
381
382		if (speed) {
383			switch (v & 0x6) {
384			case 0x6: *speed = SPEED_10000;
385				break;
386			case 0x4: *speed = SPEED_1000;
387				break;
388			case 0x2: *speed = SPEED_100;
389				break;
390			case 0x0: *speed = SPEED_10;
391				break;
392			}
393		}
394
395		if (duplex)
396			*duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF;
397
398		if (fc) {
399			unsigned int lpa, adv;
400			err = mdio_read(phy, MDIO_DEV_ANEG, 0x13, &lpa);
401			if (!err)
402				err = mdio_read(phy, MDIO_DEV_ANEG,
403				    AQ_100M_CTRL, &adv);
404			if (err)
405				return err;
406
407			if (lpa & adv & ADVERTISE_PAUSE_CAP)
408				*fc = PAUSE_RX | PAUSE_TX;
409			else if (lpa & ADVERTISE_PAUSE_CAP &&
410			    lpa & ADVERTISE_PAUSE_ASYM &&
411			    adv & ADVERTISE_PAUSE_ASYM)
412				*fc = PAUSE_TX;
413			else if (lpa & ADVERTISE_PAUSE_ASYM &&
414			    adv & ADVERTISE_PAUSE_CAP)
415				*fc = PAUSE_RX;
416			else
417				*fc = 0;
418		}
419
420	} else {
421		err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
422		if (err)
423			return (err);
424
425		v &= BMCR_SPEED1000 | BMCR_SPEED100;
426		if (speed) {
427			if (v == (BMCR_SPEED1000 | BMCR_SPEED100))
428				*speed = SPEED_10000;
429			else if (v == BMCR_SPEED1000)
430				*speed = SPEED_1000;
431			else if (v == BMCR_SPEED100)
432				*speed = SPEED_100;
433			else
434				*speed = SPEED_10;
435		}
436
437		if (duplex)
438			*duplex = DUPLEX_FULL;
439	}
440
441	link = 1;
442done:
443	if (link_ok)
444		*link_ok = link;
445	return (0);
446}
447
448static struct cphy_ops aq100x_ops = {
449	.reset             = aq100x_reset,
450	.intr_enable       = aq100x_intr_enable,
451	.intr_disable      = aq100x_intr_disable,
452	.intr_clear        = aq100x_intr_clear,
453	.intr_handler      = aq100x_intr_handler,
454	.autoneg_enable    = aq100x_autoneg_enable,
455	.autoneg_restart   = aq100x_autoneg_restart,
456	.advertise         = aq100x_advertise,
457	.set_loopback      = aq100x_set_loopback,
458	.set_speed_duplex  = aq100x_set_speed_duplex,
459	.get_link_status   = aq100x_get_link_status,
460	.power_down        = aq100x_power_down,
461};
462
463int
464t3_aq100x_phy_prep(pinfo_t *pinfo, int phy_addr,
465		       const struct mdio_ops *mdio_ops)
466{
467	struct cphy *phy = &pinfo->phy;
468	unsigned int v, v2, gpio, wait;
469	int err;
470	adapter_t *adapter = pinfo->adapter;
471
472	cphy_init(&pinfo->phy, adapter, pinfo, phy_addr, &aq100x_ops, mdio_ops,
473		  SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
474		  SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI |
475		  SUPPORTED_MISC_IRQ, "1000/10GBASE-T");
476
477	/*
478	 * Hard reset the PHY.
479	 */
480	gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
481	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
482	msleep(1);
483	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);
484
485	/*
486	 * Give it enough time to load the firmware and get ready for mdio.
487	 */
488	msleep(1000);
489	wait = 500; /* in 10ms increments */
490	do {
491		err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
492		if (err || v == 0xffff) {
493
494			/* Allow prep_adapter to succeed when ffff is read */
495
496			CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
497				phy_addr, err, v);
498			goto done;
499		}
500
501		v &= BMCR_RESET;
502		if (v)
503			msleep(10);
504	} while (v && --wait);
505	if (v) {
506		CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
507			phy_addr, v);
508
509		goto done; /* let prep_adapter succeed */
510	}
511
512	/* Firmware version check. */
513	(void) mdio_read(phy, MDIO_DEV_VEND1, AQ_FW_VERSION, &v);
514	if (v < 0x115)
515		CH_WARN(adapter, "PHY%d: unknown firmware %d.%d\n", phy_addr,
516		    v >> 8, v & 0xff);
517
518	/* The PHY should start in really-low-power mode. */
519	(void) mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
520	if ((v & BMCR_PDOWN) == 0)
521		CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
522			phy_addr);
523
524	/*
525	 * Verify XAUI and 1000-X settings, but let prep succeed no matter what.
526	 */
527	v = v2 = 0;
528	(void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_RX_CFG, &v);
529	(void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_TX_CFG, &v2);
530	if (v != 0x1b || v2 != 0x1b)
531		CH_WARN(adapter, "PHY%d: incorrect XAUI settings "
532		    "(0x%x, 0x%x).\n", phy_addr, v, v2);
533	v = 0;
534	(void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_KX_CFG, &v);
535	if ((v & 0xf) != 0xf)
536		CH_WARN(adapter, "PHY%d: incorrect 1000-X settings "
537		    "(0x%x).\n", phy_addr, v);
538
539	(void) aq100x_set_defaults(phy);
540done:
541	return (err);
542}
543