2
* Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
4
* This software is available to you under a choice of one of two
5
* licenses. You may choose to be licensed under the terms of the GNU
6
* General Public License (GPL) Version 2, available from the file
7
* COPYING in the main directory of this source tree, or the
8
* OpenIB.org BSD license below:
10
* Redistribution and use in source and binary forms, with or
11
* without modification, are permitted provided that the following
14
* - Redistributions of source code must retain the above
15
* copyright notice, this list of conditions and the following
18
* - Redistributions in binary form must reproduce the above
19
* copyright notice, this list of conditions and the following
20
* disclaimer in the documentation and/or other materials
21
* provided with the distribution.
23
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36
AEL100X_TX_CONFIG1 = 0xc002,
37
AEL1002_PWR_DOWN_HI = 0xc011,
38
AEL1002_PWR_DOWN_LO = 0xc012,
39
AEL1002_XFI_EQL = 0xc015,
40
AEL1002_LB_EN = 0xc017,
41
AEL_OPT_SETTINGS = 0xc017,
42
AEL_I2C_CTRL = 0xc30a,
43
AEL_I2C_DATA = 0xc30b,
44
AEL_I2C_STAT = 0xc30c,
45
AEL2005_GPIO_CTRL = 0xc214,
46
AEL2005_GPIO_STAT = 0xc215,
48
AEL2020_GPIO_INTR = 0xc103, /* Latch High (LH) */
49
AEL2020_GPIO_CTRL = 0xc108, /* Store Clear (SC) */
50
AEL2020_GPIO_STAT = 0xc10c, /* Read Only (RO) */
51
AEL2020_GPIO_CFG = 0xc110, /* Read Write (RW) */
53
AEL2020_GPIO_SDA = 0, /* IN: i2c serial data */
54
AEL2020_GPIO_MODDET = 1, /* IN: Module Detect */
55
AEL2020_GPIO_0 = 3, /* IN: unassigned */
56
AEL2020_GPIO_1 = 2, /* OUT: unassigned */
57
AEL2020_GPIO_LSTAT = AEL2020_GPIO_1, /* wired to link status LED */
60
enum { edc_none, edc_sr, edc_twinax };
62
/* PHY module I2C device address */
64
MODULE_DEV_ADDR = 0xa0,
68
/* PHY transceiver type */
70
phy_transtype_unknown = 0,
71
phy_transtype_sfp = 3,
72
phy_transtype_xfp = 6,
75
#define AEL2005_MODDET_IRQ 4
78
unsigned short mmd_addr;
79
unsigned short reg_addr;
80
unsigned short clear_bits;
81
unsigned short set_bits;
84
static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
88
for (err = 0; rv->mmd_addr && !err; rv++) {
89
if (rv->clear_bits == 0xffff)
90
err = t3_mdio_write(phy, rv->mmd_addr, rv->reg_addr,
93
err = t3_mdio_change_bits(phy, rv->mmd_addr,
94
rv->reg_addr, rv->clear_bits,
100
static void ael100x_txon(struct cphy *phy)
103
phy->mdio.prtad == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
106
t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
111
* Read an 8-bit word from a device attached to the PHY's i2c bus.
113
static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
116
unsigned int stat, data;
118
err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL_I2C_CTRL,
119
(dev_addr << 8) | (1 << 8) | word_addr);
123
for (i = 0; i < 200; i++) {
125
err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_STAT, &stat);
128
if ((stat & 3) == 1) {
129
err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_DATA,
136
CH_WARN(phy->adapter, "PHY %u i2c read of dev.addr %#x.%#x timed out\n",
137
phy->mdio.prtad, dev_addr, word_addr);
141
static int ael1002_power_down(struct cphy *phy, int enable)
145
err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, !!enable);
147
err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
148
MDIO_MMD_PMAPMD, MDIO_CTRL1,
149
MDIO_CTRL1_LPOWER, enable);
153
static int ael1002_reset(struct cphy *phy, int wait)
157
if ((err = ael1002_power_down(phy, 0)) ||
158
(err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL100X_TX_CONFIG1, 1)) ||
159
(err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_HI, 0)) ||
160
(err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_LO, 0)) ||
161
(err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_XFI_EQL, 0x18)) ||
162
(err = t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL1002_LB_EN,
168
static int ael1002_intr_noop(struct cphy *phy)
174
* Get link status for a 10GBASE-R device.
176
static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
177
int *duplex, int *fc)
180
unsigned int stat0, stat1, stat2;
181
int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
182
MDIO_PMA_RXDET, &stat0);
185
err = t3_mdio_read(phy, MDIO_MMD_PCS,
186
MDIO_PCS_10GBRT_STAT1, &stat1);
188
err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
189
MDIO_PHYXS_LNSTAT, &stat2);
192
*link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
195
*speed = SPEED_10000;
197
*duplex = DUPLEX_FULL;
201
static struct cphy_ops ael1002_ops = {
202
.reset = ael1002_reset,
203
.intr_enable = ael1002_intr_noop,
204
.intr_disable = ael1002_intr_noop,
205
.intr_clear = ael1002_intr_noop,
206
.intr_handler = ael1002_intr_noop,
207
.get_link_status = get_link_status_r,
208
.power_down = ael1002_power_down,
209
.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
212
int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
213
int phy_addr, const struct mdio_ops *mdio_ops)
215
cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
216
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
222
static int ael1006_reset(struct cphy *phy, int wait)
224
return t3_phy_reset(phy, MDIO_MMD_PMAPMD, wait);
227
static struct cphy_ops ael1006_ops = {
228
.reset = ael1006_reset,
229
.intr_enable = t3_phy_lasi_intr_enable,
230
.intr_disable = t3_phy_lasi_intr_disable,
231
.intr_clear = t3_phy_lasi_intr_clear,
232
.intr_handler = t3_phy_lasi_intr_handler,
233
.get_link_status = get_link_status_r,
234
.power_down = ael1002_power_down,
235
.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
238
int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
239
int phy_addr, const struct mdio_ops *mdio_ops)
241
cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
242
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
249
* Decode our module type.
251
static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms)
258
/* see SFF-8472 for below */
259
v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
264
return phy_modtype_sr;
266
return phy_modtype_lr;
268
return phy_modtype_lrm;
270
v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
276
v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
281
v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
284
return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax;
287
return phy_modtype_unknown;
291
* Code to support the Aeluros/NetLogic 2005 10Gb PHY.
293
static int ael2005_setup_sr_edc(struct cphy *phy)
295
static const struct reg_val regs[] = {
296
{ MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 },
297
{ MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a },
298
{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 },
304
err = set_phy_regs(phy, regs);
310
if (phy->priv != edc_sr)
311
err = t3_get_edc_fw(phy, EDC_OPT_AEL2005,
312
EDC_OPT_AEL2005_SIZE);
316
for (i = 0; i < EDC_OPT_AEL2005_SIZE / sizeof(u16) && !err; i += 2)
317
err = t3_mdio_write(phy, MDIO_MMD_PMAPMD,
319
phy->phy_cache[i + 1]);
325
static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
327
static const struct reg_val regs[] = {
328
{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 },
331
static const struct reg_val preemphasis[] = {
332
{ MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 },
333
{ MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 },
338
err = set_phy_regs(phy, regs);
339
if (!err && modtype == phy_modtype_twinax_long)
340
err = set_phy_regs(phy, preemphasis);
346
if (phy->priv != edc_twinax)
347
err = t3_get_edc_fw(phy, EDC_TWX_AEL2005,
348
EDC_TWX_AEL2005_SIZE);
352
for (i = 0; i < EDC_TWX_AEL2005_SIZE / sizeof(u16) && !err; i += 2)
353
err = t3_mdio_write(phy, MDIO_MMD_PMAPMD,
355
phy->phy_cache[i + 1]);
357
phy->priv = edc_twinax;
361
static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
366
v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, &stat);
370
if (stat & (1 << 8)) /* module absent */
371
return phy_modtype_none;
373
return ael2xxx_get_module_type(phy, delay_ms);
376
static int ael2005_intr_enable(struct cphy *phy)
378
int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x200);
379
return err ? err : t3_phy_lasi_intr_enable(phy);
382
static int ael2005_intr_disable(struct cphy *phy)
384
int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x100);
385
return err ? err : t3_phy_lasi_intr_disable(phy);
388
static int ael2005_intr_clear(struct cphy *phy)
390
int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0xd00);
391
return err ? err : t3_phy_lasi_intr_clear(phy);
394
static int ael2005_reset(struct cphy *phy, int wait)
396
static const struct reg_val regs0[] = {
397
{ MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 },
398
{ MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 },
399
{ MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 },
400
{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
401
{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8100 },
402
{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
403
{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 },
406
static const struct reg_val regs1[] = {
407
{ MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 },
408
{ MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 },
413
unsigned int lasi_ctrl;
415
err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
420
err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 0);
425
phy->priv = edc_none;
426
err = set_phy_regs(phy, regs0);
432
err = ael2005_get_module_type(phy, 0);
437
if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
438
err = ael2005_setup_twinax_edc(phy, err);
440
err = ael2005_setup_sr_edc(phy);
444
err = set_phy_regs(phy, regs1);
448
/* reset wipes out interrupts, reenable them if they were on */
450
err = ael2005_intr_enable(phy);
454
static int ael2005_intr_handler(struct cphy *phy)
457
int ret, edc_needed, cause = 0;
459
ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_STAT, &stat);
463
if (stat & AEL2005_MODDET_IRQ) {
464
ret = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL,
469
/* modules have max 300 ms init time after hot plug */
470
ret = ael2005_get_module_type(phy, 300);
475
if (ret == phy_modtype_none)
476
edc_needed = phy->priv; /* on unplug retain EDC */
477
else if (ret == phy_modtype_twinax ||
478
ret == phy_modtype_twinax_long)
479
edc_needed = edc_twinax;
483
if (edc_needed != phy->priv) {
484
ret = ael2005_reset(phy, 0);
485
return ret ? ret : cphy_cause_module_change;
487
cause = cphy_cause_module_change;
490
ret = t3_phy_lasi_intr_handler(phy);
495
return ret ? ret : cphy_cause_link_change;
498
static struct cphy_ops ael2005_ops = {
499
.reset = ael2005_reset,
500
.intr_enable = ael2005_intr_enable,
501
.intr_disable = ael2005_intr_disable,
502
.intr_clear = ael2005_intr_clear,
503
.intr_handler = ael2005_intr_handler,
504
.get_link_status = get_link_status_r,
505
.power_down = ael1002_power_down,
506
.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
509
int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
510
int phy_addr, const struct mdio_ops *mdio_ops)
512
cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
513
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
514
SUPPORTED_IRQ, "10GBASE-R");
516
return t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, 0,
521
* Setup EDC and other parameters for operation with an optical module.
523
static int ael2020_setup_sr_edc(struct cphy *phy)
525
static const struct reg_val regs[] = {
526
/* set CDR offset to 10 */
527
{ MDIO_MMD_PMAPMD, 0xcc01, 0xffff, 0x488a },
529
/* adjust 10G RX bias current */
530
{ MDIO_MMD_PMAPMD, 0xcb1b, 0xffff, 0x0200 },
531
{ MDIO_MMD_PMAPMD, 0xcb1c, 0xffff, 0x00f0 },
532
{ MDIO_MMD_PMAPMD, 0xcc06, 0xffff, 0x00e0 },
539
err = set_phy_regs(phy, regs);
549
* Setup EDC and other parameters for operation with an TWINAX module.
551
static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
553
/* set uC to 40MHz */
554
static const struct reg_val uCclock40MHz[] = {
555
{ MDIO_MMD_PMAPMD, 0xff28, 0xffff, 0x4001 },
556
{ MDIO_MMD_PMAPMD, 0xff2a, 0xffff, 0x0002 },
560
/* activate uC clock */
561
static const struct reg_val uCclockActivate[] = {
562
{ MDIO_MMD_PMAPMD, 0xd000, 0xffff, 0x5200 },
566
/* set PC to start of SRAM and activate uC */
567
static const struct reg_val uCactivate[] = {
568
{ MDIO_MMD_PMAPMD, 0xd080, 0xffff, 0x0100 },
569
{ MDIO_MMD_PMAPMD, 0xd092, 0xffff, 0x0000 },
574
/* set uC clock and activate it */
575
err = set_phy_regs(phy, uCclock40MHz);
579
err = set_phy_regs(phy, uCclockActivate);
584
if (phy->priv != edc_twinax)
585
err = t3_get_edc_fw(phy, EDC_TWX_AEL2020,
586
EDC_TWX_AEL2020_SIZE);
590
for (i = 0; i < EDC_TWX_AEL2020_SIZE / sizeof(u16) && !err; i += 2)
591
err = t3_mdio_write(phy, MDIO_MMD_PMAPMD,
593
phy->phy_cache[i + 1]);
595
err = set_phy_regs(phy, uCactivate);
597
phy->priv = edc_twinax;
602
* Return Module Type.
604
static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
609
v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_STAT, &stat);
613
if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) {
615
return phy_modtype_none;
618
return ael2xxx_get_module_type(phy, delay_ms);
622
* Enable PHY interrupts. We enable "Module Detection" interrupts (on any
623
* state transition) and then generic Link Alarm Status Interrupt (LASI).
625
static int ael2020_intr_enable(struct cphy *phy)
627
static const struct reg_val regs[] = {
628
/* output Module's Loss Of Signal (LOS) to LED */
629
{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
631
{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
632
0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
634
/* enable module detect status change interrupts */
635
{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
636
0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) },
641
int err, link_ok = 0;
643
/* set up "link status" LED and enable module change interrupts */
644
err = set_phy_regs(phy, regs);
648
err = get_link_status_r(phy, &link_ok, NULL, NULL, NULL);
652
t3_link_changed(phy->adapter,
655
err = t3_phy_lasi_intr_enable(phy);
663
* Disable PHY interrupts. The mirror of the above ...
665
static int ael2020_intr_disable(struct cphy *phy)
667
static const struct reg_val regs[] = {
668
/* reset "link status" LED to "off" */
669
{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
670
0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
672
/* disable module detect status change interrupts */
673
{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
674
0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) },
681
/* turn off "link status" LED and disable module change interrupts */
682
err = set_phy_regs(phy, regs);
686
return t3_phy_lasi_intr_disable(phy);
690
* Clear PHY interrupt state.
692
static int ael2020_intr_clear(struct cphy *phy)
695
* The GPIO Interrupt register on the AEL2020 is a "Latching High"
696
* (LH) register which is cleared to the current state when it's read.
697
* Thus, we simply read the register and discard the result.
700
int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat);
701
return err ? err : t3_phy_lasi_intr_clear(phy);
704
static const struct reg_val ael2020_reset_regs[] = {
705
/* Erratum #2: CDRLOL asserted, causing PMA link down status */
706
{ MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x3101 },
708
/* force XAUI to send LF when RX_LOS is asserted */
709
{ MDIO_MMD_PMAPMD, 0xcd40, 0xffff, 0x0001 },
711
/* allow writes to transceiver module EEPROM on i2c bus */
712
{ MDIO_MMD_PMAPMD, 0xff02, 0xffff, 0x0023 },
713
{ MDIO_MMD_PMAPMD, 0xff03, 0xffff, 0x0000 },
714
{ MDIO_MMD_PMAPMD, 0xff04, 0xffff, 0x0000 },
720
* Reset the PHY and put it into a canonical operating state.
722
static int ael2020_reset(struct cphy *phy, int wait)
725
unsigned int lasi_ctrl;
727
/* grab current interrupt state */
728
err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
733
err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 125);
738
/* basic initialization for all module types */
739
phy->priv = edc_none;
740
err = set_phy_regs(phy, ael2020_reset_regs);
744
/* determine module type and perform appropriate initialization */
745
err = ael2020_get_module_type(phy, 0);
748
phy->modtype = (u8)err;
749
if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
750
err = ael2020_setup_twinax_edc(phy, err);
752
err = ael2020_setup_sr_edc(phy);
756
/* reset wipes out interrupts, reenable them if they were on */
758
err = ael2005_intr_enable(phy);
763
* Handle a PHY interrupt.
765
static int ael2020_intr_handler(struct cphy *phy)
768
int ret, edc_needed, cause = 0;
770
ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat);
774
if (stat & (0x1 << AEL2020_GPIO_MODDET)) {
775
/* modules have max 300 ms init time after hot plug */
776
ret = ael2020_get_module_type(phy, 300);
780
phy->modtype = (u8)ret;
781
if (ret == phy_modtype_none)
782
edc_needed = phy->priv; /* on unplug retain EDC */
783
else if (ret == phy_modtype_twinax ||
784
ret == phy_modtype_twinax_long)
785
edc_needed = edc_twinax;
789
if (edc_needed != phy->priv) {
790
ret = ael2020_reset(phy, 0);
791
return ret ? ret : cphy_cause_module_change;
793
cause = cphy_cause_module_change;
796
ret = t3_phy_lasi_intr_handler(phy);
801
return ret ? ret : cphy_cause_link_change;
804
static struct cphy_ops ael2020_ops = {
805
.reset = ael2020_reset,
806
.intr_enable = ael2020_intr_enable,
807
.intr_disable = ael2020_intr_disable,
808
.intr_clear = ael2020_intr_clear,
809
.intr_handler = ael2020_intr_handler,
810
.get_link_status = get_link_status_r,
811
.power_down = ael1002_power_down,
812
.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
815
int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
816
const struct mdio_ops *mdio_ops)
820
cphy_init(phy, adapter, phy_addr, &ael2020_ops, mdio_ops,
821
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
822
SUPPORTED_IRQ, "10GBASE-R");
825
err = set_phy_regs(phy, ael2020_reset_regs);
832
* Get link status for a 10GBASE-X device.
834
static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
835
int *duplex, int *fc)
838
unsigned int stat0, stat1, stat2;
839
int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
840
MDIO_PMA_RXDET, &stat0);
843
err = t3_mdio_read(phy, MDIO_MMD_PCS,
844
MDIO_PCS_10GBX_STAT1, &stat1);
846
err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
847
MDIO_PHYXS_LNSTAT, &stat2);
850
*link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
853
*speed = SPEED_10000;
855
*duplex = DUPLEX_FULL;
859
static struct cphy_ops qt2045_ops = {
860
.reset = ael1006_reset,
861
.intr_enable = t3_phy_lasi_intr_enable,
862
.intr_disable = t3_phy_lasi_intr_disable,
863
.intr_clear = t3_phy_lasi_intr_clear,
864
.intr_handler = t3_phy_lasi_intr_handler,
865
.get_link_status = get_link_status_x,
866
.power_down = ael1002_power_down,
867
.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
870
int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
871
int phy_addr, const struct mdio_ops *mdio_ops)
875
cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
876
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
880
* Some cards where the PHY is supposed to be at address 0 actually
884
!t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &stat) &&
890
static int xaui_direct_reset(struct cphy *phy, int wait)
895
static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
896
int *speed, int *duplex, int *fc)
900
int prtad = phy->mdio.prtad;
902
status = t3_read_reg(phy->adapter,
903
XGM_REG(A_XGM_SERDES_STAT0, prtad)) |
904
t3_read_reg(phy->adapter,
905
XGM_REG(A_XGM_SERDES_STAT1, prtad)) |
906
t3_read_reg(phy->adapter,
907
XGM_REG(A_XGM_SERDES_STAT2, prtad)) |
908
t3_read_reg(phy->adapter,
909
XGM_REG(A_XGM_SERDES_STAT3, prtad));
910
*link_ok = !(status & F_LOWSIG0);
913
*speed = SPEED_10000;
915
*duplex = DUPLEX_FULL;
919
static int xaui_direct_power_down(struct cphy *phy, int enable)
924
static struct cphy_ops xaui_direct_ops = {
925
.reset = xaui_direct_reset,
926
.intr_enable = ael1002_intr_noop,
927
.intr_disable = ael1002_intr_noop,
928
.intr_clear = ael1002_intr_noop,
929
.intr_handler = ael1002_intr_noop,
930
.get_link_status = xaui_direct_get_link_status,
931
.power_down = xaui_direct_power_down,
934
int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
935
int phy_addr, const struct mdio_ops *mdio_ops)
937
cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
938
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,