Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / network / bge / bge-phy.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: bge-phy.fth
4\
5\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6\
7\ - Do no alter or remove copyright notices
8\
9\ - Redistribution and use of this software in source and binary forms, with
10\ or without modification, are permitted provided that the following
11\ conditions are met:
12\
13\ - Redistribution of source code must retain the above copyright notice,
14\ this list of conditions and the following disclaimer.
15\
16\ - Redistribution in binary form must reproduce the above copyright notice,
17\ this list of conditions and the following disclaimer in the
18\ documentation and/or other materials provided with the distribution.
19\
20\ Neither the name of Sun Microsystems, Inc. or the names of contributors
21\ may be used to endorse or promote products derived from this software
22\ without specific prior written permission.
23\
24\ This software is provided "AS IS," without a warranty of any kind.
25\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
26\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
27\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
28\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
29\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
30\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
31\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
32\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
33\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
34\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
35\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
36\
37\ You acknowledge that this software is not designed, licensed or
38\ intended for use in the design, construction, operation or maintenance of
39\ any nuclear facility.
40\
41\ ========== Copyright Header End ============================================
42id: @(#)bge-phy.fth 1.9 06/08/23
43purpose:
44copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved
45copyright: Use is subject to license terms.
46
47
48headers
49
500 value an-debug?
51
52d# 5 constant #rst-retries \ # of retries to reset phy
53create pattern
54 h# 5555 w, h# 0005 w, h# 2aaa w, h# 000a w, h# 3456 w, h# 0003 w,
55 h# 2aaa w, h# 000a w, h# 3333 w, h# 0003 w, h# 789a w, h# 0005 w,
56 h# 5a5a w, h# 0005 w, h# 2a6a w, h# 000a w, h# 1bcd w, h# 0003 w,
57 h# 2a5a w, h# 000a w, h# 33c3 w, h# 0003 w, h# 2ef1 w, h# 0005 w,
58
59: phy-macro-done? ( -- flag )
60 h# 16 phy@ h# 1000 and 0=
61;
62
63: wait-phy-macro-done ( -- flag )
64 d# 100 ['] phy-macro-done? wait-status
65;
66
67\ Put PHY in loopback mode temporarily to bring the link down
68: force-link-down ( -- )
69 phy-cr@ phycr.loopback or phy-cr!
70 d# 1000 ms
71 phy-cr@ phycr.loopback invert and phy-cr!
72;
73
74: phy-reset-complete? ( -- flag ) phy-cr@ phycr.reset and 0= ;
75
76: wait-phy-reset ( -- flag )
77 d# 700 ['] phy-reset-complete? wait-status
78;
79
80\ This code is taken from a recommendation by Broadcom on
81\ how to reset the PHY and check for a failed reset
82\ condition that can occur occasionally, if such a condition
83\ is detected then retry the reset for a pre-determined
84\ number of iterations
85
86: pattern@ ( index set# -- val )
87 6 * + /w * pattern + w@
88;
89
90: (reset-transceiver-once) ( -- ok? )
91 \ issue a phy reset, and wait for reset to complete
92 phy-cr@ phycr.reset or phy-cr! ( )
93 wait-phy-reset drop ( )
94 \ now go check the DFE TAPs to see if locked up, but
95 \ first, we need to set up PHY so we can read DFE TAPs
96 \ Disable Transmitter and Interrupt, while we play with
97 \ the PHY registers, so the link partner won't see any
98 \ strange data and the Driver won't see any interrupts.
99 h# 10 phy@ h# 3000 or h# 10 phy! ( )
100 \ Setup Full-Duplex, 1000 mbps
101 h# 140 phy-cr! ( )
102 \ Set to Master mode
103 h# 1800 9 phy! ( )
104
105 \ ADC and Gamma fixes only apply to Ax revisions
106 \ not Bx revisions, so check that relevant part
107 \ of revision id is 0
108 pci-rev-id h# f00 and 0= if
109 \ ADC fix
110 \ Enable SM_DSP_CLOCK & 6dB
111 h# c00 h# 18 phy! ( )
112 \ work-arounds
113 h# 201f h# 17 phy! ( )
114 h# 2aaa h# 15 phy! ( )
115
116 \ Gamma fix
117 h# a h# 17 phy! ( )
118 h# 323 h# 15 phy! ( )
119 then
120
121 \ blocks the PHY control access
122 h# 8005 h# 17 phy! ( )
123 h# 800 h# 15 phy! ( )
124 \ check TAPs for all 4 channels, as soon
125 \ as we see a lockup we'll stop checking
126 4 0 do ( )
127 \ select channel and set TAP index to 0
128 i h# 2000 * h# 200 or h# 17 phy! ( )
129 \ freeze filter again just to be safe
130 2 h# 16 phy! ( )
131 \ write fixed pattern to the RAM, 3 TAPs for
132 \ each channel, each TAP have 2 WORDs (LO/HI)
133 6 0 do ( )
134 i j pattern@ h# 15 phy! ( )
135 loop ( )
136 \ Active PHY's Macro operation to write DFE TAP from RAM,
137 \ and wait for Macro to complete
138 h# 202 h# 16 phy! ( )
139 wait-phy-macro-done drop ( )
140 \ --- done with write phase, now begin read phase ---
141 \ select channel and set TAP index to 0
142 i h# 2000 * h# 200 or h# 17 phy! ( )
143 \ Active PHY's Macro operation to load DFE TAP to RAM,
144 \ and wait for Macro to complete
145 h# 82 h# 16 phy! ( )
146 wait-phy-macro-done drop ( )
147 \ enable "pre-fetch"
148 h# 802 h# 16 phy! ( )
149 wait-phy-macro-done drop ( )
150 \ read back the TAP values
151 \ 3 TAPs for each channel, each TAP have 2 WORDs (LO/HI)
152 6 0 do ( )
153 \ read Lo/Hi then wait for 'done' is faster
154 \ For DFE TAP, the HI word contains 6 bits,
155 \ LO word contains 15 bits
156 h# 15 phy@ h# 7fff and ( dataLo )
157 h# 15 phy@ h# 3f and ( dataLo dataHi )
158 wait-phy-macro-done drop ( dataLo dataHi )
159 \ check if what we wrote is what we read back
160 i 1+ j pattern@ = swap ( hiMatch? dataLo )
161 i j pattern@ = ( hiMatch? loMatch? )
162 and 0= if ( )
163 \ if failed, then the PHY is locked up,
164 \ we need to do PHY reset again
165 unloop unloop false exit ( false )
166 then ( )
167 2 +loop ( )
168 loop ( )
169 true ( true )
170;
171
172: (reset-transceiver-special) ( -- ok? )
173 false
174 #rst-retries 0 do
175 (reset-transceiver-once) if ( false )
176 drop true leave ( true )
177 then ( false )
178 loop ( ok? )
179 \ remove block phy control
180 h# 8005 h# 17 phy! ( ok? )
181 0 h# 15 phy! ( ok? )
182 \ unfreeze DFE TAP filter for all channels
183 h# 8200 h# 17 phy! ( ok? )
184 0 h# 16 phy! ( ok? )
185 \ Restore PHY back to operating state
186 h# 400 h# 18 phy! ( ok? )
187 \ enable transmitter and interrupt
188 h# 10 phy@ h# cfff and h# 10 phy! ( ok? )
189;
190
191: (reset-transceiver-generic) ( -- ok? )
192 phy-cr@ phycr.reset or phy-cr!
193 wait-phy-reset
194;
195
196\ return true if BCM5704C rev < B0
197: bcm5704c<revb0? ( -- flag )
198 pci-dev-id BCM-5704 =
199 pci-rev-id h# f00 and 0= and
200;
201
202: (reset-transceiver) ( -- ok? )
203 pci-dev-id BCM-5703 =
204 pci-dev-id BCM-5703a = or
205 bcm5704c<revb0? or if \ The 5703 and 5704 (revs less than
206 \ B0) need a non-default method to
207 \ reset the phy
208 \ NB: 5702/5705 are not supported.
209 (reset-transceiver-special)
210 else
211 (reset-transceiver-generic)
212 then
213;
214
215: reset-transceiver ( -- ok? )
216 d# 15000 get-msecs + false
217 begin
218 over timed-out? 0= over 0= and
219 while
220 (reset-transceiver) if drop true then
221 repeat nip
222 dup 0= if ." Failed to reset transceiver!" cr exit then
223 phy-cr@ phycr.speed-100 invert and phycr.duplex invert and phy-cr!
224;
225
226: disable-auto-nego ( -- )
227 an-debug? if ." Disabling Autonegotiation" cr then
228 phy-cr@ phycr.an-enable invert and phy-cr!
229;
230
231: enable-auto-nego ( -- )
232 an-debug? if ." Enabling Autonegotiation" cr then
233 phy-cr@ phycr.an-enable phycr.an-restart or or phy-cr!
234;
235
236: an-link-speed&mode ( -- speed duplex-mode )
237
238 phy-sr@ physr.ext-status and if
239 phy-1000-sr@ h# c00 and d# 10 rshift
240 phy-1000-cr@ h# 300 and d# 8 rshift and ( 1000bt-common-cap )
241 d# 10 lshift
242 dup gsr.lp-1000fdx and if drop 1000Mbps full-duplex exit then
243 gsr.lp-1000hdx and if 1000Mbps half-duplex exit then
244 then
245
246 phy-anlpar@ phy-anar@ and ( an-common )
247 dup anlpar.100fdx and if drop 100Mbps full-duplex exit then
248 dup anlpar.100hdx and if drop 100Mbps half-duplex exit then
249 dup anlpar.10fdx and if drop 10Mbps full-duplex exit then
250 dup anlpar.10hdx and if drop 10Mbps half-duplex exit then
251;
252
253: supported-speed&mode ( speed mode$ -- bit-mask )
254 rot case
255 10Mbps of
256 " half" $= if h# 1 else h# 2 then
257 endof
258 100Mbps of
259 " half" $= if h# 4 else h# 8 then
260 endof
261 1000Mbps of
262 " half" $= if h# 10 else h# 20 then
263 endof
264 ( default ) 0
265 endcase
266;
267
268: parse-supported-abilities ( str$ -- abilities )
269 base @ >r decimal
270 ascii , left-parse-string 2drop
271 ascii , left-parse-string $number drop -rot ( speed str$ )
272 ascii , left-parse-string 2drop ( speed mode$ )
273 supported-speed&mode ( bit-mask )
274 r> base !
275;
276
277: get-supported-abilities ( phy-abilty -- phy-abilty | abilty )
278 " supported-network-types" get-my-property 0= if
279 begin
280 decode-string ?dup
281 while ( phy-abilty str1$ str2$ )
282 parse-supported-abilities ( phy-abilty str1$ mask )
283 3 roll swap xor -rot ( mask' str1$ )
284 repeat 3drop ( mask' )
285 invert h# 3f and ( abilty )
286 then
287;
288
289: phy-abilities ( -- abilities )
290 phy-sr@ d# 11 rshift h# f and
291 gmii-phy? if phy-esr@ d# 12 rshift h# 3 and else 0 then d# 4 lshift or
292 ( phy-abilty ) get-supported-abilities ( abilities )
293;
294
295\ Construct bit-mask abilities based on speed, duplex mode settings
296\ 0000.0001 10Mbps, Half Duplex
297\ 0000.0010 10Mbps, Full Duplex
298\ 0000.0100 100Mbps, Half Duplex
299\ 0000.1000 100Mbps, Full Duplex
300\ 0001.0000 1000Mbps, Half Duplex
301\ 0010.0000 1000Mbps, Full Duplex
302: construct-abilities ( speed duplex-mode -- abilities )
303 phy-abilities
304 swap case
305 half-duplex of h# 15 endof \ Mask FDX abilities
306 full-duplex of h# 2a endof \ Mask HDX abilities
307 auto-duplex of h# 3f endof
308 endcase and
309 swap case
310 10Mbps of h# 3 endof
311 100Mbps of h# c endof
312 1000Mbps of h# 30 endof
313 auto-speed of h# 3f endof
314 endcase and
315;
316
317: publish-capabilities ( -- )
318
319 user-speed user-duplex construct-abilities ( abilities )
320 dup h# f and d# 5 lshift h# 1 or phy-anar! \ anar[8:5]
321 gmii-phy? if ( abilities )
322 h# 30 and d# 4 lshift ( 1000-cap )
323 user-link-clock auto-link-clock <> if
324 gcr.ms-cfg-enable or
325 user-link-clock master-link-clock = if
326 gcr.ms-cfg-value or
327 then
328 then
329 phy-1000-cr!
330 else ( abilities )
331 drop ( )
332 then ( )
333;
334
335: match-capabilities ( -- ok? )
336 phy-sr@ physr.ext-status and if
337 phy-1000-sr@ h# c00 and d# 10 rshift
338 phy-1000-cr@ h# 300 and d# 8 rshift
339 and 0<>
340 else
341 0
342 then
343 phy-anlpar@ phy-anar@ and 0<> or
344;
345
346\ Autonegotiation may take as much as 5 seconds with 10/100 BaseT PHYs
347: wait-autoneg-complete ( -- complete? )
348 d# 5000 get-msecs + false
349 begin
350 over timed-out? 0=
351 over 0= and
352 while
353 d# 20 ms
354 phy-sr@ physr.an-complete and if
355 drop true
356 then
357 repeat nip
358;
359
360: phy-link-up? ( -- up? )
361 phy-sr@ drop
362 phy-sr@ physr.link-up and
363;
364
365: link-up? ( -- flag ) phy-link-up? ;
366
367: wait-link-up? ( -- up? )
368 wait-phy-reset drop
369 d# 2000 ['] phy-link-up? wait-status
370;
371
372: (autonegotiate) ( -- link-up? )
373
374 \ Advertise my capabilities & start auto negotiation
375 publish-capabilities
376 enable-auto-nego
377
378 \ Wait for auto negotiation to complete
379 wait-autoneg-complete
380 0= if
381 ." Timed out waiting for Autonegotiation to complete" cr
382 false exit
383 then
384
385 \ Check if autonegotiation completed by parallel detection,
386 \ and if so, whether there are any parallel detect (multiple
387 \ link fault) errors
388 phy-aner@ dup aner.lp-an-able and 0= swap aner.mlf and and if
389 ." Multiple link faults seen during Autonegotiation" cr
390 false exit
391 then
392
393 \ Check for common capabilities
394 match-capabilities 0= if
395 ." System and network incompatible for communicating" cr
396 false exit
397 then
398
399 \ Valid Link established?
400 phy-link-up?
401;
402
403: do-autonegotiation ( -- link-up? )
404 (autonegotiate) if
405 an-link-speed&mode set-chosen-speed&duplex
406 true
407 else
408 ." Check cable and try again" cr
409 false
410 then
411;
412
413: check-phy-capability ( -- )
414 user-speed user-duplex 2dup construct-abilities 0= if
415 ." Not capable of " .link-speed,duplex
416 -1 throw
417 else
418 2drop
419 then
420;
421
422\ Set/Force link speed and mode, and check link status
423\ For 1Gbps, we manually configure local PHY as SLAVE
424: speed&mode-possible? ( speed duplex-mode -- link-up? )
425 over 1000Mbps = if
426 phy-1000-cr@ h# 1800 invert and h# 1000 or phy-1000-cr!
427 then
428 phy-cr@ b# 0010.0001.0100.0000 invert and \ Mask speed & duplex bits
429 swap full-duplex = if phycr.duplex or then
430 swap case
431 10Mbps of phycr.speed-10 endof
432 100Mbps of phycr.speed-100 endof
433 1000Mbps of phycr.speed-1000 endof
434 endcase or
435 phy-cr!
436 wait-link-up?
437;
438
439
440: set-speed&mode ( -- link-up? )
441 disable-auto-nego
442 force-link-down
443 user-speed user-duplex
444 2dup speed&mode-possible? if set-chosen-speed&duplex true exit then
445 over 1000Mbps = if
446 ." Cannot bringup link using non-autonegotation." cr
447 ." Force link partner to " .link-speed,duplex ." as link-clock "
448 user-link-clock master-link-clock = if
449 ." slave"
450 else
451 ." master"
452 then
453 cr -1 throw
454 then
455 2drop false
456;
457
458\ Use non-autonegotiation only is both speed & duplex modes are specified
459: use-autonegotiation? ( -- flag )
460 user-speed auto-speed = user-duplex auto-duplex = or if
461 true exit
462 then
463 user-speed 1000Mbps = if
464 user-link-clock auto-link-clock =
465 else
466 false
467 then
468;
469
470: show-link-status ( -- )
471 phy-link-up? if
472 chosen-speed chosen-duplex .link-speed,duplex ." Link up"
473 else
474 ." Link Down"
475 then cr
476;
477
478: disable-link-events ( -- )
479 pci-dev-id BCM-5704 = \ Rev a0 of the 5704 needs non-default
480 pci-rev-id 0= and if \ timing.
481 h# 8d68 h# 1c phy! \ bcm5704 PHY-MAC timing reg
482 h# 8d68 h# 1c phy! \ needs to be written twice to stick
483 then
484 0 h# 6844 breg! \ Make sure we're in auto-access mode
485 h# 18 h# 404 breg-bset \ Clear Link Attentions (Enet MAC Status Reg)
486 h# c0000 h# 454 breg-bset \ Disable auto polling (MI Mode Reg)
487 1 ms \ wait 40 us
488 2 h# 18 phy! \ Disable Wake on Lan
489 h# 1a phy@ drop \ Read MDI Interrupt_Status Reg twice
490 h# 1a phy@ drop \ to clear sticky bits
491 h# fffd h# 1b phy! \ mask all interrupts except Link Status Change
492;
493
494
495: setup-transceiver ( -- ok? )
496 reset-transceiver drop
497 disable-link-events \ Should be turned off by reset but...
498 check-phy-capability
499 use-autonegotiation? if do-autonegotiation else set-speed&mode then
500 show-link-status
501;