• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 /*---------------------------------------------------------------------
9  * Includes
10  *---------------------------------------------------------------------
11  */
12 #include "hpm_enet_drv.h"
13 #include "hpm_dp83867_regs.h"
14 #include "hpm_dp83867.h"
15 
16 /*---------------------------------------------------------------------
17  * Internal API
18  *---------------------------------------------------------------------
19  */
dp83867_check_id(ENET_Type * ptr)20 bool dp83867_check_id(ENET_Type *ptr)
21 {
22     uint16_t id1, id2;
23 
24     id1 = enet_read_phy(ptr, DP83867_ADDR, DP83867_PHYIDR1);
25     id2 = enet_read_phy(ptr, DP83867_ADDR, DP83867_PHYIDR2);
26 
27     if (DP83867_PHYIDR1_OUI_MSB_GET(id1) == DP83867_ID1 && DP83867_PHYIDR2_OUI_LSB_GET(id2) == DP83867_ID2) {
28         return true;
29     } else {
30         return false;
31     }
32 }
33 
dp83867_write_phy_ext(ENET_Type * ptr,uint32_t phy_addr,uint32_t addr,uint32_t data)34 static void dp83867_write_phy_ext(ENET_Type *ptr, uint32_t phy_addr, uint32_t addr, uint32_t data)
35 {
36     /* set the control register for register address */
37     enet_write_phy(ptr, phy_addr, DP83867_REGCR,  DP83867_REGCR_FUNCTION_SET(0) | DP83867_REGCR_DEVAD_SET(0x1f));
38 
39     /* write the specified register address */
40     enet_write_phy(ptr, phy_addr, DP83867_ADDAR, addr);
41 
42     /* set the control register for register data */
43     enet_write_phy(ptr, phy_addr, DP83867_REGCR, DP83867_REGCR_FUNCTION_SET(1) | DP83867_REGCR_DEVAD_SET(0x1f));
44 
45     /* write the specified register data */
46     enet_write_phy(ptr, phy_addr, DP83867_ADDAR, data);
47 }
48 
dp83867_read_phy_ext(ENET_Type * ptr,uint32_t phy_addr,uint32_t addr)49 static uint16_t dp83867_read_phy_ext(ENET_Type *ptr, uint32_t phy_addr, uint32_t addr)
50 {
51     /* set the control register for register address */
52     enet_write_phy(ptr, phy_addr, DP83867_REGCR, DP83867_REGCR_FUNCTION_SET(0) | DP83867_REGCR_DEVAD_SET(0x1f));
53 
54     /* write the specified register address */
55     enet_write_phy(ptr, phy_addr, DP83867_ADDAR, addr);
56 
57     /* set the control register for register data */
58     enet_write_phy(ptr, phy_addr, DP83867_REGCR, DP83867_REGCR_FUNCTION_SET(1) | DP83867_REGCR_DEVAD_SET(0x1f));
59 
60     /* read the specified register data */
61     return enet_read_phy(ptr, phy_addr, DP83867_ADDAR);
62 }
63 /*---------------------------------------------------------------------
64  * API
65  *---------------------------------------------------------------------
66  */
dp83867_reset(ENET_Type * ptr)67 void dp83867_reset(ENET_Type *ptr)
68 {
69     uint16_t data;
70 
71     /* PHY reset */
72     enet_write_phy(ptr, DP83867_ADDR, DP83867_BMCR, DP83867_BMCR_RESET_SET(1));
73 
74     /* wait until the reset is completed */
75     do {
76         data = enet_read_phy(ptr, DP83867_ADDR, DP83867_BMCR);
77     } while (DP83867_BMCR_RESET_GET(data));
78 }
79 
dp83867_basic_mode_default_config(ENET_Type * ptr,dp83867_config_t * config)80 void dp83867_basic_mode_default_config(ENET_Type *ptr, dp83867_config_t *config)
81 {
82     (void)ptr;
83 
84     config->loopback         = false;                        /* Disable PCS loopback mode */
85     #if defined(__DISABLE_AUTO_NEGO) && (__DISABLE_AUTO_NEGO)
86     config->auto_negotiation = false;                        /* Disable Auto-Negotiation */
87     config->speed            = enet_phy_port_speed_100mbps;
88     config->duplex           = enet_phy_duplex_full;
89     #else
90     config->auto_negotiation = true;                         /* Enable Auto-Negotiation */
91     #endif
92 }
93 
dp83867_basic_mode_init(ENET_Type * ptr,dp83867_config_t * config)94 bool dp83867_basic_mode_init(ENET_Type *ptr, dp83867_config_t *config)
95 {
96     uint16_t data = 0;
97 
98     data |= DP83867_BMCR_RESET_SET(0)                        /* Normal operation */
99          |  DP83867_BMCR_LOOPBACK_SET(config->loopback)      /* Configure PCS loopback mode */
100          |  DP83867_BMCR_ANE_SET(config->auto_negotiation)   /* Configure Auto-Negotiation */
101          |  DP83867_BMCR_PWD_SET(0)                          /* Normal operation */
102          |  DP83867_BMCR_ISOLATE_SET(0)                      /* Normal operation */
103          |  DP83867_BMCR_RESTART_AN_SET(0)                   /* Normal operation (ignored when Auto-Negotiation is disabled) */
104          |  DP83867_BMCR_COLLISION_TEST_SET(0);              /* Normal operation */
105 
106     if (config->auto_negotiation == false) {
107         data |= DP83867_BMCR_SPEED0_SET(config->speed) | DP83867_BMCR_SPEED1_SET(config->speed >> 1); /* Set port speed */
108         data |= DP83867_BMCR_DUPLEX_SET(config->duplex);                                              /* Set duplex mode */
109     }
110 
111     /* check the id of dp83867 */
112     if (dp83867_check_id(ptr) == false) {
113         return false;
114     }
115 
116     enet_write_phy(ptr, DP83867_ADDR, DP83867_BMCR, data);
117     data = enet_read_phy(ptr, DP83867_ADDR, DP83867_BMCR);
118 
119     return true;
120 }
121 
dp83867_get_phy_status(ENET_Type * ptr,enet_phy_status_t * status)122 void dp83867_get_phy_status(ENET_Type *ptr, enet_phy_status_t *status)
123 {
124     uint16_t data;
125 
126     data = enet_read_phy(ptr, DP83867_ADDR, DP83867_PHYSTS);
127     status->enet_phy_link = DP83867_PHYSTS_LINK_STATUS_GET(data);
128     status->enet_phy_speed = DP83867_PHYSTS_SPEED_SELECTION_GET(data) == 0 ? enet_phy_port_speed_10mbps : DP83867_PHYSTS_SPEED_SELECTION_GET(data) == 1 ? enet_phy_port_speed_100mbps : enet_phy_port_speed_1000mbps;
129     status->enet_phy_duplex = DP83867_PHYSTS_DUPLEX_MODE_GET(data);
130 }
131 
dp83867_set_mdi_crossover_mode(ENET_Type * ptr,enet_phy_crossover_mode_t mode)132 void dp83867_set_mdi_crossover_mode(ENET_Type *ptr, enet_phy_crossover_mode_t mode)
133 {
134     uint16_t data;
135 
136     data = dp83867_read_phy_ext(ptr, DP83867_ADDR, DP83867_PHYCR);
137     data &= ~DP83867_PHYCR_MDI_CROSSOVER_MASK;
138     data |= DP83867_PHYCR_MDI_CROSSOVER_SET(mode);
139     dp83867_write_phy_ext(ptr, DP83867_ADDR, DP83867_PHYCR, data);
140 }
141