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 PMD_RSD
= 10, /* PMA/PMD receive signal detect register */
37 PCS_STAT1_X
= 24, /* 10GBASE-X PCS status 1 register */
38 PCS_STAT1_R
= 32, /* 10GBASE-R PCS status 1 register */
39 XS_LN_STAT
= 24 /* XS lane status register */
43 AEL100X_TX_DISABLE
= 9,
44 AEL100X_TX_CONFIG1
= 0xc002,
45 AEL1002_PWR_DOWN_HI
= 0xc011,
46 AEL1002_PWR_DOWN_LO
= 0xc012,
47 AEL1002_XFI_EQL
= 0xc015,
48 AEL1002_LB_EN
= 0xc017,
49 AEL_OPT_SETTINGS
= 0xc017,
50 AEL_I2C_CTRL
= 0xc30a,
51 AEL_I2C_DATA
= 0xc30b,
52 AEL_I2C_STAT
= 0xc30c,
53 AEL2005_GPIO_CTRL
= 0xc214,
54 AEL2005_GPIO_STAT
= 0xc215,
57 enum { edc_none
, edc_sr
, edc_twinax
};
59 /* PHY module I2C device address */
60 #define MODULE_DEV_ADDR 0xa0
62 #define AEL2005_MODDET_IRQ 4
65 unsigned short mmd_addr
;
66 unsigned short reg_addr
;
67 unsigned short clear_bits
;
68 unsigned short set_bits
;
71 static int set_phy_regs(struct cphy
*phy
, const struct reg_val
*rv
)
75 for (err
= 0; rv
->mmd_addr
&& !err
; rv
++) {
76 if (rv
->clear_bits
== 0xffff)
77 err
= mdio_write(phy
, rv
->mmd_addr
, rv
->reg_addr
,
80 err
= t3_mdio_change_bits(phy
, rv
->mmd_addr
,
81 rv
->reg_addr
, rv
->clear_bits
,
87 static void ael100x_txon(struct cphy
*phy
)
89 int tx_on_gpio
= phy
->addr
== 0 ? F_GPIO7_OUT_VAL
: F_GPIO2_OUT_VAL
;
92 t3_set_reg_field(phy
->adapter
, A_T3DBG_GPIO_EN
, 0, tx_on_gpio
);
96 static int ael1002_power_down(struct cphy
*phy
, int enable
)
100 err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL100X_TX_DISABLE
, !!enable
);
102 err
= t3_mdio_change_bits(phy
, MDIO_DEV_PMA_PMD
, MII_BMCR
,
103 BMCR_PDOWN
, enable
? BMCR_PDOWN
: 0);
107 static int ael1002_reset(struct cphy
*phy
, int wait
)
111 if ((err
= ael1002_power_down(phy
, 0)) ||
112 (err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL100X_TX_CONFIG1
, 1)) ||
113 (err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL1002_PWR_DOWN_HI
, 0)) ||
114 (err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL1002_PWR_DOWN_LO
, 0)) ||
115 (err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL1002_XFI_EQL
, 0x18)) ||
116 (err
= t3_mdio_change_bits(phy
, MDIO_DEV_PMA_PMD
, AEL1002_LB_EN
,
122 static int ael1002_intr_noop(struct cphy
*phy
)
128 * Get link status for a 10GBASE-R device.
130 static int get_link_status_r(struct cphy
*phy
, int *link_ok
, int *speed
,
131 int *duplex
, int *fc
)
134 unsigned int stat0
, stat1
, stat2
;
135 int err
= mdio_read(phy
, MDIO_DEV_PMA_PMD
, PMD_RSD
, &stat0
);
138 err
= mdio_read(phy
, MDIO_DEV_PCS
, PCS_STAT1_R
, &stat1
);
140 err
= mdio_read(phy
, MDIO_DEV_XGXS
, XS_LN_STAT
, &stat2
);
143 *link_ok
= (stat0
& stat1
& (stat2
>> 12)) & 1;
146 *speed
= SPEED_10000
;
148 *duplex
= DUPLEX_FULL
;
152 static struct cphy_ops ael1002_ops
= {
153 .reset
= ael1002_reset
,
154 .intr_enable
= ael1002_intr_noop
,
155 .intr_disable
= ael1002_intr_noop
,
156 .intr_clear
= ael1002_intr_noop
,
157 .intr_handler
= ael1002_intr_noop
,
158 .get_link_status
= get_link_status_r
,
159 .power_down
= ael1002_power_down
,
162 int t3_ael1002_phy_prep(struct cphy
*phy
, struct adapter
*adapter
,
163 int phy_addr
, const struct mdio_ops
*mdio_ops
)
165 cphy_init(phy
, adapter
, phy_addr
, &ael1002_ops
, mdio_ops
,
166 SUPPORTED_10000baseT_Full
| SUPPORTED_AUI
| SUPPORTED_FIBRE
,
172 static int ael1006_reset(struct cphy
*phy
, int wait
)
174 return t3_phy_reset(phy
, MDIO_DEV_PMA_PMD
, wait
);
177 static int ael1006_power_down(struct cphy
*phy
, int enable
)
179 return t3_mdio_change_bits(phy
, MDIO_DEV_PMA_PMD
, MII_BMCR
,
180 BMCR_PDOWN
, enable
? BMCR_PDOWN
: 0);
183 static struct cphy_ops ael1006_ops
= {
184 .reset
= ael1006_reset
,
185 .intr_enable
= t3_phy_lasi_intr_enable
,
186 .intr_disable
= t3_phy_lasi_intr_disable
,
187 .intr_clear
= t3_phy_lasi_intr_clear
,
188 .intr_handler
= t3_phy_lasi_intr_handler
,
189 .get_link_status
= get_link_status_r
,
190 .power_down
= ael1006_power_down
,
193 int t3_ael1006_phy_prep(struct cphy
*phy
, struct adapter
*adapter
,
194 int phy_addr
, const struct mdio_ops
*mdio_ops
)
196 cphy_init(phy
, adapter
, phy_addr
, &ael1006_ops
, mdio_ops
,
197 SUPPORTED_10000baseT_Full
| SUPPORTED_AUI
| SUPPORTED_FIBRE
,
203 static int ael2005_setup_sr_edc(struct cphy
*phy
)
205 static struct reg_val regs
[] = {
206 { MDIO_DEV_PMA_PMD
, 0xc003, 0xffff, 0x181 },
207 { MDIO_DEV_PMA_PMD
, 0xc010, 0xffff, 0x448a },
208 { MDIO_DEV_PMA_PMD
, 0xc04a, 0xffff, 0x5200 },
211 static u16 sr_edc
[] = {
486 err
= set_phy_regs(phy
, regs
);
492 for (i
= 0; i
< ARRAY_SIZE(sr_edc
) && !err
; i
+= 2)
493 err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, sr_edc
[i
],
500 static int ael2005_setup_twinax_edc(struct cphy
*phy
, int modtype
)
502 static struct reg_val regs
[] = {
503 { MDIO_DEV_PMA_PMD
, 0xc04a, 0xffff, 0x5a00 },
506 static struct reg_val preemphasis
[] = {
507 { MDIO_DEV_PMA_PMD
, 0xc014, 0xffff, 0xfe16 },
508 { MDIO_DEV_PMA_PMD
, 0xc015, 0xffff, 0xa000 },
511 static u16 twinax_edc
[] = {
881 err
= set_phy_regs(phy
, regs
);
882 if (!err
&& modtype
== phy_modtype_twinax_long
)
883 err
= set_phy_regs(phy
, preemphasis
);
889 for (i
= 0; i
< ARRAY_SIZE(twinax_edc
) && !err
; i
+= 2)
890 err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, twinax_edc
[i
],
893 phy
->priv
= edc_twinax
;
897 static int ael2005_i2c_rd(struct cphy
*phy
, int dev_addr
, int word_addr
)
900 unsigned int stat
, data
;
902 err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL_I2C_CTRL
,
903 (dev_addr
<< 8) | (1 << 8) | word_addr
);
907 for (i
= 0; i
< 5; i
++) {
909 err
= mdio_read(phy
, MDIO_DEV_PMA_PMD
, AEL_I2C_STAT
, &stat
);
912 if ((stat
& 3) == 1) {
913 err
= mdio_read(phy
, MDIO_DEV_PMA_PMD
, AEL_I2C_DATA
,
920 CH_WARN(phy
->adapter
, "PHY %u I2C read of addr %u timed out\n",
921 phy
->addr
, word_addr
);
925 static int get_module_type(struct cphy
*phy
, int delay_ms
)
930 v
= mdio_read(phy
, MDIO_DEV_PMA_PMD
, AEL2005_GPIO_CTRL
, &stat
);
934 if (stat
& (1 << 8)) /* module absent */
935 return phy_modtype_none
;
940 /* see SFF-8472 for below */
941 v
= ael2005_i2c_rd(phy
, MODULE_DEV_ADDR
, 3);
946 return phy_modtype_sr
;
948 return phy_modtype_lr
;
950 return phy_modtype_lrm
;
952 v
= ael2005_i2c_rd(phy
, MODULE_DEV_ADDR
, 6);
958 v
= ael2005_i2c_rd(phy
, MODULE_DEV_ADDR
, 10);
963 v
= ael2005_i2c_rd(phy
, MODULE_DEV_ADDR
, 0x12);
966 return v
> 10 ? phy_modtype_twinax_long
: phy_modtype_twinax
;
969 return phy_modtype_unknown
;
972 static int ael2005_intr_enable(struct cphy
*phy
)
974 int err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL2005_GPIO_CTRL
, 0x200);
975 return err
? err
: t3_phy_lasi_intr_enable(phy
);
978 static int ael2005_intr_disable(struct cphy
*phy
)
980 int err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL2005_GPIO_CTRL
, 0x100);
981 return err
? err
: t3_phy_lasi_intr_disable(phy
);
984 static int ael2005_intr_clear(struct cphy
*phy
)
986 int err
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL2005_GPIO_CTRL
, 0xd00);
987 return err
? err
: t3_phy_lasi_intr_clear(phy
);
990 static int ael2005_reset(struct cphy
*phy
, int wait
)
992 static struct reg_val regs0
[] = {
993 { MDIO_DEV_PMA_PMD
, 0xc001, 0, 1 << 5 },
994 { MDIO_DEV_PMA_PMD
, 0xc017, 0, 1 << 5 },
995 { MDIO_DEV_PMA_PMD
, 0xc013, 0xffff, 0xf341 },
996 { MDIO_DEV_PMA_PMD
, 0xc210, 0xffff, 0x8000 },
997 { MDIO_DEV_PMA_PMD
, 0xc210, 0xffff, 0x8100 },
998 { MDIO_DEV_PMA_PMD
, 0xc210, 0xffff, 0x8000 },
999 { MDIO_DEV_PMA_PMD
, 0xc210, 0xffff, 0 },
1002 static struct reg_val regs1
[] = {
1003 { MDIO_DEV_PMA_PMD
, 0xca00, 0xffff, 0x0080 },
1004 { MDIO_DEV_PMA_PMD
, 0xca12, 0xffff, 0 },
1010 err
= mdio_read(phy
, MDIO_DEV_PMA_PMD
, LASI_CTRL
, &lasi_ctrl
);
1014 err
= t3_phy_reset(phy
, MDIO_DEV_PMA_PMD
, 0);
1019 phy
->priv
= edc_none
;
1020 err
= set_phy_regs(phy
, regs0
);
1026 err
= get_module_type(phy
, 0);
1031 if (err
== phy_modtype_twinax
|| err
== phy_modtype_twinax_long
)
1032 err
= ael2005_setup_twinax_edc(phy
, err
);
1034 err
= ael2005_setup_sr_edc(phy
);
1038 err
= set_phy_regs(phy
, regs1
);
1042 /* reset wipes out interrupts, reenable them if they were on */
1044 err
= ael2005_intr_enable(phy
);
1048 static int ael2005_intr_handler(struct cphy
*phy
)
1051 int ret
, edc_needed
, cause
= 0;
1053 ret
= mdio_read(phy
, MDIO_DEV_PMA_PMD
, AEL2005_GPIO_STAT
, &stat
);
1057 if (stat
& AEL2005_MODDET_IRQ
) {
1058 ret
= mdio_write(phy
, MDIO_DEV_PMA_PMD
, AEL2005_GPIO_CTRL
,
1063 /* modules have max 300 ms init time after hot plug */
1064 ret
= get_module_type(phy
, 300);
1069 if (ret
== phy_modtype_none
)
1070 edc_needed
= phy
->priv
; /* on unplug retain EDC */
1071 else if (ret
== phy_modtype_twinax
||
1072 ret
== phy_modtype_twinax_long
)
1073 edc_needed
= edc_twinax
;
1075 edc_needed
= edc_sr
;
1077 if (edc_needed
!= phy
->priv
) {
1078 ret
= ael2005_reset(phy
, 0);
1079 return ret
? ret
: cphy_cause_module_change
;
1081 cause
= cphy_cause_module_change
;
1084 ret
= t3_phy_lasi_intr_handler(phy
);
1089 return ret
? ret
: cphy_cause_link_change
;
1092 static struct cphy_ops ael2005_ops
= {
1093 .reset
= ael2005_reset
,
1094 .intr_enable
= ael2005_intr_enable
,
1095 .intr_disable
= ael2005_intr_disable
,
1096 .intr_clear
= ael2005_intr_clear
,
1097 .intr_handler
= ael2005_intr_handler
,
1098 .get_link_status
= get_link_status_r
,
1099 .power_down
= ael1002_power_down
,
1102 int t3_ael2005_phy_prep(struct cphy
*phy
, struct adapter
*adapter
,
1103 int phy_addr
, const struct mdio_ops
*mdio_ops
)
1105 cphy_init(phy
, adapter
, phy_addr
, &ael2005_ops
, mdio_ops
,
1106 SUPPORTED_10000baseT_Full
| SUPPORTED_AUI
| SUPPORTED_FIBRE
|
1107 SUPPORTED_IRQ
, "10GBASE-R");
1109 return t3_mdio_change_bits(phy
, MDIO_DEV_PMA_PMD
, AEL_OPT_SETTINGS
, 0,
1114 * Get link status for a 10GBASE-X device.
1116 static int get_link_status_x(struct cphy
*phy
, int *link_ok
, int *speed
,
1117 int *duplex
, int *fc
)
1120 unsigned int stat0
, stat1
, stat2
;
1121 int err
= mdio_read(phy
, MDIO_DEV_PMA_PMD
, PMD_RSD
, &stat0
);
1124 err
= mdio_read(phy
, MDIO_DEV_PCS
, PCS_STAT1_X
, &stat1
);
1126 err
= mdio_read(phy
, MDIO_DEV_XGXS
, XS_LN_STAT
, &stat2
);
1129 *link_ok
= (stat0
& (stat1
>> 12) & (stat2
>> 12)) & 1;
1132 *speed
= SPEED_10000
;
1134 *duplex
= DUPLEX_FULL
;
1138 static struct cphy_ops qt2045_ops
= {
1139 .reset
= ael1006_reset
,
1140 .intr_enable
= t3_phy_lasi_intr_enable
,
1141 .intr_disable
= t3_phy_lasi_intr_disable
,
1142 .intr_clear
= t3_phy_lasi_intr_clear
,
1143 .intr_handler
= t3_phy_lasi_intr_handler
,
1144 .get_link_status
= get_link_status_x
,
1145 .power_down
= ael1006_power_down
,
1148 int t3_qt2045_phy_prep(struct cphy
*phy
, struct adapter
*adapter
,
1149 int phy_addr
, const struct mdio_ops
*mdio_ops
)
1153 cphy_init(phy
, adapter
, phy_addr
, &qt2045_ops
, mdio_ops
,
1154 SUPPORTED_10000baseT_Full
| SUPPORTED_AUI
| SUPPORTED_TP
,
1158 * Some cards where the PHY is supposed to be at address 0 actually
1161 if (!phy_addr
&& !mdio_read(phy
, MDIO_DEV_PMA_PMD
, MII_BMSR
, &stat
) &&
1167 static int xaui_direct_reset(struct cphy
*phy
, int wait
)
1172 static int xaui_direct_get_link_status(struct cphy
*phy
, int *link_ok
,
1173 int *speed
, int *duplex
, int *fc
)
1176 unsigned int status
;
1178 status
= t3_read_reg(phy
->adapter
,
1179 XGM_REG(A_XGM_SERDES_STAT0
, phy
->addr
)) |
1180 t3_read_reg(phy
->adapter
,
1181 XGM_REG(A_XGM_SERDES_STAT1
, phy
->addr
)) |
1182 t3_read_reg(phy
->adapter
,
1183 XGM_REG(A_XGM_SERDES_STAT2
, phy
->addr
)) |
1184 t3_read_reg(phy
->adapter
,
1185 XGM_REG(A_XGM_SERDES_STAT3
, phy
->addr
));
1186 *link_ok
= !(status
& F_LOWSIG0
);
1189 *speed
= SPEED_10000
;
1191 *duplex
= DUPLEX_FULL
;
1195 static int xaui_direct_power_down(struct cphy
*phy
, int enable
)
1200 static struct cphy_ops xaui_direct_ops
= {
1201 .reset
= xaui_direct_reset
,
1202 .intr_enable
= ael1002_intr_noop
,
1203 .intr_disable
= ael1002_intr_noop
,
1204 .intr_clear
= ael1002_intr_noop
,
1205 .intr_handler
= ael1002_intr_noop
,
1206 .get_link_status
= xaui_direct_get_link_status
,
1207 .power_down
= xaui_direct_power_down
,
1210 int t3_xaui_direct_phy_prep(struct cphy
*phy
, struct adapter
*adapter
,
1211 int phy_addr
, const struct mdio_ops
*mdio_ops
)
1213 cphy_init(phy
, adapter
, phy_addr
, &xaui_direct_ops
, mdio_ops
,
1214 SUPPORTED_10000baseT_Full
| SUPPORTED_AUI
| SUPPORTED_TP
,