quic/qbox
Loading...
Searching...
No Matches
dwmac.h
1/*
2 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 * Author: GreenSocs 2022
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#pragma once
9
10#include "tlm.h"
11#include "tlm_utils/simple_initiator_socket.h"
12#include "tlm_utils/simple_target_socket.h"
13#include <scp/report.h>
14#include <systemc>
15
16#include "backends/net-backend.h"
17#include "macs/dma.h"
18#include "macs/mac.h"
19#include "macs/mii.h"
20#include "macs/phy.h"
21
22#include <tlm_sockets_buswidth.h>
23#include <module_factory_registery.h>
24
25#include <deque>
26
28 struct {
29 uint32_t reserved1 : 1;
30 uint32_t sr : 1;
31 uint32_t osf : 1;
32 uint32_t rtc : 2;
33 uint32_t reserved2 : 1;
34 uint32_t fuf : 1;
35 uint32_t fef : 1;
36 uint32_t efc : 1;
37 uint32_t rfa : 2;
38 uint32_t rfd : 2;
39 uint32_t st : 1;
40 uint32_t ttc : 3;
41 uint32_t reserved3 : 3;
42 uint32_t ftf : 1;
43 uint32_t tsf : 1;
44 uint32_t reserved4 : 2;
45 uint32_t dff : 1;
46 uint32_t rsf : 1;
47 uint32_t dt : 1;
48 uint32_t reserved5 : 5;
49 };
50 uint32_t value;
51};
52
54 struct {
55 uint32_t gb : 1;
56 uint32_t gw : 1;
57 uint32_t cr : 4;
58 uint32_t gr : 5;
59 uint32_t pa : 5;
60 };
61 uint32_t value;
62};
63
65 struct {
66 uint32_t swr : 1;
67 uint32_t reserved1 : 1;
68 uint32_t dsl : 5;
69 uint32_t atds : 1;
70 uint32_t pbl : 6;
71 uint32_t reserved2 : 2;
72 uint32_t fb : 1;
73 uint32_t rpbl : 6;
74 uint32_t usp : 1;
75 uint32_t eightxpbl : 1;
76 uint32_t aal : 1;
77 uint32_t reserved3 : 6;
78 };
79 uint32_t value;
80};
81
82namespace DwmacState {
83enum Tx { TX_STOPPED = 0, TX_FETCHING = 1, TX_WAITING = 2, TX_READING = 3, TX_SUSPENDED = 6, TX_CLOSING = 7 };
84enum Rx { RX_STOPPED = 0, RX_FETCHING = 1, RX_WAITING = 3, RX_SUSPENDED = 4, RX_CLOSING = 5, RX_TRANSFERRING = 7 };
85} // namespace DwmacState
86
88 struct {
89 uint32_t ti : 1;
90 uint32_t tps : 1;
91 uint32_t tu : 1;
92 uint32_t tjt : 1;
93 uint32_t ovf : 1;
94 uint32_t unf : 1;
95 uint32_t ri : 1;
96 uint32_t ru : 1;
97 uint32_t rps : 1;
98 uint32_t rwt : 1;
99 uint32_t eti : 1;
100 uint32_t reserved1 : 2;
101 uint32_t fbi : 1;
102 uint32_t eri : 1;
103 uint32_t ais : 1;
104 uint32_t nis : 1;
105 DwmacState::Rx rs : 3;
106 DwmacState::Tx ts : 3;
107 uint32_t eb : 3;
108 uint32_t gli : 1;
109 uint32_t gmi : 1;
110 uint32_t reserved2 : 1;
111 uint32_t tti : 1;
112 uint32_t glpii : 1;
113 uint32_t reserved3 : 1;
114 };
115 uint32_t value;
116};
117
119{
120public:
121 static const uint32_t NIS_mask = 0x4045;
122 static const uint32_t AIS_mask = 0x27ba;
123 static const uint32_t NIS_bit = 1 << 16;
124 static const uint32_t AIS_bit = 1 << 15;
125 static const uint32_t IS_mask = NIS_mask | AIS_mask;
126 static const uint32_t IS_bits = NIS_bit | AIS_bit;
127 static const uint32_t BE_mask = 7;
128
129 enum IRQ {
130 EarlyReceive = 1 << 14,
131 BusError = 1 << 13,
132 EarlyTransmit = 1 << 10,
133 RxWatchdogTimeout = 1 << 9,
134 RxStopped = 1 << 8,
135 RxBufUnavailable = 1 << 7,
136 RxInt = 1 << 6,
137 Underflow = 1 << 5,
138 Overflow = 1 << 4,
139 TxJabberTimeout = 1 << 3,
140 TxBufUnavailable = 1 << 2,
141 TxStopped = 1 << 1,
142 TxInt = 1 << 0
143 };
144
145 void setTxState(DwmacState::Tx state)
146 {
147 m_dma_reg_status.ts = state;
148 m_regstate_staled = true;
149 }
150
151 void setRxState(DwmacState::Rx state)
152 {
153 m_dma_reg_status.rs = state;
154 m_regstate_staled = true;
155 }
156
157 DwmacState::Tx getTxState() const { return m_dma_reg_status.ts; }
158 DwmacState::Rx getRxState() const { return m_dma_reg_status.rs; }
159
160 void reset()
161 {
162 m_regstate_staled = false;
163
164 m_regstate = 0;
165 m_regmask = 0;
166
167 m_interrupts = 0;
168
169 m_dma_reg_status.value = 0;
170 }
171
172 void clear(uint32_t clear)
173 {
174 clear &= IS_mask | IS_bits;
175
176 if ((clear & NIS_mask) && !(clear & NIS_bit)) {
177 SCP_INFO("dwmac.h") << "Clearing normal interrupts without clearing NIS";
178 }
179
180 if ((clear & AIS_mask) && !(clear & AIS_bit)) {
181 SCP_INFO("dwmac.h") << "Clearing abnormal interrupts without clearing AIS";
182 }
183
184 m_interrupts &= ((~clear) & IS_mask);
185
186 if ((m_interrupts & NIS_mask) && (m_regmask & NIS_bit)) m_interrupts |= NIS_bit;
187 if ((m_interrupts & AIS_mask) && (m_regmask & AIS_bit)) m_interrupts |= AIS_bit;
188
189 m_regstate_staled = true;
190 }
191
192 void fire(uint32_t interrupts)
193 {
194 interrupts &= m_regmask;
195 interrupts &= IS_mask;
196
197 if ((interrupts & NIS_mask) && (m_regmask & NIS_bit)) interrupts |= NIS_bit;
198 if ((interrupts & AIS_mask) && (m_regmask & AIS_bit)) interrupts |= AIS_bit;
199 m_interrupts |= interrupts;
200 m_regstate_staled = true;
201 }
202
203 bool has_interrupts() const { return ((m_interrupts & m_regmask) != 0); }
204
205 void set_interrupts(uint32_t mask) { m_regmask = (mask & (IS_mask | IS_bits)); }
206
207 void set_status(uint32_t value) { clear(value & (IS_mask | IS_bits)); }
208
209 uint32_t interrupts() const { return m_regmask; }
210
211 uint32_t status() const
212 {
213 if (m_regstate_staled) {
214 m_regstate = m_interrupts | m_dma_reg_status.value;
215
216 m_regstate_staled = false;
217 }
218 return m_regstate;
219 }
220
221public:
222 mutable bool m_regstate_staled;
223 mutable uint32_t m_regstate;
224 uint32_t m_regmask;
225
226 uint32_t m_interrupts;
227 union status_reg m_dma_reg_status;
228};
229
230/* Basic descriptor structure for normal and alternate descriptors */
231struct dma_desc {
232 /* Receive descriptor */
233 union {
234#if 0
235 struct {
236 /* RDES0 */
238 uint32_t crc_error:1;
239 uint32_t dribbling:1;
241 uint32_t receive_watchdog:1;
242 uint32_t frame_type:1;
244 uint32_t ipc_csum_error:1;
245 uint32_t last_descriptor:1;
246 uint32_t first_descriptor:1;
247 uint32_t vlan_tag:1;
248 uint32_t overflow_error:1;
249 uint32_t length_error:1;
250 uint32_t sa_filter_fail:1;
251 uint32_t descriptor_error:1;
252 uint32_t error_summary:1;
253 uint32_t frame_length:14;
254 uint32_t da_filter_fail:1;
255 uint32_t own:1;
256 /* RDES1 */
257 uint32_t buffer1_size:11;
258 uint32_t buffer2_size:11;
259 uint32_t reserved1:2;
260 uint32_t second_address_chained:1;
261 uint32_t end_ring:1;
262 uint32_t reserved2:5;
263 uint32_t disable_ic:1;
264 } rx;
265#endif
266 struct {
267 /* RDES0 */
268 uint32_t rx_mac_addr : 1;
269 uint32_t crc_error : 1;
270 uint32_t dribbling : 1;
271 uint32_t error_gmii : 1;
272 uint32_t receive_watchdog : 1;
273 uint32_t frame_type : 1;
274 uint32_t late_collision : 1;
275 uint32_t ipc_csum_error : 1;
276 uint32_t last_descriptor : 1;
277 uint32_t first_descriptor : 1;
278 uint32_t vlan_tag : 1;
279 uint32_t overflow_error : 1;
280 uint32_t length_error : 1;
281 uint32_t sa_filter_fail : 1;
282 uint32_t descriptor_error : 1;
283 uint32_t error_summary : 1;
284 uint32_t frame_length : 14;
285 uint32_t da_filter_fail : 1;
286 uint32_t own : 1;
287 /* RDES1 */
288 uint32_t buffer1_size : 13;
289 uint32_t reserved1 : 1;
290 uint32_t second_address_chained : 1;
291 uint32_t end_ring : 1;
292 uint32_t buffer2_size : 13;
293 uint32_t reserved2 : 2;
294 uint32_t disable_ic : 1;
295 } erx; /* -- enhanced -- */
296
297 /* Transmit descriptor */
298#if 0
299 struct {
300 /* TDES0 */
301 uint32_t deferred:1;
302 uint32_t underflow_error:1;
303 uint32_t excessive_deferral:1;
304 uint32_t collision_count:4;
305 uint32_t vlan_frame:1;
306 uint32_t excessive_collisions:1;
307 uint32_t late_collision:1;
308 uint32_t no_carrier:1;
309 uint32_t loss_carrier:1;
310 uint32_t payload_error:1;
311 uint32_t frame_flushed:1;
312 uint32_t jabber_timeout:1;
313 uint32_t error_summary:1;
314 uint32_t ip_header_error:1;
315 uint32_t time_stamp_status:1;
316 uint32_t reserved1:13;
317 uint32_t own:1;
318 /* TDES1 */
319 uint32_t buffer1_size:11;
320 uint32_t buffer2_size:11;
321 uint32_t time_stamp_enable:1;
322 uint32_t disable_padding:1;
323 uint32_t second_address_chained:1;
324 uint32_t end_ring:1;
325 uint32_t crc_disable:1;
326 uint32_t checksum_insertion:2;
327 uint32_t first_segment:1;
328 uint32_t last_segment:1;
329 uint32_t interrupt:1;
330 } tx;
331#endif
332 struct {
333 /* TDES0 */
334 uint32_t deferred : 1;
335 uint32_t underflow_error : 1;
336 uint32_t excessive_deferral : 1;
337 uint32_t collision_count : 4;
338 uint32_t vlan_frame : 1;
339 uint32_t excessive_collisions : 1;
340 uint32_t late_collision : 1;
341 uint32_t no_carrier : 1;
342 uint32_t loss_carrier : 1;
343 uint32_t payload_error : 1;
344 uint32_t frame_flushed : 1;
345 uint32_t jabber_timeout : 1;
346 uint32_t error_summary : 1;
347 uint32_t ip_header_error : 1;
348 uint32_t time_stamp_status : 1;
349 uint32_t reserved1 : 2;
350 uint32_t second_address_chained : 1;
351 uint32_t end_ring : 1;
352 uint32_t checksum_insertion : 2;
353 uint32_t reserved2 : 1;
354 uint32_t time_stamp_enable : 1;
355 uint32_t disable_padding : 1;
356 uint32_t crc_disable : 1;
357 uint32_t first_segment : 1;
358 uint32_t last_segment : 1;
359 uint32_t interrupt : 1;
360 uint32_t own : 1;
361 /* TDES1 */
362 uint32_t buffer1_size : 13;
363 uint32_t reserved3 : 3;
364 uint32_t buffer2_size : 13;
365 uint32_t reserved4 : 3;
366 } etx; /* -- enhanced -- */
367 } des01;
368 unsigned int des2;
369 unsigned int des3;
370
371 /* if bus_mode.atds == 1 */
372 unsigned int des4;
373 unsigned int des5;
374 unsigned int des6;
375 unsigned int des7;
376};
377
378class dwmac : public sc_core::sc_module
379{
380protected:
381 bool warn_anregs = true;
382
383 sc_core::sc_event m_tx_event;
384 sc_core::sc_event intr_wake;
385
386 void reset();
387
388 void interrupts_fire(uint32_t interrupts);
389 void interrupts_clear(uint32_t interrupts);
390
391 bool read_tx_desc(dma_desc* desc);
392 bool read_rx_desc(dma_desc* desc);
393
394 bool tx();
395 bool rx(Payload& frame);
396
397 void move_to_next_tx_desc(dma_desc& desc);
398
399 void tx_thread();
400 void intr_thread();
401
402 /* DMA registers */
403 static const uint32_t DMA_BUS_MODE = 0x1000;
404 static const uint32_t DMA_TX_POLL = 0x1004;
405 static const uint32_t DMA_RX_POLL = 0x1008;
406 static const uint32_t DMA_RX_DESC_LIST_ADDR = 0x100C;
407 static const uint32_t DMA_TX_DESC_LIST_ADDR = 0x1010;
408 static const uint32_t DMA_STATUS = 0x1014;
409 static const uint32_t DMA_OPERATION_MODE = 0x1018;
410 static const uint32_t DMA_INTERRUPTS = 0x101C;
411 static const uint32_t DMA_COUNTERS = 0x1020;
412 static const uint32_t DMA_RX_INT_WDT = 0x1024;
413 static const uint32_t DMA_AXI_BUS_MODE = 0x1028;
414 static const uint32_t DMA_CURRENT_TX_DESC = 0x1048;
415 static const uint32_t DMA_CURRENT_RX_DESC = 0x104C;
416 static const uint32_t DMA_CURRENT_TX_BUF = 0x1050;
417 static const uint32_t DMA_CURRENT_RX_BUF = 0x1054;
418 static const uint32_t HW_FEATURE = 0x1058;
419
421 {
422 public:
423 union bus_mode_reg bus_mode;
424 uint32_t rx_desc_addr;
425 uint32_t tx_desc_addr;
427 union opr_mode_reg opr_mode;
428 uint32_t counters;
429 uint32_t current_tx_desc;
430 uint32_t current_rx_desc;
431 uint32_t current_tx_buf;
432 uint32_t current_rx_buf;
433
434 uint32_t desc_size() { return (bus_mode.atds == 0) ? 16 : 32; }
435 };
436
437 DmaRegisters m_dma;
438
439 /* DWMAC registers */
440 static const uint32_t DWMAC_VERSION_VALUE = 0x0010;
441
442 static const uint32_t DWMAC_CONFIGURATION = 0x0000;
443 static const uint32_t DWMAC_FRAME_FILTER = 0x0004;
444 static const uint32_t DWMAC_HASH_TABLE_HI = 0x0008;
445 static const uint32_t DWMAC_HASH_TABLE_LO = 0x000C;
446 static const uint32_t DWMAC_GMII_ADDRESS = 0x0010;
447 static const uint32_t DWMAC_GMII_DATA = 0x0014;
448 static const uint32_t DWMAC_FLOW_CONTROL = 0x0018;
449 static const uint32_t DWMAC_VLAN_TAG = 0x001C;
450 static const uint32_t DWMAC_VERSION = 0x0020;
451 static const uint32_t DWMAC_WAKE_UP_FILTER = 0x0028;
452 static const uint32_t DWMAC_PMT = 0x002C;
453 static const uint32_t DWMAC_INTERRUPT = 0x0038;
454 static const uint32_t DWMAC_INTERRUPT_MASK = 0x003C;
455 static const uint32_t DWMAC_AN_CONTROL = 0x00C0;
456 static const uint32_t DWMAC_AN_STATUS = 0x00C4;
457 static const uint32_t DWMAC_AN_ADVERTISEMENT = 0x00C8;
458 static const uint32_t DWMAC_AN_LINK_PARTNER_ABILITY = 0x00CC;
459 static const uint32_t DWMAC_AN_EXPANSION = 0x00D0;
460 static const uint32_t DWMAC_MAC0_HI = 0x0040;
461 static const uint32_t DWMAC_MAC0_LO = 0x0044;
462 static const uint32_t DWMAC_MACn = 0x0048;
463 static const uint32_t DWMAC_MMC_CONTROL = 0x0100;
464 static const uint32_t DWMAC_MMC_RX_INT = 0x0104;
465 static const uint32_t DWMAC_MMC_TX_INT = 0x0108;
466 static const uint32_t DWMAC_MMC_RX_INT_MASK = 0x010C;
467 static const uint32_t DWMAC_MMC_TX_INT_MASK = 0x0110;
468 static const uint32_t DWMAC_MMC_IPC_RX_INT_MASK = 0x0200;
469 static const uint32_t DWMAC_MMC_IPC_RX_INT = 0x0208;
470
471 static const uint32_t MACn_COUNT = 15;
472
473 uint32_t m_configuration;
474 uint32_t m_frame_filter;
475 uint32_t m_hash_table_hi;
476 uint32_t m_hash_table_lo;
477 union s_gmii_address m_gmii_address;
478 uint32_t m_gmii_data;
479 uint32_t m_flow_control;
480 uint32_t m_vlan_tag;
481 uint32_t m_pmt;
482 MACAddress m_mac_0;
483 MACAddress m_mac_n[MACn_COUNT];
484 uint32_t m_htbl[8];
485 uint32_t m_int_mask;
486 uint32_t m_axi_bus_mode;
487
488public:
489 sc_core::sc_out<bool> intr0, intr1;
490 tlm_utils::simple_target_socket<dwmac, DEFAULT_TLM_BUSWIDTH> socket;
491 dma dma_inst;
492 phy phy_inst;
493
494 NetworkBackend* m_backend;
495 void set_backend(NetworkBackend* backend)
496 {
497 m_backend = backend;
498 m_backend->register_receive(this, eth_rx_sc, eth_can_rx_sc);
499 }
500
501 static void eth_rx_sc(void* opaque, Payload& frame) { ((dwmac*)opaque)->payload_recv(frame); }
502
503 static int eth_can_rx_sc(void* opaque) { return 1; }
504
505 Payload m_tx_frame;
506
507
508 dwmac(sc_core::sc_module_name name);
509 virtual ~dwmac();
510
511 uint32_t read_word(uint32_t address);
512 void write_word(uint32_t address, uint32_t data);
513
514 void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
515 {
516 unsigned char* ptr = trans.get_data_ptr();
517 uint64_t addr = trans.get_address();
518
519 trans.set_dmi_allowed(false);
520 trans.set_response_status(tlm::TLM_OK_RESPONSE);
521
522 switch (trans.get_command()) {
523 case tlm::TLM_WRITE_COMMAND:
524 write_word(addr, *(uint32_t*)ptr);
525 break;
526 case tlm::TLM_READ_COMMAND:
527 *(uint32_t*)ptr = read_word(addr);
528 break;
529 default:
530 break;
531 }
532 }
533
534 virtual void payload_recv(Payload& frame);
535};
536
537extern "C" void module_register();
Definition dwmac.h:119
Definition mac.h:18
Definition net-backend.h:13
Definition payload.h:15
Definition target.h:160
Definition dma.h:13
Definition dwmac.h:421
Definition dwmac.h:379
Definition phy.h:21
Definition dwmac.h:231
Definition dwmac.h:64
Definition dwmac.h:27
Definition dwmac.h:53
Definition dwmac.h:87