2 * QEMU model of the Smartfusion2 Ethernet MAC.
4 * Copyright (c) 2020 Subbaraya Sundeep <sundeep.lkml@gmail.com>.
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * Refer to section Ethernet MAC in the document:
25 * UG0331: SmartFusion2 Microcontroller Subsystem User Guide
27 * https://www.microsemi.com/document-portal/cat_view/56661-internal-documents/
28 * 56758-soc?lang=en&limit=20&limitstart=220
31 #include "qemu/osdep.h"
33 #include "qapi/error.h"
34 #include "hw/registerfields.h"
35 #include "hw/net/msf2-emac.h"
36 #include "hw/net/mii.h"
38 #include "hw/qdev-properties.h"
39 #include "migration/vmstate.h"
42 FIELD(CFG1
, RESET
, 31, 1)
43 FIELD(CFG1
, RX_EN
, 2, 1)
44 FIELD(CFG1
, TX_EN
, 0, 1)
45 FIELD(CFG1
, LB_EN
, 8, 1)
48 REG32(HALF_DUPLEX
, 0xc)
49 REG32(MAX_FRAME_LENGTH
, 0x10)
51 FIELD(MII_CMD
, READ
, 0, 1)
53 FIELD(MII_ADDR
, REGADDR
, 0, 5)
54 FIELD(MII_ADDR
, PHYADDR
, 8, 5)
59 REG32(FIFO_CFG0
, 0x48)
60 REG32(FIFO_CFG4
, 0x58)
61 FIELD(FIFO_CFG4
, BCAST
, 9, 1)
62 FIELD(FIFO_CFG4
, MCAST
, 8, 1)
63 REG32(FIFO_CFG5
, 0x5C)
64 FIELD(FIFO_CFG5
, BCAST
, 9, 1)
65 FIELD(FIFO_CFG5
, MCAST
, 8, 1)
66 REG32(DMA_TX_CTL
, 0x180)
67 FIELD(DMA_TX_CTL
, EN
, 0, 1)
68 REG32(DMA_TX_DESC
, 0x184)
69 REG32(DMA_TX_STATUS
, 0x188)
70 FIELD(DMA_TX_STATUS
, PKTCNT
, 16, 8)
71 FIELD(DMA_TX_STATUS
, UNDERRUN
, 1, 1)
72 FIELD(DMA_TX_STATUS
, PKT_SENT
, 0, 1)
73 REG32(DMA_RX_CTL
, 0x18c)
74 FIELD(DMA_RX_CTL
, EN
, 0, 1)
75 REG32(DMA_RX_DESC
, 0x190)
76 REG32(DMA_RX_STATUS
, 0x194)
77 FIELD(DMA_RX_STATUS
, PKTCNT
, 16, 8)
78 FIELD(DMA_RX_STATUS
, OVERFLOW
, 2, 1)
79 FIELD(DMA_RX_STATUS
, PKT_RCVD
, 0, 1)
80 REG32(DMA_IRQ_MASK
, 0x198)
83 #define EMPTY_MASK (1 << 31)
84 #define PKT_SIZE 0x7FF
86 #define MAX_PKT_SIZE 2048
94 static uint32_t emac_get_isr(MSF2EmacState
*s
)
96 uint32_t ier
= s
->regs
[R_DMA_IRQ_MASK
];
97 uint32_t tx
= s
->regs
[R_DMA_TX_STATUS
] & 0xF;
98 uint32_t rx
= s
->regs
[R_DMA_RX_STATUS
] & 0xF;
99 uint32_t isr
= (rx
<< 4) | tx
;
101 s
->regs
[R_DMA_IRQ
] = ier
& isr
;
102 return s
->regs
[R_DMA_IRQ
];
105 static void emac_update_irq(MSF2EmacState
*s
)
107 bool intr
= emac_get_isr(s
);
109 qemu_set_irq(s
->irq
, intr
);
112 static void emac_load_desc(MSF2EmacState
*s
, EmacDesc
*d
, hwaddr desc
)
114 address_space_read(&s
->dma_as
, desc
, MEMTXATTRS_UNSPECIFIED
, d
, sizeof *d
);
115 /* Convert from LE into host endianness. */
116 d
->pktaddr
= le32_to_cpu(d
->pktaddr
);
117 d
->pktsize
= le32_to_cpu(d
->pktsize
);
118 d
->next
= le32_to_cpu(d
->next
);
121 static void emac_store_desc(MSF2EmacState
*s
, const EmacDesc
*d
, hwaddr desc
)
125 * Convert from host endianness into LE. We use a local struct because
126 * calling code may still want to look at the fields afterwards.
128 outd
.pktaddr
= cpu_to_le32(d
->pktaddr
);
129 outd
.pktsize
= cpu_to_le32(d
->pktsize
);
130 outd
.next
= cpu_to_le32(d
->next
);
132 address_space_write(&s
->dma_as
, desc
, MEMTXATTRS_UNSPECIFIED
, &outd
, sizeof outd
);
135 static void msf2_dma_tx(MSF2EmacState
*s
)
137 NetClientState
*nc
= qemu_get_queue(s
->nic
);
138 hwaddr desc
= s
->regs
[R_DMA_TX_DESC
];
139 uint8_t buf
[MAX_PKT_SIZE
];
145 if (!(s
->regs
[R_CFG1
] & R_CFG1_TX_EN_MASK
)) {
150 emac_load_desc(s
, &d
, desc
);
151 if (d
.pktsize
& EMPTY_MASK
) {
154 size
= d
.pktsize
& PKT_SIZE
;
155 address_space_read(&s
->dma_as
, d
.pktaddr
, MEMTXATTRS_UNSPECIFIED
,
158 * This is very basic way to send packets. Ideally there should be
159 * a FIFO and packets should be sent out from FIFO only when
160 * R_CFG1 bit 0 is set.
162 if (s
->regs
[R_CFG1
] & R_CFG1_LB_EN_MASK
) {
163 qemu_receive_packet(nc
, buf
, size
);
165 qemu_send_packet(nc
, buf
, size
);
167 d
.pktsize
|= EMPTY_MASK
;
168 emac_store_desc(s
, &d
, desc
);
169 /* update sent packets count */
170 status
= s
->regs
[R_DMA_TX_STATUS
];
171 pktcnt
= FIELD_EX32(status
, DMA_TX_STATUS
, PKTCNT
);
173 s
->regs
[R_DMA_TX_STATUS
] = FIELD_DP32(status
, DMA_TX_STATUS
,
175 s
->regs
[R_DMA_TX_STATUS
] |= R_DMA_TX_STATUS_PKT_SENT_MASK
;
178 s
->regs
[R_DMA_TX_STATUS
] |= R_DMA_TX_STATUS_UNDERRUN_MASK
;
179 s
->regs
[R_DMA_TX_CTL
] &= ~R_DMA_TX_CTL_EN_MASK
;
182 static void msf2_phy_update_link(MSF2EmacState
*s
)
184 /* Autonegotiation status mirrors link status. */
185 if (qemu_get_queue(s
->nic
)->link_down
) {
186 s
->phy_regs
[MII_BMSR
] &= ~(MII_BMSR_AN_COMP
|
189 s
->phy_regs
[MII_BMSR
] |= (MII_BMSR_AN_COMP
|
194 static void msf2_phy_reset(MSF2EmacState
*s
)
196 memset(&s
->phy_regs
[0], 0, sizeof(s
->phy_regs
));
197 s
->phy_regs
[MII_BMCR
] = 0x1140;
198 s
->phy_regs
[MII_BMSR
] = 0x7968;
199 s
->phy_regs
[MII_PHYID1
] = 0x0022;
200 s
->phy_regs
[MII_PHYID2
] = 0x1550;
201 s
->phy_regs
[MII_ANAR
] = 0x01E1;
202 s
->phy_regs
[MII_ANLPAR
] = 0xCDE1;
204 msf2_phy_update_link(s
);
207 static void write_to_phy(MSF2EmacState
*s
)
209 uint8_t reg_addr
= s
->regs
[R_MII_ADDR
] & R_MII_ADDR_REGADDR_MASK
;
210 uint8_t phy_addr
= (s
->regs
[R_MII_ADDR
] >> R_MII_ADDR_PHYADDR_SHIFT
) &
211 R_MII_ADDR_REGADDR_MASK
;
212 uint16_t data
= s
->regs
[R_MII_CTL
] & 0xFFFF;
214 if (phy_addr
!= PHYADDR
) {
220 if (data
& MII_BMCR_RESET
) {
223 data
&= ~MII_BMCR_RESET
;
225 if (data
& MII_BMCR_AUTOEN
) {
226 /* Complete autonegotiation immediately */
227 data
&= ~MII_BMCR_AUTOEN
;
228 s
->phy_regs
[MII_BMSR
] |= MII_BMSR_AN_COMP
;
233 s
->phy_regs
[reg_addr
] = data
;
236 static uint16_t read_from_phy(MSF2EmacState
*s
)
238 uint8_t reg_addr
= s
->regs
[R_MII_ADDR
] & R_MII_ADDR_REGADDR_MASK
;
239 uint8_t phy_addr
= (s
->regs
[R_MII_ADDR
] >> R_MII_ADDR_PHYADDR_SHIFT
) &
240 R_MII_ADDR_REGADDR_MASK
;
242 if (phy_addr
== PHYADDR
) {
243 return s
->phy_regs
[reg_addr
];
249 static void msf2_emac_do_reset(MSF2EmacState
*s
)
251 memset(&s
->regs
[0], 0, sizeof(s
->regs
));
252 s
->regs
[R_CFG1
] = 0x80000000;
253 s
->regs
[R_CFG2
] = 0x00007000;
254 s
->regs
[R_IFG
] = 0x40605060;
255 s
->regs
[R_HALF_DUPLEX
] = 0x00A1F037;
256 s
->regs
[R_MAX_FRAME_LENGTH
] = 0x00000600;
257 s
->regs
[R_FIFO_CFG5
] = 0X3FFFF;
262 static uint64_t emac_read(void *opaque
, hwaddr addr
, unsigned int size
)
264 MSF2EmacState
*s
= opaque
;
274 if (addr
>= ARRAY_SIZE(s
->regs
)) {
275 qemu_log_mask(LOG_GUEST_ERROR
,
276 "%s: Bad offset 0x%" HWADDR_PRIx
"\n", __func__
,
286 static void emac_write(void *opaque
, hwaddr addr
, uint64_t val64
,
289 MSF2EmacState
*s
= opaque
;
290 uint32_t value
= val64
;
297 s
->regs
[addr
] = value
;
298 if (value
& R_DMA_TX_CTL_EN_MASK
) {
303 s
->regs
[addr
] = value
;
304 if (value
& R_DMA_RX_CTL_EN_MASK
) {
305 s
->rx_desc
= s
->regs
[R_DMA_RX_DESC
];
306 qemu_flush_queued_packets(qemu_get_queue(s
->nic
));
310 s
->regs
[addr
] = value
;
311 if (value
& R_CFG1_RESET_MASK
) {
312 msf2_emac_do_reset(s
);
317 * For our implementation, turning on modules is instantaneous,
318 * so the states requested via the *ENREQ bits appear in the
319 * *ENRPLY bits immediately. Also the reset bits to reset PE-MCXMAC
320 * module are not emulated here since it deals with start of frames,
321 * inter-packet gap and control frames.
323 enreqbits
= extract32(value
, 8, 5);
324 s
->regs
[addr
] = deposit32(value
, 16, 5, enreqbits
);
328 qemu_log_mask(LOG_GUEST_ERROR
, "Tx Descriptor address should be"
329 " 32 bit aligned\n");
331 /* Ignore [1:0] bits */
332 s
->regs
[addr
] = value
& ~3;
336 qemu_log_mask(LOG_GUEST_ERROR
, "Rx Descriptor address should be"
337 " 32 bit aligned\n");
339 /* Ignore [1:0] bits */
340 s
->regs
[addr
] = value
& ~3;
342 case R_DMA_TX_STATUS
:
343 if (value
& R_DMA_TX_STATUS_UNDERRUN_MASK
) {
344 s
->regs
[addr
] &= ~R_DMA_TX_STATUS_UNDERRUN_MASK
;
346 if (value
& R_DMA_TX_STATUS_PKT_SENT_MASK
) {
347 pktcnt
= FIELD_EX32(s
->regs
[addr
], DMA_TX_STATUS
, PKTCNT
);
349 s
->regs
[addr
] = FIELD_DP32(s
->regs
[addr
], DMA_TX_STATUS
,
352 s
->regs
[addr
] &= ~R_DMA_TX_STATUS_PKT_SENT_MASK
;
356 case R_DMA_RX_STATUS
:
357 if (value
& R_DMA_RX_STATUS_OVERFLOW_MASK
) {
358 s
->regs
[addr
] &= ~R_DMA_RX_STATUS_OVERFLOW_MASK
;
360 if (value
& R_DMA_RX_STATUS_PKT_RCVD_MASK
) {
361 pktcnt
= FIELD_EX32(s
->regs
[addr
], DMA_RX_STATUS
, PKTCNT
);
363 s
->regs
[addr
] = FIELD_DP32(s
->regs
[addr
], DMA_RX_STATUS
,
366 s
->regs
[addr
] &= ~R_DMA_RX_STATUS_PKT_RCVD_MASK
;
373 if (value
& R_MII_CMD_READ_MASK
) {
374 s
->regs
[R_MII_STS
] = read_from_phy(s
);
378 s
->regs
[addr
] = value
;
382 s
->regs
[addr
] = value
;
384 * R_STA1 [31:24] : octet 1 of mac address
385 * R_STA1 [23:16] : octet 2 of mac address
386 * R_STA1 [15:8] : octet 3 of mac address
387 * R_STA1 [7:0] : octet 4 of mac address
389 stl_be_p(s
->mac_addr
, value
);
392 s
->regs
[addr
] = value
;
394 * R_STA2 [31:24] : octet 5 of mac address
395 * R_STA2 [23:16] : octet 6 of mac address
397 stw_be_p(s
->mac_addr
+ 4, value
>> 16);
400 if (addr
>= ARRAY_SIZE(s
->regs
)) {
401 qemu_log_mask(LOG_GUEST_ERROR
,
402 "%s: Bad offset 0x%" HWADDR_PRIx
"\n", __func__
,
406 s
->regs
[addr
] = value
;
412 static const MemoryRegionOps emac_ops
= {
415 .endianness
= DEVICE_NATIVE_ENDIAN
,
417 .min_access_size
= 4,
422 static bool emac_can_rx(NetClientState
*nc
)
424 MSF2EmacState
*s
= qemu_get_nic_opaque(nc
);
426 return (s
->regs
[R_CFG1
] & R_CFG1_RX_EN_MASK
) &&
427 (s
->regs
[R_DMA_RX_CTL
] & R_DMA_RX_CTL_EN_MASK
);
430 static bool addr_filter_ok(MSF2EmacState
*s
, const uint8_t *buf
)
432 /* The broadcast MAC address: FF:FF:FF:FF:FF:FF */
433 const uint8_t broadcast_addr
[] = { 0xFF, 0xFF, 0xFF, 0xFF,
435 bool bcast_en
= true;
436 bool mcast_en
= true;
438 if (s
->regs
[R_FIFO_CFG5
] & R_FIFO_CFG5_BCAST_MASK
) {
439 bcast_en
= true; /* Broadcast dont care for drop circuitry */
440 } else if (s
->regs
[R_FIFO_CFG4
] & R_FIFO_CFG4_BCAST_MASK
) {
444 if (s
->regs
[R_FIFO_CFG5
] & R_FIFO_CFG5_MCAST_MASK
) {
445 mcast_en
= true; /* Multicast dont care for drop circuitry */
446 } else if (s
->regs
[R_FIFO_CFG4
] & R_FIFO_CFG4_MCAST_MASK
) {
450 if (!memcmp(buf
, broadcast_addr
, sizeof(broadcast_addr
))) {
458 return !memcmp(buf
, s
->mac_addr
, sizeof(s
->mac_addr
));
461 static ssize_t
emac_rx(NetClientState
*nc
, const uint8_t *buf
, size_t size
)
463 MSF2EmacState
*s
= qemu_get_nic_opaque(nc
);
468 if (size
> (s
->regs
[R_MAX_FRAME_LENGTH
] & 0xFFFF)) {
471 if (!addr_filter_ok(s
, buf
)) {
475 emac_load_desc(s
, &d
, s
->rx_desc
);
477 if (d
.pktsize
& EMPTY_MASK
) {
478 address_space_write(&s
->dma_as
, d
.pktaddr
, MEMTXATTRS_UNSPECIFIED
,
479 buf
, size
& PKT_SIZE
);
480 d
.pktsize
= size
& PKT_SIZE
;
481 emac_store_desc(s
, &d
, s
->rx_desc
);
482 /* update received packets count */
483 status
= s
->regs
[R_DMA_RX_STATUS
];
484 pktcnt
= FIELD_EX32(status
, DMA_RX_STATUS
, PKTCNT
);
486 s
->regs
[R_DMA_RX_STATUS
] = FIELD_DP32(status
, DMA_RX_STATUS
,
488 s
->regs
[R_DMA_RX_STATUS
] |= R_DMA_RX_STATUS_PKT_RCVD_MASK
;
491 s
->regs
[R_DMA_RX_CTL
] &= ~R_DMA_RX_CTL_EN_MASK
;
492 s
->regs
[R_DMA_RX_STATUS
] |= R_DMA_RX_STATUS_OVERFLOW_MASK
;
498 static void msf2_emac_reset(DeviceState
*dev
)
500 MSF2EmacState
*s
= MSS_EMAC(dev
);
502 msf2_emac_do_reset(s
);
505 static void emac_set_link(NetClientState
*nc
)
507 MSF2EmacState
*s
= qemu_get_nic_opaque(nc
);
509 msf2_phy_update_link(s
);
512 static NetClientInfo net_msf2_emac_info
= {
513 .type
= NET_CLIENT_DRIVER_NIC
,
514 .size
= sizeof(NICState
),
515 .can_receive
= emac_can_rx
,
517 .link_status_changed
= emac_set_link
,
520 static void msf2_emac_realize(DeviceState
*dev
, Error
**errp
)
522 MSF2EmacState
*s
= MSS_EMAC(dev
);
525 error_setg(errp
, "MSS_EMAC 'ahb-bus' link not set");
529 address_space_init(&s
->dma_as
, s
->dma_mr
, "emac-ahb");
531 qemu_macaddr_default_if_unset(&s
->conf
.macaddr
);
532 s
->nic
= qemu_new_nic(&net_msf2_emac_info
, &s
->conf
,
533 object_get_typename(OBJECT(dev
)), dev
->id
, s
);
534 qemu_format_nic_info_str(qemu_get_queue(s
->nic
), s
->conf
.macaddr
.a
);
537 static void msf2_emac_init(Object
*obj
)
539 MSF2EmacState
*s
= MSS_EMAC(obj
);
541 sysbus_init_irq(SYS_BUS_DEVICE(obj
), &s
->irq
);
543 memory_region_init_io(&s
->mmio
, obj
, &emac_ops
, s
,
544 "msf2-emac", R_MAX
* 4);
545 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &s
->mmio
);
548 static Property msf2_emac_properties
[] = {
549 DEFINE_PROP_LINK("ahb-bus", MSF2EmacState
, dma_mr
,
550 TYPE_MEMORY_REGION
, MemoryRegion
*),
551 DEFINE_NIC_PROPERTIES(MSF2EmacState
, conf
),
552 DEFINE_PROP_END_OF_LIST(),
555 static const VMStateDescription vmstate_msf2_emac
= {
556 .name
= TYPE_MSS_EMAC
,
558 .minimum_version_id
= 1,
559 .fields
= (VMStateField
[]) {
560 VMSTATE_UINT8_ARRAY(mac_addr
, MSF2EmacState
, ETH_ALEN
),
561 VMSTATE_UINT32(rx_desc
, MSF2EmacState
),
562 VMSTATE_UINT16_ARRAY(phy_regs
, MSF2EmacState
, PHY_MAX_REGS
),
563 VMSTATE_UINT32_ARRAY(regs
, MSF2EmacState
, R_MAX
),
564 VMSTATE_END_OF_LIST()
568 static void msf2_emac_class_init(ObjectClass
*klass
, void *data
)
570 DeviceClass
*dc
= DEVICE_CLASS(klass
);
572 dc
->realize
= msf2_emac_realize
;
573 dc
->reset
= msf2_emac_reset
;
574 dc
->vmsd
= &vmstate_msf2_emac
;
575 device_class_set_props(dc
, msf2_emac_properties
);
578 static const TypeInfo msf2_emac_info
= {
579 .name
= TYPE_MSS_EMAC
,
580 .parent
= TYPE_SYS_BUS_DEVICE
,
581 .instance_size
= sizeof(MSF2EmacState
),
582 .instance_init
= msf2_emac_init
,
583 .class_init
= msf2_emac_class_init
,
586 static void msf2_emac_register_types(void)
588 type_register_static(&msf2_emac_info
);
591 type_init(msf2_emac_register_types
)