/ components / esp_eth / src / esp_eth_mac_dm9051.c
esp_eth_mac_dm9051.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 "driver/gpio.h"
 18  #include "driver/spi_master.h"
 19  #include "esp_attr.h"
 20  #include "esp_log.h"
 21  #include "esp_eth.h"
 22  #include "esp_system.h"
 23  #include "esp_intr_alloc.h"
 24  #include "esp_heap_caps.h"
 25  #include "freertos/FreeRTOS.h"
 26  #include "freertos/task.h"
 27  #include "freertos/semphr.h"
 28  #include "hal/cpu_hal.h"
 29  #include "dm9051.h"
 30  #include "sdkconfig.h"
 31  #include "esp_rom_gpio.h"
 32  #include "esp_rom_sys.h"
 33  
 34  static const char *TAG = "emac_dm9051";
 35  #define MAC_CHECK(a, str, goto_tag, ret_value, ...)                               \
 36      do                                                                            \
 37      {                                                                             \
 38          if (!(a))                                                                 \
 39          {                                                                         \
 40              ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
 41              ret = ret_value;                                                      \
 42              goto goto_tag;                                                        \
 43          }                                                                         \
 44      } while (0)
 45  
 46  #define DM9051_SPI_LOCK_TIMEOUT_MS (50)
 47  #define DM9051_PHY_OPERATION_TIMEOUT_US (1000)
 48  
 49  typedef struct {
 50      uint8_t flag;
 51      uint8_t status;
 52      uint8_t length_low;
 53      uint8_t length_high;
 54  } dm9051_rx_header_t;
 55  
 56  typedef struct {
 57      esp_eth_mac_t parent;
 58      esp_eth_mediator_t *eth;
 59      spi_device_handle_t spi_hdl;
 60      SemaphoreHandle_t spi_lock;
 61      TaskHandle_t rx_task_hdl;
 62      uint32_t sw_reset_timeout_ms;
 63      int int_gpio_num;
 64      uint8_t addr[6];
 65      bool packets_remain;
 66      bool flow_ctrl_enabled;
 67  } emac_dm9051_t;
 68  
 69  static inline bool dm9051_lock(emac_dm9051_t *emac)
 70  {
 71      return xSemaphoreTake(emac->spi_lock, pdMS_TO_TICKS(DM9051_SPI_LOCK_TIMEOUT_MS)) == pdTRUE;
 72  }
 73  
 74  static inline bool dm9051_unlock(emac_dm9051_t *emac)
 75  {
 76      return xSemaphoreGive(emac->spi_lock) == pdTRUE;
 77  }
 78  
 79  /**
 80   * @brief write value to dm9051 internal register
 81   */
 82  static esp_err_t dm9051_register_write(emac_dm9051_t *emac, uint8_t reg_addr, uint8_t value)
 83  {
 84      esp_err_t ret = ESP_OK;
 85      spi_transaction_t trans = {
 86          .cmd = DM9051_SPI_WR,
 87          .addr = reg_addr,
 88          .length = 8,
 89          .flags = SPI_TRANS_USE_TXDATA
 90      };
 91      trans.tx_data[0] = value;
 92      if (dm9051_lock(emac)) {
 93          if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) {
 94              ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__);
 95              ret = ESP_FAIL;
 96          }
 97          dm9051_unlock(emac);
 98      } else {
 99          ret = ESP_ERR_TIMEOUT;
100      }
101      return ret;
102  }
103  
104  /**
105   * @brief read value from dm9051 internal register
106   */
107  static esp_err_t dm9051_register_read(emac_dm9051_t *emac, uint8_t reg_addr, uint8_t *value)
108  {
109      esp_err_t ret = ESP_OK;
110      spi_transaction_t trans = {
111          .cmd = DM9051_SPI_RD,
112          .addr = reg_addr,
113          .length = 8,
114          .flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA
115      };
116      if (dm9051_lock(emac)) {
117          if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) {
118              ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__);
119              ret = ESP_FAIL;
120          } else {
121              *value = trans.rx_data[0];
122          }
123          dm9051_unlock(emac);
124      } else {
125          ret = ESP_ERR_TIMEOUT;
126      }
127      return ret;
128  }
129  
130  /**
131   * @brief write buffer to dm9051 internal memory
132   */
133  static esp_err_t dm9051_memory_write(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len)
134  {
135      esp_err_t ret = ESP_OK;
136      spi_transaction_t trans = {
137          .cmd = DM9051_SPI_WR,
138          .addr = DM9051_MWCMD,
139          .length = len * 8,
140          .tx_buffer = buffer
141      };
142      if (dm9051_lock(emac)) {
143          if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) {
144              ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__);
145              ret = ESP_FAIL;
146          }
147          dm9051_unlock(emac);
148      } else {
149          ret = ESP_ERR_TIMEOUT;
150      }
151      return ret;
152  }
153  
154  /**
155   * @brief read buffer from dm9051 internal memory
156   */
157  static esp_err_t dm9051_memory_read(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len)
158  {
159      esp_err_t ret = ESP_OK;
160      spi_transaction_t trans = {
161          .cmd = DM9051_SPI_RD,
162          .addr = DM9051_MRCMD,
163          .length = len * 8,
164          .rx_buffer = buffer
165      };
166      if (dm9051_lock(emac)) {
167          if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) {
168              ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__);
169              ret = ESP_FAIL;
170          }
171          dm9051_unlock(emac);
172      } else {
173          ret = ESP_ERR_TIMEOUT;
174      }
175      return ret;
176  }
177  
178  /**
179   * @brief peek buffer from dm9051 internal memory (without internal cursor moved)
180   */
181  static esp_err_t dm9051_memory_peek(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len)
182  {
183      esp_err_t ret = ESP_OK;
184      spi_transaction_t trans = {
185          .cmd = DM9051_SPI_RD,
186          .addr = DM9051_MRCMDX1,
187          .length = len * 8,
188          .rx_buffer = buffer
189      };
190      if (dm9051_lock(emac)) {
191          if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) {
192              ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__);
193              ret = ESP_FAIL;
194          }
195          dm9051_unlock(emac);
196      } else {
197          ret = ESP_ERR_TIMEOUT;
198      }
199      return ret;
200  }
201  
202  /**
203   * @brief read mac address from internal registers
204   */
205  static esp_err_t dm9051_get_mac_addr(emac_dm9051_t *emac)
206  {
207      esp_err_t ret = ESP_OK;
208      for (int i = 0; i < 6; i++) {
209          MAC_CHECK(dm9051_register_read(emac, DM9051_PAR + i, &emac->addr[i]) == ESP_OK, "read PAR failed", err, ESP_FAIL);
210      }
211      return ESP_OK;
212  err:
213      return ret;
214  }
215  
216  /**
217   * @brief set new mac address to internal registers
218   */
219  static esp_err_t dm9051_set_mac_addr(emac_dm9051_t *emac)
220  {
221      esp_err_t ret = ESP_OK;
222      for (int i = 0; i < 6; i++) {
223          MAC_CHECK(dm9051_register_write(emac, DM9051_PAR + i, emac->addr[i]) == ESP_OK, "write PAR failed", err, ESP_FAIL);
224      }
225      return ESP_OK;
226  err:
227      return ret;
228  }
229  
230  /**
231   * @brief clear multicast hash table
232   */
233  static esp_err_t dm9051_clear_multicast_table(emac_dm9051_t *emac)
234  {
235      esp_err_t ret = ESP_OK;
236      /* rx broadcast packet control by bit7 of MAC register 1DH */
237      MAC_CHECK(dm9051_register_write(emac, DM9051_BCASTCR, 0x00) == ESP_OK, "write BCASTCR failed", err, ESP_FAIL);
238      for (int i = 0; i < 7; i++) {
239          MAC_CHECK(dm9051_register_write(emac, DM9051_MAR + i, 0x00) == ESP_OK, "write MAR failed", err, ESP_FAIL);
240      }
241      /* enable receive broadcast paclets */
242      MAC_CHECK(dm9051_register_write(emac, DM9051_MAR + 7, 0x80) == ESP_OK, "write MAR failed", err, ESP_FAIL);
243      return ESP_OK;
244  err:
245      return ret;
246  }
247  
248  /**
249   * @brief software reset dm9051 internal register
250   */
251  static esp_err_t dm9051_reset(emac_dm9051_t *emac)
252  {
253      esp_err_t ret = ESP_OK;
254      /* power on phy */
255      MAC_CHECK(dm9051_register_write(emac, DM9051_GPR, 0x00) == ESP_OK, "write GPR failed", err, ESP_FAIL);
256      /* mac and phy register won't be accesable within at least 1ms */
257      vTaskDelay(pdMS_TO_TICKS(10));
258      /* software reset */
259      uint8_t ncr = NCR_RST;
260      MAC_CHECK(dm9051_register_write(emac, DM9051_NCR, ncr) == ESP_OK, "write NCR failed", err, ESP_FAIL);
261      uint32_t to = 0;
262      for (to = 0; to < emac->sw_reset_timeout_ms / 10; to++) {
263          MAC_CHECK(dm9051_register_read(emac, DM9051_NCR, &ncr) == ESP_OK, "read NCR failed", err, ESP_FAIL);
264          if (!(ncr & NCR_RST)) {
265              break;
266          }
267          vTaskDelay(pdMS_TO_TICKS(10));
268      }
269      MAC_CHECK(to < emac->sw_reset_timeout_ms / 10, "reset timeout", err, ESP_ERR_TIMEOUT);
270      return ESP_OK;
271  err:
272      return ret;
273  }
274  
275  /**
276   * @brief verify dm9051 chip ID
277   */
278  static esp_err_t dm9051_verify_id(emac_dm9051_t *emac)
279  {
280      esp_err_t ret = ESP_OK;
281      uint8_t id[2];
282      MAC_CHECK(dm9051_register_read(emac, DM9051_VIDL, &id[0]) == ESP_OK, "read VIDL failed", err, ESP_FAIL);
283      MAC_CHECK(dm9051_register_read(emac, DM9051_VIDH, &id[1]) == ESP_OK, "read VIDH failed", err, ESP_FAIL);
284      MAC_CHECK(0x0A == id[1] && 0x46 == id[0], "wrong Vendor ID", err, ESP_ERR_INVALID_VERSION);
285      MAC_CHECK(dm9051_register_read(emac, DM9051_PIDL, &id[0]) == ESP_OK, "read PIDL failed", err, ESP_FAIL);
286      MAC_CHECK(dm9051_register_read(emac, DM9051_PIDH, &id[1]) == ESP_OK, "read PIDH failed", err, ESP_FAIL);
287      MAC_CHECK(0x90 == id[1] && 0x51 == id[0], "wrong Product ID", err, ESP_ERR_INVALID_VERSION);
288      return ESP_OK;
289  err:
290      return ret;
291  }
292  
293  /**
294   * @brief default setup for dm9051 internal registers
295   */
296  static esp_err_t dm9051_setup_default(emac_dm9051_t *emac)
297  {
298      esp_err_t ret = ESP_OK;
299      /* disable wakeup */
300      MAC_CHECK(dm9051_register_write(emac, DM9051_NCR, 0x00) == ESP_OK, "write NCR failed", err, ESP_FAIL);
301      MAC_CHECK(dm9051_register_write(emac, DM9051_WCR, 0x00) == ESP_OK, "write WCR failed", err, ESP_FAIL);
302      /* stop transmitting, enable appending pad, crc for packets */
303      MAC_CHECK(dm9051_register_write(emac, DM9051_TCR, 0x00) == ESP_OK, "write TCR failed", err, ESP_FAIL);
304      /* stop receiving, no promiscuous mode, no runt packet(size < 64bytes), not all multicast packets*/
305      /* discard long packet(size > 1522bytes) and crc error packet, enable watchdog */
306      MAC_CHECK(dm9051_register_write(emac, DM9051_RCR, RCR_DIS_LONG | RCR_DIS_CRC) == ESP_OK, "write RCR failed", err, ESP_FAIL);
307      /* retry late collision packet, at most two transmit command can be issued before transmit complete */
308      MAC_CHECK(dm9051_register_write(emac, DM9051_TCR2, TCR2_RLCP) == ESP_OK, "write TCR2 failed", err, ESP_FAIL);
309      /* enable auto transmit */
310      MAC_CHECK(dm9051_register_write(emac, DM9051_ATCR, ATCR_AUTO_TX) == ESP_OK, "write ATCR failed", err, ESP_FAIL);
311      /* generate checksum for UDP, TCP and IPv4 packets */
312      MAC_CHECK(dm9051_register_write(emac, DM9051_TCSCR, TCSCR_IPCSE | TCSCR_TCPCSE | TCSCR_UDPCSE) == ESP_OK,
313                "write TCSCR failed", err, ESP_FAIL);
314      /* disable check sum for receive packets */
315      MAC_CHECK(dm9051_register_write(emac, DM9051_RCSCSR, 0x00) == ESP_OK, "write RCSCSR failed", err, ESP_FAIL);
316      /* interrupt pin config: push-pull output, active high */
317      MAC_CHECK(dm9051_register_write(emac, DM9051_INTCR, 0x00) == ESP_OK, "write INTCR failed", err, ESP_FAIL);
318      MAC_CHECK(dm9051_register_write(emac, DM9051_INTCKCR, 0x00) == ESP_OK, "write INTCKCR failed", err, ESP_FAIL);
319      /* no length limitation for rx packets */
320      MAC_CHECK(dm9051_register_write(emac, DM9051_RLENCR, 0x00) == ESP_OK, "write RLENCR failed", err, ESP_FAIL);
321      /* 3K-byte for TX and 13K-byte for RX */
322      MAC_CHECK(dm9051_register_write(emac, DM9051_MEMSCR, 0x00) == ESP_OK, "write MEMSCR failed", err, ESP_FAIL);
323      /* reset tx and rx memory pointer */
324      MAC_CHECK(dm9051_register_write(emac, DM9051_MPTRCR, MPTRCR_RST_RX | MPTRCR_RST_TX) == ESP_OK,
325                "write MPTRCR failed", err, ESP_FAIL);
326      /* clear network status: wakeup event, tx complete */
327      MAC_CHECK(dm9051_register_write(emac, DM9051_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END) == ESP_OK, "write NSR failed", err, ESP_FAIL);
328      /* clear interrupt status */
329      MAC_CHECK(dm9051_register_write(emac, DM9051_ISR, ISR_CLR_STATUS) == ESP_OK, "write ISR failed", err, ESP_FAIL);
330      return ESP_OK;
331  err:
332      return ret;
333  }
334  
335  static esp_err_t dm9051_enable_flow_ctrl(emac_dm9051_t *emac, bool enable)
336  {
337      esp_err_t ret = ESP_OK;
338      if (enable) {
339          /* send jam pattern (duration time = 1.15ms) when rx free space < 3k bytes */
340          MAC_CHECK(dm9051_register_write(emac, DM9051_BPTR, 0x3F) == ESP_OK, "write BPTR failed", err, ESP_FAIL);
341          /* flow control: high water threshold = 3k bytes, low water threshold = 8k bytes */
342          MAC_CHECK(dm9051_register_write(emac, DM9051_FCTR, 0x38) == ESP_OK, "write FCTR failed", err, ESP_FAIL);
343          /* enable flow control */
344          MAC_CHECK(dm9051_register_write(emac, DM9051_FCR, FCR_FLOW_ENABLE) == ESP_OK, "write FCR failed", err, ESP_FAIL);
345      } else {
346          /* disable flow control */
347          MAC_CHECK(dm9051_register_write(emac, DM9051_FCR, 0) == ESP_OK, "write FCR failed", err, ESP_FAIL);
348      }
349      return ESP_OK;
350  err:
351      return ret;
352  }
353  
354  /**
355   * @brief start dm9051: enable interrupt and start receive
356   */
357  static esp_err_t emac_dm9051_start(esp_eth_mac_t *mac)
358  {
359      esp_err_t ret = ESP_OK;
360      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
361      /* enable interrupt */
362      MAC_CHECK(dm9051_register_write(emac, DM9051_IMR, IMR_ALL) == ESP_OK, "write IMR failed", err, ESP_FAIL);
363      /* enable rx */
364      uint8_t rcr = 0;
365      MAC_CHECK(dm9051_register_read(emac, DM9051_RCR, &rcr) == ESP_OK, "read RCR failed", err, ESP_FAIL);
366      rcr |= RCR_RXEN;
367      MAC_CHECK(dm9051_register_write(emac, DM9051_RCR, rcr) == ESP_OK, "write RCR failed", err, ESP_FAIL);
368      return ESP_OK;
369  err:
370      return ret;
371  }
372  
373  /**
374   * @brief stop dm9051: disable interrupt and stop receive
375   */
376  static esp_err_t emac_dm9051_stop(esp_eth_mac_t *mac)
377  {
378      esp_err_t ret = ESP_OK;
379      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
380      /* disable interrupt */
381      MAC_CHECK(dm9051_register_write(emac, DM9051_IMR, 0x00) == ESP_OK, "write IMR failed", err, ESP_FAIL);
382      /* disable rx */
383      uint8_t rcr = 0;
384      MAC_CHECK(dm9051_register_read(emac, DM9051_RCR, &rcr) == ESP_OK, "read RCR failed", err, ESP_FAIL);
385      rcr &= ~RCR_RXEN;
386      MAC_CHECK(dm9051_register_write(emac, DM9051_RCR, rcr) == ESP_OK, "write RCR failed", err, ESP_FAIL);
387      return ESP_OK;
388  err:
389      return ret;
390  }
391  
392  IRAM_ATTR static void dm9051_isr_handler(void *arg)
393  {
394      emac_dm9051_t *emac = (emac_dm9051_t *)arg;
395      BaseType_t high_task_wakeup = pdFALSE;
396      /* notify dm9051 task */
397      vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
398      if (high_task_wakeup != pdFALSE) {
399          portYIELD_FROM_ISR();
400      }
401  }
402  
403  static void emac_dm9051_task(void *arg)
404  {
405      emac_dm9051_t *emac = (emac_dm9051_t *)arg;
406      uint8_t status = 0;
407      uint8_t *buffer = NULL;
408      uint32_t length = 0;
409      while (1) {
410          // block indefinitely until some task notifies me
411          ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
412          /* clear interrupt status */
413          dm9051_register_read(emac, DM9051_ISR, &status);
414          dm9051_register_write(emac, DM9051_ISR, status);
415          /* packet received */
416          if (status & ISR_PR) {
417              do {
418                  length = ETH_MAX_PACKET_SIZE;
419                  buffer = heap_caps_malloc(length, MALLOC_CAP_DMA);
420                  if (!buffer) {
421                      ESP_LOGE(TAG, "no mem for receive buffer");
422                  } else if (emac->parent.receive(&emac->parent, buffer, &length) == ESP_OK) {
423                      /* pass the buffer to stack (e.g. TCP/IP layer) */
424                      if (length) {
425                          emac->eth->stack_input(emac->eth, buffer, length);
426                      } else {
427                          free(buffer);
428                      }
429                  } else {
430                      free(buffer);
431                  }
432              } while (emac->packets_remain);
433          }
434      }
435      vTaskDelete(NULL);
436  }
437  
438  static esp_err_t emac_dm9051_set_mediator(esp_eth_mac_t *mac, esp_eth_mediator_t *eth)
439  {
440      esp_err_t ret = ESP_OK;
441      MAC_CHECK(eth, "can't set mac's mediator to null", err, ESP_ERR_INVALID_ARG);
442      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
443      emac->eth = eth;
444      return ESP_OK;
445  err:
446      return ret;
447  }
448  
449  static esp_err_t emac_dm9051_write_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value)
450  {
451      esp_err_t ret = ESP_OK;
452      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
453      /* check if phy access is in progress */
454      uint8_t epcr = 0;
455      MAC_CHECK(dm9051_register_read(emac, DM9051_EPCR, &epcr) == ESP_OK, "read EPCR failed", err, ESP_FAIL);
456      MAC_CHECK(!(epcr & EPCR_ERRE), "phy is busy", err, ESP_ERR_INVALID_STATE);
457      MAC_CHECK(dm9051_register_write(emac, DM9051_EPAR, (uint8_t)(((phy_addr << 6) & 0xFF) | phy_reg)) == ESP_OK,
458                "write EPAR failed", err, ESP_FAIL);
459      MAC_CHECK(dm9051_register_write(emac, DM9051_EPDRL, (uint8_t)(reg_value & 0xFF)) == ESP_OK,
460                "write EPDRL failed", err, ESP_FAIL);
461      MAC_CHECK(dm9051_register_write(emac, DM9051_EPDRH, (uint8_t)((reg_value >> 8) & 0xFF)) == ESP_OK,
462                "write EPDRH failed", err, ESP_FAIL);
463      /* select PHY and select write operation */
464      MAC_CHECK(dm9051_register_write(emac, DM9051_EPCR, EPCR_EPOS | EPCR_ERPRW) == ESP_OK, "write EPCR failed", err, ESP_FAIL);
465      /* polling the busy flag */
466      uint32_t to = 0;
467      do {
468          esp_rom_delay_us(100);
469          MAC_CHECK(dm9051_register_read(emac, DM9051_EPCR, &epcr) == ESP_OK, "read EPCR failed", err, ESP_FAIL);
470          to += 100;
471      } while ((epcr & EPCR_ERRE) && to < DM9051_PHY_OPERATION_TIMEOUT_US);
472      MAC_CHECK(!(epcr & EPCR_ERRE), "phy is busy", err, ESP_ERR_TIMEOUT);
473      return ESP_OK;
474  err:
475      return ret;
476  }
477  
478  static esp_err_t emac_dm9051_read_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value)
479  {
480      esp_err_t ret = ESP_OK;
481      MAC_CHECK(reg_value, "can't set reg_value to null", err, ESP_ERR_INVALID_ARG);
482      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
483      /* check if phy access is in progress */
484      uint8_t epcr = 0;
485      MAC_CHECK(dm9051_register_read(emac, DM9051_EPCR, &epcr) == ESP_OK, "read EPCR failed", err, ESP_FAIL);
486      MAC_CHECK(!(epcr & 0x01), "phy is busy", err, ESP_ERR_INVALID_STATE);
487      MAC_CHECK(dm9051_register_write(emac, DM9051_EPAR, (uint8_t)(((phy_addr << 6) & 0xFF) | phy_reg)) == ESP_OK,
488                "write EPAR failed", err, ESP_FAIL);
489      /* Select PHY and select read operation */
490      MAC_CHECK(dm9051_register_write(emac, DM9051_EPCR, 0x0C) == ESP_OK, "write EPCR failed", err, ESP_FAIL);
491      /* polling the busy flag */
492      uint32_t to = 0;
493      do {
494          esp_rom_delay_us(100);
495          MAC_CHECK(dm9051_register_read(emac, DM9051_EPCR, &epcr) == ESP_OK, "read EPCR failed", err, ESP_FAIL);
496          to += 100;
497      } while ((epcr & EPCR_ERRE) && to < DM9051_PHY_OPERATION_TIMEOUT_US);
498      MAC_CHECK(!(epcr & EPCR_ERRE), "phy is busy", err, ESP_ERR_TIMEOUT);
499      uint8_t value_h = 0;
500      uint8_t value_l = 0;
501      MAC_CHECK(dm9051_register_read(emac, DM9051_EPDRH, &value_h) == ESP_OK, "read EPDRH failed", err, ESP_FAIL);
502      MAC_CHECK(dm9051_register_read(emac, DM9051_EPDRL, &value_l) == ESP_OK, "read EPDRL failed", err, ESP_FAIL);
503      *reg_value = (value_h << 8) | value_l;
504      return ESP_OK;
505  err:
506      return ret;
507  }
508  
509  static esp_err_t emac_dm9051_set_addr(esp_eth_mac_t *mac, uint8_t *addr)
510  {
511      esp_err_t ret = ESP_OK;
512      MAC_CHECK(addr, "can't set mac addr to null", err, ESP_ERR_INVALID_ARG);
513      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
514      memcpy(emac->addr, addr, 6);
515      MAC_CHECK(dm9051_set_mac_addr(emac) == ESP_OK, "set mac address failed", err, ESP_FAIL);
516      return ESP_OK;
517  err:
518      return ret;
519  }
520  
521  static esp_err_t emac_dm9051_get_addr(esp_eth_mac_t *mac, uint8_t *addr)
522  {
523      esp_err_t ret = ESP_OK;
524      MAC_CHECK(addr, "can't set mac addr to null", err, ESP_ERR_INVALID_ARG);
525      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
526      memcpy(addr, emac->addr, 6);
527      return ESP_OK;
528  err:
529      return ret;
530  }
531  
532  static esp_err_t emac_dm9051_set_link(esp_eth_mac_t *mac, eth_link_t link)
533  {
534      esp_err_t ret = ESP_OK;
535      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
536      uint8_t nsr = 0;
537      MAC_CHECK(dm9051_register_read(emac, DM9051_NSR, &nsr) == ESP_OK, "read NSR failed", err, ESP_FAIL);
538      switch (link) {
539      case ETH_LINK_UP:
540          MAC_CHECK(nsr & NSR_LINKST, "phy is not link up", err, ESP_ERR_INVALID_STATE);
541          MAC_CHECK(mac->start(mac) == ESP_OK, "dm9051 start failed", err, ESP_FAIL);
542          break;
543      case ETH_LINK_DOWN:
544          MAC_CHECK(!(nsr & NSR_LINKST), "phy is not link down", err, ESP_ERR_INVALID_STATE);
545          MAC_CHECK(mac->stop(mac) == ESP_OK, "dm9051 stop failed", err, ESP_FAIL);
546          break;
547      default:
548          MAC_CHECK(false, "unknown link status", err, ESP_ERR_INVALID_ARG);
549          break;
550      }
551      return ESP_OK;
552  err:
553      return ret;
554  }
555  
556  static esp_err_t emac_dm9051_set_speed(esp_eth_mac_t *mac, eth_speed_t speed)
557  {
558      esp_err_t ret = ESP_OK;
559      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
560      uint8_t nsr = 0;
561      MAC_CHECK(dm9051_register_read(emac, DM9051_NSR, &nsr) == ESP_OK, "read NSR failed", err, ESP_FAIL);
562      switch (speed) {
563      case ETH_SPEED_10M:
564          MAC_CHECK(nsr & NSR_SPEED, "phy speed is not at 10Mbps", err, ESP_ERR_INVALID_STATE);
565          ESP_LOGD(TAG, "working in 10Mbps");
566          break;
567      case ETH_SPEED_100M:
568          MAC_CHECK(!(nsr & NSR_SPEED), "phy speed is not at 100Mbps", err, ESP_ERR_INVALID_STATE);
569          ESP_LOGD(TAG, "working in 100Mbps");
570          break;
571      default:
572          MAC_CHECK(false, "unknown speed", err, ESP_ERR_INVALID_ARG);
573          break;
574      }
575      return ESP_OK;
576  err:
577      return ret;
578  }
579  
580  static esp_err_t emac_dm9051_set_duplex(esp_eth_mac_t *mac, eth_duplex_t duplex)
581  {
582      esp_err_t ret = ESP_OK;
583      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
584      uint8_t ncr = 0;
585      MAC_CHECK(dm9051_register_read(emac, DM9051_NCR, &ncr) == ESP_OK, "read NCR failed", err, ESP_FAIL);
586      switch (duplex) {
587      case ETH_DUPLEX_HALF:
588          ESP_LOGD(TAG, "working in half duplex");
589          MAC_CHECK(!(ncr & NCR_FDX), "phy is not at half duplex", err, ESP_ERR_INVALID_STATE);
590          break;
591      case ETH_DUPLEX_FULL:
592          ESP_LOGD(TAG, "working in full duplex");
593          MAC_CHECK(ncr & NCR_FDX, "phy is not at full duplex", err, ESP_ERR_INVALID_STATE);
594          break;
595      default:
596          MAC_CHECK(false, "unknown duplex", err, ESP_ERR_INVALID_ARG);
597          break;
598      }
599      return ESP_OK;
600  err:
601      return ret;
602  }
603  
604  static esp_err_t emac_dm9051_set_promiscuous(esp_eth_mac_t *mac, bool enable)
605  {
606      esp_err_t ret = ESP_OK;
607      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
608      uint8_t rcr = 0;
609      MAC_CHECK(dm9051_register_read(emac, DM9051_EPDRL, &rcr) == ESP_OK, "read RCR failed", err, ESP_FAIL);
610      if (enable) {
611          rcr |= RCR_PRMSC;
612      } else {
613          rcr &= ~RCR_PRMSC;
614      }
615      MAC_CHECK(dm9051_register_write(emac, DM9051_RCR, rcr) == ESP_OK, "write RCR failed", err, ESP_FAIL);
616      return ESP_OK;
617  err:
618      return ret;
619  }
620  
621  static esp_err_t emac_dm9051_enable_flow_ctrl(esp_eth_mac_t *mac, bool enable)
622  {
623      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
624      emac->flow_ctrl_enabled = enable;
625      return ESP_OK;
626  }
627  
628  static esp_err_t emac_dm9051_set_peer_pause_ability(esp_eth_mac_t *mac, uint32_t ability)
629  {
630      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
631      // we want to enable flow control, and peer does support pause function
632      // then configure the MAC layer to enable flow control feature
633      if (emac->flow_ctrl_enabled && ability) {
634          dm9051_enable_flow_ctrl(emac, true);
635      } else {
636          dm9051_enable_flow_ctrl(emac, false);
637          ESP_LOGD(TAG, "Flow control not enabled for the link");
638      }
639      return ESP_OK;
640  }
641  
642  static esp_err_t emac_dm9051_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t length)
643  {
644      esp_err_t ret = ESP_OK;
645      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
646      /* Check if last transmit complete */
647      uint8_t tcr = 0;
648      MAC_CHECK(dm9051_register_read(emac, DM9051_TCR, &tcr) == ESP_OK, "read TCR failed", err, ESP_FAIL);
649      MAC_CHECK(!(tcr & TCR_TXREQ), "last transmit still in progress", err, ESP_ERR_INVALID_STATE);
650      /* set tx length */
651      MAC_CHECK(dm9051_register_write(emac, DM9051_TXPLL, length & 0xFF) == ESP_OK, "write TXPLL failed", err, ESP_FAIL);
652      MAC_CHECK(dm9051_register_write(emac, DM9051_TXPLH, (length >> 8) & 0xFF) == ESP_OK, "write TXPLH failed", err, ESP_FAIL);
653      /* copy data to tx memory */
654      MAC_CHECK(dm9051_memory_write(emac, buf, length) == ESP_OK, "write memory failed", err, ESP_FAIL);
655      /* issue tx polling command */
656      tcr |= TCR_TXREQ;
657      MAC_CHECK(dm9051_register_write(emac, DM9051_TCR, tcr) == ESP_OK, "write TCR failed", err, ESP_FAIL);
658      return ESP_OK;
659  err:
660      return ret;
661  }
662  
663  static esp_err_t emac_dm9051_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length)
664  {
665      esp_err_t ret = ESP_OK;
666      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
667      uint8_t rxbyte = 0;
668      uint16_t rx_len = 0;
669      __attribute__((aligned(4))) dm9051_rx_header_t header; // SPI driver needs the rx buffer 4 byte align
670      emac->packets_remain = false;
671      /* dummy read, get the most updated data */
672      MAC_CHECK(dm9051_register_read(emac, DM9051_MRCMDX, &rxbyte) == ESP_OK, "read MRCMDX failed", err, ESP_FAIL);
673      MAC_CHECK(dm9051_register_read(emac, DM9051_MRCMDX, &rxbyte) == ESP_OK, "read MRCMDX failed", err, ESP_FAIL);
674      /* rxbyte must be 0xFF, 0 or 1 */
675      if (rxbyte > 1) {
676          MAC_CHECK(mac->stop(mac) == ESP_OK, "stop dm9051 failed", err, ESP_FAIL);
677          /* reset rx fifo pointer */
678          MAC_CHECK(dm9051_register_write(emac, DM9051_MPTRCR, MPTRCR_RST_RX) == ESP_OK,
679                    "write MPTRCR failed", err, ESP_FAIL);
680          esp_rom_delay_us(10);
681          MAC_CHECK(mac->start(mac) == ESP_OK, "start dm9051 failed", err, ESP_FAIL);
682          MAC_CHECK(false, "reset rx fifo pointer", err, ESP_FAIL);
683      } else if (rxbyte) {
684          MAC_CHECK(dm9051_memory_peek(emac, (uint8_t *)&header, sizeof(header)) == ESP_OK,
685                    "peek rx header failed", err, ESP_FAIL);
686          rx_len = header.length_low + (header.length_high << 8);
687          /* check if the buffer can hold all the incoming data */
688          if (*length < rx_len - 4) {
689              ESP_LOGE(TAG, "buffer size too small");
690              /* tell upper layer the size we need */
691              *length = rx_len - 4;
692              ret = ESP_ERR_INVALID_SIZE;
693              goto err;
694          }
695          MAC_CHECK(*length >= rx_len - 4, "buffer size too small", err, ESP_ERR_INVALID_SIZE);
696          MAC_CHECK(dm9051_memory_read(emac, (uint8_t *)&header, sizeof(header)) == ESP_OK,
697                    "read rx header failed", err, ESP_FAIL);
698          MAC_CHECK(dm9051_memory_read(emac, buf, rx_len) == ESP_OK, "read rx data failed", err, ESP_FAIL);
699          MAC_CHECK(!(header.status & 0xBF), "receive status error: %xH", err, ESP_FAIL, header.status);
700          *length = rx_len - 4; // substract the CRC length (4Bytes)
701          /* dummy read, get the most updated data */
702          MAC_CHECK(dm9051_register_read(emac, DM9051_MRCMDX, &rxbyte) == ESP_OK, "read MRCMDX failed", err, ESP_FAIL);
703          MAC_CHECK(dm9051_register_read(emac, DM9051_MRCMDX, &rxbyte) == ESP_OK, "read MRCMDX failed", err, ESP_FAIL);
704          emac->packets_remain = rxbyte > 0;
705      }
706      return ESP_OK;
707  err:
708      return ret;
709  }
710  
711  static esp_err_t emac_dm9051_init(esp_eth_mac_t *mac)
712  {
713      esp_err_t ret = ESP_OK;
714      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
715      esp_eth_mediator_t *eth = emac->eth;
716      esp_rom_gpio_pad_select_gpio(emac->int_gpio_num);
717      gpio_set_direction(emac->int_gpio_num, GPIO_MODE_INPUT);
718      gpio_set_pull_mode(emac->int_gpio_num, GPIO_PULLDOWN_ONLY);
719      gpio_set_intr_type(emac->int_gpio_num, GPIO_INTR_POSEDGE);
720      gpio_intr_enable(emac->int_gpio_num);
721      gpio_isr_handler_add(emac->int_gpio_num, dm9051_isr_handler, emac);
722      MAC_CHECK(eth->on_state_changed(eth, ETH_STATE_LLINIT, NULL) == ESP_OK, "lowlevel init failed", err, ESP_FAIL);
723      /* reset dm9051 */
724      MAC_CHECK(dm9051_reset(emac) == ESP_OK, "reset dm9051 failed", err, ESP_FAIL);
725      /* verify chip id */
726      MAC_CHECK(dm9051_verify_id(emac) == ESP_OK, "vefiry chip ID failed", err, ESP_FAIL);
727      /* default setup of internal registers */
728      MAC_CHECK(dm9051_setup_default(emac) == ESP_OK, "dm9051 default setup failed", err, ESP_FAIL);
729      /* clear multicast hash table */
730      MAC_CHECK(dm9051_clear_multicast_table(emac) == ESP_OK, "clear multicast table failed", err, ESP_FAIL);
731      /* get emac address from eeprom */
732      MAC_CHECK(dm9051_get_mac_addr(emac) == ESP_OK, "fetch ethernet mac address failed", err, ESP_FAIL);
733      return ESP_OK;
734  err:
735      gpio_isr_handler_remove(emac->int_gpio_num);
736      gpio_reset_pin(emac->int_gpio_num);
737      eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
738      return ret;
739  }
740  
741  static esp_err_t emac_dm9051_deinit(esp_eth_mac_t *mac)
742  {
743      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
744      esp_eth_mediator_t *eth = emac->eth;
745      mac->stop(mac);
746      gpio_isr_handler_remove(emac->int_gpio_num);
747      gpio_reset_pin(emac->int_gpio_num);
748      eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
749      return ESP_OK;
750  }
751  
752  static esp_err_t emac_dm9051_del(esp_eth_mac_t *mac)
753  {
754      emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
755      vTaskDelete(emac->rx_task_hdl);
756      vSemaphoreDelete(emac->spi_lock);
757      free(emac);
758      return ESP_OK;
759  }
760  
761  esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, const eth_mac_config_t *mac_config)
762  {
763      esp_eth_mac_t *ret = NULL;
764      emac_dm9051_t *emac = NULL;
765      MAC_CHECK(dm9051_config, "can't set dm9051 specific config to null", err, NULL);
766      MAC_CHECK(mac_config, "can't set mac config to null", err, NULL);
767      emac = calloc(1, sizeof(emac_dm9051_t));
768      MAC_CHECK(emac, "calloc emac failed", err, NULL);
769      /* dm9051 receive is driven by interrupt only for now*/
770      MAC_CHECK(dm9051_config->int_gpio_num >= 0, "error interrupt gpio number", err, NULL);
771      /* bind methods and attributes */
772      emac->sw_reset_timeout_ms = mac_config->sw_reset_timeout_ms;
773      emac->int_gpio_num = dm9051_config->int_gpio_num;
774      emac->spi_hdl = dm9051_config->spi_hdl;
775      emac->parent.set_mediator = emac_dm9051_set_mediator;
776      emac->parent.init = emac_dm9051_init;
777      emac->parent.deinit = emac_dm9051_deinit;
778      emac->parent.start = emac_dm9051_start;
779      emac->parent.stop = emac_dm9051_stop;
780      emac->parent.del = emac_dm9051_del;
781      emac->parent.write_phy_reg = emac_dm9051_write_phy_reg;
782      emac->parent.read_phy_reg = emac_dm9051_read_phy_reg;
783      emac->parent.set_addr = emac_dm9051_set_addr;
784      emac->parent.get_addr = emac_dm9051_get_addr;
785      emac->parent.set_speed = emac_dm9051_set_speed;
786      emac->parent.set_duplex = emac_dm9051_set_duplex;
787      emac->parent.set_link = emac_dm9051_set_link;
788      emac->parent.set_promiscuous = emac_dm9051_set_promiscuous;
789      emac->parent.set_peer_pause_ability = emac_dm9051_set_peer_pause_ability;
790      emac->parent.enable_flow_ctrl = emac_dm9051_enable_flow_ctrl;
791      emac->parent.transmit = emac_dm9051_transmit;
792      emac->parent.receive = emac_dm9051_receive;
793      /* create mutex */
794      emac->spi_lock = xSemaphoreCreateMutex();
795      MAC_CHECK(emac->spi_lock, "create lock failed", err, NULL);
796      /* create dm9051 task */
797      BaseType_t core_num = tskNO_AFFINITY;
798      if (mac_config->flags & ETH_MAC_FLAG_PIN_TO_CORE) {
799          core_num = cpu_hal_get_core_id();
800      }
801      BaseType_t xReturned = xTaskCreatePinnedToCore(emac_dm9051_task, "dm9051_tsk", mac_config->rx_task_stack_size, emac,
802                             mac_config->rx_task_prio, &emac->rx_task_hdl, core_num);
803      MAC_CHECK(xReturned == pdPASS, "create dm9051 task failed", err, NULL);
804      return &(emac->parent);
805  
806  err:
807      if (emac) {
808          if (emac->rx_task_hdl) {
809              vTaskDelete(emac->rx_task_hdl);
810          }
811          if (emac->spi_lock) {
812              vSemaphoreDelete(emac->spi_lock);
813          }
814          free(emac);
815      }
816      return ret;
817  }