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 
15 #pragma once
16 #include <stdint.h>
17 #include <stddef.h>
18 #include <assert.h>
19 #include "sdkconfig.h"
20 #include "soc/soc.h"
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 // These are the register definitions for the OpenCores Ethernet MAC.
27 // See comments in esp_eth_mac_openeth.c for more details about this driver.
28 
29 // DMA buffers configuration
30 #define DMA_BUF_SIZE    1600
31 #define RX_BUF_COUNT    CONFIG_ETH_OPENETH_DMA_RX_BUFFER_NUM
32 #define TX_BUF_COUNT    CONFIG_ETH_OPENETH_DMA_TX_BUFFER_NUM
33 
34 // This driver uses the interrupt source number of the internal EMAC of the ESP32 chip,
35 // and uses the same register address base. This of course only works in QEMU, where
36 // the OpenCores MAC is mapped to the same register base and to the same interrupt
37 // source. This driver does a sanity check that it is not running on the real ESP32
38 // chip, using the EMAC date register.
39 #define OPENETH_INTR_SOURCE         ETS_ETH_MAC_INTR_SOURCE
40 #define OPENETH_BASE                DR_REG_EMAC_BASE
41 
42 // OpenCores ethmac registers
43 #define OPENETH_MODER_REG           (OPENETH_BASE + 0x00)
44 #define OPENETH_MODER_DEFAULT       0xa000
45 // OPENETH_RST: reset the MAC
46 #define OPENETH_RST   BIT(11)
47 // OPENETH_PRO: enable promiscuous mode
48 #define OPENETH_PRO   BIT(5)
49 // OPENETH_TXEN: enable transmit
50 #define OPENETH_TXEN   BIT(1)
51 // OPENETH_RXEN: enable receive
52 #define OPENETH_RXEN   BIT(0)
53 
54 #define OPENETH_INT_SOURCE_REG      (OPENETH_BASE + 0x04)
55 #define OPENETH_INT_MASK_REG        (OPENETH_BASE + 0x08)
56 // These bits apply to INT_SOURCE and INT_MASK registers:
57 // OPENETH_INT_BUSY: Buffer was received and discarded due to lack of buffers
58 #define OPENETH_INT_BUSY   BIT(4)
59 // OPENETH_INT_RXB: Frame received
60 #define OPENETH_INT_RXB   BIT(2)
61 // OPENETH_INT_TXB: Frame transmitted
62 #define OPENETH_INT_TXB   BIT(0)
63 
64 // IPGT, IPGR1, IPGR2 registers are not implemented in QEMU, hence not used here
65 #define OPENETH_PACKETLEN_REG       (OPENETH_BASE + 0x18)
66 // OPENETH_MINFL: minimum frame length
67 #define OPENETH_MINFL_S 16
68 #define OPENETH_MINFL_V 0xffff
69 #define OPENETH_MINFL_M (OPENETH_MINFL_V << OPENETH_MINFL_S)
70 // OPENETH_MAXFL: maximum frame length
71 #define OPENETH_MAXFL_S 0
72 #define OPENETH_MAXFL_V 0xffff
73 #define OPENETH_MAXFL_M (OPENETH_MAXFL_V << OPENETH_MAXFL_S)
74 
75 // COLLCONF is not implemented in QEMU
76 #define OPENETH_TX_BD_NUM_REG       (OPENETH_BASE + 0x20)
77 // CTRLMODER, MIIMODER are not implemented in QEMU
78 #define OPENETH_MIICOMMAND_REG      (OPENETH_BASE + 0x2c)
79 // OPENETH_WCTRLDATA: write control data
80 #define OPENETH_WCTRLDATA   BIT(2)
81 // OPENETH_RSTAT: read status
82 #define OPENETH_RSTAT       BIT(1)
83 // OPENETH_SCANSTAT: scan status
84 #define OPENETH_SCANSTAT    BIT(0)
85 
86 #define OPENETH_MIIADDRESS_REG      (OPENETH_BASE + 0x30)
87 // OPENETH_RGAD: register address
88 #define OPENETH_RGAD_S 8
89 #define OPENETH_RGAD_V 0x1f
90 #define OPENETH_RGAD_M (OPENETH_RGAD_V << OPENETH_RGAD_S)
91 // OPENETH_FIAD: PHY address
92 #define OPENETH_FIAD_S 0
93 #define OPENETH_FIAD_V 0x1f
94 #define OPENETH_FIAD_N (OPENETH_FIAD_V << OPENETH_FIAD_S)
95 
96 #define OPENETH_MIITX_DATA_REG      (OPENETH_BASE + 0x34)
97 #define OPENETH_MIIRX_DATA_REG      (OPENETH_BASE + 0x38)
98 #define OPENETH_MII_DATA_MASK 0xffff
99 
100 #define OPENETH_MIISTATUS_REG       (OPENETH_BASE + 0x3c)
101 // OPENETH_LINKFAIL: link is down
102 #define OPENETH_LINKFAIL BIT(0)
103 
104 // OPENETH_MAC_ADDR0_REG: bytes 2-5 of the MAC address (byte 5 in LSB)
105 #define OPENETH_MAC_ADDR0_REG       (OPENETH_BASE + 0x40)
106 // OPENETH_MAC_ADDR1_REG: bytes 0-1 of the MAC address (byte 1 in LSB)
107 #define OPENETH_MAC_ADDR1_REG       (OPENETH_BASE + 0x44)
108 
109 #define OPENETH_HASH0_ADR_REG       (OPENETH_BASE + 0x48)
110 #define OPENETH_HASH1_ADR_REG       (OPENETH_BASE + 0x4c)
111 
112 // Location of the DMA descriptors
113 #define OPENETH_DESC_BASE           (OPENETH_BASE + 0x400)
114 // Total number of (TX + RX) DMA descriptors
115 #define OPENETH_DESC_CNT            128
116 
117 
118 // Structures describing TX and RX descriptors.
119 // The field names are same as in the OpenCores ethmac documentation.
120 typedef struct {
121     uint16_t cs: 1;     //!< Carrier sense lost (flag set by HW)
122     uint16_t df: 1;     //!< Defer indication (flag set by HW)
123     uint16_t lc: 1;     //!< Late collision occured (flag set by HW)
124     uint16_t rl: 1;     //!< TX failed due to retransmission limit (flag set by HW)
125     uint16_t rtry: 4;   //!< Number of retries before the frame was sent (set by HW)
126     uint16_t ur: 1;     //!< Underrun status (flag set by HW)
127     uint16_t rsv: 2;    //!< Reserved
128     uint16_t crc: 1;    //!< Add CRC at the end of the packet
129     uint16_t pad: 1;    //!< Add padding to the end of short packets
130     uint16_t wr: 1;     //!< Wrap-around. 0: not the last descriptor in the table, 1: last descriptor.
131     uint16_t irq: 1;    //!< Generate interrupt after this descriptor is transmitted
132     uint16_t rd: 1;     //!< Descriptor ready. 0: descriptor owned by SW, 1: descriptor owned by HW. Cleared by HW.
133 
134     uint16_t len;       //!< Number of bytes to be transmitted
135     void* txpnt;        //!< Pointer to the data to transmit
136 } openeth_tx_desc_t;
137 
138 _Static_assert(sizeof(openeth_tx_desc_t) == 8, "incorrect size of openeth_tx_desc_t");
139 
140 typedef struct {
141     uint16_t lc: 1;     //!< Late collision flag
142     uint16_t crc: 1;    //!< RX CRC error flag
143     uint16_t sf: 1;     //!< Frame shorter than set in PACKETLEN register
144     uint16_t tl: 1;     //!< Frame longer than set in PACKETLEN register
145     uint16_t dn: 1;     //!< Dribble nibble (frame length not divisible by 8 bits) flag
146     uint16_t is: 1;     //!< Invalid symbol flag
147     uint16_t or: 1;     //!< Overrun flag
148     uint16_t m: 1;      //!< Frame received because of the promiscuous mode
149     uint16_t rsv: 5;    //!< Reserved
150     uint16_t wr: 1;     //!< Wrap-around. 0: not the last descriptor in the table, 1: last descriptor.
151     uint16_t irq: 1;    //!< Generate interrupt after this descriptor is transmitted
152     uint16_t e: 1;      //!< The buffer is empty. 0: descriptor owned by SW, 1: descriptor owned by HW.
153 
154     uint16_t len;       //!< Number of bytes received (filled by HW)
155     void* rxpnt;        //!< Pointer to the receive buffer
156 } openeth_rx_desc_t;
157 
158 _Static_assert(sizeof(openeth_rx_desc_t) == 8, "incorrect size of openeth_rx_desc_t");
159 
160 
openeth_tx_desc(int idx)161 static inline openeth_tx_desc_t* openeth_tx_desc(int idx)
162 {
163     assert(idx < TX_BUF_COUNT);
164     return &((openeth_tx_desc_t*)OPENETH_DESC_BASE)[idx];
165 }
166 
openeth_rx_desc(int idx)167 static inline openeth_rx_desc_t* openeth_rx_desc(int idx)
168 {
169     assert(idx < OPENETH_DESC_CNT - TX_BUF_COUNT);
170     return &((openeth_rx_desc_t*)OPENETH_DESC_BASE)[idx + TX_BUF_COUNT];
171 }
172 
openeth_enable(void)173 static inline void openeth_enable(void)
174 {
175     REG_SET_BIT(OPENETH_MODER_REG, OPENETH_TXEN | OPENETH_RXEN | OPENETH_PRO);
176     REG_SET_BIT(OPENETH_INT_MASK_REG, OPENETH_INT_RXB);
177 }
178 
openeth_disable(void)179 static inline void openeth_disable(void)
180 {
181     REG_CLR_BIT(OPENETH_INT_MASK_REG, OPENETH_INT_RXB);
182     REG_CLR_BIT(OPENETH_MODER_REG, OPENETH_TXEN | OPENETH_RXEN | OPENETH_PRO);
183 }
184 
openeth_reset(void)185 static inline void openeth_reset(void)
186 {
187     REG_SET_BIT(OPENETH_MODER_REG, OPENETH_RST);
188     REG_CLR_BIT(OPENETH_MODER_REG, OPENETH_RST);
189 }
190 
openeth_init_tx_desc(openeth_tx_desc_t * desc,void * buf)191 static inline void openeth_init_tx_desc(openeth_tx_desc_t* desc, void* buf)
192 {
193     *desc = (openeth_tx_desc_t) {
194         .rd = 0,
195         .txpnt = buf
196     };
197 }
198 
openeth_init_rx_desc(openeth_rx_desc_t * desc,void * buf)199 static inline void openeth_init_rx_desc(openeth_rx_desc_t* desc, void* buf)
200 {
201     *desc = (openeth_rx_desc_t) {
202         .e = 1,
203         .irq = 1,
204         .rxpnt = buf
205     };
206 }
207 
openeth_set_tx_desc_cnt(int tx_desc_cnt)208 static inline void openeth_set_tx_desc_cnt(int tx_desc_cnt)
209 {
210     assert(tx_desc_cnt <= OPENETH_DESC_CNT);
211     REG_WRITE(OPENETH_TX_BD_NUM_REG, tx_desc_cnt);
212 }
213 
214 #ifdef __cplusplus
215 }
216 #endif
217