[kernel] move lots of kernel related packages to the new system/ folder
[openwrt.git] / package / system / ep80579-drivers / patches / 150-ocracoke_island.patch
1 --- a/Embedded/src/GbE/iegbe_oem_phy.c
2 +++ b/Embedded/src/GbE/iegbe_oem_phy.c
3 @@ -65,6 +65,10 @@ static int32_t iegbe_oem_link_m88_setup(
4  static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw);
5  static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw);
6  
7 +static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw);
8 +static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data);
9 +static int32_t oi_phy_setup (struct iegbe_hw *hw);
10 +
11  /**
12   * iegbe_oem_setup_link
13   * @hw: iegbe_hw struct containing device specific information
14 @@ -114,6 +118,10 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
15      }
16  
17      switch (hw->phy_id) {
18 +       case BCM5395S_PHY_ID:
19 +               return E1000_SUCCESS;
20 +               break;
21 +
22          case M88E1000_I_PHY_ID:
23          case M88E1141_E_PHY_ID:
24              ret_val = iegbe_oem_link_m88_setup(hw);
25 @@ -121,6 +129,12 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
26                  return ret_val; 
27              }
28          break; 
29 +       case BCM5481_PHY_ID:
30 +               ret_val = iegbe_oem_link_bcm5481_setup(hw);
31 +               if(ret_val) { 
32 +                       return ret_val; 
33 +               }
34 +               break; 
35          default:
36              DEBUGOUT("Invalid PHY ID\n");
37              return -E1000_ERR_PHY_TYPE;
38 @@ -179,6 +193,51 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
39  #endif /* ifdef EXTERNAL_MDIO */
40  }
41  
42 +/**
43 + * iegbe_oem_link_bcm5481_setup
44 + * @hw: iegbe_hw struct containing device specific information
45 + *
46 + * Returns E1000_SUCCESS, negative E1000 error code on failure
47 + *
48 + * copied verbatim from iegbe_oem_link_m88_setup
49 + **/
50 +static int32_t
51 +iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw)
52 +{
53 +       int32_t ret_val;
54 +       uint16_t phy_data;
55 +
56 +       //DEBUGFUNC(__func__);
57 +
58 +       if(!hw)
59 +               return -1;
60 +
61 +       /* phy_reset_disable is set in iegbe_oem_set_phy_mode */
62 +       if(hw->phy_reset_disable)
63 +               return E1000_SUCCESS;
64 +
65 +       // Enable MDIX in extended control reg.
66 +       ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data);
67 +       if(ret_val)
68 +       {
69 +               DEBUGOUT("Unable to read BCM5481_ECTRL register\n");
70 +               return ret_val;
71 +       }
72 +
73 +       phy_data &= ~BCM5481_ECTRL_DISMDIX;
74 +       ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data);
75 +       if(ret_val)
76 +       {
77 +               DEBUGOUT("Unable to write BCM5481_ECTRL register\n");
78 +               return ret_val;
79 +       }
80 +
81 +       ret_val = oi_phy_setup (hw);
82 +       if (ret_val)
83 +               return ret_val;
84 +
85 +       return E1000_SUCCESS;
86 +}
87  
88  /**
89   * iegbe_oem_link_m88_setup
90 @@ -340,6 +399,11 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw,
91       * see iegbe_phy_force_speed_duplex, which does the following for M88
92       */
93        switch (hw->phy_id) {
94 +               case BCM5395S_PHY_ID:
95 +               case BCM5481_PHY_ID:
96 +                       DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n");
97 +                       break;
98 +
99            case M88E1000_I_PHY_ID:
100            case M88E1141_E_PHY_ID:
101                ret_val = iegbe_oem_read_phy_reg_ex(hw, 
102 @@ -415,6 +479,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw
103       switch (hw->phy_id) {
104           case M88E1000_I_PHY_ID:
105           case M88E1141_E_PHY_ID:
106 +               case BCM5481_PHY_ID:
107 +               case BCM5395S_PHY_ID:
108               DEBUGOUT("No DSP to reset on OEM PHY\n");
109           break;
110           default:
111 @@ -460,6 +526,11 @@ iegbe_oem_cleanup_after_phy_reset(struct
112       * see iegbe_phy_force_speed_duplex, which does the following for M88
113       */
114      switch (hw->phy_id) {
115 +               case BCM5395S_PHY_ID:
116 +               case BCM5481_PHY_ID:
117 +            DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n");
118 +        break;
119 +
120          case M88E1000_I_PHY_ID:
121          case M88E1141_E_PHY_ID:
122              /*
123 @@ -573,6 +644,11 @@ iegbe_oem_set_phy_mode(struct iegbe_hw *
124       * use iegbe_set_phy_mode as example
125       */
126      switch (hw->phy_id) {
127 +               case BCM5395S_PHY_ID:
128 +               case BCM5481_PHY_ID:
129 +             DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n");
130 +         break;
131 +
132           case M88E1000_I_PHY_ID:
133           case M88E1141_E_PHY_ID:
134               ret_val = iegbe_read_eeprom(hw, 
135 @@ -641,6 +717,19 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw
136      }
137      hw->phy_type = iegbe_phy_oem;
138  
139 +{
140 +       // If MAC2 (BCM5395 switch), manually detect the phy
141 +       struct iegbe_adapter *adapter;
142 +       uint32_t device_number;
143 +       adapter = (struct iegbe_adapter *) hw->back;
144 +       device_number = PCI_SLOT(adapter->pdev->devfn);
145 +       if (device_number == ICP_XXXX_MAC_2) {
146 +               hw->phy_id = BCM5395S_PHY_ID;
147 +               hw->phy_revision = 0;
148 +               return E1000_SUCCESS;
149 +       }
150 +}
151 +
152      ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high);
153      if(ret_val) {
154          DEBUGOUT("Unable to read PHY register PHY_ID1\n");
155 @@ -690,6 +779,8 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw)
156      switch (hw->phy_id) {
157           case M88E1000_I_PHY_ID:
158           case M88E1141_E_PHY_ID:
159 +               case BCM5481_PHY_ID:
160 +               case BCM5395S_PHY_ID:
161               phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT;
162           break;
163           default:
164 @@ -738,6 +829,8 @@ iegbe_oem_phy_is_copper(struct iegbe_hw
165      switch (hw->phy_id) {
166          case M88E1000_I_PHY_ID:
167          case M88E1141_E_PHY_ID:
168 +               case BCM5481_PHY_ID:
169 +               case BCM5395S_PHY_ID:
170              isCopper = TRUE;
171          break;
172          default:
173 @@ -796,13 +889,13 @@ iegbe_oem_get_phy_dev_number(struct iegb
174         switch(device_number)
175      {
176        case ICP_XXXX_MAC_0: 
177 -             hw->phy_addr = 0x00;
178 +             hw->phy_addr = 0x01;
179           break;
180        case ICP_XXXX_MAC_1: 
181 -             hw->phy_addr = 0x01;
182 +             hw->phy_addr = 0x02;
183           break;
184        case ICP_XXXX_MAC_2: 
185 -             hw->phy_addr = 0x02;
186 +             hw->phy_addr = 0x00;
187           break;
188           default:  hw->phy_addr = 0x00;
189      }
190 @@ -851,6 +944,12 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter
191      if(!adapter || !ifr) {
192          return -1;
193      }
194 +
195 +       // If MAC2 (BCM5395 switch) then leave now
196 +       if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) {
197 +                       return -1;
198 +       }
199 +
200      switch (data->reg_num) {
201          case PHY_CTRL:
202              if(mii_reg & MII_CR_POWER_DOWN) {
203 @@ -987,6 +1086,11 @@ void iegbe_oem_get_phy_regs(struct iegbe
204       * [10] = mdix mode
205       */
206      switch (adapter->hw.phy_id) {
207 +       case BCM5395S_PHY_ID:
208 +       case BCM5481_PHY_ID:
209 +               DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n");
210 +       break;
211 +
212          case M88E1000_I_PHY_ID:
213          case M88E1141_E_PHY_ID:
214              if(corrected_len > 0) {
215 @@ -1068,8 +1172,13 @@ iegbe_oem_phy_loopback(struct iegbe_adap
216       * Loopback configuration is the same for each of the supported PHYs.
217       */
218      switch (adapter->hw.phy_id) {
219 +               case BCM5395S_PHY_ID:
220 +                       DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n");
221 +                       break;
222 +
223          case M88E1000_I_PHY_ID:
224          case M88E1141_E_PHY_ID:
225 +               case BCM5481_PHY_ID:
226  
227            adapter->hw.autoneg = FALSE;
228  
229 @@ -1182,8 +1291,14 @@ iegbe_oem_loopback_cleanup(struct iegbe_
230      }
231  
232      switch (adapter->hw.phy_id) {
233 +               case BCM5395S_PHY_ID:
234 +               DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n");
235 +               return;
236 +               break;
237 +
238          case M88E1000_I_PHY_ID:
239          case M88E1141_E_PHY_ID:
240 +               case BCM5481_PHY_ID:
241          default:
242              adapter->hw.autoneg = TRUE;
243          
244 @@ -1243,6 +1358,11 @@ iegbe_oem_phy_speed_downgraded(struct ie
245       */
246  
247      switch (hw->phy_id) {
248 +               case BCM5395S_PHY_ID:
249 +               case BCM5481_PHY_ID:
250 +                       *isDowngraded = 0;
251 +                       break;
252 +
253          case M88E1000_I_PHY_ID:
254          case M88E1141_E_PHY_ID:
255              ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, 
256 @@ -1305,6 +1425,11 @@ iegbe_oem_check_polarity(struct iegbe_hw
257       */
258  
259      switch (hw->phy_id) {
260 +               case BCM5395S_PHY_ID:
261 +               case BCM5481_PHY_ID:
262 +                       *polarity = 0;
263 +                       break;
264 +
265          case M88E1000_I_PHY_ID:
266          case M88E1141_E_PHY_ID:
267              /* return the Polarity bit in the Status register. */
268 @@ -1367,6 +1492,25 @@ iegbe_oem_phy_is_full_duplex(struct iegb
269       */
270          
271        switch (hw->phy_id) {
272 +               case BCM5395S_PHY_ID:
273 +                       /* Always full duplex */
274 +                       *isFD = 1;
275 +                       break;
276 +
277 +               case BCM5481_PHY_ID:
278 +                       ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
279 +                       if(ret_val) return ret_val;
280 +
281 +                               switch (BCM5481_ASTAT_HCD(phy_data)) {
282 +                                       case BCM5481_ASTAT_1KBTFD:
283 +                                       case BCM5481_ASTAT_100BTXFD:
284 +                                               *isFD = 1;
285 +                                               break;
286 +                                       default:
287 +                                               *isFD = 0;
288 +                               }
289 +                       break;
290 +
291            case M88E1000_I_PHY_ID:
292            case M88E1141_E_PHY_ID:
293               ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
294 @@ -1423,6 +1567,25 @@ iegbe_oem_phy_is_speed_1000(struct iegbe
295       */
296  
297      switch (hw->phy_id) {
298 +               case BCM5395S_PHY_ID:
299 +                       /* Always 1000mb */
300 +                       *is1000 = 1;
301 +                       break;
302 +
303 +               case BCM5481_PHY_ID:
304 +                       ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
305 +                       if(ret_val) return ret_val;
306 +
307 +                               switch (BCM5481_ASTAT_HCD(phy_data)) {
308 +                                       case BCM5481_ASTAT_1KBTFD:
309 +                                       case BCM5481_ASTAT_1KBTHD:
310 +                                               *is1000 = 1;
311 +                                       break;
312 +                               default:
313 +                                       *is1000 = 0;
314 +                               }
315 +                       break;
316 +
317          case M88E1000_I_PHY_ID:
318          case M88E1141_E_PHY_ID:
319              ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, 
320 @@ -1478,6 +1641,25 @@ iegbe_oem_phy_is_speed_100(struct iegbe_
321       * see iegbe_config_mac_to_phy
322       */
323      switch (hw->phy_id) {
324 +               case BCM5395S_PHY_ID:
325 +                       /* Always 1000Mb, never 100mb */
326 +                       *is100 = 0;
327 +                       break;
328 +
329 +               case BCM5481_PHY_ID:
330 +                       ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
331 +                       if(ret_val) return ret_val;
332 +
333 +                       switch (BCM5481_ASTAT_HCD(phy_data)) {
334 +                               case BCM5481_ASTAT_100BTXFD:
335 +                               case BCM5481_ASTAT_100BTXHD:
336 +                                       *is100 = 1;
337 +                                       break;
338 +                               default:
339 +                                       *is100 = 0;
340 +                       }
341 +                       break;
342 +
343          case M88E1000_I_PHY_ID:
344          case M88E1141_E_PHY_ID:
345              ret_val = iegbe_oem_read_phy_reg_ex(hw, 
346 @@ -1535,6 +1717,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw *
347       * see iegbe_phy_m88_get_info
348       */
349      switch (hw->phy_id) {
350 +               case BCM5395S_PHY_ID:
351 +               case BCM5481_PHY_ID:
352 +                       DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n");
353 +                       break;
354 +
355          case M88E1000_I_PHY_ID:
356          case M88E1141_E_PHY_ID:
357    /* The downshift status is checked only once, after link is
358 @@ -1636,8 +1823,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw *
359       * the M88 used in truxton. 
360       */
361      switch (hw->phy_id) {
362 +               case BCM5395S_PHY_ID:
363 +                       DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n");
364 +                       break;
365 +
366          case M88E1000_I_PHY_ID:
367          case M88E1141_E_PHY_ID:
368 +               case BCM5481_PHY_ID:
369              ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data);
370              if(ret_val) {
371                  DEBUGOUT("Unable to read register PHY_CTRL\n");
372 @@ -1699,6 +1891,8 @@ iegbe_oem_phy_init_script(struct iegbe_h
373      switch (hw->phy_id) {
374          case M88E1000_I_PHY_ID:
375          case M88E1141_E_PHY_ID:
376 +               case BCM5481_PHY_ID:
377 +               case BCM5395S_PHY_ID:
378              DEBUGOUT("Nothing to do for OEM PHY Init");
379          break;
380          default:
381 @@ -1735,6 +1929,11 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h
382          return -1;
383      }
384  
385 +       if (hw->phy_id == BCM5395S_PHY_ID) {
386 +               DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n");
387 +               return -1;
388 +       }
389 +
390      /* call the GCU func that will read the phy
391       * 
392       * Make note that the M88 phy is what'll be used on Truxton.
393 @@ -1782,6 +1981,11 @@ iegbe_oem_set_trans_gasket(struct iegbe_
394      }
395  
396       switch (hw->phy_id) {
397 +               case BCM5395S_PHY_ID:
398 +               case BCM5481_PHY_ID:
399 +                       DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n");
400 +                       break;
401 +
402           case M88E1000_I_PHY_ID:
403           case M88E1141_E_PHY_ID:
404           /* Gasket set correctly for Marvell Phys, so nothing to do */
405 @@ -1886,6 +2090,8 @@ iegbe_oem_phy_needs_reset_with_mac(struc
406      switch (hw->phy_id) {
407          case M88E1000_I_PHY_ID:
408          case M88E1141_E_PHY_ID:
409 +               case BCM5481_PHY_ID:
410 +               case BCM5395S_PHY_ID:
411              ret_val = FALSE;
412          break;
413          default:
414 @@ -1935,6 +2141,8 @@ iegbe_oem_config_dsp_after_link_change(s
415      switch (hw->phy_id) {
416          case M88E1000_I_PHY_ID:
417          case M88E1141_E_PHY_ID:
418 +               case BCM5481_PHY_ID:
419 +               case BCM5395S_PHY_ID:
420              DEBUGOUT("No DSP to configure on OEM PHY");
421          break;
422          default:
423 @@ -1978,6 +2186,12 @@ iegbe_oem_get_cable_length(struct iegbe_
424      }
425  
426      switch (hw->phy_id) {
427 +               case BCM5395S_PHY_ID:
428 +               case BCM5481_PHY_ID:
429 +                       *min_length = 0;
430 +                       *max_length = iegbe_igp_cable_length_150;
431 +                       break;
432 +
433          case M88E1000_I_PHY_ID:
434          case M88E1141_E_PHY_ID:
435              ret_val = iegbe_oem_read_phy_reg_ex(hw, 
436 @@ -2061,6 +2275,23 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw
437       */
438  
439      switch (hw->phy_id) {
440 +               case BCM5395S_PHY_ID:
441 +                       /* Link always up */
442 +                       *isUp = TRUE;
443 +                       return E1000_SUCCESS;
444 +                       break;
445 +
446 +               case BCM5481_PHY_ID:
447 +                       iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data);
448 +                       ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data);
449 +                       if(ret_val)
450 +                       {
451 +                               DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n");
452 +                               return ret_val;
453 +                       }
454 +                       statusMask = BCM5481_ESTAT_LINK;
455 +                       break;
456 +
457          case M88E1000_I_PHY_ID:
458          case M88E1141_E_PHY_ID:
459              iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); 
460 @@ -2092,3 +2323,210 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw
461  #endif /* ifdef EXTERNAL_MDIO */
462  }
463  
464 +
465 +
466 +//-----
467 +// Read BCM5481 expansion register
468 +//
469 +int32_t
470 +bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data)
471 +{
472 +       int ret;
473 +       uint16_t selector;
474 +       uint16_t reg_data;
475 +
476 +       // Get the current value of bits 15:12
477 +       ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector);
478 +       if (ret)
479 +               return ret;
480 +
481 +       // Select the expansion register
482 +       selector &= 0xf000;
483 +       selector |= (0xf << 8) | (reg);
484 +       iegbe_oem_write_phy_reg_ex (hw, 0x17, selector);
485 +
486 +       // Read the expansion register
487 +       ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &reg_data);
488 +
489 +       // De-select the expansion registers.
490 +       selector &= 0xf000;
491 +       iegbe_oem_write_phy_reg_ex (hw, 0x17, selector);
492 +
493 +       if (ret)
494 +               return ret;
495 +
496 +       *data = reg_data;
497 +       return ret;
498 +}
499 +
500 +//-----
501 +//     Read reg 0x18 sub-register
502 +//
503 +static int32_t
504 +bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data)
505 +{
506 +       int     ret;
507 +       uint16_t        tmp_data;
508 +
509 +       // Select reg 0x18, sv
510 +       tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL;
511 +       ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data);
512 +       if(ret)
513 +               return ret;
514 +
515 +       // Read reg 0x18, sv
516 +       ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data);
517 +       if(ret)
518 +               return ret;
519 +
520 +       *data = tmp_data;
521 +       return ret;
522 +}
523 +
524 +//-----
525 +//     Read reg 0x1C sub-register
526 +//
527 +int32_t
528 +bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data)
529 +{
530 +       int ret;
531 +       uint16_t tmp_data;
532 +
533 +       // Select reg 0x1c, sv
534 +       tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT);
535 +
536 +       ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data);
537 +       if(ret)
538 +               return ret;
539 +
540 +       // Read reg 0x1c, sv
541 +       ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data);
542 +       if(ret)
543 +               return ret;
544 +
545 +       *data = tmp_data;
546 +       return ret;
547 +}
548 +
549 +//-----
550 +//     Read-modify-write a 0x1C register.
551 +//
552 +//     hw   - hardware access info.
553 +//     reg  - 0x1C register to modify.
554 +//     data - bits which should be set.
555 +//     mask - the '1' bits in this argument will be cleared in the data
556 +//         read from 'reg' then 'data' will be or'd in and the result
557 +//         will be written to 'reg'.
558 +
559 +int32_t
560 +bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask)
561 +{
562 +       int32_t         ret;
563 +       uint16_t        reg_data;
564 +
565 +       ret = 0;
566 +
567 +       ret = bcm5481_read_1csv (hw, reg, &reg_data);
568 +       if (ret)
569 +       {
570 +               DEBUGOUT("Unable to read BCM5481 1CH register\n");
571 +               printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg);
572 +               return ret;
573 +       }
574 +
575 +       reg_data &= ~mask;
576 +       reg_data |= (BCM5481_R1CH_WE | data);
577 +
578 +       ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data);
579 +       if(ret)
580 +       {
581 +               DEBUGOUT("Unable to write BCM5481 1CH register\n");
582 +               printk (KERN_ERR "Unable to write BCM5481 1CH register\n");
583 +               return ret;
584 +       }
585 +
586 +       return ret;
587 +}
588 +
589 +int32_t
590 +oi_phy_setup (struct iegbe_hw *hw)
591 +{
592 +       int     ret;
593 +       uint16_t        pmii_data;
594 +       uint16_t        mctrl_data;
595 +       uint16_t        cacr_data;
596 +
597 +       ret = 0;
598 +
599 +       // Set low power mode via reg 0x18, sv010, bit 6
600 +       // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits.
601 +       ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data);
602 +       if (ret)
603 +       {
604 +               DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n");
605 +               printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n");
606 +               return ret;
607 +       }
608 +
609 +       // Set the LPM bit in the data just read and write back to sv010
610 +       // The shadow register select bits [2:0] are set by reading the sv010
611 +       // register.
612 +       pmii_data |= BCM5481_R18H_SV010_LPM;
613 +       ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data);
614 +       if(ret)
615 +       {
616 +               DEBUGOUT("Unable to write BCM5481_R18H register\n");
617 +               printk (KERN_ERR "Unable to write BCM5481_R18H register\n");
618 +               return ret;
619 +       }
620 +
621 +
622 +       // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111
623 +
624 +       if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data))
625 +       {
626 +               DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n");
627 +               printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n");
628 +               return ret;
629 +       }
630 +       mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW);
631 +
632 +       ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data);
633 +       if(ret)
634 +       {
635 +               DEBUGOUT("Unable to write BCM5481_R18H register\n");
636 +               printk (KERN_ERR "Unable to write BCM5481_R18H register\n");
637 +               return ret;
638 +       }
639 +
640 +       // Enable RGMII transmit clock delay in reg 0x1c, sv00011
641 +       ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data);
642 +       if (ret)
643 +       {
644 +               DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n");
645 +               printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n");
646 +               return ret;
647 +       }
648 +
649 +       cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD);
650 +
651 +       ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data);
652 +       if(ret)
653 +       {
654 +               DEBUGOUT("Unable to write BCM5481_R1CH register\n");
655 +               printk (KERN_ERR "Unable to write BCM5481_R1CH register\n");
656 +               return ret;
657 +       }
658 +
659 +       // Enable dual link speed indication (0x1c, sv 00010, bit 2)
660 +       ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK);
661 +       if (ret)
662 +               return ret;
663 +
664 +       // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0)
665 +       ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN);
666 +       if (ret)
667 +               return ret;
668 +
669 +       return ret;
670 +}
671 --- a/Embedded/src/GbE/iegbe_oem_phy.h
672 +++ b/Embedded/src/GbE/iegbe_oem_phy.h
673 @@ -95,6 +95,8 @@ int32_t iegbe_oem_phy_is_link_up(struct
674  
675  #define DEFAULT_ICP_XXXX_TIPG_IPGT 8      /* Inter Packet Gap Transmit Time */
676  #define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL 
677 +#define BCM5481_PHY_ID         0x0143BCA0
678 +#define BCM5395S_PHY_ID                0x0143BCF0
679  
680  /* Miscellaneous defines */
681  #ifdef IEGBE_10_100_ONLY
682 @@ -103,5 +105,65 @@ int32_t iegbe_oem_phy_is_link_up(struct
683      #define ICP_XXXX_AUTONEG_ADV_DEFAULT       0x2F
684  #endif
685  
686 +/* BCM5481 specifics */
687 +
688 +#define BCM5481_ECTRL          (0x10)
689 +#define BCM5481_ESTAT          (0x11)
690 +#define BCM5481_RXERR          (0x12)
691 +#define BCM5481_EXPRW          (0x15)
692 +#define BCM5481_EXPACC         (0x17)
693 +#define BCM5481_ASTAT          (0x19)
694 +#define BCM5481_R18H           (0x18)
695 +#define BCM5481_R1CH           (0x1c)
696 +
697 +/* indirect register access via register 18h */
698 +
699 +#define BCM5481_R18H_SV_MASK   (7) // Mask for SV bits.
700 +#define BCM5481_R18H_SV_ACTRL  (0) // SV000 Aux. control
701 +#define BCM5481_R18H_SV_10BT   (1) // SV001 10Base-T
702 +#define BCM5481_R18H_SV_PMII   (2) // SV010 Power/MII control
703 +#define BCM5481_R18H_SV_MTEST  (4) // SV100 Misc. test
704 +#define BCM5481_R18H_SV_MCTRL  (7) // SV111 Misc. control
705 +
706 +#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity
707 +#define BCM5481_R18H_SV010_LPM (1 << 6)
708 +#define BCM5481_R18H_SV111_SKEW        (1 << 8)
709 +#define BCM5481_R18H_WE                (1 << 15) // Write enable
710 +
711 +// 0x1c registers
712 +#define BCM5481_R1CH_SV_SHIFT  (10)
713 +#define BCM5481_R1CH_SV_MASK   (0x1f)
714 +#define BCM5481_R1CH_SC1       (0x02) // sv00010 Spare control 1
715 +#define BCM5481_R1CH_CACR      (0x03) // sv00011 Clock alignment control
716 +#define BCM5481_R1CH_LCTRL     (0x09) // sv01001 LED control
717 +#define BCM5481_R1CH_LEDS1     (0x0d) // sv01101 LED selector 1
718 +
719 +// 0x1c common
720 +#define BCM5481_R1CH_WE                (1 << 15) // Write enable
721 +
722 +// 0x1c, sv 00010
723 +#define BCM5481_R1CH_SC1_LINK  (1 << 2) // sv00010 Linkspeed
724 +
725 +// 0x1c, sv 00011
726 +#define BCM5481_R1CH_CACR_TCD  (1 << 9) // sv00011 RGMII tx clock delay
727 +
728 +// 0x1c, sv 01001
729 +#define BCM5481_R1CH_LCTRL_ALEN        (1 << 4) // Activity/Link enable on ACTIVITY LED
730 +#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED
731 +
732 +#define BCM5481_ECTRL_DISMDIX  (1 <<14)
733 +
734 +#define BCM5481_MCTRL_AUTOMDIX (1 <<9)
735 +
736 +#define BCM5481_ESTAT_LINK     (1 << 8)
737 +
738 +#define BCM5481_ASTAT_ANC      (1 << 15)
739 +#define BCM5481_ASTAT_ANHCD    (7 << 8)
740 +#define BCM5481_ASTAT_HCD(x)   ((x >> 8) & 7)
741 +#define BCM5481_ASTAT_1KBTFD   (0x7)
742 +#define BCM5481_ASTAT_1KBTHD   (0x6)
743 +#define BCM5481_ASTAT_100BTXFD (0x5)
744 +#define BCM5481_ASTAT_100BTXHD (0x3)
745 +
746  #endif /* ifndef _IEGBE_OEM_PHY_H_ */
747