esp_eth_phy_dp83848.c
1 // Copyright 2019 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #include <string.h> 15 #include <stdlib.h> 16 #include <sys/cdefs.h> 17 #include "esp_log.h" 18 #include "esp_eth.h" 19 #include "eth_phy_regs_struct.h" 20 #include "freertos/FreeRTOS.h" 21 #include "freertos/task.h" 22 #include "driver/gpio.h" 23 #include "esp_rom_gpio.h" 24 #include "esp_rom_sys.h" 25 26 static const char *TAG = "dp83848"; 27 #define PHY_CHECK(a, str, goto_tag, ...) \ 28 do \ 29 { \ 30 if (!(a)) \ 31 { \ 32 ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ 33 goto goto_tag; \ 34 } \ 35 } while (0) 36 37 /***************Vendor Specific Register***************/ 38 39 /** 40 * @brief PHYSTS(PHY Status Register) 41 * 42 */ 43 typedef union { 44 struct { 45 uint32_t link_status : 1; /* Link Status */ 46 uint32_t speed_status : 1; /* Speed Status */ 47 uint32_t duplex_status : 1; /* Duplex Status */ 48 uint32_t loopback_status : 1; /* MII Loopback */ 49 uint32_t auto_nego_complete : 1; /* Auto-Negotiation Complete */ 50 uint32_t jabber_detect : 1; /* Jabber Detect */ 51 uint32_t remote_fault : 1; /* Remote Fault */ 52 uint32_t mii_interrupt : 1; /* MII Interrupt Pending */ 53 uint32_t page_received : 1; /* Link Code Word Page Received */ 54 uint32_t descrambler_lock : 1; /* Descrambler Lock */ 55 uint32_t signal_detect : 1; /* Signal Detect */ 56 uint32_t false_carrier_sense_latch : 1; /* False Carrier Sense Latch */ 57 uint32_t polarity_status : 1; /* Polarity Status */ 58 uint32_t receive_error_latch : 1; /* Receive Error Latch */ 59 uint32_t mdix_mode : 1; /* MDI-X mode reported by auto-negotiation */ 60 uint32_t reserved : 1; /* Reserved */ 61 }; 62 uint32_t val; 63 } physts_reg_t; 64 #define ETH_PHY_STS_REG_ADDR (0x10) 65 66 /** 67 * @brief PHYCR(PHY Control Register) 68 * 69 */ 70 typedef union { 71 struct { 72 uint32_t phy_addr : 5; /* PHY Address */ 73 uint32_t led_cfg : 2; /* LED Configuration Modes */ 74 uint32_t bypass_led_stretching : 1; /* Bypass LED Stretching */ 75 uint32_t bist_start : 1; /* BIST Start */ 76 uint32_t bist_status : 1; /* BIST Test Status */ 77 uint32_t psr_15 : 1; /* BIST Sequence select */ 78 uint32_t bist_force_error : 1; /* BIST Force Error */ 79 uint32_t pause_trans_negotiate : 1; /* Pause Transmit Negotiated Status */ 80 uint32_t pause_receive_negotiat : 1; /* Pause Receive Negotiated Status */ 81 uint32_t force_mdix : 1; /* Force MDIX */ 82 uint32_t en_auto_mdix : 1; /* Auto-MDIX Enable */ 83 }; 84 uint32_t val; 85 } phycr_reg_t; 86 #define ETH_PHY_CR_REG_ADDR (0x19) 87 88 typedef struct { 89 esp_eth_phy_t parent; 90 esp_eth_mediator_t *eth; 91 uint32_t addr; 92 uint32_t reset_timeout_ms; 93 uint32_t autonego_timeout_ms; 94 eth_link_t link_status; 95 int reset_gpio_num; 96 } phy_dp83848_t; 97 98 static esp_err_t dp83848_update_link_duplex_speed(phy_dp83848_t *dp83848) 99 { 100 esp_eth_mediator_t *eth = dp83848->eth; 101 eth_speed_t speed = ETH_SPEED_10M; 102 eth_duplex_t duplex = ETH_DUPLEX_HALF; 103 uint32_t peer_pause_ability = false; 104 anlpar_reg_t anlpar; 105 physts_reg_t physts; 106 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)) == ESP_OK, 107 "read ANLPAR failed", err); 108 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_STS_REG_ADDR, &(physts.val)) == ESP_OK, 109 "read PHYSTS failed", err); 110 eth_link_t link = physts.link_status ? ETH_LINK_UP : ETH_LINK_DOWN; 111 /* check if link status changed */ 112 if (dp83848->link_status != link) { 113 /* when link up, read negotiation result */ 114 if (link == ETH_LINK_UP) { 115 if (physts.speed_status) { 116 speed = ETH_SPEED_10M; 117 } else { 118 speed = ETH_SPEED_100M; 119 } 120 if (physts.duplex_status) { 121 duplex = ETH_DUPLEX_FULL; 122 } else { 123 duplex = ETH_DUPLEX_HALF; 124 } 125 PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK, 126 "change speed failed", err); 127 PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK, 128 "change duplex failed", err); 129 /* if we're in duplex mode, and peer has the flow control ability */ 130 if (duplex == ETH_DUPLEX_FULL && anlpar.symmetric_pause) { 131 peer_pause_ability = 1; 132 } else { 133 peer_pause_ability = 0; 134 } 135 PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_PAUSE, (void *)peer_pause_ability) == ESP_OK, 136 "change pause ability failed", err); 137 } 138 PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, 139 "change link failed", err); 140 dp83848->link_status = link; 141 } 142 return ESP_OK; 143 err: 144 return ESP_FAIL; 145 } 146 147 static esp_err_t dp83848_set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth) 148 { 149 PHY_CHECK(eth, "can't set mediator to null", err); 150 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 151 dp83848->eth = eth; 152 return ESP_OK; 153 err: 154 return ESP_ERR_INVALID_ARG; 155 } 156 157 static esp_err_t dp83848_get_link(esp_eth_phy_t *phy) 158 { 159 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 160 /* Updata information about link, speed, duplex */ 161 PHY_CHECK(dp83848_update_link_duplex_speed(dp83848) == ESP_OK, "update link duplex speed failed", err); 162 return ESP_OK; 163 err: 164 return ESP_FAIL; 165 } 166 167 static esp_err_t dp83848_reset(esp_eth_phy_t *phy) 168 { 169 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 170 dp83848->link_status = ETH_LINK_DOWN; 171 esp_eth_mediator_t *eth = dp83848->eth; 172 bmcr_reg_t bmcr = {.reset = 1}; 173 PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, 174 "write BMCR failed", err); 175 /* Wait for reset complete */ 176 uint32_t to = 0; 177 for (to = 0; to < dp83848->reset_timeout_ms / 10; to++) { 178 vTaskDelay(pdMS_TO_TICKS(10)); 179 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, 180 "read BMCR failed", err); 181 if (!bmcr.reset) { 182 break; 183 } 184 } 185 PHY_CHECK(to < dp83848->reset_timeout_ms / 10, "reset timeout", err); 186 return ESP_OK; 187 err: 188 return ESP_FAIL; 189 } 190 191 static esp_err_t dp83848_reset_hw(esp_eth_phy_t *phy) 192 { 193 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 194 if (dp83848->reset_gpio_num >= 0) { 195 esp_rom_gpio_pad_select_gpio(dp83848->reset_gpio_num); 196 gpio_set_direction(dp83848->reset_gpio_num, GPIO_MODE_OUTPUT); 197 gpio_set_level(dp83848->reset_gpio_num, 0); 198 esp_rom_delay_us(100); // insert min input assert time 199 gpio_set_level(dp83848->reset_gpio_num, 1); 200 } 201 return ESP_OK; 202 } 203 204 static esp_err_t dp83848_negotiate(esp_eth_phy_t *phy) 205 { 206 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 207 esp_eth_mediator_t *eth = dp83848->eth; 208 /* Start auto negotiation */ 209 bmcr_reg_t bmcr = { 210 .speed_select = 1, /* 100Mbps */ 211 .duplex_mode = 1, /* Full Duplex */ 212 .en_auto_nego = 1, /* Auto Negotiation */ 213 .restart_auto_nego = 1 /* Restart Auto Negotiation */ 214 }; 215 PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, 216 "write BMCR failed", err); 217 /* Wait for auto negotiation complete */ 218 bmsr_reg_t bmsr; 219 physts_reg_t physts; 220 uint32_t to = 0; 221 for (to = 0; to < dp83848->autonego_timeout_ms / 10; to++) { 222 vTaskDelay(pdMS_TO_TICKS(10)); 223 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, 224 "read BMSR failed", err); 225 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_STS_REG_ADDR, &(physts.val)) == ESP_OK, 226 "read PHYSTS failed", err); 227 if (bmsr.auto_nego_complete && physts.auto_nego_complete) { 228 break; 229 } 230 } 231 /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ 232 if (to >= dp83848->autonego_timeout_ms / 10) { 233 ESP_LOGW(TAG, "auto negotiation timeout"); 234 } 235 /* Updata information about link, speed, duplex */ 236 PHY_CHECK(dp83848_update_link_duplex_speed(dp83848) == ESP_OK, "update link duplex speed failed", err); 237 return ESP_OK; 238 err: 239 return ESP_FAIL; 240 } 241 242 static esp_err_t dp83848_pwrctl(esp_eth_phy_t *phy, bool enable) 243 { 244 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 245 esp_eth_mediator_t *eth = dp83848->eth; 246 bmcr_reg_t bmcr; 247 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, 248 "read BMCR failed", err); 249 if (!enable) { 250 /* Enable IEEE Power Down Mode */ 251 bmcr.power_down = 1; 252 } else { 253 /* Disable IEEE Power Down Mode */ 254 bmcr.power_down = 0; 255 } 256 PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, 257 "write BMCR failed", err); 258 if (!enable) { 259 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, 260 "read BMCR failed", err); 261 PHY_CHECK(bmcr.power_down == 1, "power down failed", err); 262 } else { 263 /* wait for power up complete */ 264 uint32_t to = 0; 265 for (to = 0; to < dp83848->reset_timeout_ms / 10; to++) { 266 vTaskDelay(pdMS_TO_TICKS(10)); 267 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, 268 "read BMCR failed", err); 269 if (bmcr.power_down == 0) { 270 break; 271 } 272 } 273 PHY_CHECK(to < dp83848->reset_timeout_ms / 10, "power up timeout", err); 274 } 275 return ESP_OK; 276 err: 277 return ESP_FAIL; 278 } 279 280 static esp_err_t dp83848_set_addr(esp_eth_phy_t *phy, uint32_t addr) 281 { 282 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 283 dp83848->addr = addr; 284 return ESP_OK; 285 } 286 287 static esp_err_t dp83848_get_addr(esp_eth_phy_t *phy, uint32_t *addr) 288 { 289 PHY_CHECK(addr, "addr can't be null", err); 290 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 291 *addr = dp83848->addr; 292 return ESP_OK; 293 err: 294 return ESP_ERR_INVALID_ARG; 295 } 296 297 static esp_err_t dp83848_del(esp_eth_phy_t *phy) 298 { 299 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 300 free(dp83848); 301 return ESP_OK; 302 } 303 304 static esp_err_t dp83848_advertise_pause_ability(esp_eth_phy_t *phy, uint32_t ability) 305 { 306 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 307 esp_eth_mediator_t *eth = dp83848->eth; 308 /* Set PAUSE function ability */ 309 anar_reg_t anar; 310 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_ANAR_REG_ADDR, &(anar.val)) == ESP_OK, 311 "read ANAR failed", err); 312 if (ability) { 313 anar.asymmetric_pause = 1; 314 anar.symmetric_pause = 1; 315 } else { 316 anar.asymmetric_pause = 0; 317 anar.symmetric_pause = 0; 318 } 319 PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_ANAR_REG_ADDR, anar.val) == ESP_OK, 320 "write ANAR failed", err); 321 return ESP_OK; 322 err: 323 return ESP_FAIL; 324 } 325 326 static esp_err_t dp83848_init(esp_eth_phy_t *phy) 327 { 328 phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); 329 esp_eth_mediator_t *eth = dp83848->eth; 330 // Detect PHY address 331 if (dp83848->addr == ESP_ETH_PHY_ADDR_AUTO) { 332 PHY_CHECK(esp_eth_detect_phy_addr(eth, &dp83848->addr) == ESP_OK, "Detect PHY address failed", err); 333 } 334 /* Power on Ethernet PHY */ 335 PHY_CHECK(dp83848_pwrctl(phy, true) == ESP_OK, "power control failed", err); 336 /* Reset Ethernet PHY */ 337 PHY_CHECK(dp83848_reset(phy) == ESP_OK, "reset failed", err); 338 /* Check PHY ID */ 339 phyidr1_reg_t id1; 340 phyidr2_reg_t id2; 341 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK, 342 "read ID1 failed", err); 343 PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK, 344 "read ID2 failed", err); 345 PHY_CHECK(id1.oui_msb == 0x2000 && id2.oui_lsb == 0x17 && id2.vendor_model == 0x09, 346 "wrong chip ID", err); 347 return ESP_OK; 348 err: 349 return ESP_FAIL; 350 } 351 352 static esp_err_t dp83848_deinit(esp_eth_phy_t *phy) 353 { 354 /* Power off Ethernet PHY */ 355 PHY_CHECK(dp83848_pwrctl(phy, false) == ESP_OK, "power control failed", err); 356 return ESP_OK; 357 err: 358 return ESP_FAIL; 359 } 360 361 esp_eth_phy_t *esp_eth_phy_new_dp83848(const eth_phy_config_t *config) 362 { 363 PHY_CHECK(config, "can't set phy config to null", err); 364 phy_dp83848_t *dp83848 = calloc(1, sizeof(phy_dp83848_t)); 365 PHY_CHECK(dp83848, "calloc dp83848 failed", err); 366 dp83848->addr = config->phy_addr; 367 dp83848->reset_timeout_ms = config->reset_timeout_ms; 368 dp83848->link_status = ETH_LINK_DOWN; 369 dp83848->reset_gpio_num = config->reset_gpio_num; 370 dp83848->autonego_timeout_ms = config->autonego_timeout_ms; 371 dp83848->parent.reset = dp83848_reset; 372 dp83848->parent.reset_hw = dp83848_reset_hw; 373 dp83848->parent.init = dp83848_init; 374 dp83848->parent.deinit = dp83848_deinit; 375 dp83848->parent.set_mediator = dp83848_set_mediator; 376 dp83848->parent.negotiate = dp83848_negotiate; 377 dp83848->parent.get_link = dp83848_get_link; 378 dp83848->parent.pwrctl = dp83848_pwrctl; 379 dp83848->parent.get_addr = dp83848_get_addr; 380 dp83848->parent.set_addr = dp83848_set_addr; 381 dp83848->parent.advertise_pause_ability = dp83848_advertise_pause_ability; 382 dp83848->parent.del = dp83848_del; 383 384 return &(dp83848->parent); 385 err: 386 return NULL; 387 }