Mercurial > illumos > illumos-gate
comparison usr/src/uts/common/io/atge/atge_mii.c @ 13768:ed21ea5d20cf
212 Atheros AR8132 / L1c Gigabit Ethernet Adapter
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Milan Jurik <milan.jurik@xylab.cz>
Approved by: Dan McDonald <danmcd@nexenta.com>
author | Gary Mills <gary_mills@fastmail.fm> |
---|---|
date | Fri, 10 Aug 2012 10:52:49 -0400 |
parents | db56a54bf91c |
children |
comparison
equal
deleted
inserted
replaced
13767:8c906b14afbd | 13768:ed21ea5d20cf |
---|---|
1 /* | |
2 * CDDL HEADER START | |
3 * | |
4 * The contents of this file are subject to the terms of the | |
5 * Common Development and Distribution License (the "License"). | |
6 * You may not use this file except in compliance with the License. | |
7 * | |
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 * or http://www.opensolaris.org/os/licensing. | |
10 * See the License for the specific language governing permissions | |
11 * and limitations under the License. | |
12 * | |
13 * When distributing Covered Code, include this CDDL HEADER in each | |
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 * If applicable, add the following below this CDDL HEADER, with the | |
16 * fields enclosed by brackets "[]" replaced with your own identifying | |
17 * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 * | |
19 * CDDL HEADER END | |
20 */ | |
21 | |
22 /* | |
23 * Copyright (c) 2012 Gary Mills | |
24 * | |
25 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. | |
26 */ | |
1 /* | 27 /* |
2 * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org> | 28 * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org> |
3 * All rights reserved. | 29 * All rights reserved. |
4 * | 30 * |
5 * Redistribution and use in source and binary forms, with or without | 31 * Redistribution and use in source and binary forms, with or without |
28 #include <sys/mii.h> | 54 #include <sys/mii.h> |
29 #include <sys/miiregs.h> | 55 #include <sys/miiregs.h> |
30 | 56 |
31 #include "atge.h" | 57 #include "atge.h" |
32 #include "atge_cmn_reg.h" | 58 #include "atge_cmn_reg.h" |
59 #include "atge_l1c_reg.h" | |
33 #include "atge_l1e_reg.h" | 60 #include "atge_l1e_reg.h" |
34 #include "atge_l1_reg.h" | 61 #include "atge_l1_reg.h" |
35 | 62 |
36 uint16_t | 63 uint16_t |
37 atge_mii_read(void *arg, uint8_t phy, uint8_t reg) | 64 atge_mii_read(void *arg, uint8_t phy, uint8_t reg) |
88 OUTL(atgep, ATGE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE | | 115 OUTL(atgep, ATGE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE | |
89 (val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT | | 116 (val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT | |
90 MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg)); | 117 MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg)); |
91 | 118 |
92 for (i = PHY_TIMEOUT; i > 0; i--) { | 119 for (i = PHY_TIMEOUT; i > 0; i--) { |
93 drv_usecwait(1); | 120 drv_usecwait(5); |
94 v = INL(atgep, ATGE_MDIO); | 121 v = INL(atgep, ATGE_MDIO); |
95 if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0) | 122 if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0) |
96 break; | 123 break; |
97 } | 124 } |
98 | 125 |
208 | 235 |
209 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0); | 236 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0); |
210 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x024E); | 237 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x024E); |
211 } | 238 } |
212 } | 239 } |
240 | |
241 void | |
242 atge_l1c_mii_reset(void *arg) | |
243 { | |
244 atge_t *atgep = arg; | |
245 uint16_t data; | |
246 int phyaddr; | |
247 | |
248 phyaddr = mii_get_addr(atgep->atge_mii); | |
249 | |
250 /* Reset magic from Linux, via Freebsd */ | |
251 OUTW(atgep, ATGE_GPHY_CTRL, | |
252 GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE | GPHY_CTRL_SEL_ANA_RESET); | |
253 (void) INW(atgep, ATGE_GPHY_CTRL); | |
254 drv_usecwait(10 * 1000); | |
255 | |
256 OUTW(atgep, ATGE_GPHY_CTRL, | |
257 GPHY_CTRL_EXT_RESET | GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE | | |
258 GPHY_CTRL_SEL_ANA_RESET); | |
259 (void) INW(atgep, ATGE_GPHY_CTRL); | |
260 drv_usecwait(10 * 1000); | |
261 | |
262 /* | |
263 * Some fast ethernet chips may not be able to auto-nego with | |
264 * switches even though they have 1000T based PHY. Hence we need | |
265 * to write 0 to MII_MSCONTROL control register. | |
266 */ | |
267 if (atgep->atge_flags & ATGE_FLAG_FASTETHER) | |
268 atge_mii_write(atgep, phyaddr, MII_MSCONTROL, 0x0); | |
269 | |
270 /* DSP fixup, Vendor magic. */ | |
271 switch (ATGE_DID(atgep)) { | |
272 uint16_t reg; | |
273 | |
274 case ATGE_CHIP_AR8152V1_DEV_ID: | |
275 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x000A); | |
276 reg = atge_mii_read(atgep, phyaddr, ATPHY_DBG_DATA); | |
277 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, reg & 0xDFFF); | |
278 /* FALLTHROUGH */ | |
279 case ATGE_CHIP_AR8151V2_DEV_ID: | |
280 case ATGE_CHIP_AR8151V1_DEV_ID: | |
281 case ATGE_CHIP_AR8152V2_DEV_ID: | |
282 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x003B); | |
283 reg = atge_mii_read(atgep, phyaddr, ATPHY_DBG_DATA); | |
284 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, reg & 0xFFF7); | |
285 drv_usecwait(20 * 1000); | |
286 break; | |
287 } | |
288 | |
289 switch (ATGE_DID(atgep)) { | |
290 case ATGE_CHIP_AR8151V1_DEV_ID: | |
291 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x0029); | |
292 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x929D); | |
293 break; | |
294 case ATGE_CHIP_AR8151V2_DEV_ID: | |
295 case ATGE_CHIP_AR8152V2_DEV_ID: | |
296 case ATGE_CHIP_L1CG_DEV_ID: | |
297 case ATGE_CHIP_L1CF_DEV_ID: | |
298 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x0029); | |
299 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0xB6DD); | |
300 break; | |
301 } | |
302 | |
303 /* Load DSP codes, vendor magic. */ | |
304 data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE | | |
305 ((1 << ANA_INTERVAL_SEL_TIMER_SHIFT) & | |
306 ANA_INTERVAL_SEL_TIMER_MASK); | |
307 atge_mii_write(atgep, phyaddr, | |
308 ATPHY_DBG_ADDR, MII_ANA_CFG18); | |
309 atge_mii_write(atgep, phyaddr, | |
310 ATPHY_DBG_DATA, data); | |
311 | |
312 data = ((2 << ANA_SERDES_CDR_BW_SHIFT) & ANA_SERDES_CDR_BW_MASK) | | |
313 ANA_MS_PAD_DBG | ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | | |
314 ANA_SERDES_EN_PLL | ANA_SERDES_EN_LCKDT; | |
315 atge_mii_write(atgep, phyaddr, | |
316 ATPHY_DBG_ADDR, MII_ANA_CFG5); | |
317 atge_mii_write(atgep, phyaddr, | |
318 ATPHY_DBG_DATA, data); | |
319 | |
320 data = ((44 << ANA_LONG_CABLE_TH_100_SHIFT) & | |
321 ANA_LONG_CABLE_TH_100_MASK) | | |
322 ((33 << ANA_SHORT_CABLE_TH_100_SHIFT) & | |
323 ANA_SHORT_CABLE_TH_100_SHIFT) | | |
324 ANA_BP_BAD_LINK_ACCUM | ANA_BP_SMALL_BW; | |
325 atge_mii_write(atgep, phyaddr, | |
326 ATPHY_DBG_ADDR, MII_ANA_CFG54); | |
327 atge_mii_write(atgep, phyaddr, | |
328 ATPHY_DBG_DATA, data); | |
329 | |
330 data = ((11 << ANA_IECHO_ADJ_3_SHIFT) & ANA_IECHO_ADJ_3_MASK) | | |
331 ((11 << ANA_IECHO_ADJ_2_SHIFT) & ANA_IECHO_ADJ_2_MASK) | | |
332 ((8 << ANA_IECHO_ADJ_1_SHIFT) & ANA_IECHO_ADJ_1_MASK) | | |
333 ((8 << ANA_IECHO_ADJ_0_SHIFT) & ANA_IECHO_ADJ_0_MASK); | |
334 atge_mii_write(atgep, phyaddr, | |
335 ATPHY_DBG_ADDR, MII_ANA_CFG4); | |
336 atge_mii_write(atgep, phyaddr, | |
337 ATPHY_DBG_DATA, data); | |
338 | |
339 data = ((7 & ANA_MANUL_SWICH_ON_SHIFT) & ANA_MANUL_SWICH_ON_MASK) | | |
340 ANA_RESTART_CAL | ANA_MAN_ENABLE | ANA_SEL_HSP | ANA_EN_HB | | |
341 ANA_OEN_125M; | |
342 atge_mii_write(atgep, phyaddr, | |
343 ATPHY_DBG_ADDR, MII_ANA_CFG0); | |
344 atge_mii_write(atgep, phyaddr, | |
345 ATPHY_DBG_DATA, data); | |
346 drv_usecwait(1000); | |
347 } | |
348 | |
349 uint16_t | |
350 atge_l1c_mii_read(void *arg, uint8_t phy, uint8_t reg) | |
351 { | |
352 | |
353 if (phy != 0) { | |
354 /* avoid PHY address alias */ | |
355 return (0xffffU); | |
356 } | |
357 | |
358 return (atge_mii_read(arg, phy, reg)); | |
359 } | |
360 | |
361 void | |
362 atge_l1c_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t val) | |
363 { | |
364 | |
365 if (phy != 0) { | |
366 /* avoid PHY address alias */ | |
367 return; | |
368 } | |
369 | |
370 if (reg == MII_CONTROL) { | |
371 /* | |
372 * Don't issue a reset if MII_CONTROL_RESET is set. | |
373 * Otherwise it occasionally | |
374 * advertises incorrect capability. | |
375 */ | |
376 if ((val & MII_CONTROL_RESET) == 0) { | |
377 /* RESET bit is required to set mode */ | |
378 atge_mii_write(arg, phy, reg, val | MII_CONTROL_RESET); | |
379 } | |
380 } else { | |
381 atge_mii_write(arg, phy, reg, val); | |
382 } | |
383 } |