]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - sys/dev/cxgb/common/cxgb_ael1002.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / sys / dev / cxgb / common / cxgb_ael1002.c
1 /**************************************************************************
2
3 Copyright (c) 2007-2009, Chelsio Inc.
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, 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
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY 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
38 enum {
39         PMD_RSD     = 10,   /* PMA/PMD receive signal detect register */
40         PCS_STAT1_X = 24,   /* 10GBASE-X PCS status 1 register */
41         PCS_STAT1_R = 32,   /* 10GBASE-R PCS status 1 register */
42         XS_LN_STAT  = 24    /* XS lane status register */
43 };
44
45 enum {
46         AEL100X_TX_DISABLE  = 9,
47         AEL100X_TX_CONFIG1  = 0xc002,
48         AEL1002_PWR_DOWN_HI = 0xc011,
49         AEL1002_PWR_DOWN_LO = 0xc012,
50         AEL1002_XFI_EQL     = 0xc015,
51         AEL1002_LB_EN       = 0xc017,
52         AEL_OPT_SETTINGS    = 0xc017,
53         AEL_I2C_CTRL        = 0xc30a,
54         AEL_I2C_DATA        = 0xc30b,
55         AEL_I2C_STAT        = 0xc30c,
56         AEL2005_GPIO_CTRL   = 0xc214,
57         AEL2005_GPIO_STAT   = 0xc215,
58 };
59
60 enum { edc_none, edc_sr, edc_twinax };
61
62 /* PHY module I2C device address */
63 enum {
64         MODULE_DEV_ADDR = 0xa0,
65         SFF_DEV_ADDR    = 0xa2,
66 };
67
68 /* PHY transceiver type */
69 enum {
70         phy_transtype_unknown = 0,
71         phy_transtype_sfp     = 3,
72         phy_transtype_xfp     = 6,
73 };              
74
75 #define AEL2005_MODDET_IRQ 4
76
77 struct reg_val {
78         unsigned short mmd_addr;
79         unsigned short reg_addr;
80         unsigned short clear_bits;
81         unsigned short set_bits;
82 };
83
84 static int get_module_type(struct cphy *phy);
85
86 static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
87 {
88         int err;
89
90         for (err = 0; rv->mmd_addr && !err; rv++) {
91                 if (rv->clear_bits == 0xffff)
92                         err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
93                                          rv->set_bits);
94                 else
95                         err = t3_mdio_change_bits(phy, rv->mmd_addr,
96                                                   rv->reg_addr, rv->clear_bits,
97                                                   rv->set_bits);
98         }
99         return err;
100 }
101
102 static void ael100x_txon(struct cphy *phy)
103 {
104         int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
105
106         msleep(100);
107         t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
108         msleep(30);
109 }
110
111 static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
112 {
113         int i, err;
114         unsigned int stat, data;
115
116         err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
117                          (dev_addr << 8) | (1 << 8) | word_addr);
118         if (err)
119                 return err;
120
121         for (i = 0; i < 200; i++) {
122                 msleep(1);
123                 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
124                 if (err)
125                         return err;
126                 if ((stat & 3) == 1) {
127                         err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA,
128                                         &data);
129                         if (err)
130                                 return err;
131                         return data >> 8;
132                 }
133         }
134         CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n",
135                 phy->addr, word_addr);
136         return -ETIMEDOUT;
137 }
138
139 static int ael_i2c_wr(struct cphy *phy, int dev_addr, int word_addr, int data)
140 {
141         int i, err;
142         unsigned int stat;
143
144         err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, data);
145         if (err)
146                 return err;
147
148         err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
149                          (dev_addr << 8) | word_addr);
150         if (err)
151                 return err;
152
153         for (i = 0; i < 200; i++) {
154                 msleep(1);
155                 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
156                 if (err)
157                         return err;
158                 if ((stat & 3) == 1)
159                         return 0;
160         }
161         CH_WARN(phy->adapter, "PHY %u I2C Write of addr %u timed out\n",
162                 phy->addr, word_addr);
163         return -ETIMEDOUT;
164 }
165
166 static int get_phytrans_type(struct cphy *phy)
167 {
168         int v;
169
170         v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0);
171         if (v < 0)
172                 return phy_transtype_unknown;
173
174         return v;
175 }
176
177 static int ael_laser_down(struct cphy *phy, int enable)
178 {
179         int v, dev_addr;
180
181         v = get_phytrans_type(phy);
182         if (v < 0)
183                 return v;
184
185         if (v == phy_transtype_sfp) {
186                 /* Check SFF Soft TX disable is supported */
187                 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 93);
188                 if (v < 0)
189                         return v;
190
191                 v &= 0x40;
192                 if (!v)
193                         return v;
194
195                 dev_addr = SFF_DEV_ADDR;        
196         } else if (v == phy_transtype_xfp)
197                 dev_addr = MODULE_DEV_ADDR;
198         else
199                 return v;
200
201         v = ael_i2c_rd(phy, dev_addr, 110);
202         if (v < 0)
203                 return v;
204
205         if (enable)
206                 v |= 0x40;
207         else
208                 v &= ~0x40;
209
210         v = ael_i2c_wr(phy, dev_addr, 110, v);
211
212         return v;
213 }
214
215 static int ael1002_power_down(struct cphy *phy, int enable)
216 {
217         int err;
218
219         err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
220         if (!err)
221                 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
222                                           BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
223         return err;
224 }
225
226 static int ael1002_get_module_type(struct cphy *phy, int delay_ms)
227 {
228         int v;
229
230         if (delay_ms)
231                 msleep(delay_ms);
232
233         v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0);
234
235         return v == -ETIMEDOUT ? phy_modtype_none : get_module_type(phy);
236 }
237
238 static int ael1002_reset(struct cphy *phy, int wait)
239 {
240         int err;
241
242         if ((err = ael1002_power_down(phy, 0)) ||
243             (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
244             (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
245             (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
246             (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
247             (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
248                                        0, 1 << 5)))
249                 return err;
250
251         err = ael1002_get_module_type(phy, 300);
252         if (err >= 0)
253                 phy->modtype = err;
254
255         return 0;
256 }
257
258 static int ael1002_intr_noop(struct cphy *phy)
259 {
260         return 0;
261 }
262
263 /*
264  * Get link status for a 10GBASE-R device.
265  */
266 static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
267                              int *duplex, int *fc)
268 {
269         if (link_ok) {
270                 unsigned int stat0, stat1, stat2;
271                 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
272
273                 if (!err)
274                         err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1);
275                 if (!err)
276                         err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
277                 if (err)
278                         return err;
279                 *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
280         }
281         if (speed)
282                 *speed = SPEED_10000;
283         if (duplex)
284                 *duplex = DUPLEX_FULL;
285         return 0;
286 }
287
288 #ifdef C99_NOT_SUPPORTED
289 static struct cphy_ops ael1002_ops = {
290         ael1002_reset,
291         ael1002_intr_noop,
292         ael1002_intr_noop,
293         ael1002_intr_noop,
294         ael1002_intr_noop,
295         NULL,
296         NULL,
297         NULL,
298         NULL,
299         NULL,
300         get_link_status_r,
301         ael1002_power_down,
302 };
303 #else
304 static struct cphy_ops ael1002_ops = {
305         .reset           = ael1002_reset,
306         .intr_enable     = ael1002_intr_noop,
307         .intr_disable    = ael1002_intr_noop,
308         .intr_clear      = ael1002_intr_noop,
309         .intr_handler    = ael1002_intr_noop,
310         .get_link_status = get_link_status_r,
311         .power_down      = ael1002_power_down,
312 };
313 #endif
314
315 int t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
316                         const struct mdio_ops *mdio_ops)
317 {
318         int err;
319
320         cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
321                   SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
322                   "10GBASE-R");
323         ael100x_txon(phy);
324         ael_laser_down(phy, 0);
325
326         err = ael1002_get_module_type(phy, 0);
327         if (err >= 0)
328                 phy->modtype = err;
329
330         return 0;
331 }
332
333 static int ael1006_reset(struct cphy *phy, int wait)
334 {
335         int err;
336
337         err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
338         if (err)
339                 return err;
340
341         t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 
342                          F_GPIO6_OUT_VAL, 0);
343
344         msleep(125);
345
346         t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 
347                          F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL);
348
349         msleep(125);
350
351         err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
352         if (err)
353                 return err;
354
355         msleep(125);
356
357         err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1);
358         if (err)
359                 return err;
360         
361         msleep(125);
362
363         err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0);
364
365         return err;
366            
367 }
368
369 static int ael1006_power_down(struct cphy *phy, int enable)
370 {
371         return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
372                                    BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
373 }
374
375 #ifdef C99_NOT_SUPPORTED
376 static struct cphy_ops ael1006_ops = {
377         ael1006_reset,
378         t3_phy_lasi_intr_enable,
379         t3_phy_lasi_intr_disable,
380         t3_phy_lasi_intr_clear,
381         t3_phy_lasi_intr_handler,
382         NULL,
383         NULL,
384         NULL,
385         NULL,
386         NULL,
387         get_link_status_r,
388         ael1006_power_down,
389 };
390 #else
391 static struct cphy_ops ael1006_ops = {
392         .reset           = ael1006_reset,
393         .intr_enable     = t3_phy_lasi_intr_enable,
394         .intr_disable    = t3_phy_lasi_intr_disable,
395         .intr_clear      = t3_phy_lasi_intr_clear,
396         .intr_handler    = t3_phy_lasi_intr_handler,
397         .get_link_status = get_link_status_r,
398         .power_down      = ael1006_power_down,
399 };
400 #endif
401
402 int t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
403                         const struct mdio_ops *mdio_ops)
404 {
405         cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
406                   SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
407                   "10GBASE-SR");
408         ael100x_txon(phy);
409         return 0;
410 }
411
412 static int ael2005_setup_sr_edc(struct cphy *phy)
413 {
414         static struct reg_val regs[] = {
415                 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
416                 { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
417                 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
418                 { 0, 0, 0, 0 }
419         };
420         static u16 sr_edc[] = {
421                 0xcc00, 0x2ff4,
422                 0xcc01, 0x3cd4,
423                 0xcc02, 0x2015,
424                 0xcc03, 0x3105,
425                 0xcc04, 0x6524,
426                 0xcc05, 0x27ff,
427                 0xcc06, 0x300f,
428                 0xcc07, 0x2c8b,
429                 0xcc08, 0x300b,
430                 0xcc09, 0x4009,
431                 0xcc0a, 0x400e,
432                 0xcc0b, 0x2f72,
433                 0xcc0c, 0x3002,
434                 0xcc0d, 0x1002,
435                 0xcc0e, 0x2172,
436                 0xcc0f, 0x3012,
437                 0xcc10, 0x1002,
438                 0xcc11, 0x25d2,
439                 0xcc12, 0x3012,
440                 0xcc13, 0x1002,
441                 0xcc14, 0xd01e,
442                 0xcc15, 0x27d2,
443                 0xcc16, 0x3012,
444                 0xcc17, 0x1002,
445                 0xcc18, 0x2004,
446                 0xcc19, 0x3c84,
447                 0xcc1a, 0x6436,
448                 0xcc1b, 0x2007,
449                 0xcc1c, 0x3f87,
450                 0xcc1d, 0x8676,
451                 0xcc1e, 0x40b7,
452                 0xcc1f, 0xa746,
453                 0xcc20, 0x4047,
454                 0xcc21, 0x5673,
455                 0xcc22, 0x2982,
456                 0xcc23, 0x3002,
457                 0xcc24, 0x13d2,
458                 0xcc25, 0x8bbd,
459                 0xcc26, 0x2862,
460                 0xcc27, 0x3012,
461                 0xcc28, 0x1002,
462                 0xcc29, 0x2092,
463                 0xcc2a, 0x3012,
464                 0xcc2b, 0x1002,
465                 0xcc2c, 0x5cc3,
466                 0xcc2d, 0x314,
467                 0xcc2e, 0x2942,
468                 0xcc2f, 0x3002,
469                 0xcc30, 0x1002,
470                 0xcc31, 0xd019,
471                 0xcc32, 0x2032,
472                 0xcc33, 0x3012,
473                 0xcc34, 0x1002,
474                 0xcc35, 0x2a04,
475                 0xcc36, 0x3c74,
476                 0xcc37, 0x6435,
477                 0xcc38, 0x2fa4,
478                 0xcc39, 0x3cd4,
479                 0xcc3a, 0x6624,
480                 0xcc3b, 0x5563,
481                 0xcc3c, 0x2d42,
482                 0xcc3d, 0x3002,
483                 0xcc3e, 0x13d2,
484                 0xcc3f, 0x464d,
485                 0xcc40, 0x2862,
486                 0xcc41, 0x3012,
487                 0xcc42, 0x1002,
488                 0xcc43, 0x2032,
489                 0xcc44, 0x3012,
490                 0xcc45, 0x1002,
491                 0xcc46, 0x2fb4,
492                 0xcc47, 0x3cd4,
493                 0xcc48, 0x6624,
494                 0xcc49, 0x5563,
495                 0xcc4a, 0x2d42,
496                 0xcc4b, 0x3002,
497                 0xcc4c, 0x13d2,
498                 0xcc4d, 0x2ed2,
499                 0xcc4e, 0x3002,
500                 0xcc4f, 0x1002,
501                 0xcc50, 0x2fd2,
502                 0xcc51, 0x3002,
503                 0xcc52, 0x1002,
504                 0xcc53, 0x004,
505                 0xcc54, 0x2942,
506                 0xcc55, 0x3002,
507                 0xcc56, 0x1002,
508                 0xcc57, 0x2092,
509                 0xcc58, 0x3012,
510                 0xcc59, 0x1002,
511                 0xcc5a, 0x5cc3,
512                 0xcc5b, 0x317,
513                 0xcc5c, 0x2f72,
514                 0xcc5d, 0x3002,
515                 0xcc5e, 0x1002,
516                 0xcc5f, 0x2942,
517                 0xcc60, 0x3002,
518                 0xcc61, 0x1002,
519                 0xcc62, 0x22cd,
520                 0xcc63, 0x301d,
521                 0xcc64, 0x2862,
522                 0xcc65, 0x3012,
523                 0xcc66, 0x1002,
524                 0xcc67, 0x2ed2,
525                 0xcc68, 0x3002,
526                 0xcc69, 0x1002,
527                 0xcc6a, 0x2d72,
528                 0xcc6b, 0x3002,
529                 0xcc6c, 0x1002,
530                 0xcc6d, 0x628f,
531                 0xcc6e, 0x2112,
532                 0xcc6f, 0x3012,
533                 0xcc70, 0x1002,
534                 0xcc71, 0x5aa3,
535                 0xcc72, 0x2dc2,
536                 0xcc73, 0x3002,
537                 0xcc74, 0x1312,
538                 0xcc75, 0x6f72,
539                 0xcc76, 0x1002,
540                 0xcc77, 0x2807,
541                 0xcc78, 0x31a7,
542                 0xcc79, 0x20c4,
543                 0xcc7a, 0x3c24,
544                 0xcc7b, 0x6724,
545                 0xcc7c, 0x1002,
546                 0xcc7d, 0x2807,
547                 0xcc7e, 0x3187,
548                 0xcc7f, 0x20c4,
549                 0xcc80, 0x3c24,
550                 0xcc81, 0x6724,
551                 0xcc82, 0x1002,
552                 0xcc83, 0x2514,
553                 0xcc84, 0x3c64,
554                 0xcc85, 0x6436,
555                 0xcc86, 0xdff4,
556                 0xcc87, 0x6436,
557                 0xcc88, 0x1002,
558                 0xcc89, 0x40a4,
559                 0xcc8a, 0x643c,
560                 0xcc8b, 0x4016,
561                 0xcc8c, 0x8c6c,
562                 0xcc8d, 0x2b24,
563                 0xcc8e, 0x3c24,
564                 0xcc8f, 0x6435,
565                 0xcc90, 0x1002,
566                 0xcc91, 0x2b24,
567                 0xcc92, 0x3c24,
568                 0xcc93, 0x643a,
569                 0xcc94, 0x4025,
570                 0xcc95, 0x8a5a,
571                 0xcc96, 0x1002,
572                 0xcc97, 0x2731,
573                 0xcc98, 0x3011,
574                 0xcc99, 0x1001,
575                 0xcc9a, 0xc7a0,
576                 0xcc9b, 0x100,
577                 0xcc9c, 0xc502,
578                 0xcc9d, 0x53ac,
579                 0xcc9e, 0xc503,
580                 0xcc9f, 0xd5d5,
581                 0xcca0, 0xc600,
582                 0xcca1, 0x2a6d,
583                 0xcca2, 0xc601,
584                 0xcca3, 0x2a4c,
585                 0xcca4, 0xc602,
586                 0xcca5, 0x111,
587                 0xcca6, 0xc60c,
588                 0xcca7, 0x5900,
589                 0xcca8, 0xc710,
590                 0xcca9, 0x700,
591                 0xccaa, 0xc718,
592                 0xccab, 0x700,
593                 0xccac, 0xc720,
594                 0xccad, 0x4700,
595                 0xccae, 0xc801,
596                 0xccaf, 0x7f50,
597                 0xccb0, 0xc802,
598                 0xccb1, 0x7760,
599                 0xccb2, 0xc803,
600                 0xccb3, 0x7fce,
601                 0xccb4, 0xc804,
602                 0xccb5, 0x5700,
603                 0xccb6, 0xc805,
604                 0xccb7, 0x5f11,
605                 0xccb8, 0xc806,
606                 0xccb9, 0x4751,
607                 0xccba, 0xc807,
608                 0xccbb, 0x57e1,
609                 0xccbc, 0xc808,
610                 0xccbd, 0x2700,
611                 0xccbe, 0xc809,
612                 0xccbf, 0x000,
613                 0xccc0, 0xc821,
614                 0xccc1, 0x002,
615                 0xccc2, 0xc822,
616                 0xccc3, 0x014,
617                 0xccc4, 0xc832,
618                 0xccc5, 0x1186,
619                 0xccc6, 0xc847,
620                 0xccc7, 0x1e02,
621                 0xccc8, 0xc013,
622                 0xccc9, 0xf341,
623                 0xccca, 0xc01a,
624                 0xcccb, 0x446,
625                 0xcccc, 0xc024,
626                 0xcccd, 0x1000,
627                 0xccce, 0xc025,
628                 0xcccf, 0xa00,
629                 0xccd0, 0xc026,
630                 0xccd1, 0xc0c,
631                 0xccd2, 0xc027,
632                 0xccd3, 0xc0c,
633                 0xccd4, 0xc029,
634                 0xccd5, 0x0a0,
635                 0xccd6, 0xc030,
636                 0xccd7, 0xa00,
637                 0xccd8, 0xc03c,
638                 0xccd9, 0x01c,
639                 0xccda, 0xc005,
640                 0xccdb, 0x7a06,
641                 0xccdc, 0x000,
642                 0xccdd, 0x2731,
643                 0xccde, 0x3011,
644                 0xccdf, 0x1001,
645                 0xcce0, 0xc620,
646                 0xcce1, 0x000,
647                 0xcce2, 0xc621,
648                 0xcce3, 0x03f,
649                 0xcce4, 0xc622,
650                 0xcce5, 0x000,
651                 0xcce6, 0xc623,
652                 0xcce7, 0x000,
653                 0xcce8, 0xc624,
654                 0xcce9, 0x000,
655                 0xccea, 0xc625,
656                 0xcceb, 0x000,
657                 0xccec, 0xc627,
658                 0xcced, 0x000,
659                 0xccee, 0xc628,
660                 0xccef, 0x000,
661                 0xccf0, 0xc62c,
662                 0xccf1, 0x000,
663                 0xccf2, 0x000,
664                 0xccf3, 0x2806,
665                 0xccf4, 0x3cb6,
666                 0xccf5, 0xc161,
667                 0xccf6, 0x6134,
668                 0xccf7, 0x6135,
669                 0xccf8, 0x5443,
670                 0xccf9, 0x303,
671                 0xccfa, 0x6524,
672                 0xccfb, 0x00b,
673                 0xccfc, 0x1002,
674                 0xccfd, 0x2104,
675                 0xccfe, 0x3c24,
676                 0xccff, 0x2105,
677                 0xcd00, 0x3805,
678                 0xcd01, 0x6524,
679                 0xcd02, 0xdff4,
680                 0xcd03, 0x4005,
681                 0xcd04, 0x6524,
682                 0xcd05, 0x1002,
683                 0xcd06, 0x5dd3,
684                 0xcd07, 0x306,
685                 0xcd08, 0x2ff7,
686                 0xcd09, 0x38f7,
687                 0xcd0a, 0x60b7,
688                 0xcd0b, 0xdffd,
689                 0xcd0c, 0x00a,
690                 0xcd0d, 0x1002,
691                 0xcd0e, 0
692         };
693         int i, err;
694
695         err = set_phy_regs(phy, regs);
696         if (err)
697                 return err;
698
699         msleep(50);
700
701         for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
702                 err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
703                                  sr_edc[i + 1]);
704         if (!err)
705                 phy->priv = edc_sr;
706         return err;
707 }
708
709 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
710 {
711         static struct reg_val regs[] = {
712                 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
713                 { 0, 0, 0, 0 }
714         };
715         static struct reg_val preemphasis[] = {
716                 { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
717                 { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
718                 { 0, 0, 0, 0 }
719         };
720         static u16 twinax_edc[] = {
721                 0xcc00, 0x4009,
722                 0xcc01, 0x27ff,
723                 0xcc02, 0x300f,
724                 0xcc03, 0x40aa,
725                 0xcc04, 0x401c,
726                 0xcc05, 0x401e,
727                 0xcc06, 0x2ff4,
728                 0xcc07, 0x3cd4,
729                 0xcc08, 0x2035,
730                 0xcc09, 0x3145,
731                 0xcc0a, 0x6524,
732                 0xcc0b, 0x26a2,
733                 0xcc0c, 0x3012,
734                 0xcc0d, 0x1002,
735                 0xcc0e, 0x29c2,
736                 0xcc0f, 0x3002,
737                 0xcc10, 0x1002,
738                 0xcc11, 0x2072,
739                 0xcc12, 0x3012,
740                 0xcc13, 0x1002,
741                 0xcc14, 0x22cd,
742                 0xcc15, 0x301d,
743                 0xcc16, 0x2e52,
744                 0xcc17, 0x3012,
745                 0xcc18, 0x1002,
746                 0xcc19, 0x28e2,
747                 0xcc1a, 0x3002,
748                 0xcc1b, 0x1002,
749                 0xcc1c, 0x628f,
750                 0xcc1d, 0x2ac2,
751                 0xcc1e, 0x3012,
752                 0xcc1f, 0x1002,
753                 0xcc20, 0x5553,
754                 0xcc21, 0x2ae2,
755                 0xcc22, 0x3002,
756                 0xcc23, 0x1302,
757                 0xcc24, 0x401e,
758                 0xcc25, 0x2be2,
759                 0xcc26, 0x3012,
760                 0xcc27, 0x1002,
761                 0xcc28, 0x2da2,
762                 0xcc29, 0x3012,
763                 0xcc2a, 0x1002,
764                 0xcc2b, 0x2ba2,
765                 0xcc2c, 0x3002,
766                 0xcc2d, 0x1002,
767                 0xcc2e, 0x5ee3,
768                 0xcc2f, 0x305,
769                 0xcc30, 0x400e,
770                 0xcc31, 0x2bc2,
771                 0xcc32, 0x3002,
772                 0xcc33, 0x1002,
773                 0xcc34, 0x2b82,
774                 0xcc35, 0x3012,
775                 0xcc36, 0x1002,
776                 0xcc37, 0x5663,
777                 0xcc38, 0x302,
778                 0xcc39, 0x401e,
779                 0xcc3a, 0x6f72,
780                 0xcc3b, 0x1002,
781                 0xcc3c, 0x628f,
782                 0xcc3d, 0x2be2,
783                 0xcc3e, 0x3012,
784                 0xcc3f, 0x1002,
785                 0xcc40, 0x22cd,
786                 0xcc41, 0x301d,
787                 0xcc42, 0x2e52,
788                 0xcc43, 0x3012,
789                 0xcc44, 0x1002,
790                 0xcc45, 0x2522,
791                 0xcc46, 0x3012,
792                 0xcc47, 0x1002,
793                 0xcc48, 0x2da2,
794                 0xcc49, 0x3012,
795                 0xcc4a, 0x1002,
796                 0xcc4b, 0x2ca2,
797                 0xcc4c, 0x3012,
798                 0xcc4d, 0x1002,
799                 0xcc4e, 0x2fa4,
800                 0xcc4f, 0x3cd4,
801                 0xcc50, 0x6624,
802                 0xcc51, 0x410b,
803                 0xcc52, 0x56b3,
804                 0xcc53, 0x3c4,
805                 0xcc54, 0x2fb2,
806                 0xcc55, 0x3002,
807                 0xcc56, 0x1002,
808                 0xcc57, 0x220b,
809                 0xcc58, 0x303b,
810                 0xcc59, 0x56b3,
811                 0xcc5a, 0x3c3,
812                 0xcc5b, 0x866b,
813                 0xcc5c, 0x400c,
814                 0xcc5d, 0x23a2,
815                 0xcc5e, 0x3012,
816                 0xcc5f, 0x1002,
817                 0xcc60, 0x2da2,
818                 0xcc61, 0x3012,
819                 0xcc62, 0x1002,
820                 0xcc63, 0x2ca2,
821                 0xcc64, 0x3012,
822                 0xcc65, 0x1002,
823                 0xcc66, 0x2fb4,
824                 0xcc67, 0x3cd4,
825                 0xcc68, 0x6624,
826                 0xcc69, 0x56b3,
827                 0xcc6a, 0x3c3,
828                 0xcc6b, 0x866b,
829                 0xcc6c, 0x401c,
830                 0xcc6d, 0x2205,
831                 0xcc6e, 0x3035,
832                 0xcc6f, 0x5b53,
833                 0xcc70, 0x2c52,
834                 0xcc71, 0x3002,
835                 0xcc72, 0x13c2,
836                 0xcc73, 0x5cc3,
837                 0xcc74, 0x317,
838                 0xcc75, 0x2522,
839                 0xcc76, 0x3012,
840                 0xcc77, 0x1002,
841                 0xcc78, 0x2da2,
842                 0xcc79, 0x3012,
843                 0xcc7a, 0x1002,
844                 0xcc7b, 0x2b82,
845                 0xcc7c, 0x3012,
846                 0xcc7d, 0x1002,
847                 0xcc7e, 0x5663,
848                 0xcc7f, 0x303,
849                 0xcc80, 0x401e,
850                 0xcc81, 0x004,
851                 0xcc82, 0x2c42,
852                 0xcc83, 0x3012,
853                 0xcc84, 0x1002,
854                 0xcc85, 0x6f72,
855                 0xcc86, 0x1002,
856                 0xcc87, 0x628f,
857                 0xcc88, 0x2304,
858                 0xcc89, 0x3c84,
859                 0xcc8a, 0x6436,
860                 0xcc8b, 0xdff4,
861                 0xcc8c, 0x6436,
862                 0xcc8d, 0x2ff5,
863                 0xcc8e, 0x3005,
864                 0xcc8f, 0x8656,
865                 0xcc90, 0xdfba,
866                 0xcc91, 0x56a3,
867                 0xcc92, 0xd05a,
868                 0xcc93, 0x21c2,
869                 0xcc94, 0x3012,
870                 0xcc95, 0x1392,
871                 0xcc96, 0xd05a,
872                 0xcc97, 0x56a3,
873                 0xcc98, 0xdfba,
874                 0xcc99, 0x383,
875                 0xcc9a, 0x6f72,
876                 0xcc9b, 0x1002,
877                 0xcc9c, 0x28c5,
878                 0xcc9d, 0x3005,
879                 0xcc9e, 0x4178,
880                 0xcc9f, 0x5653,
881                 0xcca0, 0x384,
882                 0xcca1, 0x22b2,
883                 0xcca2, 0x3012,
884                 0xcca3, 0x1002,
885                 0xcca4, 0x2be5,
886                 0xcca5, 0x3005,
887                 0xcca6, 0x41e8,
888                 0xcca7, 0x5653,
889                 0xcca8, 0x382,
890                 0xcca9, 0x002,
891                 0xccaa, 0x4258,
892                 0xccab, 0x2474,
893                 0xccac, 0x3c84,
894                 0xccad, 0x6437,
895                 0xccae, 0xdff4,
896                 0xccaf, 0x6437,
897                 0xccb0, 0x2ff5,
898                 0xccb1, 0x3c05,
899                 0xccb2, 0x8757,
900                 0xccb3, 0xb888,
901                 0xccb4, 0x9787,
902                 0xccb5, 0xdff4,
903                 0xccb6, 0x6724,
904                 0xccb7, 0x866a,
905                 0xccb8, 0x6f72,
906                 0xccb9, 0x1002,
907                 0xccba, 0x2d01,
908                 0xccbb, 0x3011,
909                 0xccbc, 0x1001,
910                 0xccbd, 0xc620,
911                 0xccbe, 0x14e5,
912                 0xccbf, 0xc621,
913                 0xccc0, 0xc53d,
914                 0xccc1, 0xc622,
915                 0xccc2, 0x3cbe,
916                 0xccc3, 0xc623,
917                 0xccc4, 0x4452,
918                 0xccc5, 0xc624,
919                 0xccc6, 0xc5c5,
920                 0xccc7, 0xc625,
921                 0xccc8, 0xe01e,
922                 0xccc9, 0xc627,
923                 0xccca, 0x000,
924                 0xcccb, 0xc628,
925                 0xcccc, 0x000,
926                 0xcccd, 0xc62b,
927                 0xccce, 0x000,
928                 0xcccf, 0xc62c,
929                 0xccd0, 0x000,
930                 0xccd1, 0x000,
931                 0xccd2, 0x2d01,
932                 0xccd3, 0x3011,
933                 0xccd4, 0x1001,
934                 0xccd5, 0xc620,
935                 0xccd6, 0x000,
936                 0xccd7, 0xc621,
937                 0xccd8, 0x000,
938                 0xccd9, 0xc622,
939                 0xccda, 0x0ce,
940                 0xccdb, 0xc623,
941                 0xccdc, 0x07f,
942                 0xccdd, 0xc624,
943                 0xccde, 0x032,
944                 0xccdf, 0xc625,
945                 0xcce0, 0x000,
946                 0xcce1, 0xc627,
947                 0xcce2, 0x000,
948                 0xcce3, 0xc628,
949                 0xcce4, 0x000,
950                 0xcce5, 0xc62b,
951                 0xcce6, 0x000,
952                 0xcce7, 0xc62c,
953                 0xcce8, 0x000,
954                 0xcce9, 0x000,
955                 0xccea, 0x2d01,
956                 0xcceb, 0x3011,
957                 0xccec, 0x1001,
958                 0xcced, 0xc502,
959                 0xccee, 0x609f,
960                 0xccef, 0xc600,
961                 0xccf0, 0x2a6e,
962                 0xccf1, 0xc601,
963                 0xccf2, 0x2a2c,
964                 0xccf3, 0xc60c,
965                 0xccf4, 0x5400,
966                 0xccf5, 0xc710,
967                 0xccf6, 0x700,
968                 0xccf7, 0xc718,
969                 0xccf8, 0x700,
970                 0xccf9, 0xc720,
971                 0xccfa, 0x4700,
972                 0xccfb, 0xc728,
973                 0xccfc, 0x700,
974                 0xccfd, 0xc729,
975                 0xccfe, 0x1207,
976                 0xccff, 0xc801,
977                 0xcd00, 0x7f50,
978                 0xcd01, 0xc802,
979                 0xcd02, 0x7760,
980                 0xcd03, 0xc803,
981                 0xcd04, 0x7fce,
982                 0xcd05, 0xc804,
983                 0xcd06, 0x520e,
984                 0xcd07, 0xc805,
985                 0xcd08, 0x5c11,
986                 0xcd09, 0xc806,
987                 0xcd0a, 0x3c51,
988                 0xcd0b, 0xc807,
989                 0xcd0c, 0x4061,
990                 0xcd0d, 0xc808,
991                 0xcd0e, 0x49c1,
992                 0xcd0f, 0xc809,
993                 0xcd10, 0x3840,
994                 0xcd11, 0xc80a,
995                 0xcd12, 0x000,
996                 0xcd13, 0xc821,
997                 0xcd14, 0x002,
998                 0xcd15, 0xc822,
999                 0xcd16, 0x046,
1000                 0xcd17, 0xc844,
1001                 0xcd18, 0x182f,
1002                 0xcd19, 0xc013,
1003                 0xcd1a, 0xf341,
1004                 0xcd1b, 0xc01a,
1005                 0xcd1c, 0x446,
1006                 0xcd1d, 0xc024,
1007                 0xcd1e, 0x1000,
1008                 0xcd1f, 0xc025,
1009                 0xcd20, 0xa00,
1010                 0xcd21, 0xc026,
1011                 0xcd22, 0xc0c,
1012                 0xcd23, 0xc027,
1013                 0xcd24, 0xc0c,
1014                 0xcd25, 0xc029,
1015                 0xcd26, 0x0a0,
1016                 0xcd27, 0xc030,
1017                 0xcd28, 0xa00,
1018                 0xcd29, 0xc03c,
1019                 0xcd2a, 0x01c,
1020                 0xcd2b, 0x000,
1021                 0xcd2c, 0x2b84,
1022                 0xcd2d, 0x3c74,
1023                 0xcd2e, 0x6435,
1024                 0xcd2f, 0xdff4,
1025                 0xcd30, 0x6435,
1026                 0xcd31, 0x2806,
1027                 0xcd32, 0x3006,
1028                 0xcd33, 0x8565,
1029                 0xcd34, 0x2b24,
1030                 0xcd35, 0x3c24,
1031                 0xcd36, 0x6436,
1032                 0xcd37, 0x1002,
1033                 0xcd38, 0x2b24,
1034                 0xcd39, 0x3c24,
1035                 0xcd3a, 0x6436,
1036                 0xcd3b, 0x4045,
1037                 0xcd3c, 0x8656,
1038                 0xcd3d, 0x1002,
1039                 0xcd3e, 0x2807,
1040                 0xcd3f, 0x31a7,
1041                 0xcd40, 0x20c4,
1042                 0xcd41, 0x3c24,
1043                 0xcd42, 0x6724,
1044                 0xcd43, 0x1002,
1045                 0xcd44, 0x2807,
1046                 0xcd45, 0x3187,
1047                 0xcd46, 0x20c4,
1048                 0xcd47, 0x3c24,
1049                 0xcd48, 0x6724,
1050                 0xcd49, 0x1002,
1051                 0xcd4a, 0x2514,
1052                 0xcd4b, 0x3c64,
1053                 0xcd4c, 0x6436,
1054                 0xcd4d, 0xdff4,
1055                 0xcd4e, 0x6436,
1056                 0xcd4f, 0x1002,
1057                 0xcd50, 0x2806,
1058                 0xcd51, 0x3cb6,
1059                 0xcd52, 0xc161,
1060                 0xcd53, 0x6134,
1061                 0xcd54, 0x6135,
1062                 0xcd55, 0x5443,
1063                 0xcd56, 0x303,
1064                 0xcd57, 0x6524,
1065                 0xcd58, 0x00b,
1066                 0xcd59, 0x1002,
1067                 0xcd5a, 0xd019,
1068                 0xcd5b, 0x2104,
1069                 0xcd5c, 0x3c24,
1070                 0xcd5d, 0x2105,
1071                 0xcd5e, 0x3805,
1072                 0xcd5f, 0x6524,
1073                 0xcd60, 0xdff4,
1074                 0xcd61, 0x4005,
1075                 0xcd62, 0x6524,
1076                 0xcd63, 0x2e8d,
1077                 0xcd64, 0x303d,
1078                 0xcd65, 0x5dd3,
1079                 0xcd66, 0x306,
1080                 0xcd67, 0x2ff7,
1081                 0xcd68, 0x38f7,
1082                 0xcd69, 0x60b7,
1083                 0xcd6a, 0xdffd,
1084                 0xcd6b, 0x00a,
1085                 0xcd6c, 0x1002,
1086                 0xcd6d, 0
1087         };
1088         int i, err;
1089
1090         err = set_phy_regs(phy, regs);
1091         if (!err && modtype == phy_modtype_twinax_long)
1092                 err = set_phy_regs(phy, preemphasis);
1093         if (err)
1094                 return err;
1095
1096         msleep(50);
1097
1098         for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1099                 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1100                                  twinax_edc[i + 1]);
1101         if (!err)
1102                 phy->priv = edc_twinax;
1103         return err;
1104 }
1105
1106 static int get_module_type(struct cphy *phy)
1107 {
1108         int v;
1109
1110         v = get_phytrans_type(phy);
1111         if (v == phy_transtype_sfp) {
1112                 /* SFP: see SFF-8472 for below */
1113
1114                 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
1115                 if (v < 0)
1116                         return v;
1117
1118                 if (v == 0x1)
1119                         return phy_modtype_twinax;
1120                 if (v == 0x10)
1121                         return phy_modtype_sr;
1122                 if (v == 0x20)
1123                         return phy_modtype_lr;
1124                 if (v == 0x40)
1125                         return phy_modtype_lrm;
1126
1127                 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
1128                 if (v < 0)
1129                         return v;
1130                 if (v != 4)
1131                         return phy_modtype_unknown;
1132
1133                 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
1134                 if (v < 0)
1135                         return v;
1136
1137                 if (v & 0x80) {
1138                         v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
1139                         if (v < 0)
1140                                 return v;
1141                         return v > 10 ? phy_modtype_twinax_long :
1142                             phy_modtype_twinax;
1143                 }
1144         } else if (v == phy_transtype_xfp) {
1145                 /* XFP: See INF-8077i for details. */
1146
1147                 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127);
1148                 if (v < 0)
1149                         return v;
1150
1151                 if (v != 1) {
1152                         /* XXX: set page select to table 1 yourself */
1153                         return phy_modtype_unknown;
1154                 }
1155
1156                 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131);
1157                 if (v < 0)
1158                         return v;
1159                 v &= 0xf0;
1160                 if (v == 0x10)
1161                         return phy_modtype_lrm;
1162                 if (v == 0x40)
1163                         return phy_modtype_lr;
1164                 if (v == 0x80)
1165                         return phy_modtype_sr;
1166         }
1167
1168         return phy_modtype_unknown;
1169 }
1170
1171
1172 static int ael2005_intr_enable(struct cphy *phy)
1173 {
1174         int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1175         return err ? err : t3_phy_lasi_intr_enable(phy);
1176 }
1177
1178 static int ael2005_intr_disable(struct cphy *phy)
1179 {
1180         int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1181         return err ? err : t3_phy_lasi_intr_disable(phy);
1182 }
1183
1184 static int ael2005_intr_clear(struct cphy *phy)
1185 {
1186         int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1187         return err ? err : t3_phy_lasi_intr_clear(phy);
1188 }
1189
1190 static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1191 {
1192         int v;
1193         unsigned int stat;
1194
1195         v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1196         if (v)
1197                 return v;
1198
1199         if (stat & (1 << 8))                    /* module absent */
1200                 return phy_modtype_none;
1201
1202         if (delay_ms)
1203                 msleep(delay_ms);
1204
1205         return get_module_type(phy);
1206 }
1207
1208 static int ael2005_reset(struct cphy *phy, int wait)
1209 {
1210         static struct reg_val regs0[] = {
1211                 { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1212                 { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1213                 { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1214                 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1215                 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1216                 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1217                 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1218                 { 0, 0, 0, 0 }
1219         };
1220         static struct reg_val regs1[] = {
1221                 { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1222                 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1223                 { 0, 0, 0, 0 }
1224         };
1225
1226         int err, lasi_ctrl;
1227
1228         err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1229         if (err)
1230                 return err;
1231
1232         err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1233         if (err)
1234                 return err;
1235
1236         msleep(125);
1237         phy->priv = edc_none;
1238         err = set_phy_regs(phy, regs0);
1239         if (err)
1240                 return err;
1241
1242         msleep(50);
1243
1244         err = ael2005_get_module_type(phy, 0);
1245         if (err < 0)
1246                 return err;
1247         phy->modtype = (u8)err;
1248
1249         if (err == phy_modtype_none || err == phy_modtype_unknown)
1250                 err = 0;
1251         else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1252                 err = ael2005_setup_twinax_edc(phy, err);
1253         else
1254                 err = ael2005_setup_sr_edc(phy);
1255         if (err)
1256                 return err;
1257
1258         err = set_phy_regs(phy, regs1);
1259         if (err)
1260                 return err;
1261
1262         /* reset wipes out interrupts, reenable them if they were on */
1263         if (lasi_ctrl & 1)
1264                 err = ael2005_intr_enable(phy);
1265         return err;
1266 }
1267
1268 static int ael2005_intr_handler(struct cphy *phy)
1269 {
1270         unsigned int stat;
1271         int ret, edc_needed, cause = 0;
1272
1273         ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1274         if (ret)
1275                 return ret;
1276
1277         if (stat & AEL2005_MODDET_IRQ) {
1278                 ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1279                                  0xd00);
1280                 if (ret)
1281                         return ret;
1282
1283                 /* modules have max 300 ms init time after hot plug */
1284                 ret = ael2005_get_module_type(phy, 300);
1285                 if (ret < 0)
1286                         return ret;
1287
1288                 phy->modtype = (u8)ret;
1289                 if (ret == phy_modtype_none)
1290                         edc_needed = phy->priv;       /* on unplug retain EDC */
1291                 else if (ret == phy_modtype_twinax ||
1292                          ret == phy_modtype_twinax_long)
1293                         edc_needed = edc_twinax;
1294                 else
1295                         edc_needed = edc_sr;
1296
1297                 if (edc_needed != phy->priv) {
1298                         ret = ael2005_reset(phy, 0);
1299                         return ret ? ret : cphy_cause_module_change;
1300                 }
1301                 cause = cphy_cause_module_change;
1302         }
1303
1304         ret = t3_phy_lasi_intr_handler(phy);
1305         if (ret < 0)
1306                 return ret;
1307
1308         ret |= cause;
1309         if (!ret)
1310                 ret |= cphy_cause_link_change;
1311         return ret;
1312 }
1313
1314 #ifdef C99_NOT_SUPPORTED
1315 static struct cphy_ops ael2005_ops = {
1316         ael2005_reset,
1317         ael2005_intr_enable,
1318         ael2005_intr_disable,
1319         ael2005_intr_clear,
1320         ael2005_intr_handler,
1321         NULL,
1322         NULL,
1323         NULL,
1324         NULL,
1325         NULL,
1326         get_link_status_r,
1327         ael1002_power_down,
1328 };
1329 #else
1330 static struct cphy_ops ael2005_ops = {
1331         .reset           = ael2005_reset,
1332         .intr_enable     = ael2005_intr_enable,
1333         .intr_disable    = ael2005_intr_disable,
1334         .intr_clear      = ael2005_intr_clear,
1335         .intr_handler    = ael2005_intr_handler,
1336         .get_link_status = get_link_status_r,
1337         .power_down      = ael1002_power_down,
1338 };
1339 #endif
1340
1341 int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1342                         const struct mdio_ops *mdio_ops)
1343 {
1344         int err;
1345         cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
1346                   SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1347                   SUPPORTED_IRQ, "10GBASE-R");
1348         msleep(125);
1349         ael_laser_down(phy, 0);
1350
1351         err = ael2005_get_module_type(phy, 0);
1352         if (err >= 0)
1353                 phy->modtype = err;
1354
1355         return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1356                                    1 << 5);
1357 }
1358
1359 /*
1360  * Get link status for a 10GBASE-X device.
1361  */
1362 static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
1363                              int *duplex, int *fc)
1364 {
1365         if (link_ok) {
1366                 unsigned int stat0, stat1, stat2;
1367                 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
1368
1369                 if (!err)
1370                         err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
1371                 if (!err)
1372                         err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
1373                 if (err)
1374                         return err;
1375                 *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
1376         }
1377         if (speed)
1378                 *speed = SPEED_10000;
1379         if (duplex)
1380                 *duplex = DUPLEX_FULL;
1381         return 0;
1382 }
1383
1384 #ifdef C99_NOT_SUPPORTED
1385 static struct cphy_ops qt2045_ops = {
1386         ael1006_reset,
1387         t3_phy_lasi_intr_enable,
1388         t3_phy_lasi_intr_disable,
1389         t3_phy_lasi_intr_clear,
1390         t3_phy_lasi_intr_handler,
1391         NULL,
1392         NULL,
1393         NULL,
1394         NULL,
1395         NULL,
1396         get_link_status_x,
1397         ael1006_power_down,
1398 };
1399 #else
1400 static struct cphy_ops qt2045_ops = {
1401         .reset           = ael1006_reset,
1402         .intr_enable     = t3_phy_lasi_intr_enable,
1403         .intr_disable    = t3_phy_lasi_intr_disable,
1404         .intr_clear      = t3_phy_lasi_intr_clear,
1405         .intr_handler    = t3_phy_lasi_intr_handler,
1406         .get_link_status = get_link_status_x,
1407         .power_down      = ael1006_power_down,
1408 };
1409 #endif
1410
1411 int t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1412                        const struct mdio_ops *mdio_ops)
1413 {
1414         unsigned int stat;
1415
1416         cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
1417                   SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1418                   "10GBASE-CX4");
1419
1420         /*
1421          * Some cards where the PHY is supposed to be at address 0 actually
1422          * have it at 1.
1423          */
1424         if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
1425             stat == 0xffff)
1426                 phy->addr = 1;
1427         return 0;
1428 }
1429
1430 static int xaui_direct_reset(struct cphy *phy, int wait)
1431 {
1432         return 0;
1433 }
1434
1435 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
1436                                        int *speed, int *duplex, int *fc)
1437 {
1438         if (link_ok) {
1439                 unsigned int status;
1440
1441                 status = t3_read_reg(phy->adapter,
1442                                      XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
1443                          t3_read_reg(phy->adapter,
1444                                      XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
1445                          t3_read_reg(phy->adapter,
1446                                      XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
1447                          t3_read_reg(phy->adapter,
1448                                      XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
1449                 *link_ok = !(status & F_LOWSIG0);
1450         }
1451         if (speed)
1452                 *speed = SPEED_10000;
1453         if (duplex)
1454                 *duplex = DUPLEX_FULL;
1455         return 0;
1456 }
1457
1458 static int xaui_direct_power_down(struct cphy *phy, int enable)
1459 {
1460         return 0;
1461 }
1462
1463 #ifdef C99_NOT_SUPPORTED
1464 static struct cphy_ops xaui_direct_ops = {
1465         xaui_direct_reset,
1466         ael1002_intr_noop,
1467         ael1002_intr_noop,
1468         ael1002_intr_noop,
1469         ael1002_intr_noop,
1470         NULL,
1471         NULL,
1472         NULL,
1473         NULL,
1474         NULL,
1475         xaui_direct_get_link_status,
1476         xaui_direct_power_down,
1477 };
1478 #else
1479 static struct cphy_ops xaui_direct_ops = {
1480         .reset           = xaui_direct_reset,
1481         .intr_enable     = ael1002_intr_noop,
1482         .intr_disable    = ael1002_intr_noop,
1483         .intr_clear      = ael1002_intr_noop,
1484         .intr_handler    = ael1002_intr_noop,
1485         .get_link_status = xaui_direct_get_link_status,
1486         .power_down      = xaui_direct_power_down,
1487 };
1488 #endif
1489
1490 int t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1491                             const struct mdio_ops *mdio_ops)
1492 {
1493         cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
1494                   SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1495                   "10GBASE-CX4");
1496         return 0;
1497 }