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