1 /*******************************************************************************
2  * Copyright 2020 Microchip Corporation.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Microsemi VSC8662 PHY interface driver implementation to support the silicon
7  * validation board.
8  *
9  * Will need to modify FW based on MSS GPIO configuration.
10  *
11  */
12 #include "mpfs_hal/mss_hal.h"
13 #include "hal/hal.h"
14 
15 #include "drivers/mss_ethernet_mac/mss_ethernet_registers.h"
16 #include "drivers/mss_ethernet_mac/mss_ethernet_mac_regs.h"
17 #include "drivers/mss_ethernet_mac/mss_ethernet_mac_sw_cfg.h"
18 #include "drivers/mss_ethernet_mac/mss_ethernet_mac.h"
19 #include "drivers/mss_ethernet_mac/phy.h"
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 #if MSS_MAC_USE_PHY_VSC8662
26 
27 /**************************************************************************/
28 /* Preprocessor Macros                                                    */
29 /**************************************************************************/
30 
31 #define BMSR_AUTO_NEGOTIATION_COMPLETE  (0x0020U)
32 
33 /**************************************************************************//**
34  * Ensure ports 2 and 3 are shut down as they are not bonded out for the
35  * VSC8862.
36  */
vsc8662_post_reset_step_01(const mss_mac_instance_t * this_mac)37 static void vsc8662_post_reset_step_01(const mss_mac_instance_t *this_mac)
38 {
39     uint32_t phy_base_address;
40 
41     phy_base_address = this_mac->phy_addr & 0xFCU; /* Calculate base address for chip */
42     MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + 2), 31, 0x0000U);
43     MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + 2),  0, 0x0800U);
44     MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + 3), 31, 0x0000U);
45     MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + 3),  0, 0x0800U);
46 }
47 
48 
49 /**************************************************************************//**
50  * Enable broadcast writes for the VSC8662
51  */
vsc8662_enable_bcast_writes(const mss_mac_instance_t * this_mac)52 static void vsc8662_enable_bcast_writes(const mss_mac_instance_t *this_mac)
53 {
54     uint32_t phy_base_address;
55     uint16_t temp_reg;
56 
57     phy_base_address = this_mac->phy_addr & 0xFCU; /* Calculate base address for chip */
58     MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address), 31, 0x0000U);
59     temp_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)(phy_base_address), 22);
60     temp_reg |= 0x0001U;
61     MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address), 22, temp_reg);
62 }
63 
64 
65 /**************************************************************************//**
66  * Disable broadcast writes for the VSC8662
67  */
vsc8662_disable_bcast_writes(const mss_mac_instance_t * this_mac)68 static void vsc8662_disable_bcast_writes(const mss_mac_instance_t *this_mac)
69 {
70     uint32_t phy_base_address;
71     uint16_t temp_reg;
72 
73     phy_base_address = this_mac->phy_addr & 0xFCU; /* Calculate base address for chip */
74     MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address), 31, 0x0000U);
75     temp_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)(phy_base_address), 22);
76     temp_reg &= 0xFFFEU;
77     MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address), 22, temp_reg);
78 }
79 
80 
81 /**************************************************************************//**
82  * Enable LED blinking for the VSC8662
83  */
vsc8662_enable_LED_blink(const mss_mac_instance_t * this_mac)84 static void vsc8662_enable_LED_blink(const mss_mac_instance_t *this_mac)
85 {
86     uint32_t phy_base_address;
87     uint16_t temp_reg;
88     uint32_t count;
89 
90     phy_base_address = this_mac->phy_addr & 0xFCU; /* Calculate base address for chip */
91 
92     for(count = 0; count != 2; count++)
93     {
94         /* Enable LED blink port[count] */
95         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 31, 0x0001U);
96         temp_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 19);
97         temp_reg |= 0x0800U;
98         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 19, temp_reg);
99 
100         /* Soft reset port[count] */
101         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 31, 0x0000U);
102         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count),  0, 0x9040U);
103     }
104 }
105 
106 
107 /**************************************************************************//**
108  * Apply 100/1000BASE-T amplitude correction fix for the VSC8662.
109  */
vsc8662_100tx_1000t_amplitude_fix(const mss_mac_instance_t * this_mac)110 static void vsc8662_100tx_1000t_amplitude_fix(const mss_mac_instance_t *this_mac)
111 {
112     uint32_t phy_base_address;
113     uint16_t temp_reg;
114     uint32_t count;
115 
116     phy_base_address = this_mac->phy_addr & 0xFCU; /* Calculate base address for chip */
117 
118     for(count = 0; count != 2; count++)
119     {
120         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 31, 0x52B5U);
121 
122         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0000U);
123         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x003FU);
124         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x8794U);
125 
126         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x00F7U);
127         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0xADB4U);
128         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x879EU);
129 
130         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0000U);
131         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x0032U);
132         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87A0U);
133 
134         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0041U);
135         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x0410U);
136         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87A2U);
137 
138         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0041U);
139         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x0410U);
140         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87A4U);
141 
142         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0041U);
143         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x0284U);
144         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87A6U);
145 
146         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0092U);
147         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0xBCB8U);
148         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87A8U);
149 
150         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0003U);
151         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0xCFBFU);
152         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87AAU);
153 
154         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0049U);
155         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x2451U);
156         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87ACU);
157 
158         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0001U);
159         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x1410U);
160         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87C0U);
161 
162         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0010U);
163         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0xB498U);
164         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87E8U);
165 
166         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0071U);
167         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0xE7DDU);
168         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87EAU);
169 
170         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0069U);
171         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x6512U);
172         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87ECU);
173 
174         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0049U);
175         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x2451U);
176         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87EEU);
177 
178         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0045U);
179         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x0410U);
180         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87F0U);
181 
182         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0041U);
183         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x0410U);
184         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87F2U);
185 
186         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0000U);
187         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x0010U);
188         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x87F4U);
189 
190         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 31, 0x2A30U);
191         temp_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 9);
192         temp_reg = (uint16_t)((temp_reg & 0xFFFFU) | 0x0040U);
193         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 9, temp_reg);
194 
195         temp_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 22);
196         temp_reg = (uint16_t)((temp_reg & 0xFFFFU) | 0x0010U);
197         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 22, temp_reg);
198         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 31, 0x0000U);
199     }
200 }
201 
202 
203 /**************************************************************************//**
204  * Apply 10BASE-T performance fix for the VSC8662.
205  */
vsc8662_10t_performance_fix(const mss_mac_instance_t * this_mac)206 static void vsc8662_10t_performance_fix(const mss_mac_instance_t *this_mac)
207 {
208     uint32_t phy_base_address;
209     uint16_t temp_reg;
210     uint32_t count;
211 
212     phy_base_address = this_mac->phy_addr & 0xFCU; /* Calculate base address for chip */
213 
214     for(count = 0; count != 2; count++)
215     {
216         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 31, 0x2A30U);
217         temp_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 0);
218         temp_reg = (uint16_t)((temp_reg & 0xFFEFU) | 0x0060U);
219         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 0, temp_reg);
220 
221         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 31, 0x52B5U);
222 
223         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0012U);
224         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x480AU);
225         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x8F82U);
226 
227         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0000U);
228         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x0422U);
229         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x8F86U);
230 
231         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x003CU);
232         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0x3800U);
233         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x8F8AU);
234 
235         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 18, 0x0008U);
236         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 17, 0xE33FU);
237         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 16, 0x83AEU);
238 
239         MSS_MAC_write_phy_reg(this_mac, (uint8_t)(phy_base_address + count), 31, 0x0000U);
240     }
241 }
242 
243 
244 /**************************************************************************//**
245  *
246  */
MSS_MAC_VSC8662_phy_init(const void * v_this_mac,uint8_t phy_addr)247 void MSS_MAC_VSC8662_phy_init(/* mss_mac_instance_t*/ const void *v_this_mac, uint8_t phy_addr)
248 {
249     uint16_t temp_reg;
250     volatile uint16_t phy_reg;
251     const mss_mac_instance_t *this_mac = (const mss_mac_instance_t *)v_this_mac;
252     mss_mac_instance_t *phy_mac;
253     volatile uint32_t sgmii_aneg_timeout = 100000U;
254     uint16_t autoneg_complete;
255     volatile uint64_t timer_count = 1000000;
256 
257     /* Do hardware reset if possible/necessary */
258 
259     /* Phy is actually attached to another MAC... */
260     if((struct mss_mac_instance *)0UL != this_mac->phy_controller)
261     {
262         phy_mac = (mss_mac_instance_t *)this_mac->phy_controller;
263     }
264     else
265     {
266         phy_mac = (mss_mac_instance_t *)this_mac;
267     }
268 #if defined(MSS_MAC_PHY_HW_RESET) || defined(MSS_MAC_PHY_HW_SRESET)
269     if(0 == phy_mac->phy_hard_reset_done)
270     {
271         /* Active low reset pulse */
272         MSS_MAC_phy_reset(phy_mac, MSS_MAC_HARD_RESET, false);
273         MSS_MAC_phy_reset(phy_mac, MSS_MAC_HARD_RESET, true);
274 
275 #if defined(TARGET_G5_SOC)
276         /*
277          * Multiple MACs may be involved and we need to ensure all relevant MACs
278          * have the phy_hard_reset_done flag set
279          */
280 
281         if(phy_mac != this_mac) /* Simple case, set flag for all 4 MACs */
282         {
283             g_mac0.phy_hard_reset_done  = true;
284             g_emac0.phy_hard_reset_done = true;
285             g_mac1.phy_hard_reset_done  = true;
286             g_emac1.phy_hard_reset_done = true;
287         }
288         else if((&g_mac0 == phy_mac) || (&g_emac0 == phy_mac))
289         {
290             g_mac0.phy_hard_reset_done  = true;
291             g_emac0.phy_hard_reset_done = true;
292         }
293         else
294         {
295             g_mac1.phy_hard_reset_done  = true;
296             g_emac1.phy_hard_reset_done = true;
297         }
298 #else
299         phy_mac->phy_hard_reset_done = true;
300 #endif
301     }
302 #endif /* defined(MSS_MAC_PHY_HW_RESET) || defined(MSS_MAC_PHY_HW_RESET) */
303 
304     /* Select standard registers page */
305     MSS_MAC_write_phy_reg(this_mac, phy_addr, 31, 0x0000U);
306 
307     /*
308      * Enable SGMII MAC link autonegotiation and Force copper media only
309      *
310      * According to a VSC8664 app note this register needs to be updated first
311      * followed by a soft reset, the scripts and finally the rest of the user
312      * setup.
313      */
314     MSS_MAC_write_phy_reg(this_mac, phy_addr, 23, (uint16_t)(0x2880U));
315 
316     /* Soft reset */
317     temp_reg = MSS_MAC_read_phy_reg(this_mac, phy_addr, 0);
318     temp_reg |= 0x8000;
319     MSS_MAC_write_phy_reg(this_mac, phy_addr, 0, temp_reg);
320 
321     /*
322      * Need at least a 4uS pause here after setting reset bit before accessing
323      * PHY again
324      */
325     while(0 != timer_count)
326         {
327         --timer_count;
328         }
329 
330     /* First take care of all the fixes and adjustments from the data sheet */
331     vsc8662_post_reset_step_01(this_mac);
332     vsc8662_enable_LED_blink(this_mac);
333     vsc8662_100tx_1000t_amplitude_fix(this_mac);
334     vsc8662_10t_performance_fix(this_mac);
335 
336     /* Select standard registers page */
337     MSS_MAC_write_phy_reg(this_mac, phy_addr, 31, 0x0000U);
338 
339     if(MSS_MAC_SPEED_AN == this_mac->speed_mode)
340     {
341         /* Full duplex, autonegotiation and 1000Mbps as starting point */
342         MSS_MAC_write_phy_reg(this_mac, phy_addr, MII_BMCR, (uint16_t)(BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000));
343     }
344     else
345     {
346         temp_reg = 0x0000U; /* Default with 10M, half duplex */
347 
348         if((MSS_MAC_10_FDX == this_mac->speed_mode) || (MSS_MAC_100_FDX == this_mac->speed_mode) || (MSS_MAC_1000_FDX == this_mac->speed_mode))
349         {
350             temp_reg |= BMCR_FULLDPLX;
351         }
352 
353         if((MSS_MAC_100_FDX == this_mac->speed_mode) || (MSS_MAC_100_HDX == this_mac->speed_mode))
354         {
355             temp_reg |= BMCR_SPEED100;
356         }
357 
358         if((MSS_MAC_1000_FDX == this_mac->speed_mode) || (MSS_MAC_1000_HDX == this_mac->speed_mode))
359         {
360             temp_reg |=  BMCR_SPEED1000;
361         }
362 
363         /* Apply static speed/duplex selection */
364         MSS_MAC_write_phy_reg(this_mac, phy_addr, MII_BMCR, temp_reg);
365     }
366 
367     /* Full duplex modes */
368     MSS_MAC_write_phy_reg(this_mac, phy_addr, MII_ADVERTISE, (uint16_t)(ADVERTISE_FULL));
369 
370     /* Full duplex mode or half duplex, multi port device */
371     if((MSS_MAC_10_FDX == this_mac->speed_mode) || (MSS_MAC_100_FDX == this_mac->speed_mode) || (MSS_MAC_1000_FDX == this_mac->speed_mode))
372     {
373         MSS_MAC_write_phy_reg(this_mac, phy_addr, MII_CTRL1000, (uint16_t)(ADVERTISE_1000FULL | 0x0400U ));
374     }
375     else
376     {
377         MSS_MAC_write_phy_reg(this_mac, phy_addr, MII_CTRL1000, (uint16_t)(ADVERTISE_1000HALF | 0x0400U ));
378     }
379     /* Auto MDI/MDI-X, Do not ignore advertised ability, enable CLKOUT */
380     MSS_MAC_write_phy_reg(this_mac, phy_addr, 18, (uint16_t)(0x0089U));
381 
382     /* SGMII no input preamble, 2 byte output preamble, 9/12K jumbo frames (12K for 60ppm clock) */
383     MSS_MAC_write_phy_reg(this_mac, phy_addr, 24, (uint16_t)(0xC050U));
384 
385     /* Select selection of LED activity modes for 4 LEDs */
386     MSS_MAC_write_phy_reg(this_mac, phy_addr, 29, (uint16_t)(0x0123U));
387 
388     /* Clear this for consistency as many bits are CMODE selections */
389     MSS_MAC_write_phy_reg(this_mac, phy_addr, 30, (uint16_t)(0x0000U));
390 
391     /* Select extended registers page */
392     MSS_MAC_write_phy_reg(this_mac, phy_addr, 31, 0x0001U);
393 
394     /* Enable RX Equalization and Hysteresis on SERDES interface */
395     MSS_MAC_write_phy_reg(this_mac, phy_addr, 11, (uint16_t)(0x0292U));
396 
397     /* Clear SIGDET polarity to active high */
398     temp_reg = MSS_MAC_read_phy_reg(this_mac, phy_addr, 19);
399     temp_reg &= 0xFFFE;
400     MSS_MAC_write_phy_reg(this_mac, phy_addr, 19, temp_reg);
401 
402     /* Ensure all CMODE bits are clear */
403     temp_reg = MSS_MAC_read_phy_reg(this_mac, phy_addr, 20);
404     temp_reg &= 0xFE6F;
405     MSS_MAC_write_phy_reg(this_mac, phy_addr, 20, temp_reg);
406 
407     /* Select general purpose registers page */
408     MSS_MAC_write_phy_reg(this_mac, phy_addr, 31, 0x0010U);
409 
410     /* Disable SIGDET operation */
411     MSS_MAC_write_phy_reg(this_mac, phy_addr, 13, (uint16_t)(0x000FU));
412 
413 #if defined(MSS_MAC_VSC8662_NWC_25)
414     /* 25MHZ Recovered clock 1 and 2 enabled with ref clock source and no squelch */
415     MSS_MAC_write_phy_reg(this_mac, phy_addr, 23, (uint16_t)(0x8033U));
416     MSS_MAC_write_phy_reg(this_mac, phy_addr, 24, (uint16_t)(0x8033U));
417 #elif defined(MSS_MAC_VSC8662_NWC_125)
418     /* 125MHZ Recovered clock 1 and 2 enabled with ref clock source and no squelch */
419     MSS_MAC_write_phy_reg(this_mac, phy_addr, 23, (uint16_t)(0x8133U));
420     MSS_MAC_write_phy_reg(this_mac, phy_addr, 24, (uint16_t)(0x8133U));
421 #endif
422 
423     /* Select standard registers page */
424     MSS_MAC_write_phy_reg(this_mac, phy_addr, 31, 0x0000U);
425 
426     phy_reg = (uint16_t)this_mac->mac_base->PCS_CONTROL;
427     phy_reg |= 0x1000U;
428     this_mac->mac_base->PCS_CONTROL = phy_reg;
429     phy_reg |= 0x0200U;
430     this_mac->mac_base->PCS_CONTROL = phy_reg;
431 
432     /* Wait for SGMII auto-negotiation to complete. */
433     do {
434         phy_reg = (uint16_t)this_mac->mac_base->PCS_STATUS;
435         autoneg_complete = phy_reg & BMSR_AUTO_NEGOTIATION_COMPLETE;
436         --sgmii_aneg_timeout;
437     } while(((0U == autoneg_complete) && (0U != sgmii_aneg_timeout)) || (0xFFFFU == phy_reg));
438 }
439 
440 
441 /**************************************************************************//**
442  *
443  */
MSS_MAC_VSC8662_phy_set_link_speed(void * v_this_mac,uint32_t speed_duplex_select,mss_mac_speed_mode_t speed_mode)444 void MSS_MAC_VSC8662_phy_set_link_speed(/* mss_mac_instance_t */ void *v_this_mac, uint32_t speed_duplex_select, mss_mac_speed_mode_t speed_mode)
445 {
446     mss_mac_instance_t *this_mac = (mss_mac_instance_t *)v_this_mac;
447     uint16_t phy_reg;
448     uint32_t inc;
449     uint32_t speed_select;
450     const uint16_t mii_advertise_bits[4] = {ADVERTISE_10FULL, ADVERTISE_10HALF,
451                                             ADVERTISE_100FULL, ADVERTISE_100HALF};
452 
453     this_mac->speed_mode = speed_mode;
454 
455     if(MSS_MAC_SPEED_AN == speed_mode) /* Set auto-negotiation advertisement. */
456     {
457         /* Set 10Mbps and 100Mbps advertisement. */
458         phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_ADVERTISE);
459         phy_reg &= (uint16_t)(~(ADVERTISE_10HALF | ADVERTISE_10FULL |
460                      ADVERTISE_100HALF | ADVERTISE_100FULL));
461 
462         speed_select = speed_duplex_select;
463         for(inc = 0U; inc < 4U; ++inc)
464         {
465             uint32_t advertise;
466             advertise = speed_select & 0x00000001U;
467             if(advertise != 0U)
468             {
469                 phy_reg |= mii_advertise_bits[inc];
470             }
471             speed_select = speed_select >> 1U;
472         }
473 
474         MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_ADVERTISE, phy_reg);
475 
476         /* Set 1000Mbps advertisement. */
477         phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_CTRL1000);
478         phy_reg &= (uint16_t)(~(ADVERTISE_1000FULL | ADVERTISE_1000HALF));
479 
480         if((speed_duplex_select & MSS_MAC_ANEG_1000M_FD) != 0U)
481         {
482             phy_reg |= ADVERTISE_1000FULL;
483         }
484 
485         if((speed_duplex_select & MSS_MAC_ANEG_1000M_HD) != 0U)
486         {
487             phy_reg |= ADVERTISE_1000HALF;
488         }
489 
490         MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_CTRL1000, phy_reg);
491     }
492     else
493     {
494         uint16_t temp_reg = 0x0000U; /* Default with 10M, half duplex */
495 
496         if((MSS_MAC_10_FDX == this_mac->speed_mode) || (MSS_MAC_100_FDX == this_mac->speed_mode) || (MSS_MAC_1000_FDX == this_mac->speed_mode))
497         {
498             temp_reg |= BMCR_FULLDPLX;
499         }
500 
501         if((MSS_MAC_100_FDX == this_mac->speed_mode) || (MSS_MAC_100_HDX == this_mac->speed_mode))
502         {
503             temp_reg |= BMCR_SPEED100;
504         }
505 
506         if((MSS_MAC_1000_FDX == this_mac->speed_mode) || (MSS_MAC_1000_HDX == this_mac->speed_mode))
507         {
508             temp_reg |=  BMCR_SPEED1000;
509             /* Set Master mode */
510             phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_CTRL1000);
511             phy_reg |= 0x1800U;
512             MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_CTRL1000, phy_reg);
513         }
514 
515         /* Apply static speed/duplex selection */
516         MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_BMCR, temp_reg);
517 
518         /* Full duplex mode or half duplex, multi port device */
519         if((MSS_MAC_10_FDX == this_mac->speed_mode) || (MSS_MAC_100_FDX == this_mac->speed_mode) || (MSS_MAC_1000_FDX == this_mac->speed_mode))
520         {
521             MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_CTRL1000, (uint16_t)(ADVERTISE_1000FULL | 0x0400U ));
522         }
523         else
524         {
525             MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_CTRL1000, (uint16_t)(ADVERTISE_1000HALF | 0x0400U ));
526         }
527     }
528 }
529 
530 
531 /**************************************************************************//**
532  *
533  */
MSS_MAC_VSC8662_phy_autonegotiate(const void * v_this_mac)534 void MSS_MAC_VSC8662_phy_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac)
535 {
536     const mss_mac_instance_t *this_mac = (const mss_mac_instance_t *)v_this_mac;
537     volatile uint16_t phy_reg;
538     uint16_t autoneg_complete;
539     volatile uint32_t copper_aneg_timeout = 100000U;
540 
541     if(MSS_MAC_SPEED_AN == this_mac->speed_mode) /* Only do if allowed */
542     {
543         phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 2U);
544         phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 3U);
545 
546         /* Enable auto-negotiation. */
547         phy_reg = 0x1340U;
548         MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_BMCR, phy_reg);
549 
550         /* Wait for copper auto-negotiation to complete. */
551         do {
552             phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_BMSR);
553             autoneg_complete = phy_reg & BMSR_AUTO_NEGOTIATION_COMPLETE;
554             --copper_aneg_timeout;
555         } while(((0U == autoneg_complete) && (copper_aneg_timeout != 0u)) || (0xFFFF == phy_reg));
556     }
557 }
558 
559 
560 /**************************************************************************//**
561  *
562  */
MSS_MAC_VSC8662_mac_autonegotiate(const void * v_this_mac)563 void MSS_MAC_VSC8662_mac_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac)
564 {
565     const mss_mac_instance_t *this_mac = (const mss_mac_instance_t *)v_this_mac;
566     volatile uint16_t phy_reg;
567     uint16_t autoneg_complete;
568     volatile uint32_t copper_aneg_timeout = 10000U;
569 
570     /* Enable auto-negotiation. */
571     phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 27);
572     phy_reg |= 0x1000U;
573     MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 27, phy_reg);
574 
575     if(0U == this_mac->is_emac)
576     {
577         volatile uint32_t temp_reg;
578 
579         temp_reg = this_mac->mac_base->PCS_CONTROL;
580         this_mac->mac_base->PCS_CONTROL = temp_reg | GEM_RESTART_AUTO_NEG;
581     }
582 
583     /* Wait for SGMII auto-negotiation to complete. */
584     do {
585         phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 27);
586         autoneg_complete = phy_reg & 0x0002U;
587         --copper_aneg_timeout;
588     } while(((0U == autoneg_complete) && (copper_aneg_timeout != 0u)) || (0xFFFF == phy_reg));
589 }
590 
591 
592 /**************************************************************************//**
593  *
594  */
MSS_MAC_VSC8662_phy_get_link_status(const void * v_this_mac,mss_mac_speed_t * speed,uint8_t * fullduplex)595 uint8_t MSS_MAC_VSC8662_phy_get_link_status
596 (
597     /* mss_mac_instance_t */ const void *v_this_mac,
598     mss_mac_speed_t * speed,
599     uint8_t *     fullduplex
600 )
601 {
602     const mss_mac_instance_t *this_mac = (const mss_mac_instance_t *)v_this_mac;
603     uint16_t phy_reg;
604     uint16_t link_up;
605     uint8_t link_status;
606 
607     phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, MII_BMSR);
608     link_up = phy_reg & BMSR_LSTATUS;
609 
610     if(link_up != MSS_MAC_LINK_DOWN)
611     {
612         uint16_t duplex;
613         uint16_t speed_field;
614 
615         /* Link is up. */
616         link_status = MSS_MAC_LINK_UP;
617 
618         phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 0x1CU); /* Device Auxillary Control and Status */
619         duplex = phy_reg & 0x0020U;
620         speed_field = phy_reg & 0x0018U;
621 
622         if(MSS_MAC_HALF_DUPLEX == duplex)
623         {
624             *fullduplex = MSS_MAC_HALF_DUPLEX;
625         }
626         else
627         {
628             *fullduplex = MSS_MAC_FULL_DUPLEX;
629         }
630 
631         switch(speed_field >> 3)
632         {
633             case 0U:
634                 *speed = MSS_MAC_10MBPS;
635             break;
636 
637             case 1U:
638                 *speed = MSS_MAC_100MBPS;
639             break;
640 
641             case 2U:
642                 *speed = MSS_MAC_1000MBPS;
643             break;
644 
645             default:
646                 link_status = (uint8_t)MSS_MAC_LINK_DOWN;
647             break;
648         }
649     }
650     else
651     {
652         /* Link is down. */
653         link_status = (uint8_t)MSS_MAC_LINK_DOWN;
654     }
655 
656     return link_status;
657 }
658 
659 
660 /**************************************************************************//**
661  *
662  */
663 uint16_t VSC8662_reg_0[32];
664 uint16_t VSC8662_reg_1[16];
665 uint16_t VSC8662_reg_16[32];
666 
667 void dump_vsc8662_regs(const mss_mac_instance_t * this_mac);
dump_vsc8662_regs(const mss_mac_instance_t * this_mac)668 void dump_vsc8662_regs(const mss_mac_instance_t * this_mac)
669 {
670     int32_t count;
671     uint16_t page;
672     uint16_t old_page;
673     uint16_t *pdata;
674     volatile psr_t lev;
675 
676     for(page = 0U; page <= 0x10U; page++)
677     {
678         if(0U == page)
679         {
680             pdata = VSC8662_reg_0;
681         }
682         else if(1U == page)
683         {
684             pdata = VSC8662_reg_1;
685         }
686         else if(16U == page)
687         {
688             pdata = VSC8662_reg_16;
689         }
690         else
691         {
692             pdata = VSC8662_reg_0;
693         }
694 
695         if((0U == page) || (0x10U == page))
696         {
697             for(count = 0; count <= 0x1F; count++)
698             {
699                 lev = HAL_disable_interrupts();
700                 old_page = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 0x1FU);
701 
702                 MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 0x1FU, page);
703 
704                 pdata[count] = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, (uint8_t)count);
705 
706                 MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 0x1FU, old_page);
707                 HAL_restore_interrupts(lev);
708             }
709         }
710         else
711         {
712             for(count = 0x10; count <= 0x1F; count++)
713             {
714                 lev = HAL_disable_interrupts();
715                 old_page = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 0x1FU);
716 
717                 MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 0x1FU, page);
718 
719                 pdata[count - 0X10] = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, (uint8_t)count);
720 
721                 MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->phy_addr, 0x1FU, old_page);
722                 HAL_restore_interrupts(lev);
723             }
724         }
725 
726         if(1U == page)
727         {
728             page = 0x0FU;
729         }
730     }
731 }
732 
733 #endif /* #if defined(TARGET_ALOE) */
734 #ifdef __cplusplus
735 }
736 #endif
737 
738 /******************************** END OF FILE ******************************/
739 
740 
741 
742 
743 
744 
745