1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 
7 /***********************************************************************************************************************
8  * Includes   <System Includes> , "Project Includes"
9  ***********************************************************************************************************************/
10 
11 /* Access to peripherals and board defines. */
12 #include "bsp_api.h"
13 #include "r_ether_phy.h"
14 
15 /***********************************************************************************************************************
16  * Macro definitions
17  ***********************************************************************************************************************/
18 
19 #ifndef ETHER_PHY_ERROR_RETURN
20 
21  #define ETHER_PHY_ERROR_RETURN(a, err)    FSP_ERROR_RETURN((a), (err))
22 #endif
23 
24 #define ETHERC_REG_SIZE                         (0x400UL)
25 
26 /** "RPHY" in ASCII.  Used to determine if the control block is open. */
27 #define ETHER_PHY_OPEN                          (0x52504859U)
28 
29 /* Media Independent Interface */
30 #define ETHER_PHY_MII_ST                        (1)
31 #define ETHER_PHY_MII_READ                      (2)
32 #define ETHER_PHY_MII_WRITE                     (1)
33 
34 /* Standard PHY Registers */
35 #define ETHER_PHY_REG_CONTROL                   (0)
36 #define ETHER_PHY_REG_STATUS                    (1)
37 #define ETHER_PHY_REG_IDENTIFIER1               (2)
38 #define ETHER_PHY_REG_IDENTIFIER2               (3)
39 #define ETHER_PHY_REG_AN_ADVERTISEMENT          (4)
40 #define ETHER_PHY_REG_AN_LINK_PARTNER           (5)
41 #define ETHER_PHY_REG_AN_EXPANSION              (6)
42 
43 /* Basic Mode Control Register Bit Definitions */
44 #define ETHER_PHY_CONTROL_RESET                 (1 << 15)
45 #define ETHER_PHY_CONTROL_LOOPBACK              (1 << 14)
46 #define ETHER_PHY_CONTROL_100_MBPS              (1 << 13)
47 #define ETHER_PHY_CONTROL_AN_ENABLE             (1 << 12)
48 #define ETHER_PHY_CONTROL_POWER_DOWN            (1 << 11)
49 #define ETHER_PHY_CONTROL_ISOLATE               (1 << 10)
50 #define ETHER_PHY_CONTROL_AN_RESTART            (1 << 9)
51 #define ETHER_PHY_CONTROL_FULL_DUPLEX           (1 << 8)
52 #define ETHER_PHY_CONTROL_COLLISION             (1 << 7)
53 
54 /* Basic Mode Status Register Bit Definitions */
55 #define ETHER_PHY_STATUS_100_T4                 (1 << 15)
56 #define ETHER_PHY_STATUS_100F                   (1 << 14)
57 #define ETHER_PHY_STATUS_100H                   (1 << 13)
58 #define ETHER_PHY_STATUS_10F                    (1 << 12)
59 #define ETHER_PHY_STATUS_10H                    (1 << 11)
60 #define ETHER_PHY_STATUS_AN_COMPLETE            (1 << 5)
61 #define ETHER_PHY_STATUS_RM_FAULT               (1 << 4)
62 #define ETHER_PHY_STATUS_AN_ABILITY             (1 << 3)
63 #define ETHER_PHY_STATUS_LINK_UP                (1 << 2)
64 #define ETHER_PHY_STATUS_JABBER                 (1 << 1)
65 #define ETHER_PHY_STATUS_EX_CAPABILITY          (1 << 0)
66 
67 /* Auto Negotiation Advertisement Bit Definitions */
68 #define ETHER_PHY_AN_ADVERTISEMENT_NEXT_PAGE    (1 << 15)
69 #define ETHER_PHY_AN_ADVERTISEMENT_RM_FAULT     (1 << 13)
70 #define ETHER_PHY_AN_ADVERTISEMENT_ASM_DIR      (1 << 11)
71 #define ETHER_PHY_AN_ADVERTISEMENT_PAUSE        (1 << 10)
72 #define ETHER_PHY_AN_ADVERTISEMENT_100_T4       (1 << 9)
73 #define ETHER_PHY_AN_ADVERTISEMENT_100F         (1 << 8)
74 #define ETHER_PHY_AN_ADVERTISEMENT_100H         (1 << 7)
75 #define ETHER_PHY_AN_ADVERTISEMENT_10F          (1 << 6)
76 #define ETHER_PHY_AN_ADVERTISEMENT_10H          (1 << 5)
77 #define ETHER_PHY_AN_ADVERTISEMENT_SELECTOR     (1 << 0)
78 
79 /* Auto Negotiate Link Partner Ability Bit Definitions */
80 #define ETHER_PHY_AN_LINK_PARTNER_NEXT_PAGE     (1 << 15)
81 #define ETHER_PHY_AN_LINK_PARTNER_ACK           (1 << 14)
82 #define ETHER_PHY_AN_LINK_PARTNER_RM_FAULT      (1 << 13)
83 #define ETHER_PHY_AN_LINK_PARTNER_ASM_DIR       (1 << 11)
84 #define ETHER_PHY_AN_LINK_PARTNER_PAUSE         (1 << 10)
85 #define ETHER_PHY_AN_LINK_PARTNER_100_T4        (1 << 9)
86 #define ETHER_PHY_AN_LINK_PARTNER_100F          (1 << 8)
87 #define ETHER_PHY_AN_LINK_PARTNER_100H          (1 << 7)
88 #define ETHER_PHY_AN_LINK_PARTNER_10F           (1 << 6)
89 #define ETHER_PHY_AN_LINK_PARTNER_10H           (1 << 5)
90 #define ETHER_PHY_AN_LINK_PARTNER_SELECTOR      (1 << 0)
91 
92 #define ETHER_PHY_PIR_MDI_MASK                  (1 << 3)
93 #define ETHER_PHY_PIR_MDO_HIGH                  (0x04)
94 #define ETHER_PHY_PIR_MDO_LOW                   (0x00)
95 #define ETHER_PHY_PIR_MMD_WRITE                 (0x02)
96 #define ETHER_PHY_PIR_MMD_READ                  (0x00)
97 #define ETHER_PHY_PIR_MDC_HIGH                  (0x01)
98 #define ETHER_PHY_PIR_MDC_LOW                   (0x00)
99 
100 #define ETHER_PHY_ADDRESS_SIZE                  (0x1fU)
101 #define ETHER_PHY_REGISTER_DATA_SIZE            (0xffffU)
102 
103 #define ETHER_PHY_PREAMBLE_LENGTH               (32U)
104 #define ETHER_PHY_WRITE_DATA_BIT_MASK           (0x8000)
105 
106 /***********************************************************************************************************************
107  * Typedef definitions
108  ***********************************************************************************************************************/
109 
110 /***********************************************************************************************************************
111  * Exported global variables (to be accessed by other files)
112  ***********************************************************************************************************************/
113 
114 /***********************************************************************************************************************
115  * Exported global function
116  ***********************************************************************************************************************/
117 #if (ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE)
118 extern void ether_phy_target_ksz8091rnb_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl);
119 extern bool ether_phy_target_ksz8091rnb_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl,
120                                                                         uint32_t                    line_speed_duplex);
121 
122 #endif
123 #if (ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE)
124 extern void ether_phy_target_ksz8041_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl);
125 extern bool ether_phy_target_ksz8041_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl,
126                                                                      uint32_t                    line_speed_duplex);
127 
128 #endif
129 #if (ETHER_PHY_CFG_TARGET_DP83620_ENABLE)
130 extern void ether_phy_target_dp83620_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl);
131 extern bool ether_phy_target_dp83620_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl,
132                                                                      uint32_t                    line_speed_duplex);
133 
134 #endif
135 #if (ETHER_PHY_CFG_TARGET_ICS1894_ENABLE)
136 extern void ether_phy_target_ics1894_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl);
137 extern bool ether_phy_target_ics1894_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl,
138                                                                      uint32_t                    line_speed_duplex);
139 
140 #endif
141 
142 /***********************************************************************************************************************
143  * Private global variables and functions
144  ***********************************************************************************************************************/
145 static void ether_phy_preamble(ether_phy_instance_ctrl_t * p_instance_ctrl);
146 static void ether_phy_reg_set(ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t reg_addr, int32_t option);
147 static void ether_phy_reg_read(ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t * pdata);
148 static void ether_phy_reg_write(ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t data);
149 static void ether_phy_trans_zto0(ether_phy_instance_ctrl_t * p_instance_ctrl);
150 static void ether_phy_trans_1to0(ether_phy_instance_ctrl_t * p_instance_ctrl);
151 static void ether_phy_trans_idle(ether_phy_instance_ctrl_t * p_instance_ctrl);
152 static void ether_phy_mii_write1(ether_phy_instance_ctrl_t * p_instance_ctrl);
153 static void ether_phy_mii_write0(ether_phy_instance_ctrl_t * p_instance_ctrl);
154 static void ether_phy_mii_writez(ether_phy_instance_ctrl_t * p_instance_ctrl);
155 static void ether_phy_targets_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl);
156 static bool ether_phy_targets_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl,
157                                                               uint32_t                    line_speed_duplex);
158 
159 /** ETHER_PHY HAL API mapping for Ethernet PHY Controller interface */
160 /*LDRA_INSPECTED 27 D This structure must be accessible in user code. It cannot be static. */
161 const ether_phy_api_t g_ether_phy_on_ether_phy =
162 {
163     .open                  = R_ETHER_PHY_Open,
164     .close                 = R_ETHER_PHY_Close,
165     .startAutoNegotiate    = R_ETHER_PHY_StartAutoNegotiate,
166     .linkPartnerAbilityGet = R_ETHER_PHY_LinkPartnerAbilityGet,
167     .linkStatusGet         = R_ETHER_PHY_LinkStatusGet,
168     .chipInit              = R_ETHER_PHY_ChipInit,
169     .read                  = R_ETHER_PHY_Read,
170     .write                 = R_ETHER_PHY_Write
171 };
172 
173 /*******************************************************************************************************************//**
174  * @addtogroup ETHER_PHY
175  * @{
176  **********************************************************************************************************************/
177 
178 /***********************************************************************************************************************
179  * Functions
180  **********************************************************************************************************************/
181 
182 /********************************************************************************************************************//**
183  * @brief Resets Ethernet PHY device. Implements @ref ether_phy_api_t::open.
184  *
185  * @retval  FSP_SUCCESS                             Channel opened successfully.
186  * @retval  FSP_ERR_ASSERTION                       Pointer to ETHER_PHY control block or configuration structure is NULL.
187  * @retval  FSP_ERR_ALREADY_OPEN                    Control block has already been opened or channel is being used by another
188  *                                                  instance. Call close() then open() to reconfigure.
189  * @retval  FSP_ERR_INVALID_CHANNEL                 Invalid channel number is given.
190  * @retval  FSP_ERR_INVALID_POINTER                 Pointer to p_cfg is NULL.
191  * @retval  FSP_ERR_TIMEOUT                         PHY-LSI Reset wait timeout.
192  * @retval  FSP_ERR_INVALID_ARGUMENT                Register address is incorrect
193  * @retval  FSP_ERR_NOT_INITIALIZED                 The control block has not been initialized.
194  ***********************************************************************************************************************/
R_ETHER_PHY_Open(ether_phy_ctrl_t * const p_ctrl,ether_phy_cfg_t const * const p_cfg)195 fsp_err_t R_ETHER_PHY_Open (ether_phy_ctrl_t * const p_ctrl, ether_phy_cfg_t const * const p_cfg)
196 {
197     fsp_err_t err = FSP_SUCCESS;
198     ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl;
199     R_ETHERC0_Type            * p_reg_etherc;
200 
201 #if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE)
202     FSP_ASSERT(p_instance_ctrl);
203     ETHER_PHY_ERROR_RETURN(NULL != p_cfg, FSP_ERR_INVALID_POINTER);
204     ETHER_PHY_ERROR_RETURN((ETHER_PHY_OPEN != p_instance_ctrl->open), FSP_ERR_ALREADY_OPEN);
205     ETHER_PHY_ERROR_RETURN((BSP_FEATURE_ETHER_MAX_CHANNELS > p_cfg->channel), FSP_ERR_INVALID_CHANNEL);
206 #endif
207 
208     /** Make sure this channel exists. */
209     p_reg_etherc                     = ((R_ETHERC0_Type *) (R_ETHERC0_BASE + (ETHERC_REG_SIZE * p_cfg->channel)));
210     p_instance_ctrl->p_reg_pir       = (uint32_t *) &p_reg_etherc->PIR;
211     p_instance_ctrl->local_advertise = 0;
212 
213     /* Initialize configuration of ethernet phy module. */
214     p_instance_ctrl->p_ether_phy_cfg = p_cfg;
215 
216     R_BSP_MODULE_START(FSP_IP_ETHER, p_instance_ctrl->p_ether_phy_cfg->channel);
217 
218 #if ETHER_PHY_CFG_INIT_PHY_LSI_AUTOMATIC
219     uint32_t reg   = 0;
220     uint32_t count = 0;
221 
222     p_instance_ctrl->interface_status = ETHER_PHY_INTERFACE_STATUS_INITIALIZED;
223 
224     /* Reset PHY */
225     R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_CONTROL, ETHER_PHY_CONTROL_RESET);
226 
227     /* Reset completion waiting */
228     do
229     {
230         R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_CONTROL, &reg);
231         count++;
232     } while ((reg & ETHER_PHY_CONTROL_RESET) && (count < p_cfg->phy_reset_wait_time));
233 
234     if (count < p_cfg->phy_reset_wait_time)
235     {
236         ether_phy_targets_initialize(p_instance_ctrl);
237 
238         p_instance_ctrl->open = ETHER_PHY_OPEN;
239 
240         err = FSP_SUCCESS;
241     }
242     else
243     {
244         err = FSP_ERR_TIMEOUT;
245     }
246 
247 #else
248     p_instance_ctrl->open = ETHER_PHY_OPEN;
249 
250     err = FSP_SUCCESS;
251 #endif
252 
253     return err;
254 }                                      /* End of function R_ETHER_PHY_Open() */
255 
256 /********************************************************************************************************************//**
257  * @brief Close Ethernet PHY device. Implements @ref ether_phy_api_t::close.
258  *
259  * @retval  FSP_SUCCESS                                 Channel successfully closed.
260  * @retval  FSP_ERR_ASSERTION                           Pointer to ETHER_PHY control block is NULL.
261  * @retval  FSP_ERR_NOT_OPEN                            The control block has not been opened
262  *
263  ***********************************************************************************************************************/
R_ETHER_PHY_Close(ether_phy_ctrl_t * const p_ctrl)264 fsp_err_t R_ETHER_PHY_Close (ether_phy_ctrl_t * const p_ctrl)
265 {
266     fsp_err_t err = FSP_SUCCESS;
267     ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl;
268 
269 #if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE)
270     FSP_ASSERT(p_instance_ctrl);
271     ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
272 #endif
273 
274     /** Clear configure block parameters. */
275     p_instance_ctrl->p_ether_phy_cfg = NULL;
276     p_instance_ctrl->local_advertise = 0;
277     p_instance_ctrl->p_reg_pir       = NULL;
278 
279     p_instance_ctrl->interface_status = ETHER_PHY_INTERFACE_STATUS_UNINITIALIZED;
280     p_instance_ctrl->open             = 0;
281 
282     return err;
283 }                                      /* End of function R_ETHER_PHY_Close() */
284 
285 /********************************************************************************************************************//**
286  * @brief Starts auto-negotiate. Implements @ref ether_phy_api_t::startAutoNegotiate.
287  *
288  * @retval  FSP_SUCCESS                                 ETHER_PHY successfully starts auto-negotiate.
289  * @retval  FSP_ERR_ASSERTION                           Pointer to ETHER_PHY control block is NULL.
290  * @retval  FSP_ERR_NOT_OPEN                            The control block has not been opened
291  * @retval  FSP_ERR_INVALID_ARGUMENT                    Register address is incorrect
292  * @retval  FSP_ERR_INVALID_POINTER                     Pointer to read buffer is NULL.
293  * @retval  FSP_ERR_NOT_INITIALIZED                     The control block has not been initialized
294  ***********************************************************************************************************************/
R_ETHER_PHY_StartAutoNegotiate(ether_phy_ctrl_t * const p_ctrl)295 fsp_err_t R_ETHER_PHY_StartAutoNegotiate (ether_phy_ctrl_t * const p_ctrl)
296 {
297     ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl;
298     uint32_t reg = 0;
299 
300 #if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE)
301     FSP_ASSERT(p_instance_ctrl);
302     ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
303     ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status,
304                            FSP_ERR_NOT_INITIALIZED);
305 #endif
306 
307     /* Set local ability */
308     /* When pause frame is not used */
309     if (ETHER_PHY_FLOW_CONTROL_DISABLE == p_instance_ctrl->p_ether_phy_cfg->flow_control)
310     {
311         p_instance_ctrl->local_advertise = ((((ETHER_PHY_AN_ADVERTISEMENT_100F |
312                                                ETHER_PHY_AN_ADVERTISEMENT_100H) |
313                                               ETHER_PHY_AN_ADVERTISEMENT_10F) |
314                                              ETHER_PHY_AN_ADVERTISEMENT_10H) |
315                                             ETHER_PHY_AN_ADVERTISEMENT_SELECTOR);
316     }
317     /* When pause frame is used */
318     else
319     {
320         p_instance_ctrl->local_advertise = ((((((ETHER_PHY_AN_ADVERTISEMENT_ASM_DIR |
321                                                  ETHER_PHY_AN_ADVERTISEMENT_PAUSE) |
322                                                 ETHER_PHY_AN_ADVERTISEMENT_100F) |
323                                                ETHER_PHY_AN_ADVERTISEMENT_100H) |
324                                               ETHER_PHY_AN_ADVERTISEMENT_10F) |
325                                              ETHER_PHY_AN_ADVERTISEMENT_10H) |
326                                             ETHER_PHY_AN_ADVERTISEMENT_SELECTOR);
327     }
328 
329     /* Configure what the PHY and the Ethernet controller on this board supports */
330     R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_AN_ADVERTISEMENT, p_instance_ctrl->local_advertise);
331     R_ETHER_PHY_Write(p_instance_ctrl,
332                       ETHER_PHY_REG_CONTROL,
333                       (ETHER_PHY_CONTROL_AN_ENABLE |
334                        ETHER_PHY_CONTROL_AN_RESTART));
335 
336     R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_AN_ADVERTISEMENT, &reg);
337 
338     return FSP_SUCCESS;
339 }                                      /* End of function R_ETHER_PHY_StartAutoNegotiate() */
340 
341 /********************************************************************************************************************//**
342  * @brief Reports the other side's physical capability. Implements @ref ether_phy_api_t::linkPartnerAbilityGet.
343  *
344  * @retval  FSP_SUCCESS                                 ETHER_PHY successfully get link partner ability.
345  * @retval  FSP_ERR_ASSERTION                           Pointer to ETHER_PHY control block is NULL.
346  * @retval  FSP_ERR_INVALID_POINTER                     Pointer to arguments are NULL.
347  * @retval  FSP_ERR_NOT_OPEN                            The control block has not been opened
348  * @retval  FSP_ERR_ETHER_PHY_ERROR_LINK                PHY-LSI is not link up.
349  * @retval  FSP_ERR_ETHER_PHY_NOT_READY                 The auto-negotiation isn't completed
350  * @retval  FSP_ERR_INVALID_ARGUMENT                    Status register address is incorrect
351  * @retval  FSP_ERR_NOT_INITIALIZED                     The control block has not been initialized
352  ***********************************************************************************************************************/
R_ETHER_PHY_LinkPartnerAbilityGet(ether_phy_ctrl_t * const p_ctrl,uint32_t * const p_line_speed_duplex,uint32_t * const p_local_pause,uint32_t * const p_partner_pause)353 fsp_err_t R_ETHER_PHY_LinkPartnerAbilityGet (ether_phy_ctrl_t * const p_ctrl,
354                                              uint32_t * const         p_line_speed_duplex,
355                                              uint32_t * const         p_local_pause,
356                                              uint32_t * const         p_partner_pause)
357 {
358     fsp_err_t err = FSP_SUCCESS;
359     ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl;
360     uint32_t reg               = 0;
361     uint32_t line_speed_duplex = ETHER_PHY_LINK_SPEED_NO_LINK;
362 
363 #if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE)
364     FSP_ASSERT(p_instance_ctrl);
365     ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
366     ETHER_PHY_ERROR_RETURN(NULL != p_line_speed_duplex, FSP_ERR_INVALID_POINTER);
367     ETHER_PHY_ERROR_RETURN(NULL != p_local_pause, FSP_ERR_INVALID_POINTER);
368     ETHER_PHY_ERROR_RETURN(NULL != p_partner_pause, FSP_ERR_INVALID_POINTER);
369     ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status,
370                            FSP_ERR_NOT_INITIALIZED);
371 #endif
372 
373     /* Because reading the first time shows the previous state, the Link status bit is read twice. */
374     R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_STATUS, &reg);
375     R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_STATUS, &reg);
376 
377     /* When the link isn't up, return error */
378     ETHER_PHY_ERROR_RETURN(ETHER_PHY_STATUS_LINK_UP == (reg & ETHER_PHY_STATUS_LINK_UP), FSP_ERR_ETHER_PHY_ERROR_LINK);
379 
380     /* Establish local pause capability */
381     if (ETHER_PHY_AN_ADVERTISEMENT_PAUSE == (p_instance_ctrl->local_advertise & ETHER_PHY_AN_ADVERTISEMENT_PAUSE))
382     {
383         (*p_local_pause) |= (1 << 1);
384     }
385 
386     if (ETHER_PHY_AN_ADVERTISEMENT_ASM_DIR == (p_instance_ctrl->local_advertise & ETHER_PHY_AN_ADVERTISEMENT_ASM_DIR))
387     {
388         (*p_local_pause) |= 1;
389     }
390 
391     /* When the auto-negotiation isn't completed, return error */
392     ETHER_PHY_ERROR_RETURN(ETHER_PHY_STATUS_AN_COMPLETE == (reg & ETHER_PHY_STATUS_AN_COMPLETE),
393                            FSP_ERR_ETHER_PHY_NOT_READY);
394 
395     /* Get the link partner response */
396     R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_AN_LINK_PARTNER, &reg);
397 
398     /* Establish partner pause capability */
399     if (ETHER_PHY_AN_LINK_PARTNER_PAUSE == (reg & ETHER_PHY_AN_LINK_PARTNER_PAUSE))
400     {
401         (*p_partner_pause) = (1 << 1);
402     }
403 
404     if (ETHER_PHY_AN_LINK_PARTNER_ASM_DIR == (reg & ETHER_PHY_AN_LINK_PARTNER_ASM_DIR))
405     {
406         (*p_partner_pause) |= 1;
407     }
408 
409     /* Establish the line speed and the duplex */
410     if ((ETHER_PHY_AN_LINK_PARTNER_10H == (reg & ETHER_PHY_AN_LINK_PARTNER_10H)) &&
411         ether_phy_targets_is_support_link_partner_ability(p_instance_ctrl, ETHER_PHY_LINK_SPEED_10H))
412     {
413         line_speed_duplex = ETHER_PHY_LINK_SPEED_10H;
414     }
415 
416     if ((ETHER_PHY_AN_LINK_PARTNER_10F == (reg & ETHER_PHY_AN_LINK_PARTNER_10F)) &&
417         ether_phy_targets_is_support_link_partner_ability(p_instance_ctrl, ETHER_PHY_LINK_SPEED_10F))
418     {
419         line_speed_duplex = ETHER_PHY_LINK_SPEED_10F;
420     }
421 
422     if ((ETHER_PHY_AN_LINK_PARTNER_100H == (reg & ETHER_PHY_AN_LINK_PARTNER_100H)) &&
423         ether_phy_targets_is_support_link_partner_ability(p_instance_ctrl, ETHER_PHY_LINK_SPEED_100H))
424     {
425         line_speed_duplex = ETHER_PHY_LINK_SPEED_100H;
426     }
427 
428     if ((ETHER_PHY_AN_LINK_PARTNER_100F == (reg & ETHER_PHY_AN_LINK_PARTNER_100F)) &&
429         ether_phy_targets_is_support_link_partner_ability(p_instance_ctrl, ETHER_PHY_LINK_SPEED_100F))
430     {
431         line_speed_duplex = ETHER_PHY_LINK_SPEED_100F;
432     }
433 
434     if (ETHER_PHY_LINK_SPEED_NO_LINK == line_speed_duplex)
435     {
436         err = FSP_ERR_ETHER_PHY_ERROR_LINK;
437     }
438     else
439     {
440         (*p_line_speed_duplex) = line_speed_duplex;
441     }
442 
443     return err;
444 }                                      /* End of function R_ETHER_PHY_LinkPartnerAbilityGet() */
445 
446 /********************************************************************************************************************//**
447  * @brief Returns the status of the physical link. Implements @ref ether_phy_api_t::linkStatusGet.
448  *
449  * @retval  FSP_SUCCESS                                 ETHER_PHY successfully get link partner ability.
450  * @retval  FSP_ERR_ASSERTION                           Pointer to ETHER_PHY control block is NULL.
451  * @retval  FSP_ERR_NOT_OPEN                            The control block has not been opened
452  * @retval  FSP_ERR_ETHER_PHY_ERROR_LINK                PHY-LSI is not link up.
453  * @retval  FSP_ERR_INVALID_ARGUMENT                    Status register address is incorrect
454  * @retval  FSP_ERR_INVALID_POINTER                     Pointer to read buffer is NULL.
455  * @retval  FSP_ERR_NOT_INITIALIZED                     The control block has not been initialized
456  ***********************************************************************************************************************/
R_ETHER_PHY_LinkStatusGet(ether_phy_ctrl_t * const p_ctrl)457 fsp_err_t R_ETHER_PHY_LinkStatusGet (ether_phy_ctrl_t * const p_ctrl)
458 {
459     ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl;
460     uint32_t  reg;
461     fsp_err_t err = FSP_SUCCESS;
462 
463 #if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE)
464     FSP_ASSERT(p_instance_ctrl);
465     ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
466     ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status,
467                            FSP_ERR_NOT_INITIALIZED);
468 #endif
469 
470     /* Because reading the first time shows the previous state, the Link status bit is read twice. */
471     R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_STATUS, &reg);
472     R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_STATUS, &reg);
473 
474     /* When the link isn't up, return error */
475     if (ETHER_PHY_STATUS_LINK_UP != (reg & ETHER_PHY_STATUS_LINK_UP))
476     {
477         /* Link is down */
478         err = FSP_ERR_ETHER_PHY_ERROR_LINK;
479     }
480     else
481     {
482         /* Link is up */
483         err = FSP_SUCCESS;
484     }
485 
486     return err;
487 }                                      /* End of function R_ETHER_PHY_LinkStatusGet() */
488 
489 /********************************************************************************************************************//**
490  * @brief Initialize Ethernet PHY device. Implements @ref ether_phy_api_t::chipInit.
491  *
492  * @retval  FSP_SUCCESS                             PHY device initialized successfully.
493  * @retval  FSP_ERR_ASSERTION                       Pointer to ETHER_PHY control block or configuration structure is NULL.
494  * @retval  FSP_ERR_INVALID_ARGUMENT                Address or data is not a valid size.
495  * @retval  FSP_ERR_INVALID_POINTER                 Pointer to p_cfg is NULL.
496  * @retval  FSP_ERR_NOT_INITIALIZED                 The control block has not been initialized.
497  * @retval  FSP_ERR_NOT_OPEN                        The control block has not been opened.
498  * @retval  FSP_ERR_TIMEOUT                         PHY-LSI Reset wait timeout.
499  ***********************************************************************************************************************/
R_ETHER_PHY_ChipInit(ether_phy_ctrl_t * const p_ctrl,ether_phy_cfg_t const * const p_cfg)500 fsp_err_t R_ETHER_PHY_ChipInit (ether_phy_ctrl_t * const p_ctrl, ether_phy_cfg_t const * const p_cfg)
501 {
502     fsp_err_t err = FSP_SUCCESS;
503     ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl;
504     uint32_t reg   = 0;
505     uint32_t count = 0;
506 
507 #if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE)
508     FSP_ASSERT(p_instance_ctrl);
509     ETHER_PHY_ERROR_RETURN(NULL != p_cfg, FSP_ERR_INVALID_POINTER);
510     ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
511 #endif
512 
513     p_instance_ctrl->interface_status = ETHER_PHY_INTERFACE_STATUS_INITIALIZED;
514 
515     /* Reset PHY */
516     R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_CONTROL, ETHER_PHY_CONTROL_RESET);
517 
518     /* Reset completion waiting */
519     do
520     {
521         R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_CONTROL, &reg);
522         count++;
523     } while ((reg & ETHER_PHY_CONTROL_RESET) && (count < p_cfg->phy_reset_wait_time));
524 
525     if (count < p_cfg->phy_reset_wait_time)
526     {
527         ether_phy_targets_initialize(p_instance_ctrl);
528 
529         err = FSP_SUCCESS;
530     }
531     else
532     {
533         err = FSP_ERR_TIMEOUT;
534     }
535 
536     return err;
537 }                                      /* End of function R_ETHER_PHY_ChipInit() */
538 
539 /********************************************************************************************************************//**
540  * @brief Read data from register of PHY-LSI . Implements @ref ether_phy_api_t::read.
541  *
542  * @retval  FSP_SUCCESS                                 ETHER_PHY successfully read data.
543  * @retval  FSP_ERR_ASSERTION                           Pointer to ETHER_PHY control block is NULL.
544  * @retval  FSP_ERR_INVALID_POINTER                     Pointer to read buffer is NULL.
545  * @retval  FSP_ERR_INVALID_ARGUMENT                    Address is not a valid size
546  * @retval  FSP_ERR_NOT_INITIALIZED                     The control block has not been initialized
547  ***********************************************************************************************************************/
R_ETHER_PHY_Read(ether_phy_ctrl_t * const p_ctrl,uint32_t reg_addr,uint32_t * const p_data)548 fsp_err_t R_ETHER_PHY_Read (ether_phy_ctrl_t * const p_ctrl, uint32_t reg_addr, uint32_t * const p_data)
549 {
550     ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl;
551     uint32_t data;
552 #if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE)
553     FSP_ASSERT(p_instance_ctrl);
554     ETHER_PHY_ERROR_RETURN(NULL != p_data, FSP_ERR_INVALID_POINTER);
555     ETHER_PHY_ERROR_RETURN(ETHER_PHY_ADDRESS_SIZE >= reg_addr, FSP_ERR_INVALID_ARGUMENT);
556     ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status,
557                            FSP_ERR_NOT_INITIALIZED);
558 #endif
559 
560     /*
561      * The value is read from the PHY register by the frame format of MII Management Interface provided
562      * for by Table 22-12 of 22.2.4.5 of IEEE 802.3-2008_section2.
563      */
564     ether_phy_preamble(p_instance_ctrl);
565     ether_phy_reg_set(p_instance_ctrl, reg_addr, ETHER_PHY_MII_READ);
566     ether_phy_trans_zto0(p_instance_ctrl);
567     ether_phy_reg_read(p_instance_ctrl, &data);
568     ether_phy_trans_idle(p_instance_ctrl);
569 
570     (*p_data) = data;
571 
572     return FSP_SUCCESS;
573 }                                      /* End of function R_ETHER_PHY_Read() */
574 
575 /********************************************************************************************************************//**
576  * @brief Write data to register of PHY-LSI . Implements @ref ether_phy_api_t::write.
577  *
578  * @retval  FSP_SUCCESS                                 ETHER_PHY successfully write data.
579  * @retval  FSP_ERR_ASSERTION                           Pointer to ETHER_PHY control block is NULL.
580  * @retval  FSP_ERR_INVALID_ARGUMENT                    Address or data is not a valid size
581  * @retval  FSP_ERR_NOT_INITIALIZED                     The control block has not been initialized
582  ***********************************************************************************************************************/
R_ETHER_PHY_Write(ether_phy_ctrl_t * const p_ctrl,uint32_t reg_addr,uint32_t data)583 fsp_err_t R_ETHER_PHY_Write (ether_phy_ctrl_t * const p_ctrl, uint32_t reg_addr, uint32_t data)
584 {
585     ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl;
586 
587 #if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE)
588     FSP_ASSERT(p_instance_ctrl);
589     ETHER_PHY_ERROR_RETURN(ETHER_PHY_ADDRESS_SIZE >= reg_addr, FSP_ERR_INVALID_ARGUMENT);
590     ETHER_PHY_ERROR_RETURN(ETHER_PHY_REGISTER_DATA_SIZE >= data, FSP_ERR_INVALID_ARGUMENT);
591     ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status,
592                            FSP_ERR_NOT_INITIALIZED);
593 #endif
594 
595     /*
596      * The value is read from the PHY register by the frame format of MII Management Interface provided
597      * for by Table 22-12 of 22.2.4.5 of IEEE 802.3-2008_section2.
598      */
599     ether_phy_preamble(p_instance_ctrl);
600     ether_phy_reg_set(p_instance_ctrl, reg_addr, ETHER_PHY_MII_WRITE);
601     ether_phy_trans_1to0(p_instance_ctrl);
602     ether_phy_reg_write(p_instance_ctrl, data);
603     ether_phy_trans_idle(p_instance_ctrl);
604 
605     return FSP_SUCCESS;
606 }                                      /* End of function R_ETHER_PHY_Write() */
607 
608 /*******************************************************************************************************************//**
609  * @} (end addtogroup ETHER_PHY)
610  **********************************************************************************************************************/
611 
612 /**
613  * Private functions
614  */
615 
616 /***********************************************************************************************************************
617  * Function Name: phy_preamble
618  * Description  : As preliminary preparation for access to the PHY module register,
619  *                "1" is output via the MII management interface.
620  * Arguments    : ether_channel -
621  *                    Ethernet channel number
622  * Return Value : none
623  ***********************************************************************************************************************/
ether_phy_preamble(ether_phy_instance_ctrl_t * p_instance_ctrl)624 static void ether_phy_preamble (ether_phy_instance_ctrl_t * p_instance_ctrl)
625 {
626     int16_t i;
627 
628     /*
629      * The processing of PRE (preamble) about the frame format of MII Management Interface which is
630      * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2".
631      */
632     i = ETHER_PHY_PREAMBLE_LENGTH;
633     while (i > 0)
634     {
635         ether_phy_mii_write1(p_instance_ctrl);
636         i--;
637     }
638 }                                      /* End of function ether_phy_preamble() */
639 
640 /***********************************************************************************************************************
641  * Function Name: ether_phy_reg_set
642  * Description  : Sets a PHY device to read or write mode
643  * Arguments    : ether_channel -
644  *                    Ethernet channel number
645  *                reg_addr -
646  *                    address of the PHY register
647  *                option -
648  *                    mode
649  * Return Value : none
650  ***********************************************************************************************************************/
ether_phy_reg_set(ether_phy_instance_ctrl_t * p_instance_ctrl,uint32_t reg_addr,int32_t option)651 static void ether_phy_reg_set (ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t reg_addr, int32_t option)
652 {
653     int32_t  i;
654     uint32_t data = 0;
655 
656     /*
657      * The processing of ST (start of frame),OP (operation code), PHYAD (PHY Address), and
658      * REGAD (Register Address)  about the frame format of MII Management Interface which is
659      * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2".
660      */
661     data = (ETHER_PHY_MII_ST << 14);                                             /* ST code    */
662 
663     if (ETHER_PHY_MII_READ == option)
664     {
665         data |= (ETHER_PHY_MII_READ << 12);                                      /* OP code(RD)  */
666     }
667     else
668     {
669         data |= (ETHER_PHY_MII_WRITE << 12);                                     /* OP code(WT)  */
670     }
671 
672     data |= (uint32_t) (p_instance_ctrl->phy_lsi_address << 7); /* PHY Address  */
673 
674     data |= (reg_addr << 2);                                                     /* Reg Address  */
675 
676     i = 14;
677     while (i > 0)
678     {
679         if (0 == (data & ETHER_PHY_WRITE_DATA_BIT_MASK))
680         {
681             ether_phy_mii_write0(p_instance_ctrl);
682         }
683         else
684         {
685             ether_phy_mii_write1(p_instance_ctrl);
686         }
687 
688         data = (data << 1);
689         i--;
690     }
691 }                                      /* End of function ether_phy_reg_set() */
692 
693 /***********************************************************************************************************************
694  * Function Name: ether_phy_reg_read
695  * Description  : Reads PHY register through MII interface
696  * Arguments    : p_instance_ctrl -
697  *                    Ethernet channel number
698  *                pdata -
699  *                    pointer to store the data read
700  * Return Value : none
701  ***********************************************************************************************************************/
ether_phy_reg_read(ether_phy_instance_ctrl_t * p_instance_ctrl,uint32_t * pdata)702 static void ether_phy_reg_read (ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t * pdata)
703 {
704     int32_t  i;
705     int32_t  j;
706     uint32_t reg_data;
707 
708     volatile uint32_t * petherc_pir;
709 
710     petherc_pir = p_instance_ctrl->p_reg_pir;
711 
712     /*
713      * The processing of DATA (data) about reading of the frame format of MII Management Interface which is
714      * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2".
715      */
716     reg_data = 0;
717     i        = 16;
718     while (i > 0)
719     {
720         for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
721         {
722             (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW);
723         }
724 
725         reg_data  = (reg_data << 1);
726         reg_data |= (uint32_t) (((*petherc_pir) & ETHER_PHY_PIR_MDI_MASK) >> 3); /* MDI read  */
727 
728         for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
729         {
730             (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_HIGH);
731         }
732 
733         for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
734         {
735             (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_HIGH);
736         }
737 
738         for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
739         {
740             (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW);
741         }
742 
743         i--;
744     }
745 
746     (*pdata) = reg_data;
747 }                                      /* End of function ether_phy_reg_read() */
748 
749 /***********************************************************************************************************************
750  * Function Name: ether_phy_reg_write
751  * Description  : Writes to PHY register through MII interface
752  * Arguments    : ether_channel -
753  *                    Ethernet channel number
754  *                data -
755  *                    value to write
756  * Return Value : none
757  ***********************************************************************************************************************/
ether_phy_reg_write(ether_phy_instance_ctrl_t * p_instance_ctrl,uint32_t data)758 static void ether_phy_reg_write (ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t data)
759 {
760     int32_t i;
761 
762     /*
763      * The processing of DATA (data) about writing of the frame format of MII Management Interface which is
764      * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2".
765      */
766     i = 16;
767     while (i > 0)
768     {
769         if (0 == (data & ETHER_PHY_WRITE_DATA_BIT_MASK))
770         {
771             ether_phy_mii_write0(p_instance_ctrl);
772         }
773         else
774         {
775             ether_phy_mii_write1(p_instance_ctrl);
776         }
777 
778         i--;
779         data = (data << 1);
780     }
781 }                                      /* End of function ether_phy_reg_write() */
782 
783 /***********************************************************************************************************************
784  * Function Name: ether_phy_trans_zto0
785  * Description  : Performs bus release so that PHY can drive data
786  *              : for read operation
787  * Arguments    : ether_channel -
788  *                    Ethernet channel number
789  * Return Value : none
790  ***********************************************************************************************************************/
ether_phy_trans_zto0(ether_phy_instance_ctrl_t * p_instance_ctrl)791 static void ether_phy_trans_zto0 (ether_phy_instance_ctrl_t * p_instance_ctrl)
792 {
793     /* Release the bus by writing z. */
794     ether_phy_mii_writez(p_instance_ctrl);
795 
796     /* The PHY will drive the bus to 0. */
797     ether_phy_mii_writez(p_instance_ctrl);
798 }                                      /* End of function ether_phy_trans_zto0() */
799 
800 /***********************************************************************************************************************
801  * Function Name: phy_trans_1to0
802  * Description  : Switches data bus so MII interface can drive data
803  *              : for write operation
804  * Arguments    : ether_channel -
805  *                    Ethernet channel number
806  * Return Value : none
807  ***********************************************************************************************************************/
ether_phy_trans_1to0(ether_phy_instance_ctrl_t * p_instance_ctrl)808 static void ether_phy_trans_1to0 (ether_phy_instance_ctrl_t * p_instance_ctrl)
809 {
810     /*
811      * The processing of TA (turnaround) about writing of the frame format of MII Management Interface which is
812      * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2".
813      */
814     ether_phy_mii_write1(p_instance_ctrl);
815     ether_phy_mii_write0(p_instance_ctrl);
816 }                                      /* End of function ether_phy_trans_1to0() */
817 
818 /***********************************************************************************************************************
819  * Function Name: ether_phy_trans_idle
820  * Description  : Switches data bus to IDLE state to prepare for the next transfer.
821  * Arguments    : ether_channel -
822  *                    Ethernet channel number
823  * Return Value : none
824  ***********************************************************************************************************************/
ether_phy_trans_idle(ether_phy_instance_ctrl_t * p_instance_ctrl)825 static void ether_phy_trans_idle (ether_phy_instance_ctrl_t * p_instance_ctrl)
826 {
827     volatile uint32_t * petherc_pir;
828 
829     petherc_pir = p_instance_ctrl->p_reg_pir;
830 
831     int64_t count = (int64_t) p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time * 4;
832 
833     /* Release the bus for one MDC period. */
834     for (int64_t j = count; j > 0; j--)
835     {
836         (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW);
837     }
838 }
839 
840 /***********************************************************************************************************************
841  * Function Name: ether_phy_mii_write1
842  * Description  : Outputs 1 to the MII interface
843  * Arguments    : ether_channel -
844  *                    Ethernet channel number
845  * Return Value : none
846  ***********************************************************************************************************************/
ether_phy_mii_write1(ether_phy_instance_ctrl_t * p_instance_ctrl)847 static void ether_phy_mii_write1 (ether_phy_instance_ctrl_t * p_instance_ctrl)
848 {
849     int32_t             j;
850     volatile uint32_t * petherc_pir;
851 
852     petherc_pir = p_instance_ctrl->p_reg_pir;
853 
854     /*
855      * The processing of one bit about frame format of MII Management Interface which is
856      * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2".
857      * The data that 1 is output.
858      */
859     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
860     {
861         (*petherc_pir) = (ETHER_PHY_PIR_MDO_HIGH | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_LOW);
862     }
863 
864     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
865     {
866         (*petherc_pir) = (ETHER_PHY_PIR_MDO_HIGH | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_HIGH);
867     }
868 
869     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
870     {
871         (*petherc_pir) = (ETHER_PHY_PIR_MDO_HIGH | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_HIGH);
872     }
873 
874     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
875     {
876         (*petherc_pir) = (ETHER_PHY_PIR_MDO_HIGH | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_LOW);
877     }
878 }                                      /* End of function ether_phy_mii_write1() */
879 
880 /***********************************************************************************************************************
881  * Function Name: ether_phy_mii_write0
882  * Description  : Outputs 0 to the MII interface
883  * Arguments    : ether_channel -
884  *                    Ethernet channel number
885  * Return Value : none
886  ***********************************************************************************************************************/
ether_phy_mii_write0(ether_phy_instance_ctrl_t * p_instance_ctrl)887 static void ether_phy_mii_write0 (ether_phy_instance_ctrl_t * p_instance_ctrl)
888 {
889     int32_t             j;
890     volatile uint32_t * petherc_pir;
891 
892     petherc_pir = p_instance_ctrl->p_reg_pir;
893 
894     /*
895      * The processing of one bit about frame format of MII Management Interface which is
896      * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2".
897      * The data that 0 is output.
898      */
899     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
900     {
901         (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_LOW);
902     }
903 
904     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
905     {
906         (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_HIGH);
907     }
908 
909     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
910     {
911         (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_HIGH);
912     }
913 
914     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
915     {
916         (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_LOW);
917     }
918 }                                      /* End of function ether_phy_mii_write0() */
919 
920 /***********************************************************************************************************************
921  * Function Name: ether_phy_mii_writez
922  * Description  : Outputs z to the MII interface
923  * Arguments    : ether_channel -
924  *                    Ethernet channel number
925  * Return Value : none
926  ***********************************************************************************************************************/
ether_phy_mii_writez(ether_phy_instance_ctrl_t * p_instance_ctrl)927 static void ether_phy_mii_writez (ether_phy_instance_ctrl_t * p_instance_ctrl)
928 {
929     int32_t j;
930 
931     volatile uint32_t * petherc_pir;
932 
933     petherc_pir = p_instance_ctrl->p_reg_pir;
934 
935     /*
936      * The processing of one bit about frame format of MII Management Interface which is
937      * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2".
938      * The data that z is output.
939      */
940     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
941     {
942         (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW);
943     }
944 
945     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
946     {
947         (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_HIGH);
948     }
949 
950     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
951     {
952         (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_HIGH);
953     }
954 
955     for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--)
956     {
957         (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW);
958     }
959 }
960 
961 /***********************************************************************************************************************
962  * Function Name: ether_phy_targets_initialize
963  * Description  : PHY-LSI specific initialization processing
964  * Arguments    : p_instance_ctrl -
965  *                    Ethernet control block
966  * Return Value : none
967  ***********************************************************************************************************************/
ether_phy_targets_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl)968 static void ether_phy_targets_initialize (ether_phy_instance_ctrl_t * p_instance_ctrl)
969 {
970     switch (p_instance_ctrl->p_ether_phy_cfg->phy_lsi_type)
971     {
972         /* Use KSZ8091RNB */
973 #if (ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE)
974         case ETHER_PHY_LSI_TYPE_KSZ8091RNB:
975         {
976             ether_phy_target_ksz8091rnb_initialize(p_instance_ctrl);
977             break;
978         }
979 #endif
980 
981         /* Use KSZ8041 */
982 #if (ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE)
983         case ETHER_PHY_LSI_TYPE_KSZ8041:
984         {
985             ether_phy_target_ksz8041_initialize(p_instance_ctrl);
986             break;
987         }
988 #endif
989 
990         /* Use DP83620 */
991 #if (ETHER_PHY_CFG_TARGET_DP83620_ENABLE)
992         case ETHER_PHY_LSI_TYPE_DP83620:
993         {
994             ether_phy_target_dp83620_initialize(p_instance_ctrl);
995             break;
996         }
997 #endif
998 
999         /* Use ICS1894 */
1000 #if (ETHER_PHY_CFG_TARGET_ICS1894_ENABLE)
1001         case ETHER_PHY_LSI_TYPE_ICS1894:
1002         {
1003             ether_phy_target_ics1894_initialize(p_instance_ctrl);
1004             break;
1005         }
1006 #endif
1007 
1008         /* User custom */
1009 #if (ETHER_PHY_CFG_USE_CUSTOM_PHY_LSI_ENABLE)
1010         case ETHER_PHY_LSI_TYPE_CUSTOM:
1011         {
1012             if (NULL != p_instance_ctrl->p_ether_phy_cfg->p_extend)
1013             {
1014                 ether_phy_extended_cfg_t const * p_callback = p_instance_ctrl->p_ether_phy_cfg->p_extend;
1015                 if (NULL != p_callback->p_target_init)
1016                 {
1017                     p_callback->p_target_init(p_instance_ctrl);
1018                 }
1019             }
1020 
1021             break;
1022         }
1023 #endif
1024 
1025         /* If module is configured for default LSI */
1026         default:
1027         {
1028             break;
1029         }
1030     }
1031 }                                      /* End of function ether_phy_targets_initialize() */
1032 
1033 /***********************************************************************************************************************
1034  * Function Name: ether_phy_targets_is_support_link_partner_ability
1035  * Description  : Check if the PHY-LSI connected Ethernet controller supports link ability
1036  * Arguments    : p_instance_ctrl -
1037  *                    Ethernet control block
1038  *                line_speed_duplex -
1039  *                    Line speed duplex of link partner PHY-LSI
1040  * Return Value : bool
1041  ***********************************************************************************************************************/
ether_phy_targets_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl,uint32_t line_speed_duplex)1042 static bool ether_phy_targets_is_support_link_partner_ability (ether_phy_instance_ctrl_t * p_instance_ctrl,
1043                                                                uint32_t                    line_speed_duplex)
1044 {
1045     bool result = false;
1046     FSP_PARAMETER_NOT_USED(line_speed_duplex);
1047     switch (p_instance_ctrl->p_ether_phy_cfg->phy_lsi_type)
1048     {
1049         /* Use KSZ8091RNB */
1050 #if (ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE)
1051         case ETHER_PHY_LSI_TYPE_KSZ8091RNB:
1052         {
1053             result = ether_phy_target_ksz8091rnb_is_support_link_partner_ability(p_instance_ctrl, line_speed_duplex);
1054             break;
1055         }
1056 #endif
1057 
1058         /* Use KSZ8041 */
1059 #if (ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE)
1060         case ETHER_PHY_LSI_TYPE_KSZ8041:
1061         {
1062             result = ether_phy_target_ksz8041_is_support_link_partner_ability(p_instance_ctrl, line_speed_duplex);
1063             break;
1064         }
1065 #endif
1066 
1067         /* Use DP83620 */
1068 #if (ETHER_PHY_CFG_TARGET_DP83620_ENABLE)
1069         case ETHER_PHY_LSI_TYPE_DP83620:
1070         {
1071             result = ether_phy_target_dp83620_is_support_link_partner_ability(p_instance_ctrl, line_speed_duplex);
1072             break;
1073         }
1074 #endif
1075 
1076         /* Use ICS1894 */
1077 #if (ETHER_PHY_CFG_TARGET_ICS1894_ENABLE)
1078         case ETHER_PHY_LSI_TYPE_ICS1894:
1079         {
1080             result = ether_phy_target_ics1894_is_support_link_partner_ability(p_instance_ctrl, line_speed_duplex);
1081             break;
1082         }
1083 #endif
1084 
1085         /* User custom */
1086 #if (ETHER_PHY_CFG_USE_CUSTOM_PHY_LSI_ENABLE)
1087         case ETHER_PHY_LSI_TYPE_CUSTOM:
1088         {
1089             if (NULL != p_instance_ctrl->p_ether_phy_cfg->p_extend)
1090             {
1091                 ether_phy_extended_cfg_t const * p_callback = p_instance_ctrl->p_ether_phy_cfg->p_extend;
1092                 if (NULL != p_callback->p_target_link_partner_ability_get)
1093                 {
1094                     result = p_callback->p_target_link_partner_ability_get(p_instance_ctrl, line_speed_duplex);
1095                 }
1096             }
1097 
1098             break;
1099         }
1100 #endif
1101 
1102         /* If module is configured for default LSI, always return true */
1103         default:
1104         {
1105             result = true;
1106             break;
1107         }
1108     }
1109 
1110     return result;
1111 }                                      /* End of function ether_phy_targets_is_support_link_partner_ability() */
1112