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