[PATCH v6 18/41] Add clock_isp stub

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 6 ++
 include/hw/arm/bcm2838_peripherals.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 6badda3045..1f41028649 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -17,6 +17,9 @@
 #define PCIE_MMIO_ARM_OFFSET0x6
 #define PCIE_MMIO_SIZE  0x4000
 
+#define CLOCK_ISP_OFFSET0xc11000
+#define CLOCK_ISP_SIZE  0x100
+
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
@@ -228,6 +231,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
 mmio_mr);
 
+create_unimp(s_base, >clkisp, "bcm2835-clkisp", CLOCK_ISP_OFFSET,
+ CLOCK_ISP_SIZE);
+
 /* GPIO */
 if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
 return;
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 49bb4fab08..adc02894c1 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -77,6 +77,7 @@ struct BCM2838PeripheralState {
 OrIRQState dma_9_10_irq_orgate;
 
 UnimplementedDeviceState asb;
+UnimplementedDeviceState clkisp;
 };
 
 struct BCM2838PeripheralClass {
-- 
2.34.1




[PATCH v6 39/41] Add missed BCM2835 properties

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2835_property.c   | 21 +
 include/hw/arm/raspberrypi-fw-defs.h | 11 +++
 2 files changed, 32 insertions(+)

diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index 5c48f8d743..bdd9a6bbce 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -19,6 +19,8 @@
 #include "trace.h"
 #include "hw/arm/raspi_platform.h"
 
+#define VCHI_BUSADDR_SIZE   sizeof(uint32_t)
+
 /* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
 
 static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
@@ -138,6 +140,13 @@ static void 
bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 resplen = 8;
 break;
 
+case RPI_FWREQ_GET_CLOCKS:
+/* TODO: add more clock IDs if needed */
+stl_le_phys(>dma_as, value + 12, 0);
+stl_le_phys(>dma_as, value + 16, RPI_FIRMWARE_ARM_CLK_ID);
+resplen = 8;
+break;
+
 case RPI_FWREQ_SET_CLOCK_RATE:
 case RPI_FWREQ_SET_MAX_CLOCK_RATE:
 case RPI_FWREQ_SET_MIN_CLOCK_RATE:
@@ -276,6 +285,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState 
*s, uint32_t value)
 stl_le_phys(>dma_as, value + 12, 0);
 resplen = 4;
 break;
+
 case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
 stl_le_phys(>dma_as, value + 12, 1);
 resplen = 4;
@@ -301,6 +311,17 @@ static void 
bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 resplen);
 break;
 
+case RPI_FWREQ_GET_THROTTLED:
+stl_le_phys(>dma_as, value + 12, 0);
+resplen = 4;
+break;
+
+case RPI_FWREQ_VCHIQ_INIT:
+stl_le_phys(>dma_as,
+value + offsetof(rpi_firmware_prop_request_t, payload),
+0);
+resplen = VCHI_BUSADDR_SIZE;
+break;
 default:
 qemu_log_mask(LOG_UNIMP,
   "bcm2835_property: unhandled tag 0x%08x\n", tag);
diff --git a/include/hw/arm/raspberrypi-fw-defs.h 
b/include/hw/arm/raspberrypi-fw-defs.h
index 579cf0d554..8b404e0533 100644
--- a/include/hw/arm/raspberrypi-fw-defs.h
+++ b/include/hw/arm/raspberrypi-fw-defs.h
@@ -159,4 +159,15 @@ enum rpi_firmware_clk_id {
 RPI_FIRMWARE_NUM_CLK_ID,
 };
 
+struct rpi_firmware_property_tag_header {
+uint32_t tag;
+uint32_t buf_size;
+uint32_t req_resp_size;
+};
+
+typedef struct rpi_firmware_prop_request {
+struct rpi_firmware_property_tag_header hdr;
+uint8_t payload[0];
+} rpi_firmware_prop_request_t;
+
 #endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */
-- 
2.34.1




[PATCH v6 12/41] Add memory region for BCM2837 RPiVid ASB

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/bcm2838_peripherals.c | 3 +++
 include/hw/arm/bcm2838_peripherals.h | 2 ++
 include/hw/arm/raspi_platform.h  | 2 +-
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 55ae56733f..ca2f37b260 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -185,6 +185,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 sysbus_mmio_get_region(SYS_BUS_DEVICE(>gpio), 0));
 
 object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(>gpio), "sd-bus");
+
+/* BCM2838 RPiVid ASB must be mapped to prevent kernel crash */
+create_unimp(s_base, >asb, "bcm2838-asb", BRDG_OFFSET, 0x24);
 }
 
 static void bcm2838_peripherals_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 86b0d96944..af085934c9 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -69,6 +69,8 @@ struct BCM2838PeripheralState {
 OrIRQState mmc_irq_orgate;
 OrIRQState dma_7_8_irq_orgate;
 OrIRQState dma_9_10_irq_orgate;
+
+UnimplementedDeviceState asb;
 };
 
 struct BCM2838PeripheralClass {
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
index 0db146e592..7bc4807fa5 100644
--- a/include/hw/arm/raspi_platform.h
+++ b/include/hw/arm/raspi_platform.h
@@ -73,7 +73,7 @@ uint64_t board_ram_size(uint32_t board_rev);
 #define MPHI_OFFSET 0x6000   /* Message-based Parallel Host Intf. 
*/
 #define DMA_OFFSET  0x7000   /* DMA controller, channels 0-14 */
 #define ARBA_OFFSET 0x9000
-#define BRDG_OFFSET 0xa000
+#define BRDG_OFFSET 0xa000   /* RPiVid ASB for BCM2838 (BCM2711) */
 #define ARM_OFFSET  0xB000   /* ARM control block */
 #define ARMCTRL_OFFSET  (ARM_OFFSET + 0x000)
 #define ARMCTRL_IC_OFFSET   (ARM_OFFSET + 0x200) /* Interrupt controller */
-- 
2.34.1




[PATCH v6 11/41] Temporarily disable unimplemented rpi4b devices

2024-02-25 Thread Sergey Kambalin
This commit adds RPi4B device tree modifications:
- disable pcie, rng200, thermal sensor and genet devices
  (they're going to be re-enabled in the following commits)
- create additional memory region in device tree
  if RAM amount exceeds VC base address.

Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/raspi.c  |  5 +--
 hw/arm/raspi4b.c| 62 +
 include/hw/arm/raspi_platform.h |  4 +++
 3 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 8b1a046912..a7a662f40d 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -37,9 +37,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(RaspiMachineState, RASPI_MACHINE)
 #define FIRMWARE_ADDR_3 0x8 /* Pi 3 loads kernel.img here by default */
 #define SPINTABLE_ADDR  0xd8 /* Pi 3 bootloader spintable */
 
-/* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
-#define MACH_TYPE_BCM2708   3138
-
 struct RaspiMachineState {
 /*< private >*/
 RaspiBaseMachineState parent_obj;
@@ -75,7 +72,7 @@ static const struct {
 [PROCESSOR_ID_BCM2838] = {TYPE_BCM2838, BCM283X_NCPUS},
 };
 
-static uint64_t board_ram_size(uint32_t board_rev)
+uint64_t board_ram_size(uint32_t board_rev)
 {
 assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
 return 256 * MiB << FIELD_EX32(board_rev, REV_CODE, MEMORY_SIZE);
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 36a4593928..49dec6e53a 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -21,6 +21,7 @@
 #include "hw/arm/boot.h"
 #include "qom/object.h"
 #include "hw/arm/bcm2838.h"
+#include 
 
 #define TYPE_RASPI4B_MACHINE MACHINE_TYPE_NAME("raspi4b-2g")
 OBJECT_DECLARE_SIMPLE_TYPE(Raspi4bMachineState, RASPI4B_MACHINE)
@@ -30,6 +31,66 @@ struct Raspi4bMachineState {
 BCM2838State soc;
 };
 
+/*
+ * Add second memory region if board RAM amount exceeds VC base address
+ * (see https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf
+ * 1.2 Address Map)
+ */
+static int raspi_add_memory_node(void *fdt, hwaddr mem_base, hwaddr mem_len)
+{
+int ret;
+uint32_t acells, scells;
+char *nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
+
+acells = qemu_fdt_getprop_cell(fdt, "/", "#address-cells",
+   NULL, _fatal);
+scells = qemu_fdt_getprop_cell(fdt, "/", "#size-cells",
+   NULL, _fatal);
+if (acells == 0 || scells == 0) {
+fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 
0)\n");
+ret = -1;
+} else {
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
+ret = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
+   acells, mem_base,
+   scells, mem_len);
+}
+
+g_free(nodename);
+return ret;
+}
+
+static void raspi4_modify_dtb(const struct arm_boot_info *info, void *fdt)
+{
+uint64_t ram_size;
+
+/* Temporarily disable following devices until they are implemented */
+const char *nodes_to_remove[] = {
+"brcm,bcm2711-pcie",
+"brcm,bcm2711-rng200",
+"brcm,bcm2711-thermal",
+"brcm,bcm2711-genet-v5",
+};
+
+for (int i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
+const char *dev_str = nodes_to_remove[i];
+
+int offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
+if (offset >= 0) {
+if (!fdt_nop_node(fdt, offset)) {
+warn_report("bcm2711 dtc: %s has been disabled!", dev_str);
+}
+}
+}
+
+ram_size = board_ram_size(info->board_id);
+
+if (info->ram_size > UPPER_RAM_BASE) {
+raspi_add_memory_node(fdt, UPPER_RAM_BASE, ram_size - UPPER_RAM_BASE);
+}
+}
+
 static void raspi4b_machine_init(MachineState *machine)
 {
 Raspi4bMachineState *s = RASPI4B_MACHINE(machine);
@@ -37,6 +98,7 @@ static void raspi4b_machine_init(MachineState *machine)
 RaspiBaseMachineClass *mc = RASPI_BASE_MACHINE_GET_CLASS(machine);
 BCM2838State *soc = >soc;
 
+s_base->binfo.modify_dtb = raspi4_modify_dtb;
 s_base->binfo.board_id = mc->board_rev;
 
 object_initialize_child(OBJECT(machine), "soc", soc,
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
index 45003e2425..0db146e592 100644
--- a/include/hw/arm/raspi_platform.h
+++ b/include/hw/arm/raspi_platform.h
@@ -31,6 +31,9 @@
 #include "hw/boards.h"
 #include "hw/arm/boot.h"
 
+/* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
+#define MACH_TYPE_BCM2708   3138
+
 

[PATCH v6 20/41] Add GENET register structs. Part 1

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 37 
 include/hw/net/bcm2838_genet.h | 77 +-
 2 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 4420486e00..0d98d1b30e 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -15,9 +15,46 @@
 #include "hw/irq.h"
 #include "net/checksum.h"
 #include "sysemu/dma.h"
+#include "hw/registerfields.h"
 #include "hw/net/bcm2838_genet.h"
 #include "trace.h"
 
+REG32(GENET_SYS_REV_CTRL,  0)
+FIELD(GENET_SYS_REV_CTRL, GPHY_REV,0, 16)
+FIELD(GENET_SYS_REV_CTRL, MINOR_REV,   16, 4)
+FIELD(GENET_SYS_REV_CTRL, RSVD_20_23,  20, 4)
+FIELD(GENET_SYS_REV_CTRL, MAJOR_REV,   24, 4)
+FIELD(GENET_SYS_REV_CTRL, RSVD_28_31,  28, 4)
+
+REG32(GENET_INTRL_0,0)
+FIELD(GENET_INTRL_0, SCB,   0, 1)
+FIELD(GENET_INTRL_0, EPHY,  1, 1)
+FIELD(GENET_INTRL_0, PHY_DET_R, 2, 1)
+FIELD(GENET_INTRL_0, PHY_DET_F, 3, 1)
+FIELD(GENET_INTRL_0, LINK_UP,   4, 1)
+FIELD(GENET_INTRL_0, LINK_DOWN, 5, 1)
+FIELD(GENET_INTRL_0, UMAC,  6, 1)
+FIELD(GENET_INTRL_0, UMAC_TSV,  7, 1)
+FIELD(GENET_INTRL_0, TBUF_UNDERRUN, 8, 1)
+FIELD(GENET_INTRL_0, RBUF_OVERFLOW, 9, 1)
+FIELD(GENET_INTRL_0, HFB_SM,10, 1)
+FIELD(GENET_INTRL_0, HFB_MM,11, 1)
+FIELD(GENET_INTRL_0, MPD_R, 12, 1)
+FIELD(GENET_INTRL_0, RXDMA_MBDONE,  13, 1)
+FIELD(GENET_INTRL_0, RXDMA_PDONE,   14, 1)
+FIELD(GENET_INTRL_0, RXDMA_BDONE,   15, 1)
+FIELD(GENET_INTRL_0, TXDMA_MBDONE,  16, 1)
+FIELD(GENET_INTRL_0, TXDMA_PDONE,   17, 1)
+FIELD(GENET_INTRL_0, TXDMA_BDONE,   18, 1)
+FIELD(GENET_INTRL_0, RSVD_19_22,19, 4)
+FIELD(GENET_INTRL_0, MDIO_DONE, 23, 1)
+FIELD(GENET_INTRL_0, MDIO_ERROR,24, 1)
+FIELD(GENET_INTRL_0, RSVD_25_31,25, 4)
+
+REG32(GENET_INTRL_1,  0)
+FIELD(GENET_INTRL_1, TX_INTRS,0, 16)
+FIELD(GENET_INTRL_1, RX_INTRS,16, 16)
+
 
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index d166a5c24c..f583818399 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -19,7 +19,82 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_REV_MINOR 0
 
 typedef struct {
-uint8_t stub_area[0x1]; /* temporary stub */
+uint32_t rev_ctrl;
+uint32_t port_ctrl;
+uint32_t rbuf_flush_ctrl;
+uint32_t tbuf_flush_ctrl;
+uint32_t reserved_0x10[12];
+} BCM2838GenetRegsSys;
+
+typedef struct {
+uint32_t reserved_0x0[16];
+} BCM2838GenetRegsGrBridge;
+
+typedef struct {
+uint32_t pwr_mgmt;
+uint32_t reserved_0x4[2];
+uint32_t rgmii_oob_ctrl;
+uint32_t reserved_0x10[3];
+uint32_t gphy_ctrl;
+uint32_t reserved_0x20[24];
+} BCM2838GenetRegsExt;
+
+typedef struct {
+uint32_t stat;
+uint32_t set;
+uint32_t clear;
+uint32_t mask_status;
+uint32_t mask_set;
+uint32_t mask_clear;
+uint32_t reserved_0x18[10];
+} BCM2838GenetRegsIntrl0;
+
+typedef struct {
+uint32_t stat;
+uint32_t set;
+uint32_t clear;
+uint32_t mask_status;
+uint32_t mask_set;
+uint32_t mask_clear;
+uint32_t reserved_0x18[10];
+} BCM2838GenetRegsIntrl1;
+
+typedef struct {
+uint32_t ctrl;
+uint32_t reserved_0x4[2];
+uint32_t status;
+uint32_t reserved_0x10;
+uint32_t chk_ctrl;
+uint32_t reserved_0x18[31];
+uint32_t ovfl_cnt;
+uint32_t err_cnt;
+uint32_t energy_ctrl;
+uint32_t reserved_0xA0[5];
+uint32_t size_ctrl;
+uint32_t reserved_0xB8[18];
+} BCM2838GenetRegsRbuf;
+
+typedef struct {
+uint32_t ctrl;
+uint32_t reserved_0x4[2];
+uint32_t bp_mc;
+uint32_t reserved_0x10;
+uint32_t energy_ctrl;
+uint32_t reserved_0x18[58];
+} BCM2838GenetRegsTbuf;
+
+typedef struct {
+BCM2838GenetRegsSys sys;
+BCM2838GenetRegsGrBridge gr_bridge;
+BCM2838GenetRegsExt ext;
+uint32_t reserved_0x100[64];
+BCM2838GenetRegsIntrl0 intrl0;
+BCM2838GenetRegsIntrl1 intrl1;
+uint32_t reserved_0x280[32];
+BCM2838GenetRegsRbuf rbuf;
+uint32_t reserved_0x400[128];
+BCM2838GenetRegsTbuf tbuf;
+uint32_t reserved_0x700[64];
 } BCM2838GenetRegs;
 
 struct BCM2838GenetState {
-- 
2.34.1




[PATCH v6 27/41] Implement GENET TX path

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 221 -
 include/hw/net/bcm2838_genet.h |  17 +++
 2 files changed, 237 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 1fae3ecbc2..4c9b39a3ca 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -234,6 +234,13 @@ REG16(GENET_PHY_EXP_SEL,   0)
 FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
 FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
 
+REG32(GENET_TX_CSUM_INFO,0)
+FIELD(GENET_TX_CSUM_INFO, OFFSET,0, 15)
+FIELD(GENET_TX_CSUM_INFO, PROTO_UDP, 15, 1)
+FIELD(GENET_TX_CSUM_INFO, START, 16, 15)
+FIELD(GENET_TX_CSUM_INFO, LV,30, 1)
+
+
 static void bcm2838_genet_set_qemu_mac(BCM2838GenetState *s)
 {
 const MACAddr *addr = >nic_conf.macaddr;
@@ -387,6 +394,218 @@ static uint64_t bcm2838_genet_mdio_cmd(BCM2838GenetState 
*s, uint64_t cmd)
 return cmd;
 }
 
+static void bcm2838_genet_xmit_packet(NetClientState *s, void *packet,
+  size_t size)
+{
+uint8_t *buf = packet + sizeof(BCM2838GenetXmitStatus);
+size_t len = size;
+uint16_t len_type = 0;
+
+len -= sizeof(BCM2838GenetXmitStatus);
+net_checksum_calculate(buf, len, CSUM_ALL);
+
+memcpy(_type, [12], sizeof(len_type));
+len_type = ntohs(len_type);
+if (len_type < MAX_PAYLOAD_SIZE) {
+len_type = len;
+len_type = htons(len_type);
+memcpy([12], _type, sizeof(len_type));
+}
+
+qemu_send_packet(s, buf, len);
+}
+
+static uint64_t bcm2838_genet_tx(BCM2838GenetState *s, unsigned int ring_index,
+ uint32_t prod_index,
+ uint32_t cons_index)
+{
+const unsigned int DESC_SIZE_WORDS
+= sizeof(BCM2838GenetTdmaDesc) / sizeof(uint32_t);
+const uint64_t RING_START_ADDR
+= ((uint64_t)s->regs.tdma.rings[ring_index].start_addr_hi << 32)
++ s->regs.tdma.rings[ring_index].start_addr;
+const uint64_t RING_END_ADDR
+= ((uint64_t)s->regs.tdma.rings[ring_index].end_addr_hi << 32)
++ s->regs.tdma.rings[ring_index].end_addr;
+
+hwaddr data_addr;
+uint64_t desc_index;
+uint32_t desc_status = 0;
+uint32_t buflength = 0;
+uint64_t num_descs = 0;
+uint64_t read_ptr
+= ((uint64_t)s->regs.tdma.rings[ring_index].read_ptr_hi << 32)
++ s->regs.tdma.rings[ring_index].read_ptr;
+off_t packet_off = 0;
+
+uint32_t prod_index_fld = FIELD_EX32(prod_index,
+ GENET_DMA_PROD_INDEX, INDEX);
+uint32_t cons_index_fld = FIELD_EX32(cons_index,
+GENET_DMA_CONS_INDEX, INDEX);
+
+while (cons_index_fld != prod_index_fld) {
+desc_index = read_ptr / DESC_SIZE_WORDS;
+if (desc_index >= BCM2838_GENET_DMA_DESC_CNT) {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: invalid TX descriptor index %" PRIu64 " (exceeds %u)\n",
+__func__, desc_index, BCM2838_GENET_DMA_DESC_CNT - 1);
+break;
+}
+desc_status = s->regs.tdma.descs[desc_index].length_status;
+data_addr = ((uint64_t)s->regs.tdma.descs[desc_index].address_hi << 32)
++ s->regs.tdma.descs[desc_index].address_lo;
+trace_bcm2838_genet_tx(ring_index, desc_index, desc_status,
+   data_addr);
+
+if (FIELD_EX32(desc_status, GENET_RDMA_LENGTH_STATUS, SOP) != 0) {
+packet_off = 0;
+}
+
+buflength = FIELD_EX32(desc_status,
+   GENET_RDMA_LENGTH_STATUS, BUFLENGTH);
+
+/* TODO: Add address_space_read() return value check */
+address_space_read(>dma_as, data_addr,
+MEMTXATTRS_UNSPECIFIED,
+s->tx_packet + packet_off,
+buflength);
+packet_off += buflength;
+
+if (FIELD_EX32(desc_status, GENET_RDMA_LENGTH_STATUS, EOP) != 0) {
+bcm2838_genet_xmit_packet(qemu_get_queue(s->nic), s->tx_packet,
+ packet_off);
+packet_off = 0;
+}
+
+num_descs++;
+cons_index_fld++;
+s->regs.tdma.descs[desc_index].length_status =
+FIELD_DP32(s->regs.tdma.descs[desc_index].length_status,
+   GENET_RDMA_LENGTH_STATUS, OWN, 1);
+read_ptr = read_ptr == RING_END_ADDR + 1 - DESC_SIZE_WORDS
+? RING_START_ADDR : read_ptr + DESC_SIZE_WORDS;
+}
+
+s->regs.tdma.rings[ring_index].read_ptr = read_ptr;
+s->regs.tdma.rings[ring_index].read_ptr_hi = read_ptr >> 32;
+
+return num_descs;
+}
+
+static bool bcm2838_ge

[PATCH v6 23/41] Add GENET register structs. Part 4

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 include/hw/net/bcm2838_genet.h | 37 ++
 1 file changed, 37 insertions(+)

diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 1bd004785a..94c2f3ebca 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -25,6 +25,12 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_HFB_FILTER_CNT  48
 #define BCM2838_GENET_HFB_FILTER_SIZE 128
 
+#define BCM2838_GENET_PHY_AUX_CTL_MISC  0x7
+#define BCM2838_GENET_PHY_AUX_CTL_REGS_SIZE 8
+
+#define BCM2838_GENET_PHY_EXP_SHD_BLOCKS_CNT 256
+#define BCM2838_GENET_PHY_EXP_SHD_REGS_CNT   256
+
 typedef struct {
 uint32_t rev_ctrl;
 uint32_t port_ctrl;
@@ -273,6 +279,34 @@ typedef struct {
 uint16_t rdb_data;
 } BCM2838GenetPhyRegs;
 
+typedef struct {
+uint16_t reserved_0_2[3];
+uint16_t clk_ctl;
+uint16_t scr2;
+uint16_t scr3;
+uint16_t reserved_6_9[4];
+uint16_t apd;
+uint16_t rgmii_mode;
+uint16_t reserved_12;
+uint16_t leds1;
+uint16_t reserved_14_18[5];
+uint16_t _100fx_ctrl;
+uint16_t ssd;
+uint16_t reserved_21_30[10];
+uint16_t mode;
+} BCM2838GenetPhyShdRegs;
+
+typedef struct {
+uint16_t auxctl;
+uint16_t reserved_1_6[BCM2838_GENET_PHY_AUX_CTL_REGS_SIZE - 2];
+uint16_t misc;
+} BCM2838GenetPhyAuxShdRegs;
+
+typedef struct {
+uint16_t regs[BCM2838_GENET_PHY_EXP_SHD_BLOCKS_CNT]
+ [BCM2838_GENET_PHY_EXP_SHD_REGS_CNT];
+} BCM2838GenetPhyExpShdRegs;
+
 struct BCM2838GenetState {
 /*< private >*/
 SysBusDevice parent_obj;
@@ -284,6 +318,9 @@ struct BCM2838GenetState {
 
 BCM2838GenetRegs regs;
 BCM2838GenetPhyRegs phy_regs;
+BCM2838GenetPhyShdRegs phy_shd_regs;
+BCM2838GenetPhyAuxShdRegs phy_aux_ctl_shd_regs;
+BCM2838GenetPhyExpShdRegs phy_exp_shd_regs;
 
 qemu_irq irq_default;
 qemu_irq irq_prio;
-- 
2.34.1




[PATCH v6 33/41] Add mailbox tests tags. Part 1

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 177 ++
 1 file changed, 177 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 9222b38bad..1360fbb8cf 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -116,6 +116,183 @@ typedef struct {  
  \
 };  \
 } TypeName
 
+DECLARE_TAG_TYPE(TAG_GET_FIRMWARE_REVISION_t,
+struct {},
+struct {
+uint32_t revision;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_FIRMWARE_VARIANT_t,
+struct {},
+struct {
+uint32_t variant;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_BOARD_REVISION_t,
+struct {},
+struct {
+uint32_t revision;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_ARM_MEMORY_t,
+struct {},
+struct {
+uint32_t base;
+uint32_t size;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_VC_MEMORY_t,
+struct {},
+struct {
+uint32_t base;
+uint32_t size;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_POWER_STATE_t,
+struct {
+uint32_t device_id;
+uint32_t cmd;
+},
+struct {
+uint32_t device_id;
+uint32_t cmd;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_CLOCK_STATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t cmd;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_CLOCK_RATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t rate;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_MAX_CLOCK_RATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t rate;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_MIN_CLOCK_RATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t rate;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_CLOCKS_t,
+struct {},
+struct {
+uint32_t root_clock;
+uint32_t arm_clock;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_TEMPERATURE_t,
+struct {
+uint32_t temperature_id;
+},
+struct {
+uint32_t temperature_id;
+uint32_t temperature;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_MAX_TEMPERATURE_t,
+struct {
+uint32_t temperature_id;
+},
+struct {
+uint32_t temperature_id;
+uint32_t temperature;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_ALLOCATE_t,
+struct {
+uint32_t alignment;
+},
+struct {
+uint32_t base;
+uint32_t size;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_RELEASE_t,
+struct {},
+struct {});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_BLANK_t,
+struct {
+uint32_t on;
+},
+struct {
+uint32_t on;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT_t,
+struct {},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT_t,
+struct {},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
 
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
-- 
2.34.1




[PATCH v6 06/41] Add BCM2838 GPIO stub

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/gpio/bcm2838_gpio.c | 153 +
 hw/gpio/meson.build|   5 +-
 include/hw/gpio/bcm2838_gpio.h |  40 +
 3 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 hw/gpio/bcm2838_gpio.c
 create mode 100644 include/hw/gpio/bcm2838_gpio.h

diff --git a/hw/gpio/bcm2838_gpio.c b/hw/gpio/bcm2838_gpio.c
new file mode 100644
index 00..a312490bbd
--- /dev/null
+++ b/hw/gpio/bcm2838_gpio.c
@@ -0,0 +1,153 @@
+/*
+ * Raspberry Pi (BCM2838) GPIO Controller
+ * This implementation is based on bcm2835_gpio (hw/gpio/bcm2835_gpio.c)
+ *
+ * Copyright (c) 2022 Auriga LLC
+ *
+ * Authors:
+ *  Lotosh, Aleksey 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "hw/gpio/bcm2838_gpio.h"
+
+#define GPFSEL0   0x00
+#define GPFSEL1   0x04
+#define GPFSEL2   0x08
+#define GPFSEL3   0x0C
+#define GPFSEL4   0x10
+#define GPFSEL5   0x14
+#define GPSET00x1C
+#define GPSET10x20
+#define GPCLR00x28
+#define GPCLR10x2C
+#define GPLEV00x34
+#define GPLEV10x38
+#define GPEDS00x40
+#define GPEDS10x44
+#define GPREN00x4C
+#define GPREN10x50
+#define GPFEN00x58
+#define GPFEN10x5C
+#define GPHEN00x64
+#define GPHEN10x68
+#define GPLEN00x70
+#define GPLEN10x74
+#define GPAREN0   0x7C
+#define GPAREN1   0x80
+#define GPAFEN0   0x88
+#define GPAFEN1   0x8C
+
+#define GPIO_PUP_PDN_CNTRL_REG0 0xE4
+#define GPIO_PUP_PDN_CNTRL_REG1 0xE8
+#define GPIO_PUP_PDN_CNTRL_REG2 0xEC
+#define GPIO_PUP_PDN_CNTRL_REG3 0xF0
+
+#define RESET_VAL_CNTRL_REG0 0xAAA9
+#define RESET_VAL_CNTRL_REG1 0xA0AA
+#define RESET_VAL_CNTRL_REG2 0x50AAA95A
+#define RESET_VAL_CNTRL_REG3 0x0005
+
+#define BYTES_IN_WORD4
+
+static uint64_t bcm2838_gpio_read(void *opaque, hwaddr offset, unsigned size)
+{
+uint64_t value = 0;
+
+qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+
+return value;
+}
+
+static void bcm2838_gpio_write(void *opaque, hwaddr offset, uint64_t value,
+   unsigned size)
+{
+qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+}
+
+static void bcm2838_gpio_reset(DeviceState *dev)
+{
+BCM2838GpioState *s = BCM2838_GPIO(dev);
+
+s->lev0 = 0;
+s->lev1 = 0;
+
+memset(s->fsel, 0, sizeof(s->fsel));
+
+s->pup_cntrl_reg[0] = RESET_VAL_CNTRL_REG0;
+s->pup_cntrl_reg[1] = RESET_VAL_CNTRL_REG1;
+s->pup_cntrl_reg[2] = RESET_VAL_CNTRL_REG2;
+s->pup_cntrl_reg[3] = RESET_VAL_CNTRL_REG3;
+}
+
+static const MemoryRegionOps bcm2838_gpio_ops = {
+.read = bcm2838_gpio_read,
+.write = bcm2838_gpio_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_bcm2838_gpio = {
+.name = "bcm2838_gpio",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT8_ARRAY(fsel, BCM2838GpioState, BCM2838_GPIO_NUM),
+VMSTATE_UINT32(lev0, BCM2838GpioState),
+VMSTATE_UINT32(lev1, BCM2838GpioState),
+VMSTATE_UINT8(sd_fsel, BCM2838GpioState),
+VMSTATE_UINT32_ARRAY(pup_cntrl_reg, BCM2838GpioState,
+ GPIO_PUP_PDN_CNTRL_NUM),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void bcm2838_gpio_init(Object *obj)
+{
+BCM2838GpioState *s = BCM2838_GPIO(obj);
+DeviceState *dev = DEVICE(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem, obj, _gpio_ops, s,
+  "bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
+sysbus_init_mmio(sbd, >iomem);
+qdev_init_gpio_out(dev, s->out, BCM2838_GPIO_NUM);
+}
+
+static void bcm2838_gpio_realize(DeviceState *dev, Error **errp)
+{
+/* Temporary stub. Do nothing */
+}
+
+static void bcm2838_gpio_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->vmsd = _bcm2838_gpio;
+dc->realize = _gpio_realize;
+dc->reset = _gpio_reset;
+}
+
+static const TypeInfo bcm2838_gpio_info = {
+.name  = TYPE_BCM2838_GPIO,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(BCM2838GpioState),
+.instance_init = bcm2838_gpio_init,
+.class_init= bcm2838_gpio_class_init,
+};
+
+static void bcm2838_gpio_register_types(void)
+{
+type_register_static(_gpio_info);
+}
+
+type_init(bcm2838_gpio_register_types)
diff --git a/hw/gpio/meson.build b/hw

[PATCH v6 40/41] Append added properties to mailbox test

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index c96a9ba3f3..ff7c347e7c 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -270,6 +270,12 @@ DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, ANY) {
 tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
 }
 
+/**/
+DECLARE_TEST_CASE(GET_CLOCKS) {
+g_assert_cmphex(tag->response.value.root_clock, ==, CLOCK_ID_ROOT);
+g_assert_cmphex(tag->response.value.arm_clock, ==, CLOCK_ID_ARM);
+}
+
 
/**/
 DECLARE_TEST_CASE(GET_TEMPERATURE) {
 g_assert_cmphex(tag->response.value.temperature_id, ==, 
TEMPERATURE_ID_SOC);
@@ -536,6 +542,11 @@ DECLARE_TEST_CASE(GET_COMMAND_LINE) {
 /* No special checks are needed for this test case */
 }
 
+/**/
+DECLARE_TEST_CASE(GET_THROTTLED) {
+g_assert_cmpint(tag->response.value.throttled, ==, 0);
+}
+
 
/**/
 DECLARE_TEST_CASE(FRAMEBUFFER_GET_NUM_DISPLAYS) {
 g_assert_cmpint(tag->response.value.num_displays, ==, 1);
@@ -549,6 +560,11 @@ DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_PITCH) {
 tag->request.value.pitch = DUMMY_VALUE;
 }
 
+/**/
+DECLARE_TEST_CASE(VCHIQ_INIT) {
+g_assert_cmpint(tag->response.value.zero, ==, 0);
+}
+
 
/**/
 int main(int argc, char **argv)
 {
@@ -572,6 +588,7 @@ int main(int argc, char **argv)
 QTEST_ADD_TEST_CASE(GET_CLOCK_RATE, ANY);
 QTEST_ADD_TEST_CASE(GET_MAX_CLOCK_RATE, ANY);
 QTEST_ADD_TEST_CASE(GET_MIN_CLOCK_RATE, ANY);
+QTEST_ADD_TEST_CASE(GET_CLOCKS);
 QTEST_ADD_TEST_CASE(GET_TEMPERATURE);
 QTEST_ADD_TEST_CASE(GET_MAX_TEMPERATURE);
 QTEST_ADD_TEST_CASE(FRAMEBUFFER_ALLOCATE);
@@ -607,6 +624,8 @@ int main(int argc, char **argv)
 QTEST_ADD_TEST_CASE(GET_COMMAND_LINE);
 QTEST_ADD_TEST_CASE(FRAMEBUFFER_GET_NUM_DISPLAYS);
 QTEST_ADD_TEST_CASE(FRAMEBUFFER_SET_PITCH);
+QTEST_ADD_TEST_CASE(GET_THROTTLED);
+QTEST_ADD_TEST_CASE(VCHIQ_INIT);
 
 return g_test_run();
 }
-- 
2.34.1




[PATCH v6 02/41] Split out common part of peripherals

2024-02-25 Thread Sergey Kambalin
Pre-setup for BCM2838 introduction

Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/bcm2835_peripherals.c | 198 +++
 hw/arm/bcm2836.c |  24 ++--
 include/hw/arm/bcm2835_peripherals.h |  29 +++-
 include/hw/arm/bcm2836.h |   3 +-
 4 files changed, 154 insertions(+), 100 deletions(-)

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index d5573fd954..ed38a08a57 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -30,9 +30,9 @@
 #define SEPARATE_DMA_IRQ_MAX 10
 #define ORGATED_DMA_IRQ_COUNT 4
 
-static void create_unimp(BCM2835PeripheralState *ps,
- UnimplementedDeviceState *uds,
- const char *name, hwaddr ofs, hwaddr size)
+void create_unimp(BCMSocPeripheralBaseState *ps,
+  UnimplementedDeviceState *uds,
+  const char *name, hwaddr ofs, hwaddr size)
 {
 object_initialize_child(OBJECT(ps), name, uds, TYPE_UNIMPLEMENTED_DEVICE);
 qdev_prop_set_string(DEVICE(uds), "name", name);
@@ -45,9 +45,36 @@ static void create_unimp(BCM2835PeripheralState *ps,
 static void bcm2835_peripherals_init(Object *obj)
 {
 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
+BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(obj);
+
+/* Random Number Generator */
+object_initialize_child(obj, "rng", >rng, TYPE_BCM2835_RNG);
+
+/* Thermal */
+object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2835_THERMAL);
+
+/* GPIO */
+object_initialize_child(obj, "gpio", >gpio, TYPE_BCM2835_GPIO);
+
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhci",
+   OBJECT(_base->sdhci.sdbus));
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhost",
+   OBJECT(_base->sdhost.sdbus));
+
+/* Gated DMA interrupts */
+object_initialize_child(obj, "orgated-dma-irq",
+_base->orgated_dma_irq, TYPE_OR_IRQ);
+object_property_set_int(OBJECT(_base->orgated_dma_irq), "num-lines",
+ORGATED_DMA_IRQ_COUNT, _abort);
+}
+
+static void raspi_peripherals_base_init(Object *obj)
+{
+BCMSocPeripheralBaseState *s = BCM_SOC_PERIPHERALS_BASE(obj);
+BCMSocPeripheralBaseClass *bc = BCM_SOC_PERIPHERALS_BASE_GET_CLASS(obj);
 
 /* Memory region for peripheral devices, which we export to our parent */
-memory_region_init(>peri_mr, obj,"bcm2835-peripherals", 0x100);
+memory_region_init(>peri_mr, obj, "bcm2835-peripherals", bc->peri_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_mr);
 
 /* Internal memory region for peripheral bus addresses (not exported) */
@@ -98,9 +125,6 @@ static void bcm2835_peripherals_init(Object *obj)
 object_property_add_const_link(OBJECT(>property), "dma-mr",
OBJECT(>gpu_bus_mr));
 
-/* Random Number Generator */
-object_initialize_child(obj, "rng", >rng, TYPE_BCM2835_RNG);
-
 /* Extended Mass Media Controller */
 object_initialize_child(obj, "sdhci", >sdhci, TYPE_SYSBUS_SDHCI);
 
@@ -110,25 +134,9 @@ static void bcm2835_peripherals_init(Object *obj)
 /* DMA Channels */
 object_initialize_child(obj, "dma", >dma, TYPE_BCM2835_DMA);
 
-object_initialize_child(obj, "orgated-dma-irq",
->orgated_dma_irq, TYPE_OR_IRQ);
-object_property_set_int(OBJECT(>orgated_dma_irq), "num-lines",
-ORGATED_DMA_IRQ_COUNT, _abort);
-
 object_property_add_const_link(OBJECT(>dma), "dma-mr",
OBJECT(>gpu_bus_mr));
 
-/* Thermal */
-object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2835_THERMAL);
-
-/* GPIO */
-object_initialize_child(obj, "gpio", >gpio, TYPE_BCM2835_GPIO);
-
-object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhci",
-   OBJECT(>sdhci.sdbus));
-object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhost",
-   OBJECT(>sdhost.sdbus));
-
 /* Mphi */
 object_initialize_child(obj, "mphi", >mphi, TYPE_BCM2835_MPHI);
 
@@ -152,7 +160,72 @@ static void bcm2835_peripherals_init(Object *obj)
 
 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
 {
+MemoryRegion *mphi_mr;
 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev);
+BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+int n;
+
+bcm_soc_peripherals_common_realize(dev, errp);
+
+/* Extended Mass Media Controller */
+sysbus_co

[PATCH v6 16/41] Add RPi4 RNG200

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c |   4 +
 hw/arm/bcm2838_peripherals.c |  17 ++
 hw/arm/raspi4b.c |   1 -
 hw/misc/bcm2838_rng200.c | 405 +++
 hw/misc/meson.build  |   1 +
 hw/misc/trace-events |   9 +
 include/hw/arm/bcm2838_peripherals.h |   2 +
 include/hw/misc/bcm2838_rng200.h |  43 +++
 8 files changed, 481 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/bcm2838_rng200.c
 create mode 100644 include/hw/misc/bcm2838_rng200.h

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index 481b262b02..c330322bd5 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -205,6 +205,10 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(_base->dwc2), 0,
qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_DWC2));
 
+/* Connect RNG200 to the interrupt controller */
+sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0,
+   qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_RNG200));
+
 /* Connect DMA 0-6 to the interrupt controller */
 for (int n = GIC_SPI_INTERRUPT_DMA_0; n <= GIC_SPI_INTERRUPT_DMA_6; n++) {
 sysbus_connect_irq(SYS_BUS_DEVICE(_base->dma),
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 23e1154466..4a9cbe6cf6 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -34,6 +34,9 @@ static void bcm2838_peripherals_init(Object *obj)
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* Random Number Generator */
+object_initialize_child(obj, "rng200", >rng200, TYPE_BCM2838_RNG200);
+
 /* PCIe Host Bridge */
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
@@ -75,6 +78,8 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
 MemoryRegion *regs_mr;
 MemoryRegion *mmio_mr;
+MemoryRegion *rng200_mr;
+qemu_irq rng_200_irq;
 
 int n;
 
@@ -88,6 +93,18 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCM2838_VC_PERI_LOW_BASE,
 >peri_low_mr_alias, 1);
 
+/* Random Number Generator */
+if (!sysbus_realize(SYS_BUS_DEVICE(>rng200), errp)) {
+return;
+}
+
+rng200_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng200), 0);
+memory_region_add_subregion(_base->peri_mr, RNG_OFFSET, rng200_mr);
+
+rng_200_irq = qdev_get_gpio_in_named(DEVICE(_base->ic),
+ BCM2835_IC_GPU_IRQ, INTERRUPT_RNG);
+sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0, rng_200_irq);
+
 /* Extended Mass Media Controller 2 */
 object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
  _abort);
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 2431b0b8c3..3c71fa9a9a 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -67,7 +67,6 @@ static void raspi4_modify_dtb(const struct arm_boot_info 
*info, void *fdt)
 
 /* Temporarily disable following devices until they are implemented */
 const char *nodes_to_remove[] = {
-"brcm,bcm2711-rng200",
 "brcm,bcm2711-thermal",
 "brcm,bcm2711-genet-v5",
 };
diff --git a/hw/misc/bcm2838_rng200.c b/hw/misc/bcm2838_rng200.c
new file mode 100644
index 00..84ed723a1c
--- /dev/null
+++ b/hw/misc/bcm2838_rng200.c
@@ -0,0 +1,405 @@
+/*
+ * BCM2838 Random Number Generator emulation
+ *
+ * Copyright (C) 2022 Sergey Pushkarev 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qom/object_interfaces.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "hw/misc/bcm2838_rng200.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+/* RNG200 registers */
+REG32(RNG_CTRL,   0x00)
+FIELD(RNG_CTRL, RBG_ENABLE,   0 , 1)
+FIELD(RNG_CTRL, RSVD, 1 , 12)
+FIELD(RNG_CTRL, DIV, 13 , 8)
+
+REG32(RNG_SOFT_RESET,0x04)
+REG32(RBG_SOFT_RESET,0x08)
+REG32(RNG_TOTAL_BIT_COUNT,   0x0C)
+REG32(RNG_TOTAL_BIT_COUNT_THRESHOLD, 0x10)
+
+REG32(RNG_INT_STATUS,   0x18)
+FIELD(RNG_INT_STATUS, TOTAL_BITS_COUNT_IRQ, 0, 1)
+FIELD(RNG_INT_STATUS, RSVD0,1, 4)
+FIELD(RNG_INT_STATUS, NIST_FAIL_IRQ,5, 1)
+FIE

[PATCH v6 41/41] Add RPi4B to raspi.rst

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 docs/system/arm/raspi.rst | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/docs/system/arm/raspi.rst b/docs/system/arm/raspi.rst
index d0a6f08b2b..c21b27744e 100644
--- a/docs/system/arm/raspi.rst
+++ b/docs/system/arm/raspi.rst
@@ -1,5 +1,5 @@
-Raspberry Pi boards (``raspi0``, ``raspi1ap``, ``raspi2b``, ``raspi3ap``, 
``raspi3b``)
-==
+Raspberry Pi boards (``raspi0``, ``raspi1ap``, ``raspi2b``, ``raspi3ap``, 
``raspi3b``, ``raspi4b-2g``)
+==
 
 
 QEMU provides models of the following Raspberry Pi boards:
@@ -12,12 +12,13 @@ QEMU provides models of the following Raspberry Pi boards:
   Cortex-A53 (4 cores), 512 MiB of RAM
 ``raspi3b``
   Cortex-A53 (4 cores), 1 GiB of RAM
-
+``raspi4b-2g``
+  Cortex-A72 (4 cores), 2 GiB of RAM
 
 Implemented devices
 ---
 
- * ARM1176JZF-S, Cortex-A7 or Cortex-A53 CPU
+ * ARM1176JZF-S, Cortex-A7, Cortex-A53 or Cortex-A72 CPU
  * Interrupt controller
  * DMA controller
  * Clock and reset controller (CPRMAN)
@@ -34,6 +35,8 @@ Implemented devices
  * MailBox controller (MBOX)
  * VideoCore firmware (property)
  * Peripheral SPI controller (SPI)
+ * PCIE Root Port (raspi4b-2g)
+ * GENET Ethernet Controller (raspi4b-2g)
 
 
 Missing devices
-- 
2.34.1




[PATCH v6 30/41] Add Rpi4b boot tests

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/avocado/boot_linux_console.py | 92 +
 1 file changed, 92 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index a00202df3c..f5ec6de0f1 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -501,6 +501,98 @@ def test_arm_raspi2_initrd(self):
 # Wait for VM to shut down gracefully
 self.vm.wait()
 
+def test_arm_raspi4(self):
+"""
+:avocado: tags=arch:aarch64
+:avocado: tags=machine:raspi4b-2g
+:avocado: tags=device:pl011
+:avocado: tags=accel:tcg
+:avocado: tags=rpi4b
+
+The kernel can be rebuilt using the kernel source referenced
+and following the instructions on the on:
+https://www.raspberrypi.org/documentation/linux/kernel/building.md
+"""
+
+deb_url = ('http://archive.raspberrypi.org/debian/'
+'pool/main/r/raspberrypi-firmware/'
+'raspberrypi-kernel_1.20230106-1_arm64.deb')
+deb_hash = '08dc55696535b18a6d4fe6fa10d4c0d905cbb2ed'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
+dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'earlycon=pl011,mmio32,0xfe201000 ' +
+   'console=ttyAMA0,115200 ' +
+   'root=/dev/mmcblk1p2 rootwait ' +
+   'dwc_otg.fiq_fsm_enable=0')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line,
+ '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
+ '-device', 'usb-kbd,bus=xhci.0')
+self.vm.launch()
+console_pattern = 'Kernel command line: %s' % kernel_command_line
+self.wait_for_console_pattern(console_pattern)
+console_pattern = 'Product: QEMU USB Keyboard'
+self.wait_for_console_pattern(console_pattern)
+
+
+def test_arm_raspi4_initrd(self):
+"""
+:avocado: tags=arch:aarch64
+:avocado: tags=machine:raspi4b-2g
+:avocado: tags=device:pl011
+:avocado: tags=accel:tcg
+:avocado: tags=rpi4b
+
+The kernel can be rebuilt using the kernel source referenced
+and following the instructions on the on:
+https://www.raspberrypi.org/documentation/linux/kernel/building.md
+"""
+deb_url = ('http://archive.raspberrypi.org/debian/'
+'pool/main/r/raspberrypi-firmware/'
+'raspberrypi-kernel_1.20230106-1_arm64.deb')
+deb_hash = '08dc55696535b18a6d4fe6fa10d4c0d905cbb2ed'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
+dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
+
+initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
+  '86b2be1384d41c8c388e63078a847f1e1c4cb1de/rootfs/'
+  'arm64/rootfs.cpio.gz')
+initrd_hash = 'f3d4f9fa92a49aa542f1b44d34be77bbf8ca5b9d'
+initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
+archive.gzip_uncompress(initrd_path_gz, initrd_path)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'earlycon=pl011,mmio32,0xfe201000 ' +
+   'console=ttyAMA0,115200 ' +
+   'panic=-1 noreboot ' +
+   'dwc_otg.fiq_fsm_enable=0')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
+ '-device', 'usb-kbd,bus=xhci.0',
+ '-no-reboot')
+self.vm.launch()
+self.wait_for_console_pattern('Boot successful.')
+
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+'BCM2835')
+exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+'cprman@7e101000')
+exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System 
halted')
+# TODO: Raspberry Pi4 doesn't shut down properly with recent kernels
+# Wait for VM to shut down gracefully
+  

[PATCH v6 29/41] Enable BCM2838 GENET controller

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c |  6 ++
 hw/arm/bcm2838_peripherals.c | 11 +++
 hw/arm/raspi4b.c | 20 +---
 include/hw/arm/bcm2838_peripherals.h |  2 ++
 4 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index c330322bd5..a873162f09 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -239,6 +239,12 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
   int_n);
 }
 
+/* Connect Gigabit Ethernet controller to the interrupt controller */
+sysbus_connect_irq(SYS_BUS_DEVICE(>genet), 0,
+   qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_GENET_A));
+sysbus_connect_irq(SYS_BUS_DEVICE(>genet), 1,
+   qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_GENET_B));
+
 /* Pass through inbound GPIO lines to the GIC */
 qdev_init_gpio_in(dev, bcm2838_gic_set_irq, GIC_NUM_IRQS);
 
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 1f41028649..c6083e36de 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -47,6 +47,10 @@ static void bcm2838_peripherals_init(Object *obj)
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
 
+/* Gigabit Ethernet */
+object_initialize_child(obj, "genet", >genet, TYPE_BCM2838_GENET);
+qemu_configure_nic_device(DEVICE(>genet), true, NULL);
+
 /* Extended Mass Media Controller 2 */
 object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
 
@@ -231,6 +235,13 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
 mmio_mr);
 
+/* Gigabit Ethernet */
+if (!sysbus_realize(SYS_BUS_DEVICE(>genet), errp)) {
+return;
+}
+regs_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>genet), 0);
+memory_region_add_subregion(>peri_low_mr, GENET_OFFSET, regs_mr);
+
 create_unimp(s_base, >clkisp, "bcm2835-clkisp", CLOCK_ISP_OFFSET,
  CLOCK_ISP_SIZE);
 
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 175fd2c4fa..d498bc6215 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -63,25 +63,7 @@ static int raspi_add_memory_node(void *fdt, hwaddr mem_base, 
hwaddr mem_len)
 
 static void raspi4_modify_dtb(const struct arm_boot_info *info, void *fdt)
 {
-uint64_t ram_size;
-
-/* Temporarily disable following devices until they are implemented */
-const char *nodes_to_remove[] = {
-"brcm,bcm2711-genet-v5",
-};
-
-for (int i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
-const char *dev_str = nodes_to_remove[i];
-
-int offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
-if (offset >= 0) {
-if (!fdt_nop_node(fdt, offset)) {
-warn_report("bcm2711 dtc: %s has been disabled!", dev_str);
-}
-}
-}
-
-ram_size = board_ram_size(info->board_id);
+uint64_t ram_size = board_ram_size(info->board_id);
 
 if (info->ram_size > UPPER_RAM_BASE) {
 raspi_add_memory_node(fdt, UPPER_RAM_BASE, ram_size - UPPER_RAM_BASE);
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 555d3a393f..5588b99098 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -13,6 +13,7 @@
 #include "hw/misc/bcm2838_rng200.h"
 #include "hw/misc/bcm2838_thermal.h"
 #include "hw/arm/bcm2838_pcie.h"
+#include "hw/net/bcm2838_genet.h"
 #include "hw/sd/sdhci.h"
 #include "hw/gpio/bcm2838_gpio.h"
 
@@ -73,6 +74,7 @@ struct BCM2838PeripheralState {
 SDHCIState emmc2;
 BCM2838PcieHostState pcie_host;
 BCM2838GpioState gpio;
+BCM2838GenetState genet;
 
 OrIRQState mmc_irq_orgate;
 OrIRQState dma_7_8_irq_orgate;
-- 
2.34.1




[PATCH v6 13/41] Add BCM2838 PCIE Root Complex

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_pcie.c | 82 +++
 hw/arm/meson.build|  5 ++-
 include/hw/arm/bcm2838_pcie.h | 53 ++
 3 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/bcm2838_pcie.c
 create mode 100644 include/hw/arm/bcm2838_pcie.h

diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c
new file mode 100644
index 00..cb1370433e
--- /dev/null
+++ b/hw/arm/bcm2838_pcie.c
@@ -0,0 +1,82 @@
+/*
+ * BCM2838 PCIe Root Complex emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/irq.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "qemu/module.h"
+#include "hw/arm/bcm2838_pcie.h"
+#include "trace.h"
+
+/*
+ * RC root part (D0:F0)
+ */
+
+static void bcm2838_pcie_root_port_reset_hold(Object *obj)
+{
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj);
+PCIDevice *dev = PCI_DEVICE(obj);
+BCM2838PcieRootState *s = BCM2838_PCIE_ROOT(dev);
+
+if (rpc->parent_phases.hold) {
+rpc->parent_phases.hold(obj);
+}
+
+memset(s->regs, 0xFF, sizeof(s->regs));
+}
+
+static void bcm2838_pcie_root_init(Object *obj)
+{
+PCIBridge *br = PCI_BRIDGE(obj);
+br->bus_name = "pcie.1";
+}
+
+static void bcm2838_pcie_root_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+PCIDeviceClass *k = PCI_DEVICE_CLASS(class);
+ResettableClass *rc = RESETTABLE_CLASS(class);
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(class);
+
+dc->desc = "BCM2711 PCIe Bridge";
+/*
+ * PCI-facing part of the host bridge, not usable without the host-facing
+ * part, which can't be device_add'ed.
+ */
+
+resettable_class_set_parent_phases(rc, NULL,
+   bcm2838_pcie_root_port_reset_hold,
+   NULL, >parent_phases);
+
+dc->user_creatable = false;
+k->vendor_id = BCM2838_PCIE_VENDOR_ID;
+k->device_id = BCM2838_PCIE_DEVICE_ID;
+k->revision = BCM2838_PCIE_REVISION;
+
+rpc->exp_offset = BCM2838_PCIE_EXP_CAP_OFFSET;
+rpc->aer_offset = BCM2838_PCIE_AER_CAP_OFFSET;
+}
+
+static const TypeInfo bcm2838_pcie_root_info = {
+.name = TYPE_BCM2838_PCIE_ROOT,
+.parent = TYPE_PCIE_ROOT_PORT,
+.instance_size = sizeof(BCM2838PcieRootState),
+.instance_init = bcm2838_pcie_root_init,
+.class_init = bcm2838_pcie_root_class_init,
+};
+
+static void bcm2838_pcie_register(void)
+{
+type_register_static(_pcie_root_info);
+}
+
+type_init(bcm2838_pcie_register)
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 6808135c1f..39f6df7431 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -30,7 +30,10 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: 
files('allwinner-a10.c', 'cubi
 arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 
'orangepi.c'))
 arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 
'bananapi_m2u.c'))
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
-arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: 
files('bcm2838.c', 'raspi4b.c'))
+arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: files(
+  'bcm2838.c',
+  'bcm2838_pcie.c',
+  'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
diff --git a/include/hw/arm/bcm2838_pcie.h b/include/hw/arm/bcm2838_pcie.h
new file mode 100644
index 00..39828f817f
--- /dev/null
+++ b/include/hw/arm/bcm2838_pcie.h
@@ -0,0 +1,53 @@
+/*
+ * BCM2838 PCIe Root Complex emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef BCM2838_PCIE_H
+#define BCM2838_PCIE_H
+
+#include "exec/hwaddr.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci/pcie_port.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2838_PCIE_ROOT "bcm2838-pcie-root"
+OBJECT_DECLARE_TYPE(BCM2838PcieRootState, BCM2838PcieRootClass,
+BCM2838_PCIE_ROOT)
+
+#define BCM2838_PCIE_VENDOR_ID  0x14E4
+#define BCM2838_PCIE_DEVICE_ID  0x2711
+#define BCM2838_PCIE_REVISION   20
+
+#define BCM2838_PCIE_REGS_SIZE  0x9310
+#define BCM2838_PCIE_NUM_IRQS   4
+
+#define BCM2838_PCIE_EXP_CAP_OFFSET 0xAC
+#define BCM2838_PCIE_AER_CAP_OFFSET 0x100
+
+

[PATCH v6 26/41] Implement GENET MDIO

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 126 -
 include/hw/net/bcm2838_genet.h |   3 +-
 2 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 56ff6a6f39..1fae3ecbc2 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -213,6 +213,7 @@ FIELD(GENET_PHY_STAT_1000, LOCALRXOK, 13, 1)
 FIELD(GENET_PHY_STAT_1000, MSRES, 14, 1)
 FIELD(GENET_PHY_STAT_1000, MSFAIL,15, 1)
 
+/* There are two data representations for PHY_AUX_CTRL register */
 REG16(GENET_PHY_AUX_CTRL_0,  0)
 FIELD(GENET_PHY_AUX_CTRL_0, REG_ID_MASK, 0, 3)
 FIELD(GENET_PHY_AUX_CTRL_0, RSVD_3,  3, 1)
@@ -269,6 +270,123 @@ static void bcm2838_genet_set_irq_prio(BCM2838GenetState 
*s)
 qemu_set_irq(s->irq_prio, level);
 }
 
+static void bcm2838_genet_phy_aux_ctl_write(BCM2838GenetState *s,
+uint16_t value)
+{
+uint16_t reg_id = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, REG_ID);
+uint16_t reg_id_mask = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, 
REG_ID_MASK);
+uint16_t misc_wren = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, MISC_WREN);
+uint16_t reg_data = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, REG_DATA);
+uint16_t reg_data12 = FIELD_EX16(value, GENET_PHY_AUX_CTRL_1, REG_DATA);
+
+uint16_t *phy_aux_ctl_shd_reg_id = (uint16_t *)>phy_aux_ctl_shd_regs + 
reg_id;
+uint16_t *phy_aux_ctl_shd_reg_id_mask = (uint16_t 
*)>phy_aux_ctl_shd_regs + reg_id_mask;
+
+if (reg_id_mask == BCM2838_GENET_PHY_AUX_CTL_MISC) {
+if (reg_id == BCM2838_GENET_PHY_AUX_CTL_MISC) {
+if (misc_wren == 0) {
+/* write for subsequent read (8-bit from AUX_CTL_MISC) */
+FIELD_DP16(value, GENET_PHY_AUX_CTRL_0, REG_DATA, 
*phy_aux_ctl_shd_reg_id);
+} else {
+/* write 8 bits to AUX_CTL_MISC */
+*phy_aux_ctl_shd_reg_id_mask = reg_data;
+}
+} else {
+/* write for subsequent read (12-bit) */
+FIELD_DP16(value, GENET_PHY_AUX_CTRL_1, REG_DATA, 
*phy_aux_ctl_shd_reg_id);
+}
+} else {
+/* write 12 bits */
+*phy_aux_ctl_shd_reg_id_mask = reg_data12;
+}
+
+s->phy_regs.aux_ctl = value;
+}
+
+static void bcm2838_genet_phy_shadow_write(BCM2838GenetState *s,
+   uint16_t value)
+{
+uint16_t reg_id = FIELD_EX16(value, GENET_PHY_SHADOW, REG_ID);
+uint16_t wr = FIELD_EX16(value, GENET_PHY_SHADOW, WR);
+uint16_t reg_data = FIELD_EX16(value, GENET_PHY_SHADOW, REG_DATA);
+
+uint16_t *phy_shd_reg = (uint16_t *)>phy_shd_regs + reg_id;
+
+if (wr == 0) {
+FIELD_DP16(value, GENET_PHY_SHADOW, REG_DATA, *phy_shd_reg);
+} else {
+*phy_shd_reg = reg_data;
+}
+
+s->phy_regs.shd = value;
+}
+
+static void bcm2838_genet_phy_exp_shadow_write(BCM2838GenetState *s,
+   uint16_t value)
+{
+/* TODO Stub implementation without side effect,
+just storing registers values */
+uint16_t reg_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+ GENET_PHY_EXP_SEL, REG_ID);
+uint16_t block_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+   GENET_PHY_EXP_SEL, BLOCK_ID);
+
+s->phy_exp_shd_regs.regs[block_id][reg_id] = value;
+}
+
+static uint16_t bcm2838_genet_phy_exp_shadow_read(BCM2838GenetState *s)
+{
+uint16_t reg_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+ GENET_PHY_EXP_SEL, REG_ID);
+uint16_t block_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+   GENET_PHY_EXP_SEL, BLOCK_ID);
+
+return s->phy_exp_shd_regs.regs[block_id][reg_id];
+}
+
+static uint64_t bcm2838_genet_mdio_cmd(BCM2838GenetState *s, uint64_t cmd)
+{
+uint32_t phy_reg_id = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, REG_ID);
+uint32_t phy_reg_data = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, REG_DATA);
+uint32_t start_busy = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, START_BUSY);
+uint32_t rd = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, RD);
+uint32_t wr = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, WR);
+uint16_t *phy_reg = (uint16_t *)>phy_regs + phy_reg_id;
+
+uint16_t anrestart = FIELD_EX16(phy_reg_data, GENET_PHY_BMCR, ANRESTART);
+
+if (start_busy != 0) {
+cmd = FIELD_DP32(cmd, GENET_UMAC_MDIO_CMD, START_BUSY, 0);
+
+if (rd != 0) {
+if (phy_reg_id == BCM2838_GENET_EXP_DATA) {
+cmd = FIELD_DP32(cmd, GENET_UMAC_MDIO_CMD, REG_DATA,
+ bcm2838_genet_phy_exp_shadow_read(s));
+} else {
+cmd = FIELD_DP32(cmd, GENET_UMAC_MDIO_CMD, REG_DATA, *phy_reg);
+}
+} else if (wr != 0) {
+if (phy_reg_id == BCM2838_GENET_PHY_AUX_CTL) {
+  

[PATCH v6 36/41] Add mailbox property tests. Part 1

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.c|   1 -
 tests/qtest/bcm2838-mbox-property-test.c | 207 +++
 tests/qtest/meson.build  |   2 +-
 3 files changed, 208 insertions(+), 2 deletions(-)
 create mode 100644 tests/qtest/bcm2838-mbox-property-test.c

diff --git a/tests/qtest/bcm2838-mailbox.c b/tests/qtest/bcm2838-mailbox.c
index 1efd3c628a..0928a3dff8 100644
--- a/tests/qtest/bcm2838-mailbox.c
+++ b/tests/qtest/bcm2838-mailbox.c
@@ -11,7 +11,6 @@
 #include "hw/registerfields.h"
 #include "libqtest-single.h"
 #include "bcm2838-mailbox.h"
-#include "hw/arm/raspberrypi-fw-defs.h"
 
 REG32(MBOX_EXCHNG_REG,  0)
 FIELD(MBOX_EXCHNG_REG, CHANNEL, 0, 4)
diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
new file mode 100644
index 00..acb421915b
--- /dev/null
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -0,0 +1,207 @@
+/*
+ * Tests set for BCM2838 mailbox property interface.
+ *
+ * Copyright (c) 2022 Auriga
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/registerfields.h"
+#include "libqtest-single.h"
+#include "bcm2838-mailbox.h"
+#include "hw/arm/raspberrypi-fw-defs.h"
+
+REG32(MBOX_SIZE_STAT,  0)
+FIELD(MBOX_SIZE_STAT, SIZE,0, 31)
+FIELD(MBOX_SIZE_STAT, SUCCESS, 31, 1)
+
+REG32(SET_POWER_STATE_CMD,0)
+FIELD(SET_POWER_STATE_CMD, EN,0, 1)
+FIELD(SET_POWER_STATE_CMD, WAIT,  1, 1)
+
+REG32(GET_CLOCK_STATE_CMD,0)
+FIELD(GET_CLOCK_STATE_CMD, EN,0, 1)
+FIELD(GET_CLOCK_STATE_CMD, NPRES, 1, 1)
+
+#define MBOX_TEST_MESSAGE_ADDRESS 0x1000
+
+#define TEST_TAG(x) RPI_FWREQ_ ## x
+#define TEST_TAG_TYPE(x) TAG_##x##_t
+
+#define TEST_FN_NAME(test, subtest) \
+test ## _ ## subtest ## _test
+
+#define SETUP_FN_NAME(test, subtest) \
+test ## _ ## subtest ## _setup
+
+#define CHECK_FN_NAME(test, subtest) \
+test ## _ ## subtest ## _spec_check
+
+#define DECLARE_TEST_CASE_SETUP(testname, ...)  \
+void SETUP_FN_NAME(testname, __VA_ARGS__)   \
+ (TEST_TAG_TYPE(testname) * tag)
+
+/**/
+#define DECLARE_TEST_CASE(testname, ...)   
\
+__attribute__((weak))  
\
+void SETUP_FN_NAME(testname, __VA_ARGS__)  
\
+  (TEST_TAG_TYPE(testname) * tag); 
\
+static void CHECK_FN_NAME(testname, __VA_ARGS__)   
\
+ (TEST_TAG_TYPE(testname) *tag);   
\
+static void TEST_FN_NAME(testname, __VA_ARGS__)(void) {
\
+struct {   
\
+MboxBufHeader header;  
\
+TEST_TAG_TYPE(testname) tag;   
\
+uint32_t end_tag;  
\
+} mailbox_buffer = { 0 };  
\
+   
\
+QTestState *qts = qtest_init("-machine raspi4b-2g");   
\
+   
\
+mailbox_buffer.header.size = sizeof(mailbox_buffer);   
\
+mailbox_buffer.header.req_resp_code = MBOX_PROCESS_REQUEST;
\
+   
\
+mailbox_buffer.tag.id = TEST_TAG(testname);
\
+mailbox_buffer.tag.value_buffer_size = MAX(
\
+sizeof(mailbox_buffer.tag.request.value),  
\
+sizeof(mailbox_buffer.tag.response.value));
\
+mailbox_buffer.tag.request.zero = 0;   
\
+   
\
+mailbox_buffer.end_tag = RPI_FWREQ_PROPERTY_END;   
\
+   
\
+if (SETUP_FN_NAME(testname, __VA_ARGS__)) {
\
+SETUP_FN_NAME(testname, __VA_ARGS__)(_buffer.tag); 
\
+}  
\
+   
\
+qtest_memwrite(qts, MBOX_

[PATCH v6 14/41] Add BCM2838 PCIE host

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_pcie.c | 217 +-
 hw/arm/trace-events   |   4 +
 include/hw/arm/bcm2838_pcie.h |  22 
 3 files changed, 241 insertions(+), 2 deletions(-)

diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c
index cb1370433e..348263d9fb 100644
--- a/hw/arm/bcm2838_pcie.c
+++ b/hw/arm/bcm2838_pcie.c
@@ -12,11 +12,220 @@
 #include "hw/irq.h"
 #include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
-#include "migration/vmstate.h"
-#include "qemu/module.h"
 #include "hw/arm/bcm2838_pcie.h"
 #include "trace.h"
 
+static uint32_t bcm2838_pcie_config_read(PCIDevice *d,
+ uint32_t address, int len)
+{
+return pci_default_read_config(d, address, len);
+}
+
+static void bcm2838_pcie_config_write(PCIDevice *d, uint32_t addr, uint32_t 
val,
+  int len)
+{
+return pci_default_write_config(d, addr, val, len);
+}
+
+static uint64_t bcm2838_pcie_host_read(void *opaque, hwaddr offset,
+   unsigned size) {
+hwaddr mmcfg_addr;
+uint64_t value = ~0;
+BCM2838PcieHostState *s = opaque;
+PCIExpressHost *pcie_hb = PCIE_HOST_BRIDGE(s);
+uint8_t *root_regs = s->root_port.regs;
+uint32_t *cfg_idx = (uint32_t *)(root_regs + BCM2838_PCIE_EXT_CFG_INDEX
+ - PCIE_CONFIG_SPACE_SIZE);
+
+if (offset - PCIE_CONFIG_SPACE_SIZE + size <= sizeof(s->root_port.regs)) {
+switch (offset) {
+case BCM2838_PCIE_EXT_CFG_DATA
+... BCM2838_PCIE_EXT_CFG_DATA + PCIE_CONFIG_SPACE_SIZE - 1:
+mmcfg_addr = *cfg_idx
+| PCIE_MMCFG_CONFOFFSET(offset - BCM2838_PCIE_EXT_CFG_DATA);
+value = pcie_hb->mmio.ops->read(opaque, mmcfg_addr, size);
+break;
+default:
+memcpy(, root_regs + offset - PCIE_CONFIG_SPACE_SIZE, size);
+}
+} else {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
+
+trace_bcm2838_pcie_host_read(size, offset, value);
+return value;
+}
+
+static void bcm2838_pcie_host_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size) {
+hwaddr mmcfg_addr;
+BCM2838PcieHostState *s = opaque;
+PCIExpressHost *pcie_hb = PCIE_HOST_BRIDGE(s);
+uint8_t *root_regs = s->root_port.regs;
+uint32_t *cfg_idx = (uint32_t *)(root_regs + BCM2838_PCIE_EXT_CFG_INDEX
+ - PCIE_CONFIG_SPACE_SIZE);
+
+trace_bcm2838_pcie_host_write(size, offset, value);
+
+if (offset - PCIE_CONFIG_SPACE_SIZE + size <= sizeof(s->root_port.regs)) {
+switch (offset) {
+case BCM2838_PCIE_EXT_CFG_DATA
+... BCM2838_PCIE_EXT_CFG_DATA + PCIE_CONFIG_SPACE_SIZE - 1:
+mmcfg_addr = *cfg_idx
+| PCIE_MMCFG_CONFOFFSET(offset - BCM2838_PCIE_EXT_CFG_DATA);
+pcie_hb->mmio.ops->write(opaque, mmcfg_addr, value, size);
+break;
+default:
+memcpy(root_regs + offset - PCIE_CONFIG_SPACE_SIZE, , size);
+}
+} else {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
+}
+
+static const MemoryRegionOps bcm2838_pcie_host_ops = {
+.read = bcm2838_pcie_host_read,
+.write = bcm2838_pcie_host_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {.max_access_size = sizeof(uint64_t)},
+};
+
+int bcm2838_pcie_host_set_irq_num(BCM2838PcieHostState *s, int index, int spi)
+{
+if (index >= BCM2838_PCIE_NUM_IRQS) {
+return -EINVAL;
+}
+
+s->irq_num[index] = spi;
+return 0;
+}
+
+static void bcm2838_pcie_host_set_irq(void *opaque, int irq_num, int level)
+{
+BCM2838PcieHostState *s = opaque;
+
+qemu_set_irq(s->irq[irq_num], level);
+}
+
+static PCIINTxRoute bcm2838_pcie_host_route_intx_pin_to_irq(void *opaque,
+int pin)
+{
+PCIINTxRoute route;
+BCM2838PcieHostState *s = opaque;
+
+route.irq = s->irq_num[pin];
+route.mode = route.irq < 0 ? PCI_INTX_DISABLED : PCI_INTX_ENABLED;
+
+return route;
+}
+
+static int bcm2838_pcie_host_map_irq(PCIDevice *pci_dev, int pin)
+{
+return pin;
+}
+
+static void bcm2838_pcie_host_realize(DeviceState *dev, Error **errp)
+{
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+BCM2838PcieHostState *s = BCM2838_PCIE_HOST(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+int i;
+
+memory_region_init_io(>cfg_regs, OBJECT(s), _pcie_host_ops, s,
+

[PATCH v6 34/41] Add mailbox tests tags. Part 2

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 152 ++
 1 file changed, 152 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 1360fbb8cf..b4f7b7b314 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -294,6 +294,158 @@ 
DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT_t,
 uint32_t height;
 });
 
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_DEPTH_t,
+struct {},
+struct {
+uint32_t bpp;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_DEPTH_t,
+struct {
+uint32_t bpp;
+},
+struct {
+uint32_t bpp;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_DEPTH_t,
+struct {
+uint32_t bpp;
+},
+struct {
+uint32_t bpp;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_PIXEL_ORDER_t,
+struct {},
+struct {
+uint32_t pixel_order;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_PIXEL_ORDER_t,
+struct {
+uint32_t pixel_order;
+},
+struct {
+uint32_t pixel_order;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_PIXEL_ORDER_t,
+struct {
+uint32_t pixel_order;
+},
+struct {
+uint32_t pixel_order;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_ALPHA_MODE_t,
+struct {},
+struct {
+uint32_t alpha_mode;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_ALPHA_MODE_t,
+struct {
+uint32_t alpha_mode;
+},
+struct {
+uint32_t alpha_mode;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_ALPHA_MODE_t,
+struct {
+uint32_t alpha_mode;
+},
+struct {
+uint32_t alpha_mode;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_PITCH_t,
+struct {},
+struct {
+uint32_t pitch;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_PITCH_t,
+struct {
+uint32_t pitch;
+},
+struct {});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_VIRTUAL_OFFSET_t,
+struct {},
+struct {
+uint32_t x;
+uint32_t y;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_VIRTUAL_OFFSET_t,
+struct {
+uint32_t x;
+uint32_t y;
+},
+struct {
+uint32_t x;
+uint32_t y;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_VIRTUAL_OFFSET_t,
+struct {
+uint32_t x;
+uint32_t y;
+},
+struct {
+uint32_t x;
+uint32_t y;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_OVERSCAN_t,
+struct {},
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_OVERSCAN_t,
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+},
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_OVERSCAN_t,
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+},
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_COMMAND_LINE_t,
+struct {},
+struct {});
+
+DECLARE_TAG_TYPE(TAG_GET_DMA_CHANNELS_t,
+struct {},
+struct {
+uint32_t mask;
+});
+
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
 void mbox1_write_message(uint8_t channel, uint32_t msg_addr);
-- 
2.34.1




[PATCH v6 08/41] Connect SD controller to BCM2838 GPIO

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/gpio/bcm2838_gpio.c | 52 +-
 include/hw/gpio/bcm2838_gpio.h |  5 
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/hw/gpio/bcm2838_gpio.c b/hw/gpio/bcm2838_gpio.c
index 69d15dbb49..2ddf62f695 100644
--- a/hw/gpio/bcm2838_gpio.c
+++ b/hw/gpio/bcm2838_gpio.c
@@ -17,6 +17,7 @@
 #include "qapi/error.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
+#include "hw/sd/sd.h"
 #include "hw/gpio/bcm2838_gpio.h"
 #include "hw/irq.h"
 
@@ -63,6 +64,16 @@
 
 #define BYTES_IN_WORD4
 
+/* bcm,function property */
+#define BCM2838_FSEL_GPIO_IN0
+#define BCM2838_FSEL_GPIO_OUT   1
+#define BCM2838_FSEL_ALT5   2
+#define BCM2838_FSEL_ALT4   3
+#define BCM2838_FSEL_ALT0   4
+#define BCM2838_FSEL_ALT1   5
+#define BCM2838_FSEL_ALT2   6
+#define BCM2838_FSEL_ALT3   7
+
 static uint32_t gpfsel_get(BCM2838GpioState *s, uint8_t reg)
 {
 int i;
@@ -86,6 +97,31 @@ static void gpfsel_set(BCM2838GpioState *s, uint8_t reg, 
uint32_t value)
 s->fsel[index] = fsel;
 }
 }
+
+/* SD controller selection (48-53) */
+if (s->sd_fsel != BCM2838_FSEL_GPIO_IN
+&& (s->fsel[48] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[49] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[50] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[51] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[52] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[53] == BCM2838_FSEL_GPIO_IN)
+   ) {
+/* SDHCI controller selected */
+sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
+s->sd_fsel = BCM2838_FSEL_GPIO_IN;
+} else if (s->sd_fsel != BCM2838_FSEL_ALT0
+   && (s->fsel[48] == BCM2838_FSEL_ALT0) /* SD_CLK_R */
+   && (s->fsel[49] == BCM2838_FSEL_ALT0) /* SD_CMD_R */
+   && (s->fsel[50] == BCM2838_FSEL_ALT0) /* SD_DATA0_R */
+   && (s->fsel[51] == BCM2838_FSEL_ALT0) /* SD_DATA1_R */
+   && (s->fsel[52] == BCM2838_FSEL_ALT0) /* SD_DATA2_R */
+   && (s->fsel[53] == BCM2838_FSEL_ALT0) /* SD_DATA3_R */
+  ) {
+/* SDHost controller selected */
+sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
+s->sd_fsel = BCM2838_FSEL_ALT0;
+}
 }
 
 static int gpfsel_is_out(BCM2838GpioState *s, int index)
@@ -266,6 +302,11 @@ static void bcm2838_gpio_reset(DeviceState *dev)
 
 memset(s->fsel, 0, sizeof(s->fsel));
 
+s->sd_fsel = 0;
+
+/* SDHCI is selected by default */
+sdbus_reparent_card(>sdbus, s->sdbus_sdhci);
+
 s->lev0 = 0;
 s->lev1 = 0;
 
@@ -304,6 +345,8 @@ static void bcm2838_gpio_init(Object *obj)
 DeviceState *dev = DEVICE(obj);
 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
+qbus_init(>sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(s), "sd-bus");
+
 memory_region_init_io(>iomem, obj, _gpio_ops, s,
   "bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
 sysbus_init_mmio(sbd, >iomem);
@@ -312,7 +355,14 @@ static void bcm2838_gpio_init(Object *obj)
 
 static void bcm2838_gpio_realize(DeviceState *dev, Error **errp)
 {
-/* Temporary stub. Do nothing */
+BCM2838GpioState *s = BCM2838_GPIO(dev);
+Object *obj;
+
+obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", _abort);
+s->sdbus_sdhci = SD_BUS(obj);
+
+obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", _abort);
+s->sdbus_sdhost = SD_BUS(obj);
 }
 
 static void bcm2838_gpio_class_init(ObjectClass *klass, void *data)
diff --git a/include/hw/gpio/bcm2838_gpio.h b/include/hw/gpio/bcm2838_gpio.h
index 06d48e0c19..f2a57a697f 100644
--- a/include/hw/gpio/bcm2838_gpio.h
+++ b/include/hw/gpio/bcm2838_gpio.h
@@ -14,6 +14,7 @@
 #ifndef BCM2838_GPIO_H
 #define BCM2838_GPIO_H
 
+#include "hw/sd/sd.h"
 #include "hw/sysbus.h"
 #include "qom/object.h"
 
@@ -29,6 +30,10 @@ struct BCM2838GpioState {
 
 MemoryRegion iomem;
 
+/* SDBus selector */
+SDBus sdbus;
+SDBus *sdbus_sdhci;
+SDBus *sdbus_sdhost;
 
 uint8_t fsel[BCM2838_GPIO_NUM];
 uint32_t lev0, lev1;
-- 
2.34.1




[PATCH v6 37/41] Add mailbox property tests. Part 2

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 196 ++-
 1 file changed, 195 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index acb421915b..b251d3f552 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -50,7 +50,8 @@ FIELD(GET_CLOCK_STATE_CMD, NPRES, 1, 1)
   (TEST_TAG_TYPE(testname) * tag); 
\
 static void CHECK_FN_NAME(testname, __VA_ARGS__)   
\
  (TEST_TAG_TYPE(testname) *tag);   
\
-static void TEST_FN_NAME(testname, __VA_ARGS__)(void) {
\
+static void TEST_FN_NAME(testname, __VA_ARGS__)(void)  
\
+{  
\
 struct {   
\
 MboxBufHeader header;  
\
 TEST_TAG_TYPE(testname) tag;   
\
@@ -189,6 +190,179 @@ DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, EMMC) {
 }
 
 
/**/
+DECLARE_TEST_CASE(GET_CLOCK_RATE, UART) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UART);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_UART);
+}
+DECLARE_TEST_CASE_SETUP(GET_CLOCK_RATE, UART) {
+tag->request.value.clock_id = CLOCK_ID_UART;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MAX_CLOCK_RATE, UART) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UART);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_UART);
+}
+DECLARE_TEST_CASE_SETUP(GET_MAX_CLOCK_RATE, UART) {
+tag->request.value.clock_id = CLOCK_ID_UART;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MIN_CLOCK_RATE, UART) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UART);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_UART);
+}
+DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, UART) {
+tag->request.value.clock_id = CLOCK_ID_UART;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_CLOCK_RATE, CORE) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_CORE);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_CORE);
+}
+DECLARE_TEST_CASE_SETUP(GET_CLOCK_RATE, CORE) {
+tag->request.value.clock_id = CLOCK_ID_CORE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MAX_CLOCK_RATE, CORE) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_CORE);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_CORE);
+}
+DECLARE_TEST_CASE_SETUP(GET_MAX_CLOCK_RATE, CORE) {
+tag->request.value.clock_id = CLOCK_ID_CORE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MIN_CLOCK_RATE, CORE) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_CORE);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_CORE);
+}
+DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, CORE) {
+tag->request.value.clock_id = CLOCK_ID_CORE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_CLOCK_RATE, ANY) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UNDEFINED);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_ANY);
+}
+DECLARE_TEST_CASE_SETUP(GET_CLOCK_RATE, ANY) {
+tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MAX_CLOCK_RATE, ANY) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UNDEFINED);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_ANY);
+}
+DECLARE_TEST_CASE_SETUP(GET_MAX_CLOCK_RATE, ANY) {
+tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MIN_CLOCK_RATE, ANY) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UNDEFINED);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_ANY);
+}
+DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, ANY) {
+tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_TEMPERATURE) {
+g_assert_cmphex(tag->response.value.temperature_id, ==, 
TEMPERATURE_ID_SOC);
+g_assert_cmpin

[PATCH v6 21/41] Add GENET register structs. Part 2

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 89 ++
 include/hw/net/bcm2838_genet.h | 89 ++
 2 files changed, 178 insertions(+)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 0d98d1b30e..9a99f34c4a 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -19,6 +19,7 @@
 #include "hw/net/bcm2838_genet.h"
 #include "trace.h"
 
+/* GENET layouts */
 REG32(GENET_SYS_REV_CTRL,  0)
 FIELD(GENET_SYS_REV_CTRL, GPHY_REV,0, 16)
 FIELD(GENET_SYS_REV_CTRL, MINOR_REV,   16, 4)
@@ -55,6 +56,94 @@ REG32(GENET_INTRL_1,  0)
 FIELD(GENET_INTRL_1, TX_INTRS,0, 16)
 FIELD(GENET_INTRL_1, RX_INTRS,16, 16)
 
+REG32(GENET_UMAC_CMD,  0)
+FIELD(GENET_UMAC_CMD, TX_EN,   0, 1)
+FIELD(GENET_UMAC_CMD, RX_EN,   1, 1)
+FIELD(GENET_UMAC_CMD, SPEED,   2, 2)
+FIELD(GENET_UMAC_CMD, PROMISC, 4, 1)
+FIELD(GENET_UMAC_CMD, PAD_EN,  5, 1)
+FIELD(GENET_UMAC_CMD, CRC_FWD, 6, 1)
+FIELD(GENET_UMAC_CMD, PAUSE_FWD,   7, 1)
+FIELD(GENET_UMAC_CMD, RX_PAUSE_IGNORE, 8, 1)
+FIELD(GENET_UMAC_CMD, TX_ADDR_INS, 9, 1)
+FIELD(GENET_UMAC_CMD, HD_EN,   10, 1)
+FIELD(GENET_UMAC_CMD, SW_RESET_OLD,11, 1)
+FIELD(GENET_UMAC_CMD, RSVD_12, 12, 1)
+FIELD(GENET_UMAC_CMD, SW_RESET,13, 1)
+FIELD(GENET_UMAC_CMD, RSVD_14, 14, 1)
+FIELD(GENET_UMAC_CMD, LCL_LOOP_EN, 15, 1)
+FIELD(GENET_UMAC_CMD, RSVD_16_21,  16, 6)
+FIELD(GENET_UMAC_CMD, AUTO_CONFIG, 22, 1)
+FIELD(GENET_UMAC_CMD, CNTL_FRM_EN, 23, 1)
+FIELD(GENET_UMAC_CMD, NO_LEN_CHK,  24, 1)
+FIELD(GENET_UMAC_CMD, RMT_LOOP_EN, 25, 1)
+FIELD(GENET_UMAC_CMD, RX_ERR_DISC, 26, 1)
+FIELD(GENET_UMAC_CMD, PRBL_EN, 27, 1)
+FIELD(GENET_UMAC_CMD, TX_PAUSE_IGNORE, 28, 1)
+FIELD(GENET_UMAC_CMD, TX_RX_EN,29, 1)
+FIELD(GENET_UMAC_CMD, RUNT_FILTER_DIS, 30, 1)
+FIELD(GENET_UMAC_CMD, RSVD_31, 31, 1)
+
+REG32(GENET_UMAC_MAC_0, 0)
+FIELD(GENET_UMAC_MAC_0, ADDR_3, 0,  8)
+FIELD(GENET_UMAC_MAC_0, ADDR_2, 8,  8)
+FIELD(GENET_UMAC_MAC_0, ADDR_1, 16, 8)
+FIELD(GENET_UMAC_MAC_0, ADDR_0, 24, 8)
+
+REG32(GENET_UMAC_MAC_1, 0)
+FIELD(GENET_UMAC_MAC_1, ADDR_5, 0,  8)
+FIELD(GENET_UMAC_MAC_1, ADDR_4, 8,  8)
+FIELD(GENET_UMAC_MAC_1, RSVD_16_31, 16, 8)
+
+REG32(GENET_UMAC_MDIO_CMD, 0)
+FIELD(GENET_UMAC_MDIO_CMD, REG_DATA,   0, 16)
+FIELD(GENET_UMAC_MDIO_CMD, REG_ID, 16, 5)
+FIELD(GENET_UMAC_MDIO_CMD, PHY_ID, 21, 5)
+FIELD(GENET_UMAC_MDIO_CMD, WR, 26, 1)
+FIELD(GENET_UMAC_MDIO_CMD, RD, 27, 1)
+FIELD(GENET_UMAC_MDIO_CMD, RD_FAIL,28, 1)
+FIELD(GENET_UMAC_MDIO_CMD, START_BUSY, 29, 1)
+FIELD(GENET_UMAC_MDIO_CMD, RSVD_30_31, 30, 2)
+
+REG32(GENET_DMA_RING_CFG, 0)
+FIELD(GENET_DMA_RING_CFG, EN, 0, 17)
+FIELD(GENET_DMA_RING_CFG, RSVD_17_31, 17, 14)
+
+REG32(GENET_DMA_CTRL,  0)
+FIELD(GENET_DMA_CTRL, EN,  0, 1)
+FIELD(GENET_DMA_CTRL, RING_BUF_EN, 1, 17)
+FIELD(GENET_DMA_CTRL, RSVD_18_19,  18, 2)
+FIELD(GENET_DMA_CTRL, TSB_SWAP_EN, 20, 1)
+FIELD(GENET_DMA_CTRL, RSVD_21_31,  21, 11)
+
+REG32(GENET_DMA_PROD_INDEX,  0)
+FIELD(GENET_DMA_PROD_INDEX, INDEX,   0, 16)
+FIELD(GENET_DMA_PROD_INDEX, DISCARD_CNT, 16, 16)
+
+REG32(GENET_DMA_CONS_INDEX, 0)
+FIELD(GENET_DMA_CONS_INDEX, INDEX,  0, 16)
+FIELD(GENET_DMA_CONS_INDEX, RSVD_16_31, 16, 16)
+
+REG32(GENET_DMA_STATUS, 0)
+FIELD(GENET_DMA_STATUS, DISABLED,   0, 1)
+FIELD(GENET_DMA_STATUS, DESC_RAM_INIT_BUSY, 1, 1)
+FIELD(GENET_DMA_STATUS, RSVD_2_31,  2, 30)
+
+REG32(GENET_RDMA_LENGTH_STATUS, 0)
+FIELD(GENET_RDMA_LENGTH_STATUS, OVERRUN,0, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, CRC_ERROR,  1, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, RXERR,  2, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, NO, 3, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, LG, 4, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, MULTICAST,  5, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, BROADCAST,  6, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_7_11,  7, 5)
+FIELD(GENET_RDMA_LENGTH_STATUS, WRAP,   12, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, SOP,13, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, EOP,14, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, OWN,15, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
+FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
 
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index f583818399..736b4d1757 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -18,6 +18,10 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_REV_MAJOR 6
 #define BCM2838_GENET_REV_MINOR 0
 
+#define BCM2838_GENET_DMA_DESC_CNT  256
+#define BCM2838_GENET_DMA_RING_

[PATCH v6 25/41] Implement GENET register ops

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 189 +++--
 include/hw/net/bcm2838_genet.h |   2 +
 2 files changed, 182 insertions(+), 9 deletions(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index be899b68f8..56ff6a6f39 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -233,25 +233,144 @@ REG16(GENET_PHY_EXP_SEL,   0)
 FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
 FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
 
+static void bcm2838_genet_set_qemu_mac(BCM2838GenetState *s)
+{
+const MACAddr *addr = >nic_conf.macaddr;
+
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_0, addr->a[0]);
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_1, addr->a[1]);
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_2, addr->a[2]);
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_3, addr->a[3]);
+s->regs.umac.mac1 = FIELD_DP32(s->regs.umac.mac1, GENET_UMAC_MAC_1,
+   ADDR_4, addr->a[4]);
+s->regs.umac.mac1 = FIELD_DP32(s->regs.umac.mac1, GENET_UMAC_MAC_1,
+   ADDR_5, addr->a[5]);
+}
+
+static void bcm2838_genet_set_irq_default(BCM2838GenetState *s)
+{
+uint32_t intrl_0_status = s->regs.intrl0.stat;
+uint32_t intrl_0_mask = s->regs.intrl0.mask_status;
+int level = (intrl_0_status & ~intrl_0_mask) == 0 ? 0 : 1;
+
+qemu_set_irq(s->irq_default, level);
+}
+
+static void bcm2838_genet_set_irq_prio(BCM2838GenetState *s)
+{
+uint32_t intrl_1_status = s->regs.intrl1.stat;
+uint32_t intrl_1_mask = s->regs.intrl1.mask_status;
+int level = (intrl_1_status & ~intrl_1_mask) == 0 ? 0 : 1;
+
+qemu_set_irq(s->irq_prio, level);
+}
+
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
 uint64_t value = ~0;
+BCM2838GenetState *s = opaque;
 
-qemu_log_mask(
-LOG_GUEST_ERROR,
-"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
-__func__, size, offset);
+if (offset + size < sizeof(s->regs)) {
+memcpy(, (uint8_t *)>regs + offset, size);
+} else {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
 
 trace_bcm2838_genet_read(size, offset, value);
 return value;
 }
 
 static void bcm2838_genet_write(void *opaque, hwaddr offset, uint64_t value,
-unsigned size) {
-qemu_log_mask(
-LOG_GUEST_ERROR,
-"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
-__func__, size, offset);
+unsigned size)
+{
+BCM2838GenetState *s = opaque;
+MACAddr *mac = >nic_conf.macaddr;
+NetClientState *ncs = qemu_get_queue(s->nic);
+
+trace_bcm2838_genet_write(size, offset, value);
+
+if (offset + size < sizeof(s->regs)) {
+switch (offset) {
+case BCM2838_GENET_INTRL0_SET:
+s->regs.intrl0.stat |= value;
+break;
+case BCM2838_GENET_INTRL0_CLEAR:
+s->regs.intrl0.stat &= ~value;
+break;
+case BCM2838_GENET_INTRL0_MASK_SET:
+s->regs.intrl0.mask_status |= value;
+break;
+case BCM2838_GENET_INTRL0_MASK_CLEAR:
+s->regs.intrl0.mask_status &= ~value;
+break;
+case BCM2838_GENET_INTRL1_SET:
+s->regs.intrl1.stat |= value;
+break;
+case BCM2838_GENET_INTRL1_CLEAR:
+s->regs.intrl1.stat &= ~value;
+break;
+case BCM2838_GENET_INTRL1_MASK_SET:
+s->regs.intrl1.mask_status |= value;
+break;
+case BCM2838_GENET_INTRL1_MASK_CLEAR:
+s->regs.intrl1.mask_status &= ~value;
+break;
+case BCM2838_GENET_UMAC_CMD:
+/* Complete SW reset as soon as it has been requested */
+if (FIELD_EX32(value, GENET_UMAC_CMD, SW_RESET) == 1) {
+device_cold_reset(DEVICE(s));
+value = FIELD_DP32(value, GENET_UMAC_CMD, SW_RESET, 0);
+}
+break;
+/*
+ * TODO: before changing MAC address we'd better inform QEMU
+ * network subsystem about freeing previously used one, but
+ * qemu_macaddr_set_free function isn't accessible for us (marked
+ * as static in net/net.c), see also https://lists.nongnu.org/
+ * archive/html/qemu-devel/2022-07

[PATCH v6 31/41] Add mailbox test stub

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.c | 60 +++
 tests/qtest/bcm2838-mailbox.h | 37 +
 tests/qtest/meson.build   |  1 +
 3 files changed, 98 insertions(+)
 create mode 100644 tests/qtest/bcm2838-mailbox.c
 create mode 100644 tests/qtest/bcm2838-mailbox.h

diff --git a/tests/qtest/bcm2838-mailbox.c b/tests/qtest/bcm2838-mailbox.c
new file mode 100644
index 00..0928a3dff8
--- /dev/null
+++ b/tests/qtest/bcm2838-mailbox.c
@@ -0,0 +1,60 @@
+/*
+ * Helper functions to work with BCM2838 mailbox via qtest interface.
+ *
+ * Copyright (c) 2023 Auriga LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/registerfields.h"
+#include "libqtest-single.h"
+#include "bcm2838-mailbox.h"
+
+REG32(MBOX_EXCHNG_REG,  0)
+FIELD(MBOX_EXCHNG_REG, CHANNEL, 0, 4)
+FIELD(MBOX_EXCHNG_REG, DATA,4, 28)
+
+static uint32_t qtest_mbox0_read_reg32(QTestState *s, uint32_t offset)
+{
+return qtest_readl(s, MBOX0_BASE + offset);
+}
+
+static void qtest_mbox1_write_reg32(QTestState *s, uint32_t offset, uint32_t 
value)
+{
+return qtest_writel(s, MBOX1_BASE + offset, value);
+}
+
+static void qtest_mbox1_write(QTestState *s, uint8_t channel, uint32_t data)
+{
+uint32_t mbox_reg = 0;
+
+mbox_reg = FIELD_DP32(mbox_reg, MBOX_EXCHNG_REG, CHANNEL, channel);
+mbox_reg = FIELD_DP32(mbox_reg, MBOX_EXCHNG_REG, DATA, data);
+qtest_mbox1_write_reg32(s, MBOX_REG_WRITE, mbox_reg);
+}
+
+int qtest_mbox0_has_data(QTestState *s) {
+return !(qtest_mbox0_read_reg32(s, MBOX_REG_STATUS) & MBOX_READ_EMPTY);
+}
+
+void qtest_mbox0_read_message(QTestState *s,
+  uint8_t channel,
+  void *msgbuf,
+  size_t msgbuf_size)
+{
+uint32_t mbox_reg;
+uint32_t msgaddr;
+
+g_assert(qtest_mbox0_has_data(s));
+mbox_reg = qtest_mbox0_read_reg32(s, MBOX_REG_READ);
+g_assert_cmphex(FIELD_EX32(mbox_reg, MBOX_EXCHNG_REG, CHANNEL), ==, 
channel);
+msgaddr = FIELD_EX32(mbox_reg, MBOX_EXCHNG_REG, DATA) << 4;
+qtest_memread(s, msgaddr, msgbuf, msgbuf_size);
+}
+
+void qtest_mbox1_write_message(QTestState *s, uint8_t channel, uint32_t 
msg_addr)
+{
+qtest_mbox1_write(s, channel, msg_addr >> 4);
+}
diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
new file mode 100644
index 00..e9e1f53bc9
--- /dev/null
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -0,0 +1,37 @@
+/*
+ * Declarations for BCM2838 mailbox test.
+ *
+ * Copyright (c) 2023 Auriga LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+typedef struct {
+uint32_t size;
+uint32_t req_resp_code;
+} MboxBufHeader;
+
+#define DECLARE_TAG_TYPE(TypeName, RequestValueType, ResponseValueType) \
+typedef struct {\
+uint32_t id;\
+uint32_t value_buffer_size; \
+union { \
+struct {\
+uint32_t zero;  \
+RequestValueType value; \
+} request;  \
+struct {\
+uint32_t size_stat; \
+ResponseValueType value;\
+} response; \
+};  \
+} TypeName
+
+
+int mbox0_has_data(void);
+void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
+void mbox1_write_message(uint8_t channel, uint32_t msg_addr);
+int qtest_mbox0_has_data(QTestState *s);
+void qtest_mbox0_read_message(QTestState *s, uint8_t channel, void *msgbuf, 
size_t msgbuf_size);
+void qtest_mbox1_write_message(QTestState *s, uint8_t channel, uint32_t 
msg_addr);
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 6ea77893f5..e49ce4f092 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -334,6 +334,7 @@ qtests = {
   'virtio-net-failover': files('migration-helpers.c'),
   'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
   'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'),
+  'bcm2838-mbox-property-test' : files('bcm2838-mailbox.c'),
 }
 
 if vnc.found()
-- 
2.34.1




[PATCH v6 07/41] Implement BCM2838 GPIO functionality

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/gpio/bcm2838_gpio.c | 193 -
 1 file changed, 190 insertions(+), 3 deletions(-)

diff --git a/hw/gpio/bcm2838_gpio.c b/hw/gpio/bcm2838_gpio.c
index a312490bbd..69d15dbb49 100644
--- a/hw/gpio/bcm2838_gpio.c
+++ b/hw/gpio/bcm2838_gpio.c
@@ -18,6 +18,7 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "hw/gpio/bcm2838_gpio.h"
+#include "hw/irq.h"
 
 #define GPFSEL0   0x00
 #define GPFSEL1   0x04
@@ -56,14 +57,139 @@
 #define RESET_VAL_CNTRL_REG2 0x50AAA95A
 #define RESET_VAL_CNTRL_REG3 0x0005
 
+#define NUM_FSELN_IN_GPFSELN 10
+#define NUM_BITS_FSELN   3
+#define MASK_FSELN   0x7
+
 #define BYTES_IN_WORD4
 
+static uint32_t gpfsel_get(BCM2838GpioState *s, uint8_t reg)
+{
+int i;
+uint32_t value = 0;
+for (i = 0; i < NUM_FSELN_IN_GPFSELN; i++) {
+uint32_t index = NUM_FSELN_IN_GPFSELN * reg + i;
+if (index < sizeof(s->fsel)) {
+value |= (s->fsel[index] & MASK_FSELN) << (NUM_BITS_FSELN * i);
+}
+}
+return value;
+}
+
+static void gpfsel_set(BCM2838GpioState *s, uint8_t reg, uint32_t value)
+{
+int i;
+for (i = 0; i < NUM_FSELN_IN_GPFSELN; i++) {
+uint32_t index = NUM_FSELN_IN_GPFSELN * reg + i;
+if (index < sizeof(s->fsel)) {
+int fsel = (value >> (NUM_BITS_FSELN * i)) & MASK_FSELN;
+s->fsel[index] = fsel;
+}
+}
+}
+
+static int gpfsel_is_out(BCM2838GpioState *s, int index)
+{
+if (index >= 0 && index < BCM2838_GPIO_NUM) {
+return s->fsel[index] == 1;
+}
+return 0;
+}
+
+static void gpset(BCM2838GpioState *s, uint32_t val, uint8_t start,
+  uint8_t count, uint32_t *lev)
+{
+uint32_t changes = val & ~*lev;
+uint32_t cur = 1;
+
+int i;
+for (i = 0; i < count; i++) {
+if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
+qemu_set_irq(s->out[start + i], 1);
+}
+cur <<= 1;
+}
+
+*lev |= val;
+}
+
+static void gpclr(BCM2838GpioState *s, uint32_t val, uint8_t start,
+  uint8_t count, uint32_t *lev)
+{
+uint32_t changes = val & *lev;
+uint32_t cur = 1;
+
+int i;
+for (i = 0; i < count; i++) {
+if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
+qemu_set_irq(s->out[start + i], 0);
+}
+cur <<= 1;
+}
+
+*lev &= ~val;
+}
+
 static uint64_t bcm2838_gpio_read(void *opaque, hwaddr offset, unsigned size)
 {
+BCM2838GpioState *s = (BCM2838GpioState *)opaque;
 uint64_t value = 0;
 
-qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
-  TYPE_BCM2838_GPIO, __func__, offset);
+switch (offset) {
+case GPFSEL0:
+case GPFSEL1:
+case GPFSEL2:
+case GPFSEL3:
+case GPFSEL4:
+case GPFSEL5:
+value = gpfsel_get(s, offset / BYTES_IN_WORD);
+break;
+case GPSET0:
+case GPSET1:
+case GPCLR0:
+case GPCLR1:
+/* Write Only */
+qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Attempt reading from write 
only"
+  " register. 0x%"PRIx64" will be returned."
+  " Address 0x%"HWADDR_PRIx", size %u\n",
+  TYPE_BCM2838_GPIO, __func__, value, offset, size);
+break;
+case GPLEV0:
+value = s->lev0;
+break;
+case GPLEV1:
+value = s->lev1;
+break;
+case GPEDS0:
+case GPEDS1:
+case GPREN0:
+case GPREN1:
+case GPFEN0:
+case GPFEN1:
+case GPHEN0:
+case GPHEN1:
+case GPLEN0:
+case GPLEN1:
+case GPAREN0:
+case GPAREN1:
+case GPAFEN0:
+case GPAFEN1:
+/* Not implemented */
+qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for 
%"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+break;
+case GPIO_PUP_PDN_CNTRL_REG0:
+case GPIO_PUP_PDN_CNTRL_REG1:
+case GPIO_PUP_PDN_CNTRL_REG2:
+case GPIO_PUP_PDN_CNTRL_REG3:
+value = s->pup_cntrl_reg[(offset - GPIO_PUP_PDN_CNTRL_REG0)
+ / sizeof(s->pup_cntrl_reg[0])];
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: bad offset %"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+break;
+}
 
 return value;
 }
@@ -71,14 +197,75 @@ static uint64_t bcm2838_gpio_read(void *opaque, hwaddr 
offset, unsigned size)
 static void bcm2838_gpio_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
 {
-qemu_log_mask

[PATCH v6 32/41] Add mailbox test constants

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.c |  1 +
 tests/qtest/bcm2838-mailbox.h | 88 +++
 2 files changed, 89 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.c b/tests/qtest/bcm2838-mailbox.c
index 0928a3dff8..1efd3c628a 100644
--- a/tests/qtest/bcm2838-mailbox.c
+++ b/tests/qtest/bcm2838-mailbox.c
@@ -11,6 +11,7 @@
 #include "hw/registerfields.h"
 #include "libqtest-single.h"
 #include "bcm2838-mailbox.h"
+#include "hw/arm/raspberrypi-fw-defs.h"
 
 REG32(MBOX_EXCHNG_REG,  0)
 FIELD(MBOX_EXCHNG_REG, CHANNEL, 0, 4)
diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index e9e1f53bc9..9222b38bad 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -7,6 +7,94 @@
  * See the COPYING file in the top-level directory.
  */
 
+#define MBOX0_BASE 0xFE00B880
+#define MBOX1_BASE 0xFE00B8A0
+
+#define MBOX_REG_READ   0x00
+#define MBOX_REG_WRITE  0x00
+#define MBOX_REG_PEEK   0x10
+#define MBOX_REG_SENDER 0x14
+#define MBOX_REG_STATUS 0x18
+#define MBOX_REG_CONFIG 0x1C
+
+#define MBOX_READ_EMPTY 0x4000
+
+#define MBOX_CHANNEL_ID_PROPERTY 8
+
+#define MBOX_PROCESS_REQUEST  0x
+#define MBOX_SUCCESS  0x8000
+#define MBOX_ERROR_PARSING_BUFFER 0x8001
+
+#define BOARD_REVISION0xB03115
+#define FIRMWARE_REVISION 0x548E1
+#define FIRMWARE_VARIANT  0x /* TODO: Find the real value */
+
+#define ARM_MEMORY_BASE 0x
+#define ARM_MEMORY_SIZE 0x3c00
+#define VC_MEMORY_BASE  0x3c00
+#define VC_MEMORY_SIZE  0x0400
+#define VC_FB_BASE  0x3c10
+#define VC_FB_SIZE  0x00096000
+
+#define CLOCK_ID_ROOT  0x
+#define CLOCK_ID_EMMC  0x0001
+#define CLOCK_ID_UART  0x0002
+#define CLOCK_ID_ARM   0x0003
+#define CLOCK_ID_CORE  0x0004
+#define CLOCK_ID_UNDEFINED 0x12345678
+
+#define CLOCK_RATE_EMMC 5000
+#define CLOCK_RATE_UART 300
+#define CLOCK_RATE_CORE 35000
+#define CLOCK_RATE_ANY  7
+
+#define DEVICE_ID_SD_CARD   0x
+#define DEVICE_ID_UART0 0x0001
+#define DEVICE_ID_UART1 0x0002
+#define DEVICE_ID_USB HCD   0x0003
+#define DEVICE_ID_I2C0  0x0004
+#define DEVICE_ID_I2C1  0x0005
+#define DEVICE_ID_I2C2  0x0006
+#define DEVICE_ID_SPI   0x0007
+#define DEVICE_ID_CCP2TX0x0008
+#define DEVICE_ID_UNKNOWN_0 0x0009
+#define DEVICE_ID_UNKNOWN_1 0x000a
+
+#define TEMPERATURE_ID_SOC 0x
+
+#define TEMPERATURE_SOC 25000
+#define TEMPERATURE_SOC_MAX 99000
+
+#define ALIGN_4K 4096
+
+#define PIXEL_ORDER_BGR 0
+#define PIXEL_ORDER_RGB 1
+
+#define ALPHA_MODE_ENABLED  0
+#define ALPHA_MODE_REVERSED 1
+#define ALPHA_MODE_IGNORED  2
+
+#define GPIO_MASK 0x003c
+
+#define GPIO_0 0x0080
+
+#define GPIO_DIRECTION_IN  0
+#define GPIO_DIRECTION_OUT 1
+
+#define GPIO_TERMINATION_DISABLED 0
+#define GPIO_TERMINATION_ENABLED  1
+
+#define GPIO_TERMINATION_PULLUP_DISABLED 0
+#define GPIO_TERMINATION_PULLUP_ENABLED  1
+
+#define GPIO_POLARITY_LOW  0
+#define GPIO_POLARITY_HIGH 1
+
+#define GPIO_STATE_DOWN 0
+
+/* Used to test stubs that don't perform actual work */
+#define DUMMY_VALUE 0x12345678
+
 typedef struct {
 uint32_t size;
 uint32_t req_resp_code;
-- 
2.34.1




[PATCH v6 01/41] Split out common part of BCM283X classes

2024-02-25 Thread Sergey Kambalin
Pre setup for BCM2838 introduction

Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/bcm2836.c | 103 ++-
 hw/arm/raspi.c   |   2 +-
 include/hw/arm/bcm2836.h |  26 +-
 3 files changed, 84 insertions(+), 47 deletions(-)

diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index e3ba18a8ec..e9768f2ab9 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -31,12 +31,12 @@ struct BCM283XClass {
 };
 
 static Property bcm2836_enabled_cores_property =
-DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
+DEFINE_PROP_UINT32("enabled-cpus", BCM283XBaseState, enabled_cpus, 0);
 
-static void bcm2836_init(Object *obj)
+static void bcm283x_base_init(Object *obj)
 {
-BCM283XState *s = BCM283X(obj);
-BCM283XClass *bc = BCM283X_GET_CLASS(obj);
+BCM283XBaseState *s = BCM283X_BASE(obj);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(obj);
 int n;
 
 for (n = 0; n < bc->core_count; n++) {
@@ -52,6 +52,11 @@ static void bcm2836_init(Object *obj)
 object_initialize_child(obj, "control", >control,
 TYPE_BCM2836_CONTROL);
 }
+}
+
+static void bcm283x_init(Object *obj)
+{
+BCM283XState *s = BCM283X(obj);
 
 object_initialize_child(obj, "peripherals", >peripherals,
 TYPE_BCM2835_PERIPHERALS);
@@ -63,10 +68,11 @@ static void bcm2836_init(Object *obj)
   "vcram-size");
 }
 
-static bool bcm283x_common_realize(DeviceState *dev, Error **errp)
+bool bcm283x_common_realize(DeviceState *dev, Error **errp)
 {
 BCM283XState *s = BCM283X(dev);
-BCM283XClass *bc = BCM283X_GET_CLASS(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
 Object *obj;
 
 /* common peripherals from bcm2835 */
@@ -79,90 +85,93 @@ static bool bcm283x_common_realize(DeviceState *dev, Error 
**errp)
 return false;
 }
 
-object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(>peripherals),
-  "sd-bus");
+object_property_add_alias(OBJECT(s_base), "sd-bus",
+  OBJECT(>peripherals), "sd-bus");
 
-sysbus_mmio_map_overlap(SYS_BUS_DEVICE(>peripherals), 0,
-bc->peri_base, 1);
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(>peripherals),
+0, bc->peri_base, 1);
 return true;
 }
 
 static void bcm2835_realize(DeviceState *dev, Error **errp)
 {
 BCM283XState *s = BCM283X(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
 
 if (!bcm283x_common_realize(dev, errp)) {
 return;
 }
 
-if (!qdev_realize(DEVICE(>cpu[0].core), NULL, errp)) {
+if (!qdev_realize(DEVICE(_base->cpu[0].core), NULL, errp)) {
 return;
 }
 
 /* Connect irq/fiq outputs from the interrupt controller. */
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
-qdev_get_gpio_in(DEVICE(>cpu[0].core), ARM_CPU_IRQ));
+qdev_get_gpio_in(DEVICE(_base->cpu[0].core), ARM_CPU_IRQ));
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
-qdev_get_gpio_in(DEVICE(>cpu[0].core), ARM_CPU_FIQ));
+qdev_get_gpio_in(DEVICE(_base->cpu[0].core), ARM_CPU_FIQ));
 }
 
 static void bcm2836_realize(DeviceState *dev, Error **errp)
 {
-BCM283XState *s = BCM283X(dev);
-BCM283XClass *bc = BCM283X_GET_CLASS(dev);
 int n;
+BCM283XState *s = BCM283X(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
 
 if (!bcm283x_common_realize(dev, errp)) {
 return;
 }
 
 /* bcm2836 interrupt controller (and mailboxes, etc.) */
-if (!sysbus_realize(SYS_BUS_DEVICE(>control), errp)) {
+if (!sysbus_realize(SYS_BUS_DEVICE(_base->control), errp)) {
 return;
 }
 
-sysbus_mmio_map(SYS_BUS_DEVICE(>control), 0, bc->ctrl_base);
+sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc->ctrl_base);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
-qdev_get_gpio_in_named(DEVICE(>control), "gpu-irq", 0));
+qdev_get_gpio_in_named(DEVICE(_base->control), "gpu-irq", 0));
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
-qdev_get_gpio_in_named(DEVICE(>control), "gpu-fiq", 0));
+qdev_get_gpio_in_named(DEVICE(_base->control), "gpu-fiq", 0));
 
 for (n = 0; n < BCM283X_NCPUS; n++) {
-object_property_set_int(OBJECT(>cpu[n].core), "mp-affinity",
+object_property_set_int(OBJECT(_base->cpu[n].core), "mp-affinity",
 (bc->clusterid << 8) | n, _abort);
 
 

[PATCH v6 35/41] Add mailbox tests tags. Part 3

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 78 +++
 1 file changed, 78 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index b4f7b7b314..d753f17fb2 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -446,6 +446,84 @@ DECLARE_TAG_TYPE(TAG_GET_DMA_CHANNELS_t,
 uint32_t mask;
 });
 
+DECLARE_TAG_TYPE(TAG_GET_THROTTLED_t,
+struct {},
+struct {
+uint32_t throttled;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_NUM_DISPLAYS_t,
+struct {},
+struct {
+uint32_t num_displays;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_DISPLAY_SETTINGS_t,
+struct {},
+struct {
+uint32_t display_num;
+uint32_t phys_width;
+uint32_t phys_height;
+uint32_t bpp;
+uint16_t pitch;
+uint32_t virt_width;
+uint32_t virt_height;
+uint16_t virt_width_offset;
+uint32_t virt_height_offset;
+uint32_t fb_bus_address_lo;
+uint32_t fb_bus_address_hi;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_GPIO_CONFIG_t,
+struct {
+uint32_t gpio_num;
+},
+struct {
+uint32_t zero;
+uint32_t direction;
+uint32_t polarity;
+uint32_t term_en;
+uint32_t term_pull_up;
+});
+
+
+DECLARE_TAG_TYPE(TAG_SET_GPIO_CONFIG_t,
+struct {
+uint32_t gpio_num;
+uint32_t direction;
+uint32_t polarity;
+uint32_t term_en;
+uint32_t term_pull_up;
+uint32_t state;
+},
+struct {
+uint32_t zero;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_GPIO_STATE_t,
+struct {
+uint32_t gpio_num;
+},
+struct {
+uint32_t zero;
+uint32_t state;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_GPIO_STATE_t,
+struct {
+uint32_t gpio_num;
+uint32_t state;
+},
+struct {
+uint32_t zero;
+});
+
+DECLARE_TAG_TYPE(TAG_VCHIQ_INIT_t,
+struct {},
+struct {
+uint32_t zero;
+});
+
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
 void mbox1_write_message(uint8_t channel, uint32_t msg_addr);
-- 
2.34.1




[PATCH v6 00/41] Raspberry Pi 4B machine

2024-02-25 Thread Sergey Kambalin
Introducing Raspberry Pi 4B model.
It contains new BCM2838 SoC, PCIE subsystem,
RNG200, Thermal sensor and Genet network controller.

It can work with recent linux kernels 6.x.x.
Two avocado tests was added to check that.

Unit tests has been made as read/write operations
via mailbox properties.

Genet integration test is under development.

Every single commit
1) builds without errors
2) passes regression tests
3) passes style check*
*the only exception is bcm2838-mbox-property-test.c file
containing heavy macros usage which cause a lot of
false-positives of checkpatch.pl.

I did my best to keep the commits less than 200 changes,
but had to make some of them a bit more in order to
keep their integrity.


Sergey Kambalin (41):
  Split out common part of BCM283X classes
  Split out common part of peripherals
  Split out raspi machine common part
  Introduce BCM2838 SoC
  Add GIC-400 to BCM2838 SoC
  Add BCM2838 GPIO stub
  Implement BCM2838 GPIO functionality
  Connect SD controller to BCM2838 GPIO
  Add GPIO and SD to BCM2838 periph
  Introduce Raspberry PI 4 machine
  Temporarily disable unimplemented rpi4b devices
  Add memory region for BCM2837 RPiVid ASB
  Add BCM2838 PCIE Root Complex
  Add BCM2838 PCIE host
  Enable BCM2838 PCIE
  Add RPi4 RNG200
  Implement BCM2838 thermal sensor
  Add clock_isp stub
  Add GENET stub
  Add GENET register structs. Part 1
  Add GENET register structs. Part 2
  Add GENET register structs. Part 3
  Add GENET register structs. Part 4
  Add GENET register access macros
  Implement GENET register ops
  Implement GENET MDIO
  Implement GENET TX path
  Implement GENET RX path
  Enable BCM2838 GENET controller
  Add Rpi4b boot tests
  Add mailbox test stub
  Add mailbox test constants
  Add mailbox tests tags. Part 1
  Add mailbox tests tags. Part 2
  Add mailbox tests tags. Part 3
  Add mailbox property tests. Part 1
  Add mailbox property tests. Part 2
  Add mailbox property tests. Part 3
  Add missed BCM2835 properties
  Append added properties to mailbox test
  Add RPi4B to raspi.rst

 docs/system/arm/raspi.rst|   11 +-
 hw/arm/bcm2835_peripherals.c |  215 +++--
 hw/arm/bcm2836.c |  117 ++-
 hw/arm/bcm2838.c |  282 ++
 hw/arm/bcm2838_pcie.c|  295 ++
 hw/arm/bcm2838_peripherals.c |  287 ++
 hw/arm/meson.build   |8 +-
 hw/arm/raspi.c   |  130 +--
 hw/arm/raspi4b.c |  111 +++
 hw/arm/trace-events  |7 +
 hw/gpio/bcm2838_gpio.c   |  390 
 hw/gpio/meson.build  |5 +-
 hw/misc/bcm2835_property.c   |   21 +
 hw/misc/bcm2838_rng200.c |  405 
 hw/misc/bcm2838_thermal.c|   98 ++
 hw/misc/meson.build  |2 +
 hw/misc/trace-events |9 +
 hw/net/bcm2838_genet.c   | 1088 ++
 hw/net/meson.build   |2 +
 hw/net/trace-events  |   16 +
 include/hw/arm/bcm2835_peripherals.h |   29 +-
 include/hw/arm/bcm2836.h |   27 +-
 include/hw/arm/bcm2838.h |   31 +
 include/hw/arm/bcm2838_pcie.h|   75 ++
 include/hw/arm/bcm2838_peripherals.h |   94 ++
 include/hw/arm/raspberrypi-fw-defs.h |   11 +
 include/hw/arm/raspi_platform.h  |   38 +-
 include/hw/display/bcm2835_fb.h  |2 +
 include/hw/gpio/bcm2838_gpio.h   |   45 +
 include/hw/misc/bcm2838_rng200.h |   43 +
 include/hw/misc/bcm2838_thermal.h|   24 +
 include/hw/net/bcm2838_genet.h   |  426 +
 tests/avocado/boot_linux_console.py  |   92 ++
 tests/qtest/bcm2838-mailbox.c|   60 ++
 tests/qtest/bcm2838-mailbox.h|  532 +++
 tests/qtest/bcm2838-mbox-property-test.c |  631 +
 tests/qtest/meson.build  |3 +-
 37 files changed, 5457 insertions(+), 205 deletions(-)
 create mode 100644 hw/arm/bcm2838.c
 create mode 100644 hw/arm/bcm2838_pcie.c
 create mode 100644 hw/arm/bcm2838_peripherals.c
 create mode 100644 hw/arm/raspi4b.c
 create mode 100644 hw/gpio/bcm2838_gpio.c
 create mode 100644 hw/misc/bcm2838_rng200.c
 create mode 100644 hw/misc/bcm2838_thermal.c
 create mode 100644 hw/net/bcm2838_genet.c
 create mode 100644 include/hw/arm/bcm2838.h
 create mode 100644 include/hw/arm/bcm2838_pcie.h
 create mode 100644 include/hw/arm/bcm2838_peripherals.h
 create mode 100644 include/hw/gpio/bcm2838_gpio.h
 create mode 100644 include/hw/misc/bcm2838_rng200.h
 create mode 100644 include/hw/misc/bcm2838_thermal.h
 create mode 100644 include/hw/net/bcm2838_genet.h
 create mode 100644 tests/qtest/bcm2838-mailbox.c
 create mode 100644 tests/qtest/bcm2838-mailbox.h
 create mode 100644 tests/qtest/bcm2838-mbox-property-test.c

-- 
2.34.1




[PATCH v6 17/41] Implement BCM2838 thermal sensor

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/bcm2838_peripherals.c | 11 
 hw/arm/raspi4b.c |  1 -
 hw/misc/bcm2838_thermal.c| 98 
 hw/misc/meson.build  |  1 +
 include/hw/arm/bcm2838_peripherals.h |  2 +
 include/hw/misc/bcm2838_thermal.h| 24 +++
 6 files changed, 136 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/bcm2838_thermal.c
 create mode 100644 include/hw/misc/bcm2838_thermal.h

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 4a9cbe6cf6..6badda3045 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -37,6 +37,9 @@ static void bcm2838_peripherals_init(Object *obj)
 /* Random Number Generator */
 object_initialize_child(obj, "rng200", >rng200, TYPE_BCM2838_RNG200);
 
+/* Thermal */
+object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2838_THERMAL);
+
 /* PCIe Host Bridge */
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
@@ -80,6 +83,7 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 MemoryRegion *mmio_mr;
 MemoryRegion *rng200_mr;
 qemu_irq rng_200_irq;
+MemoryRegion *thermal_mr;
 
 int n;
 
@@ -105,6 +109,13 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
  BCM2835_IC_GPU_IRQ, INTERRUPT_RNG);
 sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0, rng_200_irq);
 
+/* THERMAL */
+if (!sysbus_realize(SYS_BUS_DEVICE(>thermal), errp)) {
+return;
+}
+thermal_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>thermal), 0);
+memory_region_add_subregion( >peri_low_mr, 0x15D2000, thermal_mr);
+
 /* Extended Mass Media Controller 2 */
 object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
  _abort);
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 3c71fa9a9a..175fd2c4fa 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -67,7 +67,6 @@ static void raspi4_modify_dtb(const struct arm_boot_info 
*info, void *fdt)
 
 /* Temporarily disable following devices until they are implemented */
 const char *nodes_to_remove[] = {
-"brcm,bcm2711-thermal",
 "brcm,bcm2711-genet-v5",
 };
 
diff --git a/hw/misc/bcm2838_thermal.c b/hw/misc/bcm2838_thermal.c
new file mode 100644
index 00..3764d55b59
--- /dev/null
+++ b/hw/misc/bcm2838_thermal.c
@@ -0,0 +1,98 @@
+/*
+ * BCM2838 dummy thermal sensor
+ *
+ * Copyright (C) 2022 Maksim Kopusov 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/misc/bcm2838_thermal.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+REG32(STAT, 0x200)
+FIELD(STAT, DATA, 0, 10)
+FIELD(STAT, VALID_1, 10, 1)
+FIELD(STAT, VALID_2, 16, 1)
+
+#define BCM2838_THERMAL_SIZE 0xf00
+
+#define THERMAL_OFFSET_C 410040
+#define THERMAL_COEFF  (-487.0f)
+#define MILLIDEGREE_COEFF 1000
+
+static uint16_t bcm2838_thermal_temp2adc(int temp_C)
+{
+return (temp_C * MILLIDEGREE_COEFF - THERMAL_OFFSET_C) / THERMAL_COEFF;
+}
+
+static uint64_t bcm2838_thermal_read(void *opaque, hwaddr addr, unsigned size)
+{
+uint32_t val = 0;
+
+switch (addr) {
+case A_STAT:
+/* Temperature is always 25°C */
+val = FIELD_DP32(val, STAT, DATA, bcm2838_thermal_temp2adc(25));
+val = FIELD_DP32(val, STAT, VALID_1, 1);
+val = FIELD_DP32(val, STAT, VALID_2, 1);
+
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "%s can't access addr: 0x%"HWADDR_PRIx,
+ TYPE_BCM2838_THERMAL, addr);
+}
+return val;
+}
+
+static void bcm2838_thermal_write(void *opaque, hwaddr addr,
+  uint64_t value, unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: write 0x%" PRIx64
+" to 0x%" HWADDR_PRIx "\n",
+__func__, value, addr);
+}
+
+static const MemoryRegionOps bcm2838_thermal_ops = {
+.read = bcm2838_thermal_read,
+.write = bcm2838_thermal_write,
+.impl.max_access_size = 4,
+.valid.min_access_size = 4,
+.endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void bcm2838_thermal_realize(DeviceState *dev, Error **errp)
+{
+Bcm2838ThermalState *s = BCM2838_THERMAL(dev);
+
+memory_region_init_io(>iomem, OBJECT(s), _thermal_ops,
+  s, TYPE_BCM2838_THERMAL, BCM2838_THERMAL_SIZE);
+sysbus_init_mmio(SYS_BUS_DEVICE(s), >iomem);
+}
+
+static void bcm2838_thermal_class_init(ObjectClass *klass, 

[PATCH v6 15/41] Enable BCM2838 PCIE

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c |  9 +
 hw/arm/bcm2838_peripherals.c | 24 
 hw/arm/meson.build   |  7 ---
 hw/arm/raspi4b.c |  1 -
 include/hw/arm/bcm2838_peripherals.h |  2 ++
 5 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index ddb7c5f757..481b262b02 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -226,6 +226,15 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 qdev_connect_gpio_out(dma_9_10_irq_orgate, 0,
   qdev_get_gpio_in(gicdev, 
GIC_SPI_INTERRUPT_DMA_9_10));
 
+/* Connect PCIe host bridge to the interrupt controller */
+for (int n = 0; n < BCM2838_PCIE_NUM_IRQS; n++) {
+int int_n = GIC_SPI_INTERRUPT_PCI_INT_A + n;
+sysbus_connect_irq(SYS_BUS_DEVICE(>pcie_host), n,
+   qdev_get_gpio_in(gicdev, int_n));
+bcm2838_pcie_host_set_irq_num(BCM2838_PCIE_HOST(>pcie_host), n,
+  int_n);
+}
+
 /* Pass through inbound GPIO lines to the GIC */
 qdev_init_gpio_in(dev, bcm2838_gic_set_irq, GIC_NUM_IRQS);
 
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index ca2f37b260..23e1154466 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -12,6 +12,11 @@
 #include "hw/arm/raspi_platform.h"
 #include "hw/arm/bcm2838_peripherals.h"
 
+#define PCIE_RC_OFFSET  0x150
+#define PCIE_MMIO_OFFSET0xc000
+#define PCIE_MMIO_ARM_OFFSET0x6
+#define PCIE_MMIO_SIZE  0x4000
+
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
@@ -29,6 +34,10 @@ static void bcm2838_peripherals_init(Object *obj)
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* PCIe Host Bridge */
+object_initialize_child(obj, "pcie-host", >pcie_host,
+TYPE_BCM2838_PCIE_HOST);
+
 /* Extended Mass Media Controller 2 */
 object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
 
@@ -64,6 +73,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 MemoryRegion *mphi_mr;
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(dev);
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+MemoryRegion *regs_mr;
+MemoryRegion *mmio_mr;
+
 int n;
 
 bcm_soc_peripherals_common_realize(dev, errp);
@@ -176,6 +188,18 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(_base->peri_mr, BCM2838_MPHI_OFFSET,
 >mphi_mr_alias);
 
+/* PCIe Root Complex */
+if (!sysbus_realize(SYS_BUS_DEVICE(>pcie_host), errp)) {
+return;
+}
+/* RC registers region */
+regs_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>pcie_host), 0);
+memory_region_add_subregion(>peri_low_mr, PCIE_RC_OFFSET, regs_mr);
+/* MMIO region */
+mmio_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>pcie_host), 1);
+memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
+mmio_mr);
+
 /* GPIO */
 if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
 return;
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 39f6df7431..4d11ec0eae 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -32,7 +32,6 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: 
files('allwinner-r40.c', 'bana
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
 arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: files(
   'bcm2838.c',
-  'bcm2838_pcie.c',
   'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
@@ -70,8 +69,10 @@ system_ss.add(when: 'CONFIG_EXYNOS4', if_true: 
files('exynos4_boards.c'))
 system_ss.add(when: 'CONFIG_GUMSTIX', if_true: files('gumstix.c'))
 system_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
 system_ss.add(when: 'CONFIG_OMAP', if_true: files('omap2.c'))
-system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c'))
-system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2838_peripherals.c'))
+system_ss.add(when: 'CONFIG_RASPI', if_true: files(
+'bcm2835_peripherals.c',
+'bcm2838_peripherals.c',
+'bcm2838_pcie.c'))
 system_ss.add(when: 'CONFIG_SPITZ', if_true: files('spitz.c'))
 system_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c'))
 system_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 49dec6e53a..2431b0b8c3 100644
--- a/hw/arm/raspi4b.c
+

[PATCH v6 10/41] Introduce Raspberry PI 4 machine

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/bcm2835_peripherals.c| 17 ++--
 hw/arm/bcm2836.c|  2 +
 hw/arm/bcm2838.c|  2 +
 hw/arm/meson.build  |  2 +-
 hw/arm/raspi.c  | 27 -
 hw/arm/raspi4b.c| 70 +
 include/hw/arm/raspi_platform.h | 11 ++
 include/hw/display/bcm2835_fb.h |  2 +
 8 files changed, 119 insertions(+), 14 deletions(-)
 create mode 100644 hw/arm/raspi4b.c

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index ed38a08a57..a0bbe76f26 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -108,6 +108,7 @@ static void raspi_peripherals_base_init(Object *obj)
 /* Framebuffer */
 object_initialize_child(obj, "fb", >fb, TYPE_BCM2835_FB);
 object_property_add_alias(obj, "vcram-size", OBJECT(>fb), "vcram-size");
+object_property_add_alias(obj, "vcram-base", OBJECT(>fb), "vcram-base");
 
 object_property_add_const_link(OBJECT(>fb), "dma-mr",
OBJECT(>gpu_bus_mr));
@@ -229,7 +230,7 @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, 
Error **errp)
 Object *obj;
 MemoryRegion *ram;
 Error *err = NULL;
-uint64_t ram_size, vcram_size;
+uint64_t ram_size, vcram_size, vcram_base;
 int n;
 
 obj = object_property_get_link(OBJECT(dev), "ram", _abort);
@@ -333,11 +334,21 @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
-if (!object_property_set_uint(OBJECT(>fb), "vcram-base",
-  ram_size - vcram_size, errp)) {
+vcram_base = object_property_get_uint(OBJECT(s), "vcram-base", );
+if (err) {
+error_propagate(errp, err);
 return;
 }
 
+if (vcram_base == 0) {
+vcram_base = ram_size - vcram_size;
+}
+vcram_base = MIN(vcram_base, UPPER_RAM_BASE - vcram_size);
+
+if (!object_property_set_uint(OBJECT(>fb), "vcram-base", vcram_base,
+  errp)) {
+return;
+}
 if (!sysbus_realize(SYS_BUS_DEVICE(>fb), errp)) {
 return;
 }
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 7e4c60dd80..db191661f2 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -66,6 +66,8 @@ static void bcm283x_init(Object *obj)
   "command-line");
 object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
   "vcram-size");
+object_property_add_alias(obj, "vcram-base", OBJECT(>peripherals),
+  "vcram-base");
 }
 
 bool bcm283x_common_realize(DeviceState *dev, BCMSocPeripheralBaseState *ps,
diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index 332e906a84..ddb7c5f757 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -54,6 +54,8 @@ static void bcm2838_init(Object *obj)
   "board-rev");
 object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
   "vcram-size");
+object_property_add_alias(obj, "vcram-base", OBJECT(>peripherals),
+  "vcram-base");
 object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
   "command-line");
 
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 1390a9d7b5..6808135c1f 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -30,7 +30,7 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: 
files('allwinner-a10.c', 'cubi
 arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 
'orangepi.c'))
 arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 
'bananapi_m2u.c'))
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
-arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: 
files('bcm2838.c'))
+arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: 
files('bcm2838.c', 'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 7d04734cd2..8b1a046912 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -18,6 +18,7 @@
 #include "qapi/error.h"
 #include "hw/arm/boot.h"
 #include "hw/arm/bcm2836.h"
+#include "hw/arm/bcm2838.h"
 #include "hw/arm/raspi_platform.h"
 #include "hw/registerfields.h"
 #include "qemu/error-report.h"
@@ -61,6 +62,7 @@ typede

[PATCH v6 24/41] Add GENET register access macros

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 include/hw/net/bcm2838_genet.h | 76 ++
 1 file changed, 76 insertions(+)

diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 94c2f3ebca..e7a76cda81 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -22,9 +22,85 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_DMA_RING_CNT  17
 #define BCM2838_GENET_DMA_RING_DEFAULT  (BCM2838_GENET_DMA_RING_CNT - 1)
 
+#define BCM2838_GENET_HFB_FILTER_REGS offsetof(BCM2838GenetRegs, hfb)
+#define BCM2838_GENET_HFB_FILTER_REG(reg) (BCM2838_GENET_HFB_FILTER_REGS \
+   + offsetof(BCM2838GenetRegsHfb, 
reg))
 #define BCM2838_GENET_HFB_FILTER_CNT  48
 #define BCM2838_GENET_HFB_FILTER_SIZE 128
 
+#define BCM2838_GENET_INTRL0_REG(reg)   (offsetof(BCM2838GenetRegs, intrl0) \
++ offsetof(BCM2838GenetRegsIntrl0, 
reg))
+#define BCM2838_GENET_INTRL0_SETBCM2838_GENET_INTRL0_REG(set)
+#define BCM2838_GENET_INTRL0_CLEAR  BCM2838_GENET_INTRL0_REG(clear)
+#define BCM2838_GENET_INTRL0_MASK_SET   BCM2838_GENET_INTRL0_REG(mask_set)
+#define BCM2838_GENET_INTRL0_MASK_CLEAR BCM2838_GENET_INTRL0_REG(mask_clear)
+
+#define BCM2838_GENET_INTRL1_REG(reg)   (offsetof(BCM2838GenetRegs, intrl1) \
++ offsetof(BCM2838GenetRegsIntrl1, 
reg))
+#define BCM2838_GENET_INTRL1_SETBCM2838_GENET_INTRL1_REG(set)
+#define BCM2838_GENET_INTRL1_CLEAR  BCM2838_GENET_INTRL1_REG(clear)
+#define BCM2838_GENET_INTRL1_MASK_SET   BCM2838_GENET_INTRL1_REG(mask_set)
+#define BCM2838_GENET_INTRL1_MASK_CLEAR BCM2838_GENET_INTRL1_REG(mask_clear)
+
+#define BCM2838_GENET_UMAC_REG(reg) (offsetof(BCM2838GenetRegs, umac) \
+ + offsetof(BCM2838GenetRegsUmac, reg))
+#define BCM2838_GENET_UMAC_CMD  BCM2838_GENET_UMAC_REG(cmd)
+#define BCM2838_GENET_UMAC_MAC0 BCM2838_GENET_UMAC_REG(mac0)
+#define BCM2838_GENET_UMAC_MAC1 BCM2838_GENET_UMAC_REG(mac1)
+#define BCM2838_GENET_UMAC_MDIO_CMD BCM2838_GENET_UMAC_REG(mdio_cmd)
+
+#define BCM2838_GENET_TDMA_REGS offsetof(BCM2838GenetRegs, tdma)
+#define BCM2838_GENET_TDMA_REG(reg) (BCM2838_GENET_TDMA_REGS \
+ + offsetof(BCM2838GenetRegsTdma, reg))
+#define BCM2838_GENET_TDMA_RINGSBCM2838_GENET_TDMA_REG(rings)
+#define BCM2838_GENET_TDMA_RING_CFG BCM2838_GENET_TDMA_REG(ring_cfg)
+#define BCM2838_GENET_TDMA_CTRL BCM2838_GENET_TDMA_REG(ctrl)
+
+#define BCM2838_GENET_RDMA_REGS offsetof(BCM2838GenetRegs, rdma)
+#define BCM2838_GENET_RDMA_REG(reg) (BCM2838_GENET_RDMA_REGS \
+ + offsetof(BCM2838GenetRegsRdma, reg))
+#define BCM2838_GENET_RDMA_RINGSBCM2838_GENET_RDMA_REG(rings)
+#define BCM2838_GENET_RDMA_RING_CFG BCM2838_GENET_RDMA_REG(ring_cfg)
+#define BCM2838_GENET_RDMA_CTRL BCM2838_GENET_RDMA_REG(ctrl)
+
+#define BCM2838_GENET_TRING_REG(reg)offsetof(BCM2838GenetTdmaRing, reg)
+#define BCM2838_GENET_TRING_WRITE_PTR BCM2838_GENET_TRING_REG(write_ptr)
+#define BCM2838_GENET_TRING_WRITE_PTR_HI BCM2838_GENET_TRING_REG(write_ptr_hi)
+#define BCM2838_GENET_TRING_PROD_INDEX BCM2838_GENET_TRING_REG(prod_index)
+#define BCM2838_GENET_TRING_CONS_INDEX BCM2838_GENET_TRING_REG(cons_index)
+#define BCM2838_GENET_TRING_RING_BUF_SIZE 
BCM2838_GENET_TRING_REG(ring_buf_size)
+#define BCM2838_GENET_TRING_RING_START_ADDR BCM2838_GENET_TRING_REG(start_addr)
+#define BCM2838_GENET_TRING_RING_START_ADDR_HI 
BCM2838_GENET_TRING_REG(start_addr_hi)
+#define BCM2838_GENET_TRING_RING_END_ADDR BCM2838_GENET_TRING_REG(end_addr)
+#define BCM2838_GENET_TRING_RING_END_ADDR_HI 
BCM2838_GENET_TRING_REG(end_addr_hi)
+#define BCM2838_GENET_TRING_RING_MBUF_DONE_TRESH 
BCM2838_GENET_TRING_REG(mbuf_done_tresh)
+#define BCM2838_GENET_TRING_RING_FLOW_PERIOD 
BCM2838_GENET_TRING_REG(flow_period)
+#define BCM2838_GENET_TRING_RING_READ_PTR BCM2838_GENET_TRING_REG(read_ptr)
+#define BCM2838_GENET_TRING_RING_READ_PTR_HI 
BCM2838_GENET_TRING_REG(read_ptr_hi)
+
+#define BCM2838_GENET_RRING_REG(reg)offsetof(BCM2838GenetRdmaRing, reg)
+#define BCM2838_GENET_RRING_WRITE_PTR BCM2838_GENET_RRING_REG(write_ptr)
+#define BCM2838_GENET_RRING_WRITE_PTR_HI BCM2838_GENET_RRING_REG(write_ptr_hi)
+#define BCM2838_GENET_RRING_PROD_INDEX BCM2838_GENET_RRING_REG(prod_index)
+#define BCM2838_GENET_RRING_CONS_INDEX BCM2838_GENET_RRING_REG(cons_index)
+#define BCM2838_GENET_RRING_RING_BUF_SIZE 
BCM2838_GENET_RRING_REG(ring_buf_size)
+#define BCM2838_GENET_RRING_RING_START_ADDR BCM2838_GENET_RRING_REG(start_addr)
+#define BCM2838_GENET_RRING_RING_START_ADDR_HI 
BCM2838_GENET_RRING_REG(start_addr_hi)
+#define BCM2838_GENET_RRING_RING_END_ADDR BCM2838_GENET_RRING_REG(end_addr)
+#define BCM2838_GENET_RRING_RING_END_ADDR_HI

[PATCH v6 38/41] Add mailbox property tests. Part 3

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 213 ++-
 1 file changed, 212 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index b251d3f552..c96a9ba3f3 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -362,7 +362,194 @@ 
DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT) {
 tag->request.value.height = 600;
 }
 
-//==
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_TEST_DEPTH) {
+g_assert_cmpint(tag->response.value.bpp, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_TEST_DEPTH) {
+tag->request.value.bpp = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_DEPTH) {
+g_assert_cmpint(tag->response.value.bpp, ==, 16);
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_DEPTH) {
+g_assert_cmpint(tag->response.value.bpp, ==, 24);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_DEPTH) {
+tag->request.value.bpp = 24;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_TEST_PIXEL_ORDER) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_TEST_PIXEL_ORDER) {
+tag->request.value.pixel_order = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_PIXEL_ORDER) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, PIXEL_ORDER_RGB);
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_PIXEL_ORDER, BGR) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, PIXEL_ORDER_BGR);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_PIXEL_ORDER, BGR) {
+tag->request.value.pixel_order = PIXEL_ORDER_BGR;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_PIXEL_ORDER, RGB) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, PIXEL_ORDER_BGR);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_PIXEL_ORDER, RGB) {
+tag->request.value.pixel_order = PIXEL_ORDER_BGR;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_TEST_ALPHA_MODE) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_TEST_ALPHA_MODE) {
+tag->request.value.alpha_mode = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_ALPHA_MODE) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_IGNORED);
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_ALPHA_MODE, ENABLED) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_ENABLED);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_ALPHA_MODE, ENABLED) {
+tag->request.value.alpha_mode = ALPHA_MODE_ENABLED;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_ALPHA_MODE, REVERSED) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_REVERSED);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_ALPHA_MODE, REVERSED) {
+tag->request.value.alpha_mode = ALPHA_MODE_REVERSED;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_ALPHA_MODE, IGNORED) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_IGNORED);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_ALPHA_MODE, IGNORED) {
+tag->request.value.alpha_mode = ALPHA_MODE_IGNORED;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_PITCH) {
+g_assert_cmpint(tag->response.value.pitch, ==, 1280);
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_TEST_VIRTUAL_OFFSET) {
+g_assert_cmpint(tag->response.value.x, ==, DUMMY_VALUE);
+g_assert_cmpint(tag->response.value.y, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_TEST_VIRTUAL_OFFSET) {
+tag->request.value.x = DUMMY_VALUE;
+tag->request.value.y = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_VIRTUAL_OFFSET) {
+g_assert_cmpint

[PATCH v6 04/41] Introduce BCM2838 SoC

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/bcm2838.c | 98 
 hw/arm/bcm2838_peripherals.c | 72 
 hw/arm/meson.build   |  2 +
 include/hw/arm/bcm2838.h | 29 
 include/hw/arm/bcm2838_peripherals.h | 36 ++
 5 files changed, 237 insertions(+)
 create mode 100644 hw/arm/bcm2838.c
 create mode 100644 hw/arm/bcm2838_peripherals.c
 create mode 100644 include/hw/arm/bcm2838.h
 create mode 100644 include/hw/arm/bcm2838_peripherals.h

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
new file mode 100644
index 00..05281e247f
--- /dev/null
+++ b/hw/arm/bcm2838.c
@@ -0,0 +1,98 @@
+/*
+ * BCM2838 SoC emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/arm/raspi_platform.h"
+#include "hw/sysbus.h"
+#include "hw/arm/bcm2838.h"
+#include "trace.h"
+
+#define VIRTUAL_PMU_IRQ 7
+
+static void bcm2838_init(Object *obj)
+{
+BCM2838State *s = BCM2838(obj);
+
+object_initialize_child(obj, "peripherals", >peripherals,
+TYPE_BCM2838_PERIPHERALS);
+object_property_add_alias(obj, "board-rev", OBJECT(>peripherals),
+  "board-rev");
+object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
+  "vcram-size");
+object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
+  "command-line");
+}
+
+static void bcm2838_realize(DeviceState *dev, Error **errp)
+{
+int n;
+BCM2838State *s = BCM2838(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc_base = BCM283X_BASE_GET_CLASS(dev);
+BCM2838PeripheralState *ps = BCM2838_PERIPHERALS(>peripherals);
+BCMSocPeripheralBaseState *ps_base =
+BCM_SOC_PERIPHERALS_BASE(>peripherals);
+
+if (!bcm283x_common_realize(dev, ps_base, errp)) {
+return;
+}
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(ps), 1, BCM2838_PERI_LOW_BASE, 1);
+
+/* bcm2836 interrupt controller (and mailboxes, etc.) */
+if (!sysbus_realize(SYS_BUS_DEVICE(_base->control), errp)) {
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc_base->ctrl_base);
+
+/* Create cores */
+for (n = 0; n < bc_base->core_count; n++) {
+
+object_property_set_int(OBJECT(_base->cpu[n].core), "mp-affinity",
+(bc_base->clusterid << 8) | n, _abort);
+
+/* start powered off if not enabled */
+object_property_set_bool(OBJECT(_base->cpu[n].core),
+ "start-powered-off",
+ n >= s_base->enabled_cpus, _abort);
+
+if (!qdev_realize(DEVICE(_base->cpu[n].core), NULL, errp)) {
+return;
+}
+}
+}
+
+static void bcm2838_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+BCM283XBaseClass *bc_base = BCM283X_BASE_CLASS(oc);
+
+bc_base->cpu_type = ARM_CPU_TYPE_NAME("cortex-a72");
+bc_base->core_count = BCM283X_NCPUS;
+bc_base->peri_base = 0xfe00;
+bc_base->ctrl_base = 0xff80;
+bc_base->clusterid = 0x0;
+dc->realize = bcm2838_realize;
+}
+
+static const TypeInfo bcm2838_type = {
+.name   = TYPE_BCM2838,
+.parent = TYPE_BCM283X_BASE,
+.instance_size  = sizeof(BCM2838State),
+.instance_init  = bcm2838_init,
+.class_size = sizeof(BCM283XBaseClass),
+.class_init = bcm2838_class_init,
+};
+
+static void bcm2838_register_types(void)
+{
+type_register_static(_type);
+}
+
+type_init(bcm2838_register_types);
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
new file mode 100644
index 00..06110c724f
--- /dev/null
+++ b/hw/arm/bcm2838_peripherals.c
@@ -0,0 +1,72 @@
+/*
+ * BCM2838 peripherals emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/arm/raspi_platform.h"
+#include "hw/arm/bcm2838_peripherals.h"
+
+/* Lower peripheral base address on the VC (GPU) system bus */
+#define BCM2838_VC_PERI_LOW_BASE 0x7c00
+
+static void bcm2838_peripherals_init(Object *obj)
+{
+BCM2838PeripheralState *s = BCM2838_PERIPHERALS(obj);
+BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_GET_CLASS(obj);
+
+/* Lower memory region for peripheral devices (exported to the Soc) */
+memor

[PATCH v6 05/41] Add GIC-400 to BCM2838 SoC

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/bcm2838.c | 167 ++-
 hw/arm/trace-events  |   3 +
 include/hw/arm/bcm2838.h |   2 +
 include/hw/arm/bcm2838_peripherals.h |  37 ++
 4 files changed, 207 insertions(+), 2 deletions(-)

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index 05281e247f..332e906a84 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -14,8 +14,36 @@
 #include "hw/arm/bcm2838.h"
 #include "trace.h"
 
+#define GIC400_MAINTENANCE_IRQ  9
+#define GIC400_TIMER_NS_EL2_IRQ 10
+#define GIC400_TIMER_VIRT_IRQ   11
+#define GIC400_LEGACY_FIQ   12
+#define GIC400_TIMER_S_EL1_IRQ  13
+#define GIC400_TIMER_NS_EL1_IRQ 14
+#define GIC400_LEGACY_IRQ   15
+
+/* Number of external interrupt lines to configure the GIC with */
+#define GIC_NUM_IRQS192
+
+#define PPI(cpu, irq) (GIC_NUM_IRQS + (cpu) * GIC_INTERNAL + GIC_NR_SGIS + irq)
+
+#define GIC_BASE_OFS0x
+#define GIC_DIST_OFS0x1000
+#define GIC_CPU_OFS 0x2000
+#define GIC_VIFACE_THIS_OFS 0x4000
+#define GIC_VIFACE_OTHER_OFS(cpu)  (0x5000 + (cpu) * 0x200)
+#define GIC_VCPU_OFS0x6000
+
 #define VIRTUAL_PMU_IRQ 7
 
+static void bcm2838_gic_set_irq(void *opaque, int irq, int level)
+{
+BCM2838State *s = (BCM2838State *)opaque;
+
+trace_bcm2838_gic_set_irq(irq, level);
+qemu_set_irq(qdev_get_gpio_in(DEVICE(>gic), irq), level);
+}
+
 static void bcm2838_init(Object *obj)
 {
 BCM2838State *s = BCM2838(obj);
@@ -28,11 +56,12 @@ static void bcm2838_init(Object *obj)
   "vcram-size");
 object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
   "command-line");
+
+object_initialize_child(obj, "gic", >gic, TYPE_ARM_GIC);
 }
 
 static void bcm2838_realize(DeviceState *dev, Error **errp)
 {
-int n;
 BCM2838State *s = BCM2838(dev);
 BCM283XBaseState *s_base = BCM283X_BASE(dev);
 BCM283XBaseClass *bc_base = BCM283X_BASE_GET_CLASS(dev);
@@ -40,6 +69,8 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 BCMSocPeripheralBaseState *ps_base =
 BCM_SOC_PERIPHERALS_BASE(>peripherals);
 
+DeviceState *gicdev = NULL;
+
 if (!bcm283x_common_realize(dev, ps_base, errp)) {
 return;
 }
@@ -52,11 +83,15 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc_base->ctrl_base);
 
 /* Create cores */
-for (n = 0; n < bc_base->core_count; n++) {
+for (int n = 0; n < bc_base->core_count; n++) {
 
 object_property_set_int(OBJECT(_base->cpu[n].core), "mp-affinity",
 (bc_base->clusterid << 8) | n, _abort);
 
+/* set periphbase/CBAR value for CPU-local registers */
+object_property_set_int(OBJECT(_base->cpu[n].core), "reset-cbar",
+bc_base->peri_base, _abort);
+
 /* start powered off if not enabled */
 object_property_set_bool(OBJECT(_base->cpu[n].core),
  "start-powered-off",
@@ -66,6 +101,134 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 return;
 }
 }
+
+if (!object_property_set_uint(OBJECT(>gic), "revision", 2, errp)) {
+return;
+}
+
+if (!object_property_set_uint(OBJECT(>gic), "num-cpu", BCM283X_NCPUS,
+  errp)) {
+return;
+}
+
+if (!object_property_set_uint(OBJECT(>gic), "num-irq",
+  GIC_NUM_IRQS + GIC_INTERNAL, errp)) {
+return;
+}
+
+if (!object_property_set_bool(OBJECT(>gic),
+  "has-virtualization-extensions", true,
+  errp)) {
+return;
+}
+
+if (!sysbus_realize(SYS_BUS_DEVICE(>gic), errp)) {
+return;
+}
+
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 0,
+bc_base->ctrl_base + BCM2838_GIC_BASE + GIC_DIST_OFS);
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 1,
+bc_base->ctrl_base + BCM2838_GIC_BASE + GIC_CPU_OFS);
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 2,
+bc_base->ctrl_base + BCM2838_GIC_BASE + 
GIC_VIFACE_THIS_OFS);
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 3,
+bc_base->ctrl_base + BCM2838_GIC_BASE + GIC_VCPU_OFS);
+
+for (int n = 0; n < BCM283X_NCPUS; n++) {
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 4 + n,
+bc_base->ctrl_base + BCM2838_GIC_BASE
++ GIC_VIFACE_OTHER_OFS(n));
+}

[PATCH v6 28/41] Implement GENET RX path

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 265 -
 include/hw/net/bcm2838_genet.h |   1 +
 2 files changed, 265 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 4c9b39a3ca..61c1981e10 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -511,6 +511,25 @@ static bool 
bcm2838_genet_tdma_ring_active(BCM2838GenetState *s,
 return active;
 }
 
+static bool bcm2838_genet_rdma_ring_active(BCM2838GenetState *s,
+   unsigned int ring_index)
+{
+uint32_t ring_mask = 1 << ring_index;
+
+bool dma_en = FIELD_EX32(s->regs.rdma.ctrl, GENET_DMA_CTRL, EN) != 0;
+bool ring_en = (FIELD_EX32(s->regs.rdma.ring_cfg, GENET_DMA_RING_CFG, EN)
+& ring_mask) != 0;
+bool ring_buf_en = (FIELD_EX32(s->regs.rdma.ctrl,
+   GENET_DMA_CTRL, RING_BUF_EN)
+& ring_mask) != 0;
+bool active = dma_en && ring_en && ring_buf_en;
+
+trace_bcm2838_genet_rx_dma_ring_active(ring_index,
+   active ? "active" : "halted");
+
+return active;
+}
+
 static void bcm2838_genet_tdma(BCM2838GenetState *s, hwaddr offset,
uint64_t value)
 {
@@ -721,9 +740,251 @@ static const MemoryRegionOps bcm2838_genet_ops = {
 .valid = {.min_access_size = 4},
 };
 
+static int32_t bcm2838_genet_filter(BCM2838GenetState *s, const void *buf,
+size_t size)
+{
+qemu_log_mask(LOG_UNIMP,
+  "Packet filtration with HFB isn't implemented yet");
+return -1;
+}
+
+static int32_t bcm2838_genet_filter2ring(BCM2838GenetState *s,
+ uint32_t filter_idx)
+{
+qemu_log_mask(LOG_UNIMP,
+  "Packet filtration with HFB isn't implemented yet");
+return -1;
+}
+
+static bool is_packet_broadcast(const uint8_t *buf, size_t size)
+{
+static const uint8_t bcst_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+if (size < sizeof(bcst_addr)) {
+return false;
+}
+
+return !memcmp(buf, bcst_addr, sizeof(bcst_addr));
+}
+
+static bool is_packet_multicast(const uint8_t *buf, size_t size)
+{
+return !!(buf[0] & 0x01);
+}
+
+static ssize_t bcm2838_genet_rdma(BCM2838GenetState *s, uint32_t ring_idx,
+  const void *buf, size_t size)
+{
+const size_t DESC_WORD_SIZE =
+sizeof(BCM2838GenetRdmaDesc) / sizeof(uint32_t);
+
+ssize_t len = 0;
+BCM2838GenetRegsRdma *rdma = >regs.rdma;
+BCM2838GenetRdmaRing *ring = >rings[ring_idx];
+hwaddr write_index =
+(ring->write_ptr + ((hwaddr)ring->write_ptr_hi << 32)) / 
DESC_WORD_SIZE;
+BCM2838GenetRdmaDesc *desc = >descs[write_index];
+
+const hwaddr START_INDEX =
+(ring->start_addr + ((hwaddr)ring->start_addr_hi << 32))
+/ DESC_WORD_SIZE;
+const hwaddr END_INDEX =
+(ring->end_addr + ((hwaddr)ring->end_addr_hi << 32)) / DESC_WORD_SIZE;
+
+if (!bcm2838_genet_rdma_ring_active(s, ring_idx)) {
+return -1;
+}
+
+desc->length_status = FIELD_DP32(desc->length_status,
+ GENET_RDMA_LENGTH_STATUS, SOP, 1);
+
+while (len < size) {
+size_t l = size - len;
+size_t buf_size = ring->ring_buf_size & 0x;
+uint8_t *dma_buf = s->rx_packet;
+hwaddr dma_buf_addr =
+desc->address_lo + ((hwaddr)desc->address_hi << 32);
+MemTxResult mem_tx_result = MEMTX_OK;
+uint8_t *frame_buf = dma_buf + sizeof(BCM2838GenetXmitStatus) + 2;
+BCM2838GenetXmitStatus *xmit_status = (BCM2838GenetXmitStatus 
*)dma_buf;
+struct iovec iov;
+bool isip4, isip6;
+size_t l3hdr_off, l4hdr_off, l5hdr_off;
+eth_ip6_hdr_info ip6hdr_info;
+eth_ip4_hdr_info ip4hdr_info;
+eth_l4_hdr_info  l4hdr_info;
+
+bool crc_fwd = FIELD_EX32(s->regs.umac.cmd, GENET_UMAC_CMD, CRC_FWD);
+size_t buflength;
+uint32_t prod_index;
+
+if (l > ring->ring_buf_size) {
+l = ring->ring_buf_size;
+}
+
+memcpy(frame_buf, buf + len, l);
+iov.iov_base = frame_buf;
+iov.iov_len = l;
+eth_get_protocols(, 1, 0,
+  , ,
+  _off, _off, _off,
+  _info, _info, _info);
+
+len += l;
+
+desc->length_status = FIELD_DP32(desc->length_status,
+ GENET_RDMA_LENGTH_STATUS,
+ EOP, !!(len >= size));
+
+buflength = l + sizeof(BCM2838GenetXmitStatus) + 2;
+if 

[PATCH v6 19/41] Add GENET stub

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2838_thermal.c|  2 +-
 hw/net/bcm2838_genet.c   | 99 
 hw/net/meson.build   |  2 +
 hw/net/trace-events  | 16 +
 include/hw/arm/bcm2838_peripherals.h |  2 +
 include/hw/net/bcm2838_genet.h   | 40 +++
 6 files changed, 160 insertions(+), 1 deletion(-)
 create mode 100644 hw/net/bcm2838_genet.c
 create mode 100644 include/hw/net/bcm2838_genet.h

diff --git a/hw/misc/bcm2838_thermal.c b/hw/misc/bcm2838_thermal.c
index 3764d55b59..b5f50991d4 100644
--- a/hw/misc/bcm2838_thermal.c
+++ b/hw/misc/bcm2838_thermal.c
@@ -80,7 +80,7 @@ static void bcm2838_thermal_class_init(ObjectClass *klass, 
void *data)
 
 dc->realize = bcm2838_thermal_realize;
 
-/* This device has no state: no need for vmstate or reset */
+/* This device has nothing to save: no need for vmstate or reset */
 }
 
 static const TypeInfo bcm2838_thermal_info = {
diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
new file mode 100644
index 00..4420486e00
--- /dev/null
+++ b/hw/net/bcm2838_genet.c
@@ -0,0 +1,99 @@
+/*
+ * BCM2838 Gigabit Ethernet emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "net/eth.h"
+#include "qapi/error.h"
+#include "hw/irq.h"
+#include "net/checksum.h"
+#include "sysemu/dma.h"
+#include "hw/net/bcm2838_genet.h"
+#include "trace.h"
+
+
+static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
+{
+uint64_t value = ~0;
+
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+
+trace_bcm2838_genet_read(size, offset, value);
+return value;
+}
+
+static void bcm2838_genet_write(void *opaque, hwaddr offset, uint64_t value,
+unsigned size) {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
+
+static const MemoryRegionOps bcm2838_genet_ops = {
+.read = bcm2838_genet_read,
+.write = bcm2838_genet_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {.max_access_size = 4},
+.valid = {.min_access_size = 4},
+};
+
+
+static void bcm2838_genet_realize(DeviceState *dev, Error **errp)
+{
+BCM2838GenetState *s = BCM2838_GENET(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+/* Controller registers */
+memory_region_init_io(>regs_mr, OBJECT(s), _genet_ops, s,
+  "bcm2838_genet_regs", sizeof(s->regs));
+sysbus_init_mmio(sbd, >regs_mr);
+}
+
+static void bcm2838_genet_phy_reset(BCM2838GenetState *s)
+{
+trace_bcm2838_genet_phy_reset("done");
+}
+
+static void bcm2838_genet_reset(DeviceState *d)
+{
+BCM2838GenetState *s = BCM2838_GENET(d);
+
+memset(>regs, 0x00, sizeof(s->regs));
+
+trace_bcm2838_genet_reset("done");
+
+bcm2838_genet_phy_reset(s);
+}
+
+static void bcm2838_genet_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+
+dc->realize = bcm2838_genet_realize;
+dc->reset = bcm2838_genet_reset;
+}
+
+static const TypeInfo bcm2838_genet_info = {
+.name   = TYPE_BCM2838_GENET,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(BCM2838GenetState),
+.class_init = bcm2838_genet_class_init,
+};
+
+static void bcm2838_genet_register(void)
+{
+type_register_static(_genet_info);
+}
+
+type_init(bcm2838_genet_register)
diff --git a/hw/net/meson.build b/hw/net/meson.build
index b7426870e8..b9cd12cde2 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -70,4 +70,6 @@ system_ss.add(when: 'CONFIG_ROCKER', if_true: files(
 ), if_false: files('rocker/qmp-norocker.c'))
 system_ss.add(files('rocker/rocker-hmp-cmds.c'))
 
+system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2838_genet.c'))
+
 subdir('can')
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 78efa2ec2c..3919cb698b 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -513,3 +513,19 @@ xen_netdev_connect(int dev, unsigned int tx, unsigned int 
rx, int port) "vif%u t
 xen_netdev_frontend_changed(const char *dev, int state) "vif%s state %d"
 xen_netdev_tx(int dev, int ref, int off, int len, unsigned int flags, const 
char *c, const char *d, const char *m, const char *e) "vif%u ref %u off %u len 
%u flags 0x%x%s%s%s%s"
 xen_netdev_rx(int dev, int idx, int status, int flags) "vif%u idx %d status %d 
flags 0x%x"
+# bcm2838_gen

[PATCH v6 22/41] Add GENET register structs. Part 3

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 88 ++
 include/hw/net/bcm2838_genet.h | 88 ++
 2 files changed, 176 insertions(+)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 9a99f34c4a..be899b68f8 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -145,6 +145,94 @@ FIELD(GENET_RDMA_LENGTH_STATUS, OWN,15, 1)
 FIELD(GENET_RDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
 FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
 
+REG32(GENET_TDMA_LENGTH_STATUS, 0)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_0_3,   0, 4)
+FIELD(GENET_TDMA_LENGTH_STATUS, DO_CSUM,4, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, OW_CRC, 5, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, APPEND_CRC, 6, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_7_8,   7, 2)
+FIELD(GENET_TDMA_LENGTH_STATUS, UNDERRUN,   9, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_10_11, 10, 2)
+FIELD(GENET_TDMA_LENGTH_STATUS, WRAP,   12, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, SOP,13, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, EOP,14, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, OWN,15, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
+
+REG16(GENET_PHY_BMCR,0)
+FIELD(GENET_PHY_BMCR, RSVD_0_5,  0, 6)
+FIELD(GENET_PHY_BMCR, SPEED1000, 6, 1)
+FIELD(GENET_PHY_BMCR, CTST,  7, 1)
+FIELD(GENET_PHY_BMCR, FULLDPLX,  8, 1)
+FIELD(GENET_PHY_BMCR, ANRESTART, 9, 1)
+FIELD(GENET_PHY_BMCR, ISOLATE,   10, 1)
+FIELD(GENET_PHY_BMCR, PDOWN, 11, 1)
+FIELD(GENET_PHY_BMCR, AENABLE,   12, 1)
+FIELD(GENET_PHY_BMCR, SPEED100,  13, 1)
+FIELD(GENET_PHY_BMCR, LOOPBACK,  14, 1)
+FIELD(GENET_PHY_BMCR, RESET, 15, 1)
+
+REG16(GENET_PHY_BMSR,   0)
+FIELD(GENET_PHY_BMSR, ERCAP,0, 1)
+FIELD(GENET_PHY_BMSR, JCD,  1, 1)
+FIELD(GENET_PHY_BMSR, LSTATUS,  2, 1)
+FIELD(GENET_PHY_BMSR, ANEGCAPABLE,  3, 1)
+FIELD(GENET_PHY_BMSR, RFAULT,   4, 1)
+FIELD(GENET_PHY_BMSR, ANEGCOMPLETE, 5, 1)
+FIELD(GENET_PHY_BMSR, RSVD_6_7, 6, 2)
+FIELD(GENET_PHY_BMSR, ESTATEN,  8, 1)
+FIELD(GENET_PHY_BMSR, _100HALF2,9, 1)
+FIELD(GENET_PHY_BMSR, _100FULL2,10, 1)
+FIELD(GENET_PHY_BMSR, _10HALF,  11, 1)
+FIELD(GENET_PHY_BMSR, _10FULL,  12, 1)
+FIELD(GENET_PHY_BMSR, _100HALF, 13, 1)
+FIELD(GENET_PHY_BMSR, _100FULL, 14, 1)
+FIELD(GENET_PHY_BMSR, _10BASE4, 15, 1)
+
+REG16(GENET_PHY_LPA,   0)
+FIELD(GENET_PHY_LPA, SLCT, 0, 5)
+FIELD(GENET_PHY_LPA, _10HALF_1000XFULL,5, 1)
+FIELD(GENET_PHY_LPA, _10FULL_1000XHALF,6, 1)
+FIELD(GENET_PHY_LPA, _100HALF_1000XPAUSE,  7, 1)
+FIELD(GENET_PHY_LPA, _100FULL_1000XPAUSE_ASYM, 8, 1)
+FIELD(GENET_PHY_LPA, _100BASE4,9, 1)
+FIELD(GENET_PHY_LPA, PAUSE_CAP,10, 1)
+FIELD(GENET_PHY_LPA, PAUSE_ASYM,   11, 1)
+FIELD(GENET_PHY_LPA, RSVD_12,  12, 1)
+FIELD(GENET_PHY_LPA, RFAULT,   13, 1)
+FIELD(GENET_PHY_LPA, LPACK,14, 1)
+FIELD(GENET_PHY_LPA, NPAGE,15, 1)
+
+REG16(GENET_PHY_STAT_1000,0)
+FIELD(GENET_PHY_STAT_1000, RSVD_0_9,  0, 10)
+FIELD(GENET_PHY_STAT_1000, HALF,  10, 1)
+FIELD(GENET_PHY_STAT_1000, FULL,  11, 1)
+FIELD(GENET_PHY_STAT_1000, REMRXOK,   12, 1)
+FIELD(GENET_PHY_STAT_1000, LOCALRXOK, 13, 1)
+FIELD(GENET_PHY_STAT_1000, MSRES, 14, 1)
+FIELD(GENET_PHY_STAT_1000, MSFAIL,15, 1)
+
+REG16(GENET_PHY_AUX_CTRL_0,  0)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_ID_MASK, 0, 3)
+FIELD(GENET_PHY_AUX_CTRL_0, RSVD_3,  3, 1)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_DATA,4, 8)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_ID,  12, 3)
+FIELD(GENET_PHY_AUX_CTRL_0, MISC_WREN,   15, 1)
+
+REG16(GENET_PHY_AUX_CTRL_1,   0)
+FIELD(GENET_PHY_AUX_CTRL_1, RSVD_0_3, 0, 4)
+FIELD(GENET_PHY_AUX_CTRL_1, REG_DATA, 4, 12)
+
+REG16(GENET_PHY_SHADOW,   0)
+FIELD(GENET_PHY_SHADOW, REG_DATA, 0, 10)
+FIELD(GENET_PHY_SHADOW, REG_ID,   10, 5)
+FIELD(GENET_PHY_SHADOW, WR,   15, 1)
+
+REG16(GENET_PHY_EXP_SEL,   0)
+FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
+FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
+
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
 uint64_t value = ~0;
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 736b4d1757..1bd004785a 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -22,6 +22,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_DMA_RING_CNT  17
 #define BCM2838_GENET_DMA_RING_DEFAULT  (BCM2838_GENET_DMA_RING_CNT - 1)
 
+#define BCM2838_GENET_HFB_FILTER_CNT  48
+#define BCM2838_GENET_HFB_FILTER_SIZE 128
+
 typedef struct {
 uint32_t rev_ctrl;
 uint32_t port_ctrl;
@@ -169,6 +172,53 @@ typedef struct {
 uint32_t reserved_0x10D0[972];
 } BCM2838GenetRegsRdma

[PATCH v6 03/41] Split out raspi machine common part

2024-02-25 Thread Sergey Kambalin
Pre-setup for raspberry pi 4 introduction

Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/raspi.c  | 112 ++--
 include/hw/arm/raspi_platform.h |  21 ++
 2 files changed, 85 insertions(+), 48 deletions(-)

diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index af866ebce2..7d04734cd2 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -18,6 +18,7 @@
 #include "qapi/error.h"
 #include "hw/arm/boot.h"
 #include "hw/arm/bcm2836.h"
+#include "hw/arm/raspi_platform.h"
 #include "hw/registerfields.h"
 #include "qemu/error-report.h"
 #include "hw/boards.h"
@@ -25,6 +26,9 @@
 #include "hw/arm/boot.h"
 #include "qom/object.h"
 
+#define TYPE_RASPI_MACHINE  MACHINE_TYPE_NAME("raspi-common")
+OBJECT_DECLARE_SIMPLE_TYPE(RaspiMachineState, RASPI_MACHINE)
+
 #define SMPBOOT_ADDR0x300 /* this should leave enough space for ATAGS */
 #define MVBAR_ADDR  0x400 /* secure vectors */
 #define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
@@ -37,25 +41,10 @@
 
 struct RaspiMachineState {
 /*< private >*/
-MachineState parent_obj;
+RaspiBaseMachineState parent_obj;
 /*< public >*/
 BCM283XState soc;
-struct arm_boot_info binfo;
-};
-typedef struct RaspiMachineState RaspiMachineState;
-
-struct RaspiMachineClass {
-/*< private >*/
-MachineClass parent_obj;
-/*< public >*/
-uint32_t board_rev;
 };
-typedef struct RaspiMachineClass RaspiMachineClass;
-
-#define TYPE_RASPI_MACHINE   MACHINE_TYPE_NAME("raspi-common")
-DECLARE_OBJ_CHECKERS(RaspiMachineState, RaspiMachineClass,
- RASPI_MACHINE, TYPE_RASPI_MACHINE)
-
 
 /*
  * Board revision codes:
@@ -83,6 +72,11 @@ static const struct {
 [PROCESSOR_ID_BCM2837] = {TYPE_BCM2837, BCM283X_NCPUS},
 };
 
+static void raspi_base_machine_init(MachineState *machine,
+ BCM283XBaseState *soc);
+static void raspi_machine_class_common_init(MachineClass *mc,
+ uint32_t board_rev);
+
 static uint64_t board_ram_size(uint32_t board_rev)
 {
 assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
@@ -200,13 +194,12 @@ static void reset_secondary(ARMCPU *cpu, const struct 
arm_boot_info *info)
 cpu_set_pc(cs, info->smp_loader_start);
 }
 
-static void setup_boot(MachineState *machine, RaspiProcessorId processor_id,
-   size_t ram_size)
+static void setup_boot(MachineState *machine, ARMCPU *cpu,
+   RaspiProcessorId processor_id, size_t ram_size)
 {
-RaspiMachineState *s = RASPI_MACHINE(machine);
+RaspiBaseMachineState *s = RASPI_BASE_MACHINE(machine);
 int r;
 
-s->binfo.board_id = MACH_TYPE_BCM2708;
 s->binfo.ram_size = ram_size;
 
 if (processor_id <= PROCESSOR_ID_BCM2836) {
@@ -252,13 +245,13 @@ static void setup_boot(MachineState *machine, 
RaspiProcessorId processor_id,
 s->binfo.firmware_loaded = true;
 }
 
-arm_load_kernel(>soc.parent_obj.cpu[0].core, machine, >binfo);
+arm_load_kernel(cpu, machine, >binfo);
 }
 
-static void raspi_machine_init(MachineState *machine)
+static void raspi_base_machine_init(MachineState *machine,
+ BCM283XBaseState *soc)
 {
-RaspiMachineClass *mc = RASPI_MACHINE_GET_CLASS(machine);
-RaspiMachineState *s = RASPI_MACHINE(machine);
+RaspiBaseMachineClass *mc = RASPI_BASE_MACHINE_GET_CLASS(machine);
 uint32_t board_rev = mc->board_rev;
 uint64_t ram_size = board_ram_size(board_rev);
 uint32_t vcram_size;
@@ -279,19 +272,17 @@ static void raspi_machine_init(MachineState *machine)
 machine->ram, 0);
 
 /* Setup the SOC */
-object_initialize_child(OBJECT(machine), "soc", >soc,
-board_soc_type(board_rev));
-object_property_add_const_link(OBJECT(>soc), "ram", 
OBJECT(machine->ram));
-object_property_set_int(OBJECT(>soc), "board-rev", board_rev,
+object_property_add_const_link(OBJECT(soc), "ram", OBJECT(machine->ram));
+object_property_set_int(OBJECT(soc), "board-rev", board_rev,
 _abort);
-object_property_set_str(OBJECT(>soc), "command-line",
+object_property_set_str(OBJECT(soc), "command-line",
 machine->kernel_cmdline, _abort);
-qdev_realize(DEVICE(>soc), NULL, _fatal);
+qdev_realize(DEVICE(soc), NULL, _fatal);
 
 /* Create and plug in the SD cards */
 di = drive_get(IF_SD, 0, 0);
 blk = di ? blk_by_legacy_dinfo(di) : NULL;
-bus = qdev_get_child_bus(DEVICE(>soc), "sd-bus");
+bus = qdev_get_child_bus(DEVICE(soc), "sd-bus");
 if (bus == NULL) 

[PATCH v6 09/41] Add GPIO and SD to BCM2838 periph

2024-02-25 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
Reviewed-by: Peter Maydell 
---
 hw/arm/bcm2838_peripherals.c | 143 +++
 include/hw/arm/bcm2838_peripherals.h |   8 ++
 2 files changed, 151 insertions(+)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 06110c724f..55ae56733f 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -15,22 +15,56 @@
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
+/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
+#define BCM2835_SDHC_CAPAREG 0x52134b4
+
 static void bcm2838_peripherals_init(Object *obj)
 {
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(obj);
 BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_GET_CLASS(obj);
+BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(obj);
 
 /* Lower memory region for peripheral devices (exported to the Soc) */
 memory_region_init(>peri_low_mr, obj, "bcm2838-peripherals",
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* Extended Mass Media Controller 2 */
+object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
+
+/* GPIO */
+object_initialize_child(obj, "gpio", >gpio, TYPE_BCM2838_GPIO);
+
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhci",
+   OBJECT(_base->sdhci.sdbus));
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhost",
+   OBJECT(_base->sdhost.sdbus));
+
+object_initialize_child(obj, "mmc_irq_orgate", >mmc_irq_orgate,
+TYPE_OR_IRQ);
+object_property_set_int(OBJECT(>mmc_irq_orgate), "num-lines", 2,
+_abort);
+
+object_initialize_child(obj, "dma_7_8_irq_orgate", >dma_7_8_irq_orgate,
+TYPE_OR_IRQ);
+object_property_set_int(OBJECT(>dma_7_8_irq_orgate), "num-lines", 2,
+_abort);
+
+object_initialize_child(obj, "dma_9_10_irq_orgate", 
>dma_9_10_irq_orgate,
+TYPE_OR_IRQ);
+object_property_set_int(OBJECT(>dma_9_10_irq_orgate), "num-lines", 2,
+_abort);
 }
 
 static void bcm2838_peripherals_realize(DeviceState *dev, Error **errp)
 {
+DeviceState *mmc_irq_orgate;
+DeviceState *dma_7_8_irq_orgate;
+DeviceState *dma_9_10_irq_orgate;
+MemoryRegion *mphi_mr;
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(dev);
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+int n;
 
 bcm_soc_peripherals_common_realize(dev, errp);
 
@@ -42,6 +76,115 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCM2838_VC_PERI_LOW_BASE,
 >peri_low_mr_alias, 1);
 
+/* Extended Mass Media Controller 2 */
+object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
+ _abort);
+object_property_set_uint(OBJECT(>emmc2), "capareg",
+ BCM2835_SDHC_CAPAREG, _abort);
+object_property_set_bool(OBJECT(>emmc2), "pending-insert-quirk", true,
+ _abort);
+if (!sysbus_realize(SYS_BUS_DEVICE(>emmc2), errp)) {
+return;
+}
+
+memory_region_add_subregion(_base->peri_mr, EMMC2_OFFSET,
+
sysbus_mmio_get_region(SYS_BUS_DEVICE(>emmc2),
+0));
+
+/* According to DTS, EMMC and EMMC2 share one irq */
+if (!qdev_realize(DEVICE(>mmc_irq_orgate), NULL, errp)) {
+return;
+}
+
+mmc_irq_orgate = DEVICE(>mmc_irq_orgate);
+sysbus_connect_irq(SYS_BUS_DEVICE(>emmc2), 0,
+   qdev_get_gpio_in(mmc_irq_orgate, 0));
+
+sysbus_connect_irq(SYS_BUS_DEVICE(_base->sdhci), 0,
+   qdev_get_gpio_in(mmc_irq_orgate, 1));
+
+   /* Connect EMMC and EMMC2 to the interrupt controller */
+qdev_connect_gpio_out(mmc_irq_orgate, 0,
+  qdev_get_gpio_in_named(DEVICE(_base->ic),
+ BCM2835_IC_GPU_IRQ,
+ INTERRUPT_ARASANSDIO));
+
+/* Connect DMA 0-6 to the interrupt controller */
+for (n = 0; n < 7; n++) {
+sysbus_connect_irq(SYS_BUS_DEVICE(_base->dma), n,
+   qdev_get_gpio_in_named(DEVICE(_base->ic),
+  BCM2835_IC_GPU_IRQ,
+  GPU_INTERRUPT_DMA0 + n));
+}
+
+   /* According to DTS

[PATCH v5 19/41] Add GENET stub

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2838_thermal.c|  2 +-
 hw/net/bcm2838_genet.c   | 99 
 hw/net/meson.build   |  2 +
 hw/net/trace-events  | 16 +
 include/hw/arm/bcm2838_peripherals.h |  2 +
 include/hw/net/bcm2838_genet.h   | 40 +++
 6 files changed, 160 insertions(+), 1 deletion(-)
 create mode 100644 hw/net/bcm2838_genet.c
 create mode 100644 include/hw/net/bcm2838_genet.h

diff --git a/hw/misc/bcm2838_thermal.c b/hw/misc/bcm2838_thermal.c
index 3764d55b59..b5f50991d4 100644
--- a/hw/misc/bcm2838_thermal.c
+++ b/hw/misc/bcm2838_thermal.c
@@ -80,7 +80,7 @@ static void bcm2838_thermal_class_init(ObjectClass *klass, 
void *data)
 
 dc->realize = bcm2838_thermal_realize;
 
-/* This device has no state: no need for vmstate or reset */
+/* This device has nothing to save: no need for vmstate or reset */
 }
 
 static const TypeInfo bcm2838_thermal_info = {
diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
new file mode 100644
index 00..4420486e00
--- /dev/null
+++ b/hw/net/bcm2838_genet.c
@@ -0,0 +1,99 @@
+/*
+ * BCM2838 Gigabit Ethernet emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "net/eth.h"
+#include "qapi/error.h"
+#include "hw/irq.h"
+#include "net/checksum.h"
+#include "sysemu/dma.h"
+#include "hw/net/bcm2838_genet.h"
+#include "trace.h"
+
+
+static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
+{
+uint64_t value = ~0;
+
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+
+trace_bcm2838_genet_read(size, offset, value);
+return value;
+}
+
+static void bcm2838_genet_write(void *opaque, hwaddr offset, uint64_t value,
+unsigned size) {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
+
+static const MemoryRegionOps bcm2838_genet_ops = {
+.read = bcm2838_genet_read,
+.write = bcm2838_genet_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {.max_access_size = 4},
+.valid = {.min_access_size = 4},
+};
+
+
+static void bcm2838_genet_realize(DeviceState *dev, Error **errp)
+{
+BCM2838GenetState *s = BCM2838_GENET(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+/* Controller registers */
+memory_region_init_io(>regs_mr, OBJECT(s), _genet_ops, s,
+  "bcm2838_genet_regs", sizeof(s->regs));
+sysbus_init_mmio(sbd, >regs_mr);
+}
+
+static void bcm2838_genet_phy_reset(BCM2838GenetState *s)
+{
+trace_bcm2838_genet_phy_reset("done");
+}
+
+static void bcm2838_genet_reset(DeviceState *d)
+{
+BCM2838GenetState *s = BCM2838_GENET(d);
+
+memset(>regs, 0x00, sizeof(s->regs));
+
+trace_bcm2838_genet_reset("done");
+
+bcm2838_genet_phy_reset(s);
+}
+
+static void bcm2838_genet_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+
+dc->realize = bcm2838_genet_realize;
+dc->reset = bcm2838_genet_reset;
+}
+
+static const TypeInfo bcm2838_genet_info = {
+.name   = TYPE_BCM2838_GENET,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(BCM2838GenetState),
+.class_init = bcm2838_genet_class_init,
+};
+
+static void bcm2838_genet_register(void)
+{
+type_register_static(_genet_info);
+}
+
+type_init(bcm2838_genet_register)
diff --git a/hw/net/meson.build b/hw/net/meson.build
index b7426870e8..b9cd12cde2 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -70,4 +70,6 @@ system_ss.add(when: 'CONFIG_ROCKER', if_true: files(
 ), if_false: files('rocker/qmp-norocker.c'))
 system_ss.add(files('rocker/rocker-hmp-cmds.c'))
 
+system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2838_genet.c'))
+
 subdir('can')
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 78efa2ec2c..3919cb698b 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -513,3 +513,19 @@ xen_netdev_connect(int dev, unsigned int tx, unsigned int 
rx, int port) "vif%u t
 xen_netdev_frontend_changed(const char *dev, int state) "vif%s state %d"
 xen_netdev_tx(int dev, int ref, int off, int len, unsigned int flags, const 
char *c, const char *d, const char *m, const char *e) "vif%u ref %u off %u len 
%u flags 0x%x%s%s%s%s"
 xen_netdev_rx(int dev, int idx, int status, int flags) "vif%u idx %d status %d 
flags 0x%x"
+# bcm2838_gen

[PATCH v5 39/41] Add missed BCM2835 properties

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2835_property.c   | 21 +
 include/hw/arm/raspberrypi-fw-defs.h | 11 +++
 2 files changed, 32 insertions(+)

diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index 5c48f8d743..bdd9a6bbce 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -19,6 +19,8 @@
 #include "trace.h"
 #include "hw/arm/raspi_platform.h"
 
+#define VCHI_BUSADDR_SIZE   sizeof(uint32_t)
+
 /* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
 
 static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
@@ -138,6 +140,13 @@ static void 
bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 resplen = 8;
 break;
 
+case RPI_FWREQ_GET_CLOCKS:
+/* TODO: add more clock IDs if needed */
+stl_le_phys(>dma_as, value + 12, 0);
+stl_le_phys(>dma_as, value + 16, RPI_FIRMWARE_ARM_CLK_ID);
+resplen = 8;
+break;
+
 case RPI_FWREQ_SET_CLOCK_RATE:
 case RPI_FWREQ_SET_MAX_CLOCK_RATE:
 case RPI_FWREQ_SET_MIN_CLOCK_RATE:
@@ -276,6 +285,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState 
*s, uint32_t value)
 stl_le_phys(>dma_as, value + 12, 0);
 resplen = 4;
 break;
+
 case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
 stl_le_phys(>dma_as, value + 12, 1);
 resplen = 4;
@@ -301,6 +311,17 @@ static void 
bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 resplen);
 break;
 
+case RPI_FWREQ_GET_THROTTLED:
+stl_le_phys(>dma_as, value + 12, 0);
+resplen = 4;
+break;
+
+case RPI_FWREQ_VCHIQ_INIT:
+stl_le_phys(>dma_as,
+value + offsetof(rpi_firmware_prop_request_t, payload),
+0);
+resplen = VCHI_BUSADDR_SIZE;
+break;
 default:
 qemu_log_mask(LOG_UNIMP,
   "bcm2835_property: unhandled tag 0x%08x\n", tag);
diff --git a/include/hw/arm/raspberrypi-fw-defs.h 
b/include/hw/arm/raspberrypi-fw-defs.h
index 579cf0d554..8b404e0533 100644
--- a/include/hw/arm/raspberrypi-fw-defs.h
+++ b/include/hw/arm/raspberrypi-fw-defs.h
@@ -159,4 +159,15 @@ enum rpi_firmware_clk_id {
 RPI_FIRMWARE_NUM_CLK_ID,
 };
 
+struct rpi_firmware_property_tag_header {
+uint32_t tag;
+uint32_t buf_size;
+uint32_t req_resp_size;
+};
+
+typedef struct rpi_firmware_prop_request {
+struct rpi_firmware_property_tag_header hdr;
+uint8_t payload[0];
+} rpi_firmware_prop_request_t;
+
 #endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */
-- 
2.34.1




[PATCH v5 21/41] Add GENET register structs. Part 2

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 89 ++
 include/hw/net/bcm2838_genet.h | 89 ++
 2 files changed, 178 insertions(+)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 0d98d1b30e..9a99f34c4a 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -19,6 +19,7 @@
 #include "hw/net/bcm2838_genet.h"
 #include "trace.h"
 
+/* GENET layouts */
 REG32(GENET_SYS_REV_CTRL,  0)
 FIELD(GENET_SYS_REV_CTRL, GPHY_REV,0, 16)
 FIELD(GENET_SYS_REV_CTRL, MINOR_REV,   16, 4)
@@ -55,6 +56,94 @@ REG32(GENET_INTRL_1,  0)
 FIELD(GENET_INTRL_1, TX_INTRS,0, 16)
 FIELD(GENET_INTRL_1, RX_INTRS,16, 16)
 
+REG32(GENET_UMAC_CMD,  0)
+FIELD(GENET_UMAC_CMD, TX_EN,   0, 1)
+FIELD(GENET_UMAC_CMD, RX_EN,   1, 1)
+FIELD(GENET_UMAC_CMD, SPEED,   2, 2)
+FIELD(GENET_UMAC_CMD, PROMISC, 4, 1)
+FIELD(GENET_UMAC_CMD, PAD_EN,  5, 1)
+FIELD(GENET_UMAC_CMD, CRC_FWD, 6, 1)
+FIELD(GENET_UMAC_CMD, PAUSE_FWD,   7, 1)
+FIELD(GENET_UMAC_CMD, RX_PAUSE_IGNORE, 8, 1)
+FIELD(GENET_UMAC_CMD, TX_ADDR_INS, 9, 1)
+FIELD(GENET_UMAC_CMD, HD_EN,   10, 1)
+FIELD(GENET_UMAC_CMD, SW_RESET_OLD,11, 1)
+FIELD(GENET_UMAC_CMD, RSVD_12, 12, 1)
+FIELD(GENET_UMAC_CMD, SW_RESET,13, 1)
+FIELD(GENET_UMAC_CMD, RSVD_14, 14, 1)
+FIELD(GENET_UMAC_CMD, LCL_LOOP_EN, 15, 1)
+FIELD(GENET_UMAC_CMD, RSVD_16_21,  16, 6)
+FIELD(GENET_UMAC_CMD, AUTO_CONFIG, 22, 1)
+FIELD(GENET_UMAC_CMD, CNTL_FRM_EN, 23, 1)
+FIELD(GENET_UMAC_CMD, NO_LEN_CHK,  24, 1)
+FIELD(GENET_UMAC_CMD, RMT_LOOP_EN, 25, 1)
+FIELD(GENET_UMAC_CMD, RX_ERR_DISC, 26, 1)
+FIELD(GENET_UMAC_CMD, PRBL_EN, 27, 1)
+FIELD(GENET_UMAC_CMD, TX_PAUSE_IGNORE, 28, 1)
+FIELD(GENET_UMAC_CMD, TX_RX_EN,29, 1)
+FIELD(GENET_UMAC_CMD, RUNT_FILTER_DIS, 30, 1)
+FIELD(GENET_UMAC_CMD, RSVD_31, 31, 1)
+
+REG32(GENET_UMAC_MAC_0, 0)
+FIELD(GENET_UMAC_MAC_0, ADDR_3, 0,  8)
+FIELD(GENET_UMAC_MAC_0, ADDR_2, 8,  8)
+FIELD(GENET_UMAC_MAC_0, ADDR_1, 16, 8)
+FIELD(GENET_UMAC_MAC_0, ADDR_0, 24, 8)
+
+REG32(GENET_UMAC_MAC_1, 0)
+FIELD(GENET_UMAC_MAC_1, ADDR_5, 0,  8)
+FIELD(GENET_UMAC_MAC_1, ADDR_4, 8,  8)
+FIELD(GENET_UMAC_MAC_1, RSVD_16_31, 16, 8)
+
+REG32(GENET_UMAC_MDIO_CMD, 0)
+FIELD(GENET_UMAC_MDIO_CMD, REG_DATA,   0, 16)
+FIELD(GENET_UMAC_MDIO_CMD, REG_ID, 16, 5)
+FIELD(GENET_UMAC_MDIO_CMD, PHY_ID, 21, 5)
+FIELD(GENET_UMAC_MDIO_CMD, WR, 26, 1)
+FIELD(GENET_UMAC_MDIO_CMD, RD, 27, 1)
+FIELD(GENET_UMAC_MDIO_CMD, RD_FAIL,28, 1)
+FIELD(GENET_UMAC_MDIO_CMD, START_BUSY, 29, 1)
+FIELD(GENET_UMAC_MDIO_CMD, RSVD_30_31, 30, 2)
+
+REG32(GENET_DMA_RING_CFG, 0)
+FIELD(GENET_DMA_RING_CFG, EN, 0, 17)
+FIELD(GENET_DMA_RING_CFG, RSVD_17_31, 17, 14)
+
+REG32(GENET_DMA_CTRL,  0)
+FIELD(GENET_DMA_CTRL, EN,  0, 1)
+FIELD(GENET_DMA_CTRL, RING_BUF_EN, 1, 17)
+FIELD(GENET_DMA_CTRL, RSVD_18_19,  18, 2)
+FIELD(GENET_DMA_CTRL, TSB_SWAP_EN, 20, 1)
+FIELD(GENET_DMA_CTRL, RSVD_21_31,  21, 11)
+
+REG32(GENET_DMA_PROD_INDEX,  0)
+FIELD(GENET_DMA_PROD_INDEX, INDEX,   0, 16)
+FIELD(GENET_DMA_PROD_INDEX, DISCARD_CNT, 16, 16)
+
+REG32(GENET_DMA_CONS_INDEX, 0)
+FIELD(GENET_DMA_CONS_INDEX, INDEX,  0, 16)
+FIELD(GENET_DMA_CONS_INDEX, RSVD_16_31, 16, 16)
+
+REG32(GENET_DMA_STATUS, 0)
+FIELD(GENET_DMA_STATUS, DISABLED,   0, 1)
+FIELD(GENET_DMA_STATUS, DESC_RAM_INIT_BUSY, 1, 1)
+FIELD(GENET_DMA_STATUS, RSVD_2_31,  2, 30)
+
+REG32(GENET_RDMA_LENGTH_STATUS, 0)
+FIELD(GENET_RDMA_LENGTH_STATUS, OVERRUN,0, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, CRC_ERROR,  1, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, RXERR,  2, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, NO, 3, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, LG, 4, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, MULTICAST,  5, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, BROADCAST,  6, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_7_11,  7, 5)
+FIELD(GENET_RDMA_LENGTH_STATUS, WRAP,   12, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, SOP,13, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, EOP,14, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, OWN,15, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
+FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
 
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index f583818399..736b4d1757 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -18,6 +18,10 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_REV_MAJOR 6
 #define BCM2838_GENET_REV_MINOR 0
 
+#define BCM2838_GENET_DMA_DESC_CNT  256
+#define BCM2838_GENET_DMA_RING_

[PATCH v5 26/41] Implement GENET MDIO

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 126 -
 include/hw/net/bcm2838_genet.h |   3 +-
 2 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 56ff6a6f39..1fae3ecbc2 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -213,6 +213,7 @@ FIELD(GENET_PHY_STAT_1000, LOCALRXOK, 13, 1)
 FIELD(GENET_PHY_STAT_1000, MSRES, 14, 1)
 FIELD(GENET_PHY_STAT_1000, MSFAIL,15, 1)
 
+/* There are two data representations for PHY_AUX_CTRL register */
 REG16(GENET_PHY_AUX_CTRL_0,  0)
 FIELD(GENET_PHY_AUX_CTRL_0, REG_ID_MASK, 0, 3)
 FIELD(GENET_PHY_AUX_CTRL_0, RSVD_3,  3, 1)
@@ -269,6 +270,123 @@ static void bcm2838_genet_set_irq_prio(BCM2838GenetState 
*s)
 qemu_set_irq(s->irq_prio, level);
 }
 
+static void bcm2838_genet_phy_aux_ctl_write(BCM2838GenetState *s,
+uint16_t value)
+{
+uint16_t reg_id = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, REG_ID);
+uint16_t reg_id_mask = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, 
REG_ID_MASK);
+uint16_t misc_wren = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, MISC_WREN);
+uint16_t reg_data = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, REG_DATA);
+uint16_t reg_data12 = FIELD_EX16(value, GENET_PHY_AUX_CTRL_1, REG_DATA);
+
+uint16_t *phy_aux_ctl_shd_reg_id = (uint16_t *)>phy_aux_ctl_shd_regs + 
reg_id;
+uint16_t *phy_aux_ctl_shd_reg_id_mask = (uint16_t 
*)>phy_aux_ctl_shd_regs + reg_id_mask;
+
+if (reg_id_mask == BCM2838_GENET_PHY_AUX_CTL_MISC) {
+if (reg_id == BCM2838_GENET_PHY_AUX_CTL_MISC) {
+if (misc_wren == 0) {
+/* write for subsequent read (8-bit from AUX_CTL_MISC) */
+FIELD_DP16(value, GENET_PHY_AUX_CTRL_0, REG_DATA, 
*phy_aux_ctl_shd_reg_id);
+} else {
+/* write 8 bits to AUX_CTL_MISC */
+*phy_aux_ctl_shd_reg_id_mask = reg_data;
+}
+} else {
+/* write for subsequent read (12-bit) */
+FIELD_DP16(value, GENET_PHY_AUX_CTRL_1, REG_DATA, 
*phy_aux_ctl_shd_reg_id);
+}
+} else {
+/* write 12 bits */
+*phy_aux_ctl_shd_reg_id_mask = reg_data12;
+}
+
+s->phy_regs.aux_ctl = value;
+}
+
+static void bcm2838_genet_phy_shadow_write(BCM2838GenetState *s,
+   uint16_t value)
+{
+uint16_t reg_id = FIELD_EX16(value, GENET_PHY_SHADOW, REG_ID);
+uint16_t wr = FIELD_EX16(value, GENET_PHY_SHADOW, WR);
+uint16_t reg_data = FIELD_EX16(value, GENET_PHY_SHADOW, REG_DATA);
+
+uint16_t *phy_shd_reg = (uint16_t *)>phy_shd_regs + reg_id;
+
+if (wr == 0) {
+FIELD_DP16(value, GENET_PHY_SHADOW, REG_DATA, *phy_shd_reg);
+} else {
+*phy_shd_reg = reg_data;
+}
+
+s->phy_regs.shd = value;
+}
+
+static void bcm2838_genet_phy_exp_shadow_write(BCM2838GenetState *s,
+   uint16_t value)
+{
+/* TODO Stub implementation without side effect,
+just storing registers values */
+uint16_t reg_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+ GENET_PHY_EXP_SEL, REG_ID);
+uint16_t block_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+   GENET_PHY_EXP_SEL, BLOCK_ID);
+
+s->phy_exp_shd_regs.regs[block_id][reg_id] = value;
+}
+
+static uint16_t bcm2838_genet_phy_exp_shadow_read(BCM2838GenetState *s)
+{
+uint16_t reg_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+ GENET_PHY_EXP_SEL, REG_ID);
+uint16_t block_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+   GENET_PHY_EXP_SEL, BLOCK_ID);
+
+return s->phy_exp_shd_regs.regs[block_id][reg_id];
+}
+
+static uint64_t bcm2838_genet_mdio_cmd(BCM2838GenetState *s, uint64_t cmd)
+{
+uint32_t phy_reg_id = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, REG_ID);
+uint32_t phy_reg_data = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, REG_DATA);
+uint32_t start_busy = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, START_BUSY);
+uint32_t rd = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, RD);
+uint32_t wr = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, WR);
+uint16_t *phy_reg = (uint16_t *)>phy_regs + phy_reg_id;
+
+uint16_t anrestart = FIELD_EX16(phy_reg_data, GENET_PHY_BMCR, ANRESTART);
+
+if (start_busy != 0) {
+cmd = FIELD_DP32(cmd, GENET_UMAC_MDIO_CMD, START_BUSY, 0);
+
+if (rd != 0) {
+if (phy_reg_id == BCM2838_GENET_EXP_DATA) {
+cmd = FIELD_DP32(cmd, GENET_UMAC_MDIO_CMD, REG_DATA,
+ bcm2838_genet_phy_exp_shadow_read(s));
+} else {
+cmd = FIELD_DP32(cmd, GENET_UMAC_MDIO_CMD, REG_DATA, *phy_reg);
+}
+} else if (wr != 0) {
+if (phy_reg_id == BCM2838_GENET_PHY_AUX_CTL) {
+  

[PATCH v5 38/41] Add mailbox property tests. Part 3

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 213 ++-
 1 file changed, 212 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index b251d3f552..c96a9ba3f3 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -362,7 +362,194 @@ 
DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT) {
 tag->request.value.height = 600;
 }
 
-//==
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_TEST_DEPTH) {
+g_assert_cmpint(tag->response.value.bpp, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_TEST_DEPTH) {
+tag->request.value.bpp = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_DEPTH) {
+g_assert_cmpint(tag->response.value.bpp, ==, 16);
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_DEPTH) {
+g_assert_cmpint(tag->response.value.bpp, ==, 24);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_DEPTH) {
+tag->request.value.bpp = 24;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_TEST_PIXEL_ORDER) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_TEST_PIXEL_ORDER) {
+tag->request.value.pixel_order = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_PIXEL_ORDER) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, PIXEL_ORDER_RGB);
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_PIXEL_ORDER, BGR) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, PIXEL_ORDER_BGR);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_PIXEL_ORDER, BGR) {
+tag->request.value.pixel_order = PIXEL_ORDER_BGR;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_PIXEL_ORDER, RGB) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, PIXEL_ORDER_BGR);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_PIXEL_ORDER, RGB) {
+tag->request.value.pixel_order = PIXEL_ORDER_BGR;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_TEST_ALPHA_MODE) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_TEST_ALPHA_MODE) {
+tag->request.value.alpha_mode = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_ALPHA_MODE) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_IGNORED);
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_ALPHA_MODE, ENABLED) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_ENABLED);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_ALPHA_MODE, ENABLED) {
+tag->request.value.alpha_mode = ALPHA_MODE_ENABLED;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_ALPHA_MODE, REVERSED) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_REVERSED);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_ALPHA_MODE, REVERSED) {
+tag->request.value.alpha_mode = ALPHA_MODE_REVERSED;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_SET_ALPHA_MODE, IGNORED) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_IGNORED);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_ALPHA_MODE, IGNORED) {
+tag->request.value.alpha_mode = ALPHA_MODE_IGNORED;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_PITCH) {
+g_assert_cmpint(tag->response.value.pitch, ==, 1280);
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_TEST_VIRTUAL_OFFSET) {
+g_assert_cmpint(tag->response.value.x, ==, DUMMY_VALUE);
+g_assert_cmpint(tag->response.value.y, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_TEST_VIRTUAL_OFFSET) {
+tag->request.value.x = DUMMY_VALUE;
+tag->request.value.y = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(FRAMEBUFFER_GET_VIRTUAL_OFFSET) {
+g_assert_cmpint

[PATCH v5 13/41] Add BCM2838 PCIE Root Complex

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_pcie.c | 82 +++
 hw/arm/meson.build|  5 ++-
 include/hw/arm/bcm2838_pcie.h | 53 ++
 3 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/bcm2838_pcie.c
 create mode 100644 include/hw/arm/bcm2838_pcie.h

diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c
new file mode 100644
index 00..cb1370433e
--- /dev/null
+++ b/hw/arm/bcm2838_pcie.c
@@ -0,0 +1,82 @@
+/*
+ * BCM2838 PCIe Root Complex emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/irq.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "qemu/module.h"
+#include "hw/arm/bcm2838_pcie.h"
+#include "trace.h"
+
+/*
+ * RC root part (D0:F0)
+ */
+
+static void bcm2838_pcie_root_port_reset_hold(Object *obj)
+{
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj);
+PCIDevice *dev = PCI_DEVICE(obj);
+BCM2838PcieRootState *s = BCM2838_PCIE_ROOT(dev);
+
+if (rpc->parent_phases.hold) {
+rpc->parent_phases.hold(obj);
+}
+
+memset(s->regs, 0xFF, sizeof(s->regs));
+}
+
+static void bcm2838_pcie_root_init(Object *obj)
+{
+PCIBridge *br = PCI_BRIDGE(obj);
+br->bus_name = "pcie.1";
+}
+
+static void bcm2838_pcie_root_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+PCIDeviceClass *k = PCI_DEVICE_CLASS(class);
+ResettableClass *rc = RESETTABLE_CLASS(class);
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(class);
+
+dc->desc = "BCM2711 PCIe Bridge";
+/*
+ * PCI-facing part of the host bridge, not usable without the host-facing
+ * part, which can't be device_add'ed.
+ */
+
+resettable_class_set_parent_phases(rc, NULL,
+   bcm2838_pcie_root_port_reset_hold,
+   NULL, >parent_phases);
+
+dc->user_creatable = false;
+k->vendor_id = BCM2838_PCIE_VENDOR_ID;
+k->device_id = BCM2838_PCIE_DEVICE_ID;
+k->revision = BCM2838_PCIE_REVISION;
+
+rpc->exp_offset = BCM2838_PCIE_EXP_CAP_OFFSET;
+rpc->aer_offset = BCM2838_PCIE_AER_CAP_OFFSET;
+}
+
+static const TypeInfo bcm2838_pcie_root_info = {
+.name = TYPE_BCM2838_PCIE_ROOT,
+.parent = TYPE_PCIE_ROOT_PORT,
+.instance_size = sizeof(BCM2838PcieRootState),
+.instance_init = bcm2838_pcie_root_init,
+.class_init = bcm2838_pcie_root_class_init,
+};
+
+static void bcm2838_pcie_register(void)
+{
+type_register_static(_pcie_root_info);
+}
+
+type_init(bcm2838_pcie_register)
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 6808135c1f..39f6df7431 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -30,7 +30,10 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: 
files('allwinner-a10.c', 'cubi
 arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 
'orangepi.c'))
 arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 
'bananapi_m2u.c'))
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
-arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: 
files('bcm2838.c', 'raspi4b.c'))
+arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: files(
+  'bcm2838.c',
+  'bcm2838_pcie.c',
+  'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
diff --git a/include/hw/arm/bcm2838_pcie.h b/include/hw/arm/bcm2838_pcie.h
new file mode 100644
index 00..39828f817f
--- /dev/null
+++ b/include/hw/arm/bcm2838_pcie.h
@@ -0,0 +1,53 @@
+/*
+ * BCM2838 PCIe Root Complex emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef BCM2838_PCIE_H
+#define BCM2838_PCIE_H
+
+#include "exec/hwaddr.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci/pcie_port.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2838_PCIE_ROOT "bcm2838-pcie-root"
+OBJECT_DECLARE_TYPE(BCM2838PcieRootState, BCM2838PcieRootClass,
+BCM2838_PCIE_ROOT)
+
+#define BCM2838_PCIE_VENDOR_ID  0x14E4
+#define BCM2838_PCIE_DEVICE_ID  0x2711
+#define BCM2838_PCIE_REVISION   20
+
+#define BCM2838_PCIE_REGS_SIZE  0x9310
+#define BCM2838_PCIE_NUM_IRQS   4
+
+#define BCM2838_PCIE_EXP_CAP_OFFSET 0xAC
+#define BCM2838_PCIE_AER_CAP_OFFSET 0x100
+
+

[PATCH v5 37/41] Add mailbox property tests. Part 2

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 196 ++-
 1 file changed, 195 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index acb421915b..b251d3f552 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -50,7 +50,8 @@ FIELD(GET_CLOCK_STATE_CMD, NPRES, 1, 1)
   (TEST_TAG_TYPE(testname) * tag); 
\
 static void CHECK_FN_NAME(testname, __VA_ARGS__)   
\
  (TEST_TAG_TYPE(testname) *tag);   
\
-static void TEST_FN_NAME(testname, __VA_ARGS__)(void) {
\
+static void TEST_FN_NAME(testname, __VA_ARGS__)(void)  
\
+{  
\
 struct {   
\
 MboxBufHeader header;  
\
 TEST_TAG_TYPE(testname) tag;   
\
@@ -189,6 +190,179 @@ DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, EMMC) {
 }
 
 
/**/
+DECLARE_TEST_CASE(GET_CLOCK_RATE, UART) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UART);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_UART);
+}
+DECLARE_TEST_CASE_SETUP(GET_CLOCK_RATE, UART) {
+tag->request.value.clock_id = CLOCK_ID_UART;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MAX_CLOCK_RATE, UART) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UART);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_UART);
+}
+DECLARE_TEST_CASE_SETUP(GET_MAX_CLOCK_RATE, UART) {
+tag->request.value.clock_id = CLOCK_ID_UART;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MIN_CLOCK_RATE, UART) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UART);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_UART);
+}
+DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, UART) {
+tag->request.value.clock_id = CLOCK_ID_UART;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_CLOCK_RATE, CORE) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_CORE);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_CORE);
+}
+DECLARE_TEST_CASE_SETUP(GET_CLOCK_RATE, CORE) {
+tag->request.value.clock_id = CLOCK_ID_CORE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MAX_CLOCK_RATE, CORE) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_CORE);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_CORE);
+}
+DECLARE_TEST_CASE_SETUP(GET_MAX_CLOCK_RATE, CORE) {
+tag->request.value.clock_id = CLOCK_ID_CORE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MIN_CLOCK_RATE, CORE) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_CORE);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_CORE);
+}
+DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, CORE) {
+tag->request.value.clock_id = CLOCK_ID_CORE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_CLOCK_RATE, ANY) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UNDEFINED);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_ANY);
+}
+DECLARE_TEST_CASE_SETUP(GET_CLOCK_RATE, ANY) {
+tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MAX_CLOCK_RATE, ANY) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UNDEFINED);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_ANY);
+}
+DECLARE_TEST_CASE_SETUP(GET_MAX_CLOCK_RATE, ANY) {
+tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MIN_CLOCK_RATE, ANY) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UNDEFINED);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_ANY);
+}
+DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, ANY) {
+tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_TEMPERATURE) {
+g_assert_cmphex(tag->response.value.temperature_id, ==, 
TEMPERATURE_ID_SOC);
+g_assert_cmpin

[PATCH v5 30/41] Add Rpi4b boot tests

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/avocado/boot_linux_console.py | 92 +
 1 file changed, 92 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index 3f0180e1f8..40e4aa86e1 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -501,6 +501,98 @@ def test_arm_raspi2_initrd(self):
 # Wait for VM to shut down gracefully
 self.vm.wait()
 
+def test_arm_raspi4(self):
+"""
+:avocado: tags=arch:aarch64
+:avocado: tags=machine:raspi4b-2g
+:avocado: tags=device:pl011
+:avocado: tags=accel:tcg
+:avocado: tags=rpi4b
+
+The kernel can be rebuilt using the kernel source referenced
+and following the instructions on the on:
+https://www.raspberrypi.org/documentation/linux/kernel/building.md
+"""
+
+deb_url = ('http://archive.raspberrypi.org/debian/'
+'pool/main/r/raspberrypi-firmware/'
+'raspberrypi-kernel_1.20230106-1_arm64.deb')
+deb_hash = '08dc55696535b18a6d4fe6fa10d4c0d905cbb2ed'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
+dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'earlycon=pl011,mmio32,0xfe201000 ' +
+   'console=ttyAMA0,115200 ' +
+   'root=/dev/mmcblk1p2 rootwait ' +
+   'dwc_otg.fiq_fsm_enable=0')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line,
+ '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
+ '-device', 'usb-kbd,bus=xhci.0')
+self.vm.launch()
+console_pattern = 'Kernel command line: %s' % kernel_command_line
+self.wait_for_console_pattern(console_pattern)
+console_pattern = 'Product: QEMU USB Keyboard'
+self.wait_for_console_pattern(console_pattern)
+
+
+def test_arm_raspi4_initrd(self):
+"""
+:avocado: tags=arch:aarch64
+:avocado: tags=machine:raspi4b-2g
+:avocado: tags=device:pl011
+:avocado: tags=accel:tcg
+:avocado: tags=rpi4b
+
+The kernel can be rebuilt using the kernel source referenced
+and following the instructions on the on:
+https://www.raspberrypi.org/documentation/linux/kernel/building.md
+"""
+deb_url = ('http://archive.raspberrypi.org/debian/'
+'pool/main/r/raspberrypi-firmware/'
+'raspberrypi-kernel_1.20230106-1_arm64.deb')
+deb_hash = '08dc55696535b18a6d4fe6fa10d4c0d905cbb2ed'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
+dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
+
+initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
+  '86b2be1384d41c8c388e63078a847f1e1c4cb1de/rootfs/'
+  'arm64/rootfs.cpio.gz')
+initrd_hash = 'f3d4f9fa92a49aa542f1b44d34be77bbf8ca5b9d'
+initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
+archive.gzip_uncompress(initrd_path_gz, initrd_path)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'earlycon=pl011,mmio32,0xfe201000 ' +
+   'console=ttyAMA0,115200 ' +
+   'panic=-1 noreboot ' +
+   'dwc_otg.fiq_fsm_enable=0')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
+ '-device', 'usb-kbd,bus=xhci.0',
+ '-no-reboot')
+self.vm.launch()
+self.wait_for_console_pattern('Boot successful.')
+
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+'BCM2835')
+exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+'cprman@7e101000')
+exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System 
halted')
+# TODO: Raspberry Pi4 doesn't shut down properly with recent kernels
+# Wait for VM to shut down gracefully
+  

[PATCH v5 25/41] Implement GENET register ops

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 189 +++--
 include/hw/net/bcm2838_genet.h |   2 +
 2 files changed, 182 insertions(+), 9 deletions(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index be899b68f8..56ff6a6f39 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -233,25 +233,144 @@ REG16(GENET_PHY_EXP_SEL,   0)
 FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
 FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
 
+static void bcm2838_genet_set_qemu_mac(BCM2838GenetState *s)
+{
+const MACAddr *addr = >nic_conf.macaddr;
+
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_0, addr->a[0]);
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_1, addr->a[1]);
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_2, addr->a[2]);
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_3, addr->a[3]);
+s->regs.umac.mac1 = FIELD_DP32(s->regs.umac.mac1, GENET_UMAC_MAC_1,
+   ADDR_4, addr->a[4]);
+s->regs.umac.mac1 = FIELD_DP32(s->regs.umac.mac1, GENET_UMAC_MAC_1,
+   ADDR_5, addr->a[5]);
+}
+
+static void bcm2838_genet_set_irq_default(BCM2838GenetState *s)
+{
+uint32_t intrl_0_status = s->regs.intrl0.stat;
+uint32_t intrl_0_mask = s->regs.intrl0.mask_status;
+int level = (intrl_0_status & ~intrl_0_mask) == 0 ? 0 : 1;
+
+qemu_set_irq(s->irq_default, level);
+}
+
+static void bcm2838_genet_set_irq_prio(BCM2838GenetState *s)
+{
+uint32_t intrl_1_status = s->regs.intrl1.stat;
+uint32_t intrl_1_mask = s->regs.intrl1.mask_status;
+int level = (intrl_1_status & ~intrl_1_mask) == 0 ? 0 : 1;
+
+qemu_set_irq(s->irq_prio, level);
+}
+
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
 uint64_t value = ~0;
+BCM2838GenetState *s = opaque;
 
-qemu_log_mask(
-LOG_GUEST_ERROR,
-"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
-__func__, size, offset);
+if (offset + size < sizeof(s->regs)) {
+memcpy(, (uint8_t *)>regs + offset, size);
+} else {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
 
 trace_bcm2838_genet_read(size, offset, value);
 return value;
 }
 
 static void bcm2838_genet_write(void *opaque, hwaddr offset, uint64_t value,
-unsigned size) {
-qemu_log_mask(
-LOG_GUEST_ERROR,
-"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
-__func__, size, offset);
+unsigned size)
+{
+BCM2838GenetState *s = opaque;
+MACAddr *mac = >nic_conf.macaddr;
+NetClientState *ncs = qemu_get_queue(s->nic);
+
+trace_bcm2838_genet_write(size, offset, value);
+
+if (offset + size < sizeof(s->regs)) {
+switch (offset) {
+case BCM2838_GENET_INTRL0_SET:
+s->regs.intrl0.stat |= value;
+break;
+case BCM2838_GENET_INTRL0_CLEAR:
+s->regs.intrl0.stat &= ~value;
+break;
+case BCM2838_GENET_INTRL0_MASK_SET:
+s->regs.intrl0.mask_status |= value;
+break;
+case BCM2838_GENET_INTRL0_MASK_CLEAR:
+s->regs.intrl0.mask_status &= ~value;
+break;
+case BCM2838_GENET_INTRL1_SET:
+s->regs.intrl1.stat |= value;
+break;
+case BCM2838_GENET_INTRL1_CLEAR:
+s->regs.intrl1.stat &= ~value;
+break;
+case BCM2838_GENET_INTRL1_MASK_SET:
+s->regs.intrl1.mask_status |= value;
+break;
+case BCM2838_GENET_INTRL1_MASK_CLEAR:
+s->regs.intrl1.mask_status &= ~value;
+break;
+case BCM2838_GENET_UMAC_CMD:
+/* Complete SW reset as soon as it has been requested */
+if (FIELD_EX32(value, GENET_UMAC_CMD, SW_RESET) == 1) {
+device_cold_reset(DEVICE(s));
+value = FIELD_DP32(value, GENET_UMAC_CMD, SW_RESET, 0);
+}
+break;
+/*
+ * TODO: before changing MAC address we'd better inform QEMU
+ * network subsystem about freeing previously used one, but
+ * qemu_macaddr_set_free function isn't accessible for us (marked
+ * as static in net/net.c), see also https://lists.nongnu.org/
+ * archive/html/qemu-devel/2022-07

[PATCH v5 32/41] Add mailbox test constants

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.c |  1 +
 tests/qtest/bcm2838-mailbox.h | 88 +++
 2 files changed, 89 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.c b/tests/qtest/bcm2838-mailbox.c
index 0928a3dff8..1efd3c628a 100644
--- a/tests/qtest/bcm2838-mailbox.c
+++ b/tests/qtest/bcm2838-mailbox.c
@@ -11,6 +11,7 @@
 #include "hw/registerfields.h"
 #include "libqtest-single.h"
 #include "bcm2838-mailbox.h"
+#include "hw/arm/raspberrypi-fw-defs.h"
 
 REG32(MBOX_EXCHNG_REG,  0)
 FIELD(MBOX_EXCHNG_REG, CHANNEL, 0, 4)
diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index e9e1f53bc9..9222b38bad 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -7,6 +7,94 @@
  * See the COPYING file in the top-level directory.
  */
 
+#define MBOX0_BASE 0xFE00B880
+#define MBOX1_BASE 0xFE00B8A0
+
+#define MBOX_REG_READ   0x00
+#define MBOX_REG_WRITE  0x00
+#define MBOX_REG_PEEK   0x10
+#define MBOX_REG_SENDER 0x14
+#define MBOX_REG_STATUS 0x18
+#define MBOX_REG_CONFIG 0x1C
+
+#define MBOX_READ_EMPTY 0x4000
+
+#define MBOX_CHANNEL_ID_PROPERTY 8
+
+#define MBOX_PROCESS_REQUEST  0x
+#define MBOX_SUCCESS  0x8000
+#define MBOX_ERROR_PARSING_BUFFER 0x8001
+
+#define BOARD_REVISION0xB03115
+#define FIRMWARE_REVISION 0x548E1
+#define FIRMWARE_VARIANT  0x /* TODO: Find the real value */
+
+#define ARM_MEMORY_BASE 0x
+#define ARM_MEMORY_SIZE 0x3c00
+#define VC_MEMORY_BASE  0x3c00
+#define VC_MEMORY_SIZE  0x0400
+#define VC_FB_BASE  0x3c10
+#define VC_FB_SIZE  0x00096000
+
+#define CLOCK_ID_ROOT  0x
+#define CLOCK_ID_EMMC  0x0001
+#define CLOCK_ID_UART  0x0002
+#define CLOCK_ID_ARM   0x0003
+#define CLOCK_ID_CORE  0x0004
+#define CLOCK_ID_UNDEFINED 0x12345678
+
+#define CLOCK_RATE_EMMC 5000
+#define CLOCK_RATE_UART 300
+#define CLOCK_RATE_CORE 35000
+#define CLOCK_RATE_ANY  7
+
+#define DEVICE_ID_SD_CARD   0x
+#define DEVICE_ID_UART0 0x0001
+#define DEVICE_ID_UART1 0x0002
+#define DEVICE_ID_USB HCD   0x0003
+#define DEVICE_ID_I2C0  0x0004
+#define DEVICE_ID_I2C1  0x0005
+#define DEVICE_ID_I2C2  0x0006
+#define DEVICE_ID_SPI   0x0007
+#define DEVICE_ID_CCP2TX0x0008
+#define DEVICE_ID_UNKNOWN_0 0x0009
+#define DEVICE_ID_UNKNOWN_1 0x000a
+
+#define TEMPERATURE_ID_SOC 0x
+
+#define TEMPERATURE_SOC 25000
+#define TEMPERATURE_SOC_MAX 99000
+
+#define ALIGN_4K 4096
+
+#define PIXEL_ORDER_BGR 0
+#define PIXEL_ORDER_RGB 1
+
+#define ALPHA_MODE_ENABLED  0
+#define ALPHA_MODE_REVERSED 1
+#define ALPHA_MODE_IGNORED  2
+
+#define GPIO_MASK 0x003c
+
+#define GPIO_0 0x0080
+
+#define GPIO_DIRECTION_IN  0
+#define GPIO_DIRECTION_OUT 1
+
+#define GPIO_TERMINATION_DISABLED 0
+#define GPIO_TERMINATION_ENABLED  1
+
+#define GPIO_TERMINATION_PULLUP_DISABLED 0
+#define GPIO_TERMINATION_PULLUP_ENABLED  1
+
+#define GPIO_POLARITY_LOW  0
+#define GPIO_POLARITY_HIGH 1
+
+#define GPIO_STATE_DOWN 0
+
+/* Used to test stubs that don't perform actual work */
+#define DUMMY_VALUE 0x12345678
+
 typedef struct {
 uint32_t size;
 uint32_t req_resp_code;
-- 
2.34.1




[PATCH v5 17/41] Implement BCM2838 thermal sensor

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 27 ++--
 hw/arm/raspi4b.c |  1 -
 hw/misc/bcm2838_thermal.c| 98 
 hw/misc/meson.build  |  3 +-
 include/hw/arm/bcm2838_peripherals.h |  2 +
 include/hw/misc/bcm2838_thermal.h| 24 +++
 6 files changed, 147 insertions(+), 8 deletions(-)
 create mode 100644 hw/misc/bcm2838_thermal.c
 create mode 100644 include/hw/misc/bcm2838_thermal.h

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 6b4c840c5b..48c5fd5978 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -37,6 +37,9 @@ static void bcm2838_peripherals_init(Object *obj)
 /* Random Number Generator */
 object_initialize_child(obj, "rng200", >rng200, TYPE_BCM2838_RNG200);
 
+/* Thermal */
+object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2838_THERMAL);
+
 /* PCIe Host Bridge */
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
@@ -78,6 +81,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
 MemoryRegion *regs_mr;
 MemoryRegion *mmio_mr;
+MemoryRegion *rng200_mr;
+MemoryRegion *thermal_mr;
+qemu_irq rng_200_irq;
 
 int n;
 
@@ -95,12 +101,20 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 if (!sysbus_realize(SYS_BUS_DEVICE(>rng200), errp)) {
 return;
 }
-memory_region_add_subregion(
-_base->peri_mr, RNG_OFFSET,
-sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng200), 0));
-sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0,
-qdev_get_gpio_in_named(DEVICE(_base->ic), BCM2835_IC_GPU_IRQ,
-   INTERRUPT_RNG));
+rng200_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng200), 0);
+memory_region_add_subregion(_base->peri_mr, RNG_OFFSET, rng200_mr);
+
+rng_200_irq = qdev_get_gpio_in_named(DEVICE(_base->ic),
+ BCM2835_IC_GPU_IRQ, INTERRUPT_RNG);
+sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0, rng_200_irq);
+
+
+/* THERMAL */
+if (!sysbus_realize(SYS_BUS_DEVICE(>thermal), errp)) {
+return;
+}
+thermal_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>thermal), 0);
+memory_region_add_subregion( >peri_low_mr, 0x15D2000, thermal_mr);
 
 /* Extended Mass Media Controller 2 */
 object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
@@ -201,6 +215,7 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
  BCM2838_MPHI_SIZE);
 memory_region_add_subregion(_base->peri_mr, BCM2838_MPHI_OFFSET,
 >mphi_mr_alias);
+
 /* PCIe Root Complex */
 if (!sysbus_realize(SYS_BUS_DEVICE(>pcie_host), errp)) {
 return;
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 3c71fa9a9a..175fd2c4fa 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -67,7 +67,6 @@ static void raspi4_modify_dtb(const struct arm_boot_info 
*info, void *fdt)
 
 /* Temporarily disable following devices until they are implemented */
 const char *nodes_to_remove[] = {
-"brcm,bcm2711-thermal",
 "brcm,bcm2711-genet-v5",
 };
 
diff --git a/hw/misc/bcm2838_thermal.c b/hw/misc/bcm2838_thermal.c
new file mode 100644
index 00..3764d55b59
--- /dev/null
+++ b/hw/misc/bcm2838_thermal.c
@@ -0,0 +1,98 @@
+/*
+ * BCM2838 dummy thermal sensor
+ *
+ * Copyright (C) 2022 Maksim Kopusov 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/misc/bcm2838_thermal.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+REG32(STAT, 0x200)
+FIELD(STAT, DATA, 0, 10)
+FIELD(STAT, VALID_1, 10, 1)
+FIELD(STAT, VALID_2, 16, 1)
+
+#define BCM2838_THERMAL_SIZE 0xf00
+
+#define THERMAL_OFFSET_C 410040
+#define THERMAL_COEFF  (-487.0f)
+#define MILLIDEGREE_COEFF 1000
+
+static uint16_t bcm2838_thermal_temp2adc(int temp_C)
+{
+return (temp_C * MILLIDEGREE_COEFF - THERMAL_OFFSET_C) / THERMAL_COEFF;
+}
+
+static uint64_t bcm2838_thermal_read(void *opaque, hwaddr addr, unsigned size)
+{
+uint32_t val = 0;
+
+switch (addr) {
+case A_STAT:
+/* Temperature is always 25°C */
+val = FIELD_DP32(val, STAT, DATA, bcm2838_thermal_temp2adc(25));
+val = FIELD_DP32(val, STAT, VALID_1, 1);
+val = FIELD_DP32(val, STAT, VALID_2, 1);
+
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "%s can't access addr: 0x%"HWADDR_PRIx

[PATCH v5 34/41] Add mailbox tests tags. Part 2

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 152 ++
 1 file changed, 152 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 1360fbb8cf..b4f7b7b314 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -294,6 +294,158 @@ 
DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT_t,
 uint32_t height;
 });
 
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_DEPTH_t,
+struct {},
+struct {
+uint32_t bpp;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_DEPTH_t,
+struct {
+uint32_t bpp;
+},
+struct {
+uint32_t bpp;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_DEPTH_t,
+struct {
+uint32_t bpp;
+},
+struct {
+uint32_t bpp;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_PIXEL_ORDER_t,
+struct {},
+struct {
+uint32_t pixel_order;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_PIXEL_ORDER_t,
+struct {
+uint32_t pixel_order;
+},
+struct {
+uint32_t pixel_order;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_PIXEL_ORDER_t,
+struct {
+uint32_t pixel_order;
+},
+struct {
+uint32_t pixel_order;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_ALPHA_MODE_t,
+struct {},
+struct {
+uint32_t alpha_mode;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_ALPHA_MODE_t,
+struct {
+uint32_t alpha_mode;
+},
+struct {
+uint32_t alpha_mode;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_ALPHA_MODE_t,
+struct {
+uint32_t alpha_mode;
+},
+struct {
+uint32_t alpha_mode;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_PITCH_t,
+struct {},
+struct {
+uint32_t pitch;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_PITCH_t,
+struct {
+uint32_t pitch;
+},
+struct {});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_VIRTUAL_OFFSET_t,
+struct {},
+struct {
+uint32_t x;
+uint32_t y;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_VIRTUAL_OFFSET_t,
+struct {
+uint32_t x;
+uint32_t y;
+},
+struct {
+uint32_t x;
+uint32_t y;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_VIRTUAL_OFFSET_t,
+struct {
+uint32_t x;
+uint32_t y;
+},
+struct {
+uint32_t x;
+uint32_t y;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_OVERSCAN_t,
+struct {},
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_OVERSCAN_t,
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+},
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_OVERSCAN_t,
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+},
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_COMMAND_LINE_t,
+struct {},
+struct {});
+
+DECLARE_TAG_TYPE(TAG_GET_DMA_CHANNELS_t,
+struct {},
+struct {
+uint32_t mask;
+});
+
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
 void mbox1_write_message(uint8_t channel, uint32_t msg_addr);
-- 
2.34.1




[PATCH v5 07/41] Implement BCM2838 GPIO functionality

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/gpio/bcm2838_gpio.c | 193 -
 1 file changed, 190 insertions(+), 3 deletions(-)

diff --git a/hw/gpio/bcm2838_gpio.c b/hw/gpio/bcm2838_gpio.c
index a312490bbd..69d15dbb49 100644
--- a/hw/gpio/bcm2838_gpio.c
+++ b/hw/gpio/bcm2838_gpio.c
@@ -18,6 +18,7 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "hw/gpio/bcm2838_gpio.h"
+#include "hw/irq.h"
 
 #define GPFSEL0   0x00
 #define GPFSEL1   0x04
@@ -56,14 +57,139 @@
 #define RESET_VAL_CNTRL_REG2 0x50AAA95A
 #define RESET_VAL_CNTRL_REG3 0x0005
 
+#define NUM_FSELN_IN_GPFSELN 10
+#define NUM_BITS_FSELN   3
+#define MASK_FSELN   0x7
+
 #define BYTES_IN_WORD4
 
+static uint32_t gpfsel_get(BCM2838GpioState *s, uint8_t reg)
+{
+int i;
+uint32_t value = 0;
+for (i = 0; i < NUM_FSELN_IN_GPFSELN; i++) {
+uint32_t index = NUM_FSELN_IN_GPFSELN * reg + i;
+if (index < sizeof(s->fsel)) {
+value |= (s->fsel[index] & MASK_FSELN) << (NUM_BITS_FSELN * i);
+}
+}
+return value;
+}
+
+static void gpfsel_set(BCM2838GpioState *s, uint8_t reg, uint32_t value)
+{
+int i;
+for (i = 0; i < NUM_FSELN_IN_GPFSELN; i++) {
+uint32_t index = NUM_FSELN_IN_GPFSELN * reg + i;
+if (index < sizeof(s->fsel)) {
+int fsel = (value >> (NUM_BITS_FSELN * i)) & MASK_FSELN;
+s->fsel[index] = fsel;
+}
+}
+}
+
+static int gpfsel_is_out(BCM2838GpioState *s, int index)
+{
+if (index >= 0 && index < BCM2838_GPIO_NUM) {
+return s->fsel[index] == 1;
+}
+return 0;
+}
+
+static void gpset(BCM2838GpioState *s, uint32_t val, uint8_t start,
+  uint8_t count, uint32_t *lev)
+{
+uint32_t changes = val & ~*lev;
+uint32_t cur = 1;
+
+int i;
+for (i = 0; i < count; i++) {
+if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
+qemu_set_irq(s->out[start + i], 1);
+}
+cur <<= 1;
+}
+
+*lev |= val;
+}
+
+static void gpclr(BCM2838GpioState *s, uint32_t val, uint8_t start,
+  uint8_t count, uint32_t *lev)
+{
+uint32_t changes = val & *lev;
+uint32_t cur = 1;
+
+int i;
+for (i = 0; i < count; i++) {
+if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
+qemu_set_irq(s->out[start + i], 0);
+}
+cur <<= 1;
+}
+
+*lev &= ~val;
+}
+
 static uint64_t bcm2838_gpio_read(void *opaque, hwaddr offset, unsigned size)
 {
+BCM2838GpioState *s = (BCM2838GpioState *)opaque;
 uint64_t value = 0;
 
-qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
-  TYPE_BCM2838_GPIO, __func__, offset);
+switch (offset) {
+case GPFSEL0:
+case GPFSEL1:
+case GPFSEL2:
+case GPFSEL3:
+case GPFSEL4:
+case GPFSEL5:
+value = gpfsel_get(s, offset / BYTES_IN_WORD);
+break;
+case GPSET0:
+case GPSET1:
+case GPCLR0:
+case GPCLR1:
+/* Write Only */
+qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Attempt reading from write 
only"
+  " register. 0x%"PRIx64" will be returned."
+  " Address 0x%"HWADDR_PRIx", size %u\n",
+  TYPE_BCM2838_GPIO, __func__, value, offset, size);
+break;
+case GPLEV0:
+value = s->lev0;
+break;
+case GPLEV1:
+value = s->lev1;
+break;
+case GPEDS0:
+case GPEDS1:
+case GPREN0:
+case GPREN1:
+case GPFEN0:
+case GPFEN1:
+case GPHEN0:
+case GPHEN1:
+case GPLEN0:
+case GPLEN1:
+case GPAREN0:
+case GPAREN1:
+case GPAFEN0:
+case GPAFEN1:
+/* Not implemented */
+qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for 
%"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+break;
+case GPIO_PUP_PDN_CNTRL_REG0:
+case GPIO_PUP_PDN_CNTRL_REG1:
+case GPIO_PUP_PDN_CNTRL_REG2:
+case GPIO_PUP_PDN_CNTRL_REG3:
+value = s->pup_cntrl_reg[(offset - GPIO_PUP_PDN_CNTRL_REG0)
+ / sizeof(s->pup_cntrl_reg[0])];
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: bad offset %"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+break;
+}
 
 return value;
 }
@@ -71,14 +197,75 @@ static uint64_t bcm2838_gpio_read(void *opaque, hwaddr 
offset, unsigned size)
 static void bcm2838_gpio_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
 {
-qemu_log_mask(LOG_UNIMP, "%s: %s: not implemente

[PATCH v5 18/41] Add clock_isp stub

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 6 ++
 include/hw/arm/bcm2838_peripherals.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 48c5fd5978..35366386ca 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -17,6 +17,9 @@
 #define PCIE_MMIO_ARM_OFFSET0x6
 #define PCIE_MMIO_SIZE  0x4000
 
+#define CLOCK_ISP_OFFSET0xc11000
+#define CLOCK_ISP_SIZE  0x100
+
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
@@ -228,6 +231,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
 mmio_mr);
 
+create_unimp(s_base, >clkisp, "bcm2835-clkisp", CLOCK_ISP_OFFSET,
+ CLOCK_ISP_SIZE);
+
 /* GPIO */
 if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
 return;
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 49bb4fab08..adc02894c1 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -77,6 +77,7 @@ struct BCM2838PeripheralState {
 OrIRQState dma_9_10_irq_orgate;
 
 UnimplementedDeviceState asb;
+UnimplementedDeviceState clkisp;
 };
 
 struct BCM2838PeripheralClass {
-- 
2.34.1




[PATCH v5 33/41] Add mailbox tests tags. Part 1

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 177 ++
 1 file changed, 177 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 9222b38bad..1360fbb8cf 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -116,6 +116,183 @@ typedef struct {  
  \
 };  \
 } TypeName
 
+DECLARE_TAG_TYPE(TAG_GET_FIRMWARE_REVISION_t,
+struct {},
+struct {
+uint32_t revision;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_FIRMWARE_VARIANT_t,
+struct {},
+struct {
+uint32_t variant;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_BOARD_REVISION_t,
+struct {},
+struct {
+uint32_t revision;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_ARM_MEMORY_t,
+struct {},
+struct {
+uint32_t base;
+uint32_t size;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_VC_MEMORY_t,
+struct {},
+struct {
+uint32_t base;
+uint32_t size;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_POWER_STATE_t,
+struct {
+uint32_t device_id;
+uint32_t cmd;
+},
+struct {
+uint32_t device_id;
+uint32_t cmd;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_CLOCK_STATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t cmd;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_CLOCK_RATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t rate;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_MAX_CLOCK_RATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t rate;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_MIN_CLOCK_RATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t rate;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_CLOCKS_t,
+struct {},
+struct {
+uint32_t root_clock;
+uint32_t arm_clock;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_TEMPERATURE_t,
+struct {
+uint32_t temperature_id;
+},
+struct {
+uint32_t temperature_id;
+uint32_t temperature;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_MAX_TEMPERATURE_t,
+struct {
+uint32_t temperature_id;
+},
+struct {
+uint32_t temperature_id;
+uint32_t temperature;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_ALLOCATE_t,
+struct {
+uint32_t alignment;
+},
+struct {
+uint32_t base;
+uint32_t size;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_RELEASE_t,
+struct {},
+struct {});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_BLANK_t,
+struct {
+uint32_t on;
+},
+struct {
+uint32_t on;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT_t,
+struct {},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT_t,
+struct {},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
 
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
-- 
2.34.1




[PATCH v5 08/41] Connect SD controller to BCM2838 GPIO

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/gpio/bcm2838_gpio.c | 52 +-
 include/hw/gpio/bcm2838_gpio.h |  5 
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/hw/gpio/bcm2838_gpio.c b/hw/gpio/bcm2838_gpio.c
index 69d15dbb49..2ddf62f695 100644
--- a/hw/gpio/bcm2838_gpio.c
+++ b/hw/gpio/bcm2838_gpio.c
@@ -17,6 +17,7 @@
 #include "qapi/error.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
+#include "hw/sd/sd.h"
 #include "hw/gpio/bcm2838_gpio.h"
 #include "hw/irq.h"
 
@@ -63,6 +64,16 @@
 
 #define BYTES_IN_WORD4
 
+/* bcm,function property */
+#define BCM2838_FSEL_GPIO_IN0
+#define BCM2838_FSEL_GPIO_OUT   1
+#define BCM2838_FSEL_ALT5   2
+#define BCM2838_FSEL_ALT4   3
+#define BCM2838_FSEL_ALT0   4
+#define BCM2838_FSEL_ALT1   5
+#define BCM2838_FSEL_ALT2   6
+#define BCM2838_FSEL_ALT3   7
+
 static uint32_t gpfsel_get(BCM2838GpioState *s, uint8_t reg)
 {
 int i;
@@ -86,6 +97,31 @@ static void gpfsel_set(BCM2838GpioState *s, uint8_t reg, 
uint32_t value)
 s->fsel[index] = fsel;
 }
 }
+
+/* SD controller selection (48-53) */
+if (s->sd_fsel != BCM2838_FSEL_GPIO_IN
+&& (s->fsel[48] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[49] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[50] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[51] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[52] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[53] == BCM2838_FSEL_GPIO_IN)
+   ) {
+/* SDHCI controller selected */
+sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
+s->sd_fsel = BCM2838_FSEL_GPIO_IN;
+} else if (s->sd_fsel != BCM2838_FSEL_ALT0
+   && (s->fsel[48] == BCM2838_FSEL_ALT0) /* SD_CLK_R */
+   && (s->fsel[49] == BCM2838_FSEL_ALT0) /* SD_CMD_R */
+   && (s->fsel[50] == BCM2838_FSEL_ALT0) /* SD_DATA0_R */
+   && (s->fsel[51] == BCM2838_FSEL_ALT0) /* SD_DATA1_R */
+   && (s->fsel[52] == BCM2838_FSEL_ALT0) /* SD_DATA2_R */
+   && (s->fsel[53] == BCM2838_FSEL_ALT0) /* SD_DATA3_R */
+  ) {
+/* SDHost controller selected */
+sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
+s->sd_fsel = BCM2838_FSEL_ALT0;
+}
 }
 
 static int gpfsel_is_out(BCM2838GpioState *s, int index)
@@ -266,6 +302,11 @@ static void bcm2838_gpio_reset(DeviceState *dev)
 
 memset(s->fsel, 0, sizeof(s->fsel));
 
+s->sd_fsel = 0;
+
+/* SDHCI is selected by default */
+sdbus_reparent_card(>sdbus, s->sdbus_sdhci);
+
 s->lev0 = 0;
 s->lev1 = 0;
 
@@ -304,6 +345,8 @@ static void bcm2838_gpio_init(Object *obj)
 DeviceState *dev = DEVICE(obj);
 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
+qbus_init(>sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(s), "sd-bus");
+
 memory_region_init_io(>iomem, obj, _gpio_ops, s,
   "bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
 sysbus_init_mmio(sbd, >iomem);
@@ -312,7 +355,14 @@ static void bcm2838_gpio_init(Object *obj)
 
 static void bcm2838_gpio_realize(DeviceState *dev, Error **errp)
 {
-/* Temporary stub. Do nothing */
+BCM2838GpioState *s = BCM2838_GPIO(dev);
+Object *obj;
+
+obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", _abort);
+s->sdbus_sdhci = SD_BUS(obj);
+
+obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", _abort);
+s->sdbus_sdhost = SD_BUS(obj);
 }
 
 static void bcm2838_gpio_class_init(ObjectClass *klass, void *data)
diff --git a/include/hw/gpio/bcm2838_gpio.h b/include/hw/gpio/bcm2838_gpio.h
index 06d48e0c19..f2a57a697f 100644
--- a/include/hw/gpio/bcm2838_gpio.h
+++ b/include/hw/gpio/bcm2838_gpio.h
@@ -14,6 +14,7 @@
 #ifndef BCM2838_GPIO_H
 #define BCM2838_GPIO_H
 
+#include "hw/sd/sd.h"
 #include "hw/sysbus.h"
 #include "qom/object.h"
 
@@ -29,6 +30,10 @@ struct BCM2838GpioState {
 
 MemoryRegion iomem;
 
+/* SDBus selector */
+SDBus sdbus;
+SDBus *sdbus_sdhci;
+SDBus *sdbus_sdhost;
 
 uint8_t fsel[BCM2838_GPIO_NUM];
 uint32_t lev0, lev1;
-- 
2.34.1




[PATCH v5 31/41] Add mailbox test stub

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.c | 60 +++
 tests/qtest/bcm2838-mailbox.h | 37 +
 tests/qtest/meson.build   |  1 +
 3 files changed, 98 insertions(+)
 create mode 100644 tests/qtest/bcm2838-mailbox.c
 create mode 100644 tests/qtest/bcm2838-mailbox.h

diff --git a/tests/qtest/bcm2838-mailbox.c b/tests/qtest/bcm2838-mailbox.c
new file mode 100644
index 00..0928a3dff8
--- /dev/null
+++ b/tests/qtest/bcm2838-mailbox.c
@@ -0,0 +1,60 @@
+/*
+ * Helper functions to work with BCM2838 mailbox via qtest interface.
+ *
+ * Copyright (c) 2023 Auriga LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/registerfields.h"
+#include "libqtest-single.h"
+#include "bcm2838-mailbox.h"
+
+REG32(MBOX_EXCHNG_REG,  0)
+FIELD(MBOX_EXCHNG_REG, CHANNEL, 0, 4)
+FIELD(MBOX_EXCHNG_REG, DATA,4, 28)
+
+static uint32_t qtest_mbox0_read_reg32(QTestState *s, uint32_t offset)
+{
+return qtest_readl(s, MBOX0_BASE + offset);
+}
+
+static void qtest_mbox1_write_reg32(QTestState *s, uint32_t offset, uint32_t 
value)
+{
+return qtest_writel(s, MBOX1_BASE + offset, value);
+}
+
+static void qtest_mbox1_write(QTestState *s, uint8_t channel, uint32_t data)
+{
+uint32_t mbox_reg = 0;
+
+mbox_reg = FIELD_DP32(mbox_reg, MBOX_EXCHNG_REG, CHANNEL, channel);
+mbox_reg = FIELD_DP32(mbox_reg, MBOX_EXCHNG_REG, DATA, data);
+qtest_mbox1_write_reg32(s, MBOX_REG_WRITE, mbox_reg);
+}
+
+int qtest_mbox0_has_data(QTestState *s) {
+return !(qtest_mbox0_read_reg32(s, MBOX_REG_STATUS) & MBOX_READ_EMPTY);
+}
+
+void qtest_mbox0_read_message(QTestState *s,
+  uint8_t channel,
+  void *msgbuf,
+  size_t msgbuf_size)
+{
+uint32_t mbox_reg;
+uint32_t msgaddr;
+
+g_assert(qtest_mbox0_has_data(s));
+mbox_reg = qtest_mbox0_read_reg32(s, MBOX_REG_READ);
+g_assert_cmphex(FIELD_EX32(mbox_reg, MBOX_EXCHNG_REG, CHANNEL), ==, 
channel);
+msgaddr = FIELD_EX32(mbox_reg, MBOX_EXCHNG_REG, DATA) << 4;
+qtest_memread(s, msgaddr, msgbuf, msgbuf_size);
+}
+
+void qtest_mbox1_write_message(QTestState *s, uint8_t channel, uint32_t 
msg_addr)
+{
+qtest_mbox1_write(s, channel, msg_addr >> 4);
+}
diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
new file mode 100644
index 00..e9e1f53bc9
--- /dev/null
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -0,0 +1,37 @@
+/*
+ * Declarations for BCM2838 mailbox test.
+ *
+ * Copyright (c) 2023 Auriga LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+typedef struct {
+uint32_t size;
+uint32_t req_resp_code;
+} MboxBufHeader;
+
+#define DECLARE_TAG_TYPE(TypeName, RequestValueType, ResponseValueType) \
+typedef struct {\
+uint32_t id;\
+uint32_t value_buffer_size; \
+union { \
+struct {\
+uint32_t zero;  \
+RequestValueType value; \
+} request;  \
+struct {\
+uint32_t size_stat; \
+ResponseValueType value;\
+} response; \
+};  \
+} TypeName
+
+
+int mbox0_has_data(void);
+void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
+void mbox1_write_message(uint8_t channel, uint32_t msg_addr);
+int qtest_mbox0_has_data(QTestState *s);
+void qtest_mbox0_read_message(QTestState *s, uint8_t channel, void *msgbuf, 
size_t msgbuf_size);
+void qtest_mbox1_write_message(QTestState *s, uint8_t channel, uint32_t 
msg_addr);
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 2b89e8634b..e312634963 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -333,6 +333,7 @@ qtests = {
   'virtio-net-failover': files('migration-helpers.c'),
   'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
   'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'),
+  'bcm2838-mbox-property-test' : files('bcm2838-mailbox.c'),
 }
 
 if vnc.found()
-- 
2.34.1




[PATCH v5 15/41] Enable BCM2838 PCIE

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c |  9 +
 hw/arm/bcm2838_peripherals.c | 23 +++
 hw/arm/meson.build   |  7 ---
 hw/arm/raspi4b.c |  1 -
 include/hw/arm/bcm2838_peripherals.h |  2 ++
 5 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index ddb7c5f757..481b262b02 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -226,6 +226,15 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 qdev_connect_gpio_out(dma_9_10_irq_orgate, 0,
   qdev_get_gpio_in(gicdev, 
GIC_SPI_INTERRUPT_DMA_9_10));
 
+/* Connect PCIe host bridge to the interrupt controller */
+for (int n = 0; n < BCM2838_PCIE_NUM_IRQS; n++) {
+int int_n = GIC_SPI_INTERRUPT_PCI_INT_A + n;
+sysbus_connect_irq(SYS_BUS_DEVICE(>pcie_host), n,
+   qdev_get_gpio_in(gicdev, int_n));
+bcm2838_pcie_host_set_irq_num(BCM2838_PCIE_HOST(>pcie_host), n,
+  int_n);
+}
+
 /* Pass through inbound GPIO lines to the GIC */
 qdev_init_gpio_in(dev, bcm2838_gic_set_irq, GIC_NUM_IRQS);
 
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index ca2f37b260..7e86ebb555 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -12,6 +12,11 @@
 #include "hw/arm/raspi_platform.h"
 #include "hw/arm/bcm2838_peripherals.h"
 
+#define PCIE_RC_OFFSET  0x150
+#define PCIE_MMIO_OFFSET0xc000
+#define PCIE_MMIO_ARM_OFFSET0x6
+#define PCIE_MMIO_SIZE  0x4000
+
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
@@ -29,6 +34,10 @@ static void bcm2838_peripherals_init(Object *obj)
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* PCIe Host Bridge */
+object_initialize_child(obj, "pcie-host", >pcie_host,
+TYPE_BCM2838_PCIE_HOST);
+
 /* Extended Mass Media Controller 2 */
 object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
 
@@ -64,6 +73,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 MemoryRegion *mphi_mr;
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(dev);
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+MemoryRegion *regs_mr;
+MemoryRegion *mmio_mr;
+
 int n;
 
 bcm_soc_peripherals_common_realize(dev, errp);
@@ -175,6 +187,17 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
  BCM2838_MPHI_SIZE);
 memory_region_add_subregion(_base->peri_mr, BCM2838_MPHI_OFFSET,
 >mphi_mr_alias);
+/* PCIe Root Complex */
+if (!sysbus_realize(SYS_BUS_DEVICE(>pcie_host), errp)) {
+return;
+}
+/* RC registers region */
+regs_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>pcie_host), 0);
+memory_region_add_subregion(>peri_low_mr, PCIE_RC_OFFSET, regs_mr);
+/* MMIO region */
+mmio_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>pcie_host), 1);
+memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
+mmio_mr);
 
 /* GPIO */
 if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 39f6df7431..4d11ec0eae 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -32,7 +32,6 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: 
files('allwinner-r40.c', 'bana
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
 arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: files(
   'bcm2838.c',
-  'bcm2838_pcie.c',
   'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
@@ -70,8 +69,10 @@ system_ss.add(when: 'CONFIG_EXYNOS4', if_true: 
files('exynos4_boards.c'))
 system_ss.add(when: 'CONFIG_GUMSTIX', if_true: files('gumstix.c'))
 system_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
 system_ss.add(when: 'CONFIG_OMAP', if_true: files('omap2.c'))
-system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c'))
-system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2838_peripherals.c'))
+system_ss.add(when: 'CONFIG_RASPI', if_true: files(
+'bcm2835_peripherals.c',
+'bcm2838_peripherals.c',
+'bcm2838_pcie.c'))
 system_ss.add(when: 'CONFIG_SPITZ', if_true: files('spitz.c'))
 system_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c'))
 system_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 49dec6e53a..2431b0b8c3 

[PATCH v5 24/41] Add GENET register access macros

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 include/hw/net/bcm2838_genet.h | 76 ++
 1 file changed, 76 insertions(+)

diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 94c2f3ebca..e7a76cda81 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -22,9 +22,85 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_DMA_RING_CNT  17
 #define BCM2838_GENET_DMA_RING_DEFAULT  (BCM2838_GENET_DMA_RING_CNT - 1)
 
+#define BCM2838_GENET_HFB_FILTER_REGS offsetof(BCM2838GenetRegs, hfb)
+#define BCM2838_GENET_HFB_FILTER_REG(reg) (BCM2838_GENET_HFB_FILTER_REGS \
+   + offsetof(BCM2838GenetRegsHfb, 
reg))
 #define BCM2838_GENET_HFB_FILTER_CNT  48
 #define BCM2838_GENET_HFB_FILTER_SIZE 128
 
+#define BCM2838_GENET_INTRL0_REG(reg)   (offsetof(BCM2838GenetRegs, intrl0) \
++ offsetof(BCM2838GenetRegsIntrl0, 
reg))
+#define BCM2838_GENET_INTRL0_SETBCM2838_GENET_INTRL0_REG(set)
+#define BCM2838_GENET_INTRL0_CLEAR  BCM2838_GENET_INTRL0_REG(clear)
+#define BCM2838_GENET_INTRL0_MASK_SET   BCM2838_GENET_INTRL0_REG(mask_set)
+#define BCM2838_GENET_INTRL0_MASK_CLEAR BCM2838_GENET_INTRL0_REG(mask_clear)
+
+#define BCM2838_GENET_INTRL1_REG(reg)   (offsetof(BCM2838GenetRegs, intrl1) \
++ offsetof(BCM2838GenetRegsIntrl1, 
reg))
+#define BCM2838_GENET_INTRL1_SETBCM2838_GENET_INTRL1_REG(set)
+#define BCM2838_GENET_INTRL1_CLEAR  BCM2838_GENET_INTRL1_REG(clear)
+#define BCM2838_GENET_INTRL1_MASK_SET   BCM2838_GENET_INTRL1_REG(mask_set)
+#define BCM2838_GENET_INTRL1_MASK_CLEAR BCM2838_GENET_INTRL1_REG(mask_clear)
+
+#define BCM2838_GENET_UMAC_REG(reg) (offsetof(BCM2838GenetRegs, umac) \
+ + offsetof(BCM2838GenetRegsUmac, reg))
+#define BCM2838_GENET_UMAC_CMD  BCM2838_GENET_UMAC_REG(cmd)
+#define BCM2838_GENET_UMAC_MAC0 BCM2838_GENET_UMAC_REG(mac0)
+#define BCM2838_GENET_UMAC_MAC1 BCM2838_GENET_UMAC_REG(mac1)
+#define BCM2838_GENET_UMAC_MDIO_CMD BCM2838_GENET_UMAC_REG(mdio_cmd)
+
+#define BCM2838_GENET_TDMA_REGS offsetof(BCM2838GenetRegs, tdma)
+#define BCM2838_GENET_TDMA_REG(reg) (BCM2838_GENET_TDMA_REGS \
+ + offsetof(BCM2838GenetRegsTdma, reg))
+#define BCM2838_GENET_TDMA_RINGSBCM2838_GENET_TDMA_REG(rings)
+#define BCM2838_GENET_TDMA_RING_CFG BCM2838_GENET_TDMA_REG(ring_cfg)
+#define BCM2838_GENET_TDMA_CTRL BCM2838_GENET_TDMA_REG(ctrl)
+
+#define BCM2838_GENET_RDMA_REGS offsetof(BCM2838GenetRegs, rdma)
+#define BCM2838_GENET_RDMA_REG(reg) (BCM2838_GENET_RDMA_REGS \
+ + offsetof(BCM2838GenetRegsRdma, reg))
+#define BCM2838_GENET_RDMA_RINGSBCM2838_GENET_RDMA_REG(rings)
+#define BCM2838_GENET_RDMA_RING_CFG BCM2838_GENET_RDMA_REG(ring_cfg)
+#define BCM2838_GENET_RDMA_CTRL BCM2838_GENET_RDMA_REG(ctrl)
+
+#define BCM2838_GENET_TRING_REG(reg)offsetof(BCM2838GenetTdmaRing, reg)
+#define BCM2838_GENET_TRING_WRITE_PTR BCM2838_GENET_TRING_REG(write_ptr)
+#define BCM2838_GENET_TRING_WRITE_PTR_HI BCM2838_GENET_TRING_REG(write_ptr_hi)
+#define BCM2838_GENET_TRING_PROD_INDEX BCM2838_GENET_TRING_REG(prod_index)
+#define BCM2838_GENET_TRING_CONS_INDEX BCM2838_GENET_TRING_REG(cons_index)
+#define BCM2838_GENET_TRING_RING_BUF_SIZE 
BCM2838_GENET_TRING_REG(ring_buf_size)
+#define BCM2838_GENET_TRING_RING_START_ADDR BCM2838_GENET_TRING_REG(start_addr)
+#define BCM2838_GENET_TRING_RING_START_ADDR_HI 
BCM2838_GENET_TRING_REG(start_addr_hi)
+#define BCM2838_GENET_TRING_RING_END_ADDR BCM2838_GENET_TRING_REG(end_addr)
+#define BCM2838_GENET_TRING_RING_END_ADDR_HI 
BCM2838_GENET_TRING_REG(end_addr_hi)
+#define BCM2838_GENET_TRING_RING_MBUF_DONE_TRESH 
BCM2838_GENET_TRING_REG(mbuf_done_tresh)
+#define BCM2838_GENET_TRING_RING_FLOW_PERIOD 
BCM2838_GENET_TRING_REG(flow_period)
+#define BCM2838_GENET_TRING_RING_READ_PTR BCM2838_GENET_TRING_REG(read_ptr)
+#define BCM2838_GENET_TRING_RING_READ_PTR_HI 
BCM2838_GENET_TRING_REG(read_ptr_hi)
+
+#define BCM2838_GENET_RRING_REG(reg)offsetof(BCM2838GenetRdmaRing, reg)
+#define BCM2838_GENET_RRING_WRITE_PTR BCM2838_GENET_RRING_REG(write_ptr)
+#define BCM2838_GENET_RRING_WRITE_PTR_HI BCM2838_GENET_RRING_REG(write_ptr_hi)
+#define BCM2838_GENET_RRING_PROD_INDEX BCM2838_GENET_RRING_REG(prod_index)
+#define BCM2838_GENET_RRING_CONS_INDEX BCM2838_GENET_RRING_REG(cons_index)
+#define BCM2838_GENET_RRING_RING_BUF_SIZE 
BCM2838_GENET_RRING_REG(ring_buf_size)
+#define BCM2838_GENET_RRING_RING_START_ADDR BCM2838_GENET_RRING_REG(start_addr)
+#define BCM2838_GENET_RRING_RING_START_ADDR_HI 
BCM2838_GENET_RRING_REG(start_addr_hi)
+#define BCM2838_GENET_RRING_RING_END_ADDR BCM2838_GENET_RRING_REG(end_addr)
+#define BCM2838_GENET_RRING_RING_END_ADDR_HI

[PATCH v5 22/41] Add GENET register structs. Part 3

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 88 ++
 include/hw/net/bcm2838_genet.h | 88 ++
 2 files changed, 176 insertions(+)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 9a99f34c4a..be899b68f8 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -145,6 +145,94 @@ FIELD(GENET_RDMA_LENGTH_STATUS, OWN,15, 1)
 FIELD(GENET_RDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
 FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
 
+REG32(GENET_TDMA_LENGTH_STATUS, 0)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_0_3,   0, 4)
+FIELD(GENET_TDMA_LENGTH_STATUS, DO_CSUM,4, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, OW_CRC, 5, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, APPEND_CRC, 6, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_7_8,   7, 2)
+FIELD(GENET_TDMA_LENGTH_STATUS, UNDERRUN,   9, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_10_11, 10, 2)
+FIELD(GENET_TDMA_LENGTH_STATUS, WRAP,   12, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, SOP,13, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, EOP,14, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, OWN,15, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
+
+REG16(GENET_PHY_BMCR,0)
+FIELD(GENET_PHY_BMCR, RSVD_0_5,  0, 6)
+FIELD(GENET_PHY_BMCR, SPEED1000, 6, 1)
+FIELD(GENET_PHY_BMCR, CTST,  7, 1)
+FIELD(GENET_PHY_BMCR, FULLDPLX,  8, 1)
+FIELD(GENET_PHY_BMCR, ANRESTART, 9, 1)
+FIELD(GENET_PHY_BMCR, ISOLATE,   10, 1)
+FIELD(GENET_PHY_BMCR, PDOWN, 11, 1)
+FIELD(GENET_PHY_BMCR, AENABLE,   12, 1)
+FIELD(GENET_PHY_BMCR, SPEED100,  13, 1)
+FIELD(GENET_PHY_BMCR, LOOPBACK,  14, 1)
+FIELD(GENET_PHY_BMCR, RESET, 15, 1)
+
+REG16(GENET_PHY_BMSR,   0)
+FIELD(GENET_PHY_BMSR, ERCAP,0, 1)
+FIELD(GENET_PHY_BMSR, JCD,  1, 1)
+FIELD(GENET_PHY_BMSR, LSTATUS,  2, 1)
+FIELD(GENET_PHY_BMSR, ANEGCAPABLE,  3, 1)
+FIELD(GENET_PHY_BMSR, RFAULT,   4, 1)
+FIELD(GENET_PHY_BMSR, ANEGCOMPLETE, 5, 1)
+FIELD(GENET_PHY_BMSR, RSVD_6_7, 6, 2)
+FIELD(GENET_PHY_BMSR, ESTATEN,  8, 1)
+FIELD(GENET_PHY_BMSR, _100HALF2,9, 1)
+FIELD(GENET_PHY_BMSR, _100FULL2,10, 1)
+FIELD(GENET_PHY_BMSR, _10HALF,  11, 1)
+FIELD(GENET_PHY_BMSR, _10FULL,  12, 1)
+FIELD(GENET_PHY_BMSR, _100HALF, 13, 1)
+FIELD(GENET_PHY_BMSR, _100FULL, 14, 1)
+FIELD(GENET_PHY_BMSR, _10BASE4, 15, 1)
+
+REG16(GENET_PHY_LPA,   0)
+FIELD(GENET_PHY_LPA, SLCT, 0, 5)
+FIELD(GENET_PHY_LPA, _10HALF_1000XFULL,5, 1)
+FIELD(GENET_PHY_LPA, _10FULL_1000XHALF,6, 1)
+FIELD(GENET_PHY_LPA, _100HALF_1000XPAUSE,  7, 1)
+FIELD(GENET_PHY_LPA, _100FULL_1000XPAUSE_ASYM, 8, 1)
+FIELD(GENET_PHY_LPA, _100BASE4,9, 1)
+FIELD(GENET_PHY_LPA, PAUSE_CAP,10, 1)
+FIELD(GENET_PHY_LPA, PAUSE_ASYM,   11, 1)
+FIELD(GENET_PHY_LPA, RSVD_12,  12, 1)
+FIELD(GENET_PHY_LPA, RFAULT,   13, 1)
+FIELD(GENET_PHY_LPA, LPACK,14, 1)
+FIELD(GENET_PHY_LPA, NPAGE,15, 1)
+
+REG16(GENET_PHY_STAT_1000,0)
+FIELD(GENET_PHY_STAT_1000, RSVD_0_9,  0, 10)
+FIELD(GENET_PHY_STAT_1000, HALF,  10, 1)
+FIELD(GENET_PHY_STAT_1000, FULL,  11, 1)
+FIELD(GENET_PHY_STAT_1000, REMRXOK,   12, 1)
+FIELD(GENET_PHY_STAT_1000, LOCALRXOK, 13, 1)
+FIELD(GENET_PHY_STAT_1000, MSRES, 14, 1)
+FIELD(GENET_PHY_STAT_1000, MSFAIL,15, 1)
+
+REG16(GENET_PHY_AUX_CTRL_0,  0)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_ID_MASK, 0, 3)
+FIELD(GENET_PHY_AUX_CTRL_0, RSVD_3,  3, 1)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_DATA,4, 8)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_ID,  12, 3)
+FIELD(GENET_PHY_AUX_CTRL_0, MISC_WREN,   15, 1)
+
+REG16(GENET_PHY_AUX_CTRL_1,   0)
+FIELD(GENET_PHY_AUX_CTRL_1, RSVD_0_3, 0, 4)
+FIELD(GENET_PHY_AUX_CTRL_1, REG_DATA, 4, 12)
+
+REG16(GENET_PHY_SHADOW,   0)
+FIELD(GENET_PHY_SHADOW, REG_DATA, 0, 10)
+FIELD(GENET_PHY_SHADOW, REG_ID,   10, 5)
+FIELD(GENET_PHY_SHADOW, WR,   15, 1)
+
+REG16(GENET_PHY_EXP_SEL,   0)
+FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
+FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
+
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
 uint64_t value = ~0;
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 736b4d1757..1bd004785a 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -22,6 +22,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_DMA_RING_CNT  17
 #define BCM2838_GENET_DMA_RING_DEFAULT  (BCM2838_GENET_DMA_RING_CNT - 1)
 
+#define BCM2838_GENET_HFB_FILTER_CNT  48
+#define BCM2838_GENET_HFB_FILTER_SIZE 128
+
 typedef struct {
 uint32_t rev_ctrl;
 uint32_t port_ctrl;
@@ -169,6 +172,53 @@ typedef struct {
 uint32_t reserved_0x10D0[972];
 } BCM2838GenetRegsRdma

[PATCH v5 23/41] Add GENET register structs. Part 4

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 include/hw/net/bcm2838_genet.h | 37 ++
 1 file changed, 37 insertions(+)

diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 1bd004785a..94c2f3ebca 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -25,6 +25,12 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_HFB_FILTER_CNT  48
 #define BCM2838_GENET_HFB_FILTER_SIZE 128
 
+#define BCM2838_GENET_PHY_AUX_CTL_MISC  0x7
+#define BCM2838_GENET_PHY_AUX_CTL_REGS_SIZE 8
+
+#define BCM2838_GENET_PHY_EXP_SHD_BLOCKS_CNT 256
+#define BCM2838_GENET_PHY_EXP_SHD_REGS_CNT   256
+
 typedef struct {
 uint32_t rev_ctrl;
 uint32_t port_ctrl;
@@ -273,6 +279,34 @@ typedef struct {
 uint16_t rdb_data;
 } BCM2838GenetPhyRegs;
 
+typedef struct {
+uint16_t reserved_0_2[3];
+uint16_t clk_ctl;
+uint16_t scr2;
+uint16_t scr3;
+uint16_t reserved_6_9[4];
+uint16_t apd;
+uint16_t rgmii_mode;
+uint16_t reserved_12;
+uint16_t leds1;
+uint16_t reserved_14_18[5];
+uint16_t _100fx_ctrl;
+uint16_t ssd;
+uint16_t reserved_21_30[10];
+uint16_t mode;
+} BCM2838GenetPhyShdRegs;
+
+typedef struct {
+uint16_t auxctl;
+uint16_t reserved_1_6[BCM2838_GENET_PHY_AUX_CTL_REGS_SIZE - 2];
+uint16_t misc;
+} BCM2838GenetPhyAuxShdRegs;
+
+typedef struct {
+uint16_t regs[BCM2838_GENET_PHY_EXP_SHD_BLOCKS_CNT]
+ [BCM2838_GENET_PHY_EXP_SHD_REGS_CNT];
+} BCM2838GenetPhyExpShdRegs;
+
 struct BCM2838GenetState {
 /*< private >*/
 SysBusDevice parent_obj;
@@ -284,6 +318,9 @@ struct BCM2838GenetState {
 
 BCM2838GenetRegs regs;
 BCM2838GenetPhyRegs phy_regs;
+BCM2838GenetPhyShdRegs phy_shd_regs;
+BCM2838GenetPhyAuxShdRegs phy_aux_ctl_shd_regs;
+BCM2838GenetPhyExpShdRegs phy_exp_shd_regs;
 
 qemu_irq irq_default;
 qemu_irq irq_prio;
-- 
2.34.1




[PATCH v5 27/41] Implement GENET TX path

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 221 -
 include/hw/net/bcm2838_genet.h |  17 +++
 2 files changed, 237 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 1fae3ecbc2..4c9b39a3ca 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -234,6 +234,13 @@ REG16(GENET_PHY_EXP_SEL,   0)
 FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
 FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
 
+REG32(GENET_TX_CSUM_INFO,0)
+FIELD(GENET_TX_CSUM_INFO, OFFSET,0, 15)
+FIELD(GENET_TX_CSUM_INFO, PROTO_UDP, 15, 1)
+FIELD(GENET_TX_CSUM_INFO, START, 16, 15)
+FIELD(GENET_TX_CSUM_INFO, LV,30, 1)
+
+
 static void bcm2838_genet_set_qemu_mac(BCM2838GenetState *s)
 {
 const MACAddr *addr = >nic_conf.macaddr;
@@ -387,6 +394,218 @@ static uint64_t bcm2838_genet_mdio_cmd(BCM2838GenetState 
*s, uint64_t cmd)
 return cmd;
 }
 
+static void bcm2838_genet_xmit_packet(NetClientState *s, void *packet,
+  size_t size)
+{
+uint8_t *buf = packet + sizeof(BCM2838GenetXmitStatus);
+size_t len = size;
+uint16_t len_type = 0;
+
+len -= sizeof(BCM2838GenetXmitStatus);
+net_checksum_calculate(buf, len, CSUM_ALL);
+
+memcpy(_type, [12], sizeof(len_type));
+len_type = ntohs(len_type);
+if (len_type < MAX_PAYLOAD_SIZE) {
+len_type = len;
+len_type = htons(len_type);
+memcpy([12], _type, sizeof(len_type));
+}
+
+qemu_send_packet(s, buf, len);
+}
+
+static uint64_t bcm2838_genet_tx(BCM2838GenetState *s, unsigned int ring_index,
+ uint32_t prod_index,
+ uint32_t cons_index)
+{
+const unsigned int DESC_SIZE_WORDS
+= sizeof(BCM2838GenetTdmaDesc) / sizeof(uint32_t);
+const uint64_t RING_START_ADDR
+= ((uint64_t)s->regs.tdma.rings[ring_index].start_addr_hi << 32)
++ s->regs.tdma.rings[ring_index].start_addr;
+const uint64_t RING_END_ADDR
+= ((uint64_t)s->regs.tdma.rings[ring_index].end_addr_hi << 32)
++ s->regs.tdma.rings[ring_index].end_addr;
+
+hwaddr data_addr;
+uint64_t desc_index;
+uint32_t desc_status = 0;
+uint32_t buflength = 0;
+uint64_t num_descs = 0;
+uint64_t read_ptr
+= ((uint64_t)s->regs.tdma.rings[ring_index].read_ptr_hi << 32)
++ s->regs.tdma.rings[ring_index].read_ptr;
+off_t packet_off = 0;
+
+uint32_t prod_index_fld = FIELD_EX32(prod_index,
+ GENET_DMA_PROD_INDEX, INDEX);
+uint32_t cons_index_fld = FIELD_EX32(cons_index,
+GENET_DMA_CONS_INDEX, INDEX);
+
+while (cons_index_fld != prod_index_fld) {
+desc_index = read_ptr / DESC_SIZE_WORDS;
+if (desc_index >= BCM2838_GENET_DMA_DESC_CNT) {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: invalid TX descriptor index %" PRIu64 " (exceeds %u)\n",
+__func__, desc_index, BCM2838_GENET_DMA_DESC_CNT - 1);
+break;
+}
+desc_status = s->regs.tdma.descs[desc_index].length_status;
+data_addr = ((uint64_t)s->regs.tdma.descs[desc_index].address_hi << 32)
++ s->regs.tdma.descs[desc_index].address_lo;
+trace_bcm2838_genet_tx(ring_index, desc_index, desc_status,
+   data_addr);
+
+if (FIELD_EX32(desc_status, GENET_RDMA_LENGTH_STATUS, SOP) != 0) {
+packet_off = 0;
+}
+
+buflength = FIELD_EX32(desc_status,
+   GENET_RDMA_LENGTH_STATUS, BUFLENGTH);
+
+/* TODO: Add address_space_read() return value check */
+address_space_read(>dma_as, data_addr,
+MEMTXATTRS_UNSPECIFIED,
+s->tx_packet + packet_off,
+buflength);
+packet_off += buflength;
+
+if (FIELD_EX32(desc_status, GENET_RDMA_LENGTH_STATUS, EOP) != 0) {
+bcm2838_genet_xmit_packet(qemu_get_queue(s->nic), s->tx_packet,
+ packet_off);
+packet_off = 0;
+}
+
+num_descs++;
+cons_index_fld++;
+s->regs.tdma.descs[desc_index].length_status =
+FIELD_DP32(s->regs.tdma.descs[desc_index].length_status,
+   GENET_RDMA_LENGTH_STATUS, OWN, 1);
+read_ptr = read_ptr == RING_END_ADDR + 1 - DESC_SIZE_WORDS
+? RING_START_ADDR : read_ptr + DESC_SIZE_WORDS;
+}
+
+s->regs.tdma.rings[ring_index].read_ptr = read_ptr;
+s->regs.tdma.rings[ring_index].read_ptr_hi = read_ptr >> 32;
+
+return num_descs;
+}
+
+static bool bcm2838_ge

[PATCH v5 14/41] Add BCM2838 PCIE host

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_pcie.c | 217 +-
 hw/arm/trace-events   |   4 +
 include/hw/arm/bcm2838_pcie.h |  22 
 3 files changed, 241 insertions(+), 2 deletions(-)

diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c
index cb1370433e..348263d9fb 100644
--- a/hw/arm/bcm2838_pcie.c
+++ b/hw/arm/bcm2838_pcie.c
@@ -12,11 +12,220 @@
 #include "hw/irq.h"
 #include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
-#include "migration/vmstate.h"
-#include "qemu/module.h"
 #include "hw/arm/bcm2838_pcie.h"
 #include "trace.h"
 
+static uint32_t bcm2838_pcie_config_read(PCIDevice *d,
+ uint32_t address, int len)
+{
+return pci_default_read_config(d, address, len);
+}
+
+static void bcm2838_pcie_config_write(PCIDevice *d, uint32_t addr, uint32_t 
val,
+  int len)
+{
+return pci_default_write_config(d, addr, val, len);
+}
+
+static uint64_t bcm2838_pcie_host_read(void *opaque, hwaddr offset,
+   unsigned size) {
+hwaddr mmcfg_addr;
+uint64_t value = ~0;
+BCM2838PcieHostState *s = opaque;
+PCIExpressHost *pcie_hb = PCIE_HOST_BRIDGE(s);
+uint8_t *root_regs = s->root_port.regs;
+uint32_t *cfg_idx = (uint32_t *)(root_regs + BCM2838_PCIE_EXT_CFG_INDEX
+ - PCIE_CONFIG_SPACE_SIZE);
+
+if (offset - PCIE_CONFIG_SPACE_SIZE + size <= sizeof(s->root_port.regs)) {
+switch (offset) {
+case BCM2838_PCIE_EXT_CFG_DATA
+... BCM2838_PCIE_EXT_CFG_DATA + PCIE_CONFIG_SPACE_SIZE - 1:
+mmcfg_addr = *cfg_idx
+| PCIE_MMCFG_CONFOFFSET(offset - BCM2838_PCIE_EXT_CFG_DATA);
+value = pcie_hb->mmio.ops->read(opaque, mmcfg_addr, size);
+break;
+default:
+memcpy(, root_regs + offset - PCIE_CONFIG_SPACE_SIZE, size);
+}
+} else {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
+
+trace_bcm2838_pcie_host_read(size, offset, value);
+return value;
+}
+
+static void bcm2838_pcie_host_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size) {
+hwaddr mmcfg_addr;
+BCM2838PcieHostState *s = opaque;
+PCIExpressHost *pcie_hb = PCIE_HOST_BRIDGE(s);
+uint8_t *root_regs = s->root_port.regs;
+uint32_t *cfg_idx = (uint32_t *)(root_regs + BCM2838_PCIE_EXT_CFG_INDEX
+ - PCIE_CONFIG_SPACE_SIZE);
+
+trace_bcm2838_pcie_host_write(size, offset, value);
+
+if (offset - PCIE_CONFIG_SPACE_SIZE + size <= sizeof(s->root_port.regs)) {
+switch (offset) {
+case BCM2838_PCIE_EXT_CFG_DATA
+... BCM2838_PCIE_EXT_CFG_DATA + PCIE_CONFIG_SPACE_SIZE - 1:
+mmcfg_addr = *cfg_idx
+| PCIE_MMCFG_CONFOFFSET(offset - BCM2838_PCIE_EXT_CFG_DATA);
+pcie_hb->mmio.ops->write(opaque, mmcfg_addr, value, size);
+break;
+default:
+memcpy(root_regs + offset - PCIE_CONFIG_SPACE_SIZE, , size);
+}
+} else {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
+}
+
+static const MemoryRegionOps bcm2838_pcie_host_ops = {
+.read = bcm2838_pcie_host_read,
+.write = bcm2838_pcie_host_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {.max_access_size = sizeof(uint64_t)},
+};
+
+int bcm2838_pcie_host_set_irq_num(BCM2838PcieHostState *s, int index, int spi)
+{
+if (index >= BCM2838_PCIE_NUM_IRQS) {
+return -EINVAL;
+}
+
+s->irq_num[index] = spi;
+return 0;
+}
+
+static void bcm2838_pcie_host_set_irq(void *opaque, int irq_num, int level)
+{
+BCM2838PcieHostState *s = opaque;
+
+qemu_set_irq(s->irq[irq_num], level);
+}
+
+static PCIINTxRoute bcm2838_pcie_host_route_intx_pin_to_irq(void *opaque,
+int pin)
+{
+PCIINTxRoute route;
+BCM2838PcieHostState *s = opaque;
+
+route.irq = s->irq_num[pin];
+route.mode = route.irq < 0 ? PCI_INTX_DISABLED : PCI_INTX_ENABLED;
+
+return route;
+}
+
+static int bcm2838_pcie_host_map_irq(PCIDevice *pci_dev, int pin)
+{
+return pin;
+}
+
+static void bcm2838_pcie_host_realize(DeviceState *dev, Error **errp)
+{
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+BCM2838PcieHostState *s = BCM2838_PCIE_HOST(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+int i;
+
+memory_region_init_io(>cfg_regs, OBJECT(s), _pcie_host_ops, s,
+

[PATCH v5 01/41] Split out common part of BCM283X classes

2024-02-18 Thread Sergey Kambalin
Pre setup for BCM2838 introduction

Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2836.c | 103 ++-
 hw/arm/raspi.c   |   2 +-
 include/hw/arm/bcm2836.h |  26 +-
 3 files changed, 84 insertions(+), 47 deletions(-)

diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index e3ba18a8ec..e9768f2ab9 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -31,12 +31,12 @@ struct BCM283XClass {
 };
 
 static Property bcm2836_enabled_cores_property =
-DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
+DEFINE_PROP_UINT32("enabled-cpus", BCM283XBaseState, enabled_cpus, 0);
 
-static void bcm2836_init(Object *obj)
+static void bcm283x_base_init(Object *obj)
 {
-BCM283XState *s = BCM283X(obj);
-BCM283XClass *bc = BCM283X_GET_CLASS(obj);
+BCM283XBaseState *s = BCM283X_BASE(obj);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(obj);
 int n;
 
 for (n = 0; n < bc->core_count; n++) {
@@ -52,6 +52,11 @@ static void bcm2836_init(Object *obj)
 object_initialize_child(obj, "control", >control,
 TYPE_BCM2836_CONTROL);
 }
+}
+
+static void bcm283x_init(Object *obj)
+{
+BCM283XState *s = BCM283X(obj);
 
 object_initialize_child(obj, "peripherals", >peripherals,
 TYPE_BCM2835_PERIPHERALS);
@@ -63,10 +68,11 @@ static void bcm2836_init(Object *obj)
   "vcram-size");
 }
 
-static bool bcm283x_common_realize(DeviceState *dev, Error **errp)
+bool bcm283x_common_realize(DeviceState *dev, Error **errp)
 {
 BCM283XState *s = BCM283X(dev);
-BCM283XClass *bc = BCM283X_GET_CLASS(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
 Object *obj;
 
 /* common peripherals from bcm2835 */
@@ -79,90 +85,93 @@ static bool bcm283x_common_realize(DeviceState *dev, Error 
**errp)
 return false;
 }
 
-object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(>peripherals),
-  "sd-bus");
+object_property_add_alias(OBJECT(s_base), "sd-bus",
+  OBJECT(>peripherals), "sd-bus");
 
-sysbus_mmio_map_overlap(SYS_BUS_DEVICE(>peripherals), 0,
-bc->peri_base, 1);
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(>peripherals),
+0, bc->peri_base, 1);
 return true;
 }
 
 static void bcm2835_realize(DeviceState *dev, Error **errp)
 {
 BCM283XState *s = BCM283X(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
 
 if (!bcm283x_common_realize(dev, errp)) {
 return;
 }
 
-if (!qdev_realize(DEVICE(>cpu[0].core), NULL, errp)) {
+if (!qdev_realize(DEVICE(_base->cpu[0].core), NULL, errp)) {
 return;
 }
 
 /* Connect irq/fiq outputs from the interrupt controller. */
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
-qdev_get_gpio_in(DEVICE(>cpu[0].core), ARM_CPU_IRQ));
+qdev_get_gpio_in(DEVICE(_base->cpu[0].core), ARM_CPU_IRQ));
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
-qdev_get_gpio_in(DEVICE(>cpu[0].core), ARM_CPU_FIQ));
+qdev_get_gpio_in(DEVICE(_base->cpu[0].core), ARM_CPU_FIQ));
 }
 
 static void bcm2836_realize(DeviceState *dev, Error **errp)
 {
-BCM283XState *s = BCM283X(dev);
-BCM283XClass *bc = BCM283X_GET_CLASS(dev);
 int n;
+BCM283XState *s = BCM283X(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
 
 if (!bcm283x_common_realize(dev, errp)) {
 return;
 }
 
 /* bcm2836 interrupt controller (and mailboxes, etc.) */
-if (!sysbus_realize(SYS_BUS_DEVICE(>control), errp)) {
+if (!sysbus_realize(SYS_BUS_DEVICE(_base->control), errp)) {
 return;
 }
 
-sysbus_mmio_map(SYS_BUS_DEVICE(>control), 0, bc->ctrl_base);
+sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc->ctrl_base);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
-qdev_get_gpio_in_named(DEVICE(>control), "gpu-irq", 0));
+qdev_get_gpio_in_named(DEVICE(_base->control), "gpu-irq", 0));
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
-qdev_get_gpio_in_named(DEVICE(>control), "gpu-fiq", 0));
+qdev_get_gpio_in_named(DEVICE(_base->control), "gpu-fiq", 0));
 
 for (n = 0; n < BCM283X_NCPUS; n++) {
-object_property_set_int(OBJECT(>cpu[n].core), "mp-affinity",
+object_property_set_int(OBJECT(_base->cpu[n].core), "mp-affinity",
 (bc->clusterid << 8) | n, _abort);
 
 /* set periphbase/CBAR value f

[PATCH v5 29/41] Enable BCM2838 GENET controller

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c |  6 ++
 hw/arm/bcm2838_peripherals.c | 11 +++
 hw/arm/raspi4b.c | 20 +---
 include/hw/arm/bcm2838_peripherals.h |  2 ++
 4 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index c330322bd5..a873162f09 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -239,6 +239,12 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
   int_n);
 }
 
+/* Connect Gigabit Ethernet controller to the interrupt controller */
+sysbus_connect_irq(SYS_BUS_DEVICE(>genet), 0,
+   qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_GENET_A));
+sysbus_connect_irq(SYS_BUS_DEVICE(>genet), 1,
+   qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_GENET_B));
+
 /* Pass through inbound GPIO lines to the GIC */
 qdev_init_gpio_in(dev, bcm2838_gic_set_irq, GIC_NUM_IRQS);
 
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 35366386ca..d3e2ea7b09 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -47,6 +47,10 @@ static void bcm2838_peripherals_init(Object *obj)
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
 
+/* Gigabit Ethernet */
+object_initialize_child(obj, "genet", >genet, TYPE_BCM2838_GENET);
+qemu_configure_nic_device(DEVICE(>genet), true, NULL);
+
 /* Extended Mass Media Controller 2 */
 object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
 
@@ -231,6 +235,13 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
 mmio_mr);
 
+/* Gigabit Ethernet */
+if (!sysbus_realize(SYS_BUS_DEVICE(>genet), errp)) {
+return;
+}
+regs_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>genet), 0);
+memory_region_add_subregion(>peri_low_mr, GENET_OFFSET, regs_mr);
+
 create_unimp(s_base, >clkisp, "bcm2835-clkisp", CLOCK_ISP_OFFSET,
  CLOCK_ISP_SIZE);
 
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 175fd2c4fa..d498bc6215 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -63,25 +63,7 @@ static int raspi_add_memory_node(void *fdt, hwaddr mem_base, 
hwaddr mem_len)
 
 static void raspi4_modify_dtb(const struct arm_boot_info *info, void *fdt)
 {
-uint64_t ram_size;
-
-/* Temporarily disable following devices until they are implemented */
-const char *nodes_to_remove[] = {
-"brcm,bcm2711-genet-v5",
-};
-
-for (int i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
-const char *dev_str = nodes_to_remove[i];
-
-int offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
-if (offset >= 0) {
-if (!fdt_nop_node(fdt, offset)) {
-warn_report("bcm2711 dtc: %s has been disabled!", dev_str);
-}
-}
-}
-
-ram_size = board_ram_size(info->board_id);
+uint64_t ram_size = board_ram_size(info->board_id);
 
 if (info->ram_size > UPPER_RAM_BASE) {
 raspi_add_memory_node(fdt, UPPER_RAM_BASE, ram_size - UPPER_RAM_BASE);
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 555d3a393f..5588b99098 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -13,6 +13,7 @@
 #include "hw/misc/bcm2838_rng200.h"
 #include "hw/misc/bcm2838_thermal.h"
 #include "hw/arm/bcm2838_pcie.h"
+#include "hw/net/bcm2838_genet.h"
 #include "hw/sd/sdhci.h"
 #include "hw/gpio/bcm2838_gpio.h"
 
@@ -73,6 +74,7 @@ struct BCM2838PeripheralState {
 SDHCIState emmc2;
 BCM2838PcieHostState pcie_host;
 BCM2838GpioState gpio;
+BCM2838GenetState genet;
 
 OrIRQState mmc_irq_orgate;
 OrIRQState dma_7_8_irq_orgate;
-- 
2.34.1




[PATCH v5 28/41] Implement GENET RX path

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 265 -
 include/hw/net/bcm2838_genet.h |   1 +
 2 files changed, 265 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 4c9b39a3ca..61c1981e10 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -511,6 +511,25 @@ static bool 
bcm2838_genet_tdma_ring_active(BCM2838GenetState *s,
 return active;
 }
 
+static bool bcm2838_genet_rdma_ring_active(BCM2838GenetState *s,
+   unsigned int ring_index)
+{
+uint32_t ring_mask = 1 << ring_index;
+
+bool dma_en = FIELD_EX32(s->regs.rdma.ctrl, GENET_DMA_CTRL, EN) != 0;
+bool ring_en = (FIELD_EX32(s->regs.rdma.ring_cfg, GENET_DMA_RING_CFG, EN)
+& ring_mask) != 0;
+bool ring_buf_en = (FIELD_EX32(s->regs.rdma.ctrl,
+   GENET_DMA_CTRL, RING_BUF_EN)
+& ring_mask) != 0;
+bool active = dma_en && ring_en && ring_buf_en;
+
+trace_bcm2838_genet_rx_dma_ring_active(ring_index,
+   active ? "active" : "halted");
+
+return active;
+}
+
 static void bcm2838_genet_tdma(BCM2838GenetState *s, hwaddr offset,
uint64_t value)
 {
@@ -721,9 +740,251 @@ static const MemoryRegionOps bcm2838_genet_ops = {
 .valid = {.min_access_size = 4},
 };
 
+static int32_t bcm2838_genet_filter(BCM2838GenetState *s, const void *buf,
+size_t size)
+{
+qemu_log_mask(LOG_UNIMP,
+  "Packet filtration with HFB isn't implemented yet");
+return -1;
+}
+
+static int32_t bcm2838_genet_filter2ring(BCM2838GenetState *s,
+ uint32_t filter_idx)
+{
+qemu_log_mask(LOG_UNIMP,
+  "Packet filtration with HFB isn't implemented yet");
+return -1;
+}
+
+static bool is_packet_broadcast(const uint8_t *buf, size_t size)
+{
+static const uint8_t bcst_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+if (size < sizeof(bcst_addr)) {
+return false;
+}
+
+return !memcmp(buf, bcst_addr, sizeof(bcst_addr));
+}
+
+static bool is_packet_multicast(const uint8_t *buf, size_t size)
+{
+return !!(buf[0] & 0x01);
+}
+
+static ssize_t bcm2838_genet_rdma(BCM2838GenetState *s, uint32_t ring_idx,
+  const void *buf, size_t size)
+{
+const size_t DESC_WORD_SIZE =
+sizeof(BCM2838GenetRdmaDesc) / sizeof(uint32_t);
+
+ssize_t len = 0;
+BCM2838GenetRegsRdma *rdma = >regs.rdma;
+BCM2838GenetRdmaRing *ring = >rings[ring_idx];
+hwaddr write_index =
+(ring->write_ptr + ((hwaddr)ring->write_ptr_hi << 32)) / 
DESC_WORD_SIZE;
+BCM2838GenetRdmaDesc *desc = >descs[write_index];
+
+const hwaddr START_INDEX =
+(ring->start_addr + ((hwaddr)ring->start_addr_hi << 32))
+/ DESC_WORD_SIZE;
+const hwaddr END_INDEX =
+(ring->end_addr + ((hwaddr)ring->end_addr_hi << 32)) / DESC_WORD_SIZE;
+
+if (!bcm2838_genet_rdma_ring_active(s, ring_idx)) {
+return -1;
+}
+
+desc->length_status = FIELD_DP32(desc->length_status,
+ GENET_RDMA_LENGTH_STATUS, SOP, 1);
+
+while (len < size) {
+size_t l = size - len;
+size_t buf_size = ring->ring_buf_size & 0x;
+uint8_t *dma_buf = s->rx_packet;
+hwaddr dma_buf_addr =
+desc->address_lo + ((hwaddr)desc->address_hi << 32);
+MemTxResult mem_tx_result = MEMTX_OK;
+uint8_t *frame_buf = dma_buf + sizeof(BCM2838GenetXmitStatus) + 2;
+BCM2838GenetXmitStatus *xmit_status = (BCM2838GenetXmitStatus 
*)dma_buf;
+struct iovec iov;
+bool isip4, isip6;
+size_t l3hdr_off, l4hdr_off, l5hdr_off;
+eth_ip6_hdr_info ip6hdr_info;
+eth_ip4_hdr_info ip4hdr_info;
+eth_l4_hdr_info  l4hdr_info;
+
+bool crc_fwd = FIELD_EX32(s->regs.umac.cmd, GENET_UMAC_CMD, CRC_FWD);
+size_t buflength;
+uint32_t prod_index;
+
+if (l > ring->ring_buf_size) {
+l = ring->ring_buf_size;
+}
+
+memcpy(frame_buf, buf + len, l);
+iov.iov_base = frame_buf;
+iov.iov_len = l;
+eth_get_protocols(, 1, 0,
+  , ,
+  _off, _off, _off,
+  _info, _info, _info);
+
+len += l;
+
+desc->length_status = FIELD_DP32(desc->length_status,
+ GENET_RDMA_LENGTH_STATUS,
+ EOP, !!(len >= size));
+
+buflength = l + sizeof(BCM2838GenetXmitStatus) + 2;
+if 

[PATCH v5 05/41] Add GIC-400 to BCM2838 SoC

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c | 167 ++-
 hw/arm/trace-events  |   3 +
 include/hw/arm/bcm2838.h |   2 +
 include/hw/arm/bcm2838_peripherals.h |  37 ++
 4 files changed, 207 insertions(+), 2 deletions(-)

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index 05281e247f..332e906a84 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -14,8 +14,36 @@
 #include "hw/arm/bcm2838.h"
 #include "trace.h"
 
+#define GIC400_MAINTENANCE_IRQ  9
+#define GIC400_TIMER_NS_EL2_IRQ 10
+#define GIC400_TIMER_VIRT_IRQ   11
+#define GIC400_LEGACY_FIQ   12
+#define GIC400_TIMER_S_EL1_IRQ  13
+#define GIC400_TIMER_NS_EL1_IRQ 14
+#define GIC400_LEGACY_IRQ   15
+
+/* Number of external interrupt lines to configure the GIC with */
+#define GIC_NUM_IRQS192
+
+#define PPI(cpu, irq) (GIC_NUM_IRQS + (cpu) * GIC_INTERNAL + GIC_NR_SGIS + irq)
+
+#define GIC_BASE_OFS0x
+#define GIC_DIST_OFS0x1000
+#define GIC_CPU_OFS 0x2000
+#define GIC_VIFACE_THIS_OFS 0x4000
+#define GIC_VIFACE_OTHER_OFS(cpu)  (0x5000 + (cpu) * 0x200)
+#define GIC_VCPU_OFS0x6000
+
 #define VIRTUAL_PMU_IRQ 7
 
+static void bcm2838_gic_set_irq(void *opaque, int irq, int level)
+{
+BCM2838State *s = (BCM2838State *)opaque;
+
+trace_bcm2838_gic_set_irq(irq, level);
+qemu_set_irq(qdev_get_gpio_in(DEVICE(>gic), irq), level);
+}
+
 static void bcm2838_init(Object *obj)
 {
 BCM2838State *s = BCM2838(obj);
@@ -28,11 +56,12 @@ static void bcm2838_init(Object *obj)
   "vcram-size");
 object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
   "command-line");
+
+object_initialize_child(obj, "gic", >gic, TYPE_ARM_GIC);
 }
 
 static void bcm2838_realize(DeviceState *dev, Error **errp)
 {
-int n;
 BCM2838State *s = BCM2838(dev);
 BCM283XBaseState *s_base = BCM283X_BASE(dev);
 BCM283XBaseClass *bc_base = BCM283X_BASE_GET_CLASS(dev);
@@ -40,6 +69,8 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 BCMSocPeripheralBaseState *ps_base =
 BCM_SOC_PERIPHERALS_BASE(>peripherals);
 
+DeviceState *gicdev = NULL;
+
 if (!bcm283x_common_realize(dev, ps_base, errp)) {
 return;
 }
@@ -52,11 +83,15 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc_base->ctrl_base);
 
 /* Create cores */
-for (n = 0; n < bc_base->core_count; n++) {
+for (int n = 0; n < bc_base->core_count; n++) {
 
 object_property_set_int(OBJECT(_base->cpu[n].core), "mp-affinity",
 (bc_base->clusterid << 8) | n, _abort);
 
+/* set periphbase/CBAR value for CPU-local registers */
+object_property_set_int(OBJECT(_base->cpu[n].core), "reset-cbar",
+bc_base->peri_base, _abort);
+
 /* start powered off if not enabled */
 object_property_set_bool(OBJECT(_base->cpu[n].core),
  "start-powered-off",
@@ -66,6 +101,134 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 return;
 }
 }
+
+if (!object_property_set_uint(OBJECT(>gic), "revision", 2, errp)) {
+return;
+}
+
+if (!object_property_set_uint(OBJECT(>gic), "num-cpu", BCM283X_NCPUS,
+  errp)) {
+return;
+}
+
+if (!object_property_set_uint(OBJECT(>gic), "num-irq",
+  GIC_NUM_IRQS + GIC_INTERNAL, errp)) {
+return;
+}
+
+if (!object_property_set_bool(OBJECT(>gic),
+  "has-virtualization-extensions", true,
+  errp)) {
+return;
+}
+
+if (!sysbus_realize(SYS_BUS_DEVICE(>gic), errp)) {
+return;
+}
+
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 0,
+bc_base->ctrl_base + BCM2838_GIC_BASE + GIC_DIST_OFS);
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 1,
+bc_base->ctrl_base + BCM2838_GIC_BASE + GIC_CPU_OFS);
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 2,
+bc_base->ctrl_base + BCM2838_GIC_BASE + 
GIC_VIFACE_THIS_OFS);
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 3,
+bc_base->ctrl_base + BCM2838_GIC_BASE + GIC_VCPU_OFS);
+
+for (int n = 0; n < BCM283X_NCPUS; n++) {
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 4 + n,
+bc_base->ctrl_base + BCM2838_GIC_BASE
++ GIC_VIFACE_OTHER_OFS(n));
+}
+
+gi

[PATCH v5 41/41] Add RPi4B to paspi.rst

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 docs/system/arm/raspi.rst | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/docs/system/arm/raspi.rst b/docs/system/arm/raspi.rst
index d0a6f08b2b..c21b27744e 100644
--- a/docs/system/arm/raspi.rst
+++ b/docs/system/arm/raspi.rst
@@ -1,5 +1,5 @@
-Raspberry Pi boards (``raspi0``, ``raspi1ap``, ``raspi2b``, ``raspi3ap``, 
``raspi3b``)
-==
+Raspberry Pi boards (``raspi0``, ``raspi1ap``, ``raspi2b``, ``raspi3ap``, 
``raspi3b``, ``raspi4b-2g``)
+==
 
 
 QEMU provides models of the following Raspberry Pi boards:
@@ -12,12 +12,13 @@ QEMU provides models of the following Raspberry Pi boards:
   Cortex-A53 (4 cores), 512 MiB of RAM
 ``raspi3b``
   Cortex-A53 (4 cores), 1 GiB of RAM
-
+``raspi4b-2g``
+  Cortex-A72 (4 cores), 2 GiB of RAM
 
 Implemented devices
 ---
 
- * ARM1176JZF-S, Cortex-A7 or Cortex-A53 CPU
+ * ARM1176JZF-S, Cortex-A7, Cortex-A53 or Cortex-A72 CPU
  * Interrupt controller
  * DMA controller
  * Clock and reset controller (CPRMAN)
@@ -34,6 +35,8 @@ Implemented devices
  * MailBox controller (MBOX)
  * VideoCore firmware (property)
  * Peripheral SPI controller (SPI)
+ * PCIE Root Port (raspi4b-2g)
+ * GENET Ethernet Controller (raspi4b-2g)
 
 
 Missing devices
-- 
2.34.1




[PATCH v5 20/41] Add GENET register structs. Part 1

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 37 
 include/hw/net/bcm2838_genet.h | 77 +-
 2 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 4420486e00..0d98d1b30e 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -15,9 +15,46 @@
 #include "hw/irq.h"
 #include "net/checksum.h"
 #include "sysemu/dma.h"
+#include "hw/registerfields.h"
 #include "hw/net/bcm2838_genet.h"
 #include "trace.h"
 
+REG32(GENET_SYS_REV_CTRL,  0)
+FIELD(GENET_SYS_REV_CTRL, GPHY_REV,0, 16)
+FIELD(GENET_SYS_REV_CTRL, MINOR_REV,   16, 4)
+FIELD(GENET_SYS_REV_CTRL, RSVD_20_23,  20, 4)
+FIELD(GENET_SYS_REV_CTRL, MAJOR_REV,   24, 4)
+FIELD(GENET_SYS_REV_CTRL, RSVD_28_31,  28, 4)
+
+REG32(GENET_INTRL_0,0)
+FIELD(GENET_INTRL_0, SCB,   0, 1)
+FIELD(GENET_INTRL_0, EPHY,  1, 1)
+FIELD(GENET_INTRL_0, PHY_DET_R, 2, 1)
+FIELD(GENET_INTRL_0, PHY_DET_F, 3, 1)
+FIELD(GENET_INTRL_0, LINK_UP,   4, 1)
+FIELD(GENET_INTRL_0, LINK_DOWN, 5, 1)
+FIELD(GENET_INTRL_0, UMAC,  6, 1)
+FIELD(GENET_INTRL_0, UMAC_TSV,  7, 1)
+FIELD(GENET_INTRL_0, TBUF_UNDERRUN, 8, 1)
+FIELD(GENET_INTRL_0, RBUF_OVERFLOW, 9, 1)
+FIELD(GENET_INTRL_0, HFB_SM,10, 1)
+FIELD(GENET_INTRL_0, HFB_MM,11, 1)
+FIELD(GENET_INTRL_0, MPD_R, 12, 1)
+FIELD(GENET_INTRL_0, RXDMA_MBDONE,  13, 1)
+FIELD(GENET_INTRL_0, RXDMA_PDONE,   14, 1)
+FIELD(GENET_INTRL_0, RXDMA_BDONE,   15, 1)
+FIELD(GENET_INTRL_0, TXDMA_MBDONE,  16, 1)
+FIELD(GENET_INTRL_0, TXDMA_PDONE,   17, 1)
+FIELD(GENET_INTRL_0, TXDMA_BDONE,   18, 1)
+FIELD(GENET_INTRL_0, RSVD_19_22,19, 4)
+FIELD(GENET_INTRL_0, MDIO_DONE, 23, 1)
+FIELD(GENET_INTRL_0, MDIO_ERROR,24, 1)
+FIELD(GENET_INTRL_0, RSVD_25_31,25, 4)
+
+REG32(GENET_INTRL_1,  0)
+FIELD(GENET_INTRL_1, TX_INTRS,0, 16)
+FIELD(GENET_INTRL_1, RX_INTRS,16, 16)
+
 
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index d166a5c24c..f583818399 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -19,7 +19,82 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_REV_MINOR 0
 
 typedef struct {
-uint8_t stub_area[0x1]; /* temporary stub */
+uint32_t rev_ctrl;
+uint32_t port_ctrl;
+uint32_t rbuf_flush_ctrl;
+uint32_t tbuf_flush_ctrl;
+uint32_t reserved_0x10[12];
+} BCM2838GenetRegsSys;
+
+typedef struct {
+uint32_t reserved_0x0[16];
+} BCM2838GenetRegsGrBridge;
+
+typedef struct {
+uint32_t pwr_mgmt;
+uint32_t reserved_0x4[2];
+uint32_t rgmii_oob_ctrl;
+uint32_t reserved_0x10[3];
+uint32_t gphy_ctrl;
+uint32_t reserved_0x20[24];
+} BCM2838GenetRegsExt;
+
+typedef struct {
+uint32_t stat;
+uint32_t set;
+uint32_t clear;
+uint32_t mask_status;
+uint32_t mask_set;
+uint32_t mask_clear;
+uint32_t reserved_0x18[10];
+} BCM2838GenetRegsIntrl0;
+
+typedef struct {
+uint32_t stat;
+uint32_t set;
+uint32_t clear;
+uint32_t mask_status;
+uint32_t mask_set;
+uint32_t mask_clear;
+uint32_t reserved_0x18[10];
+} BCM2838GenetRegsIntrl1;
+
+typedef struct {
+uint32_t ctrl;
+uint32_t reserved_0x4[2];
+uint32_t status;
+uint32_t reserved_0x10;
+uint32_t chk_ctrl;
+uint32_t reserved_0x18[31];
+uint32_t ovfl_cnt;
+uint32_t err_cnt;
+uint32_t energy_ctrl;
+uint32_t reserved_0xA0[5];
+uint32_t size_ctrl;
+uint32_t reserved_0xB8[18];
+} BCM2838GenetRegsRbuf;
+
+typedef struct {
+uint32_t ctrl;
+uint32_t reserved_0x4[2];
+uint32_t bp_mc;
+uint32_t reserved_0x10;
+uint32_t energy_ctrl;
+uint32_t reserved_0x18[58];
+} BCM2838GenetRegsTbuf;
+
+typedef struct {
+BCM2838GenetRegsSys sys;
+BCM2838GenetRegsGrBridge gr_bridge;
+BCM2838GenetRegsExt ext;
+uint32_t reserved_0x100[64];
+BCM2838GenetRegsIntrl0 intrl0;
+BCM2838GenetRegsIntrl1 intrl1;
+uint32_t reserved_0x280[32];
+BCM2838GenetRegsRbuf rbuf;
+uint32_t reserved_0x400[128];
+BCM2838GenetRegsTbuf tbuf;
+uint32_t reserved_0x700[64];
 } BCM2838GenetRegs;
 
 struct BCM2838GenetState {
-- 
2.34.1




[PATCH v5 10/41] Introduce Raspberry PI 4 machine

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2835_peripherals.c| 17 ++--
 hw/arm/bcm2836.c|  2 +
 hw/arm/bcm2838.c|  2 +
 hw/arm/meson.build  |  2 +-
 hw/arm/raspi.c  | 27 -
 hw/arm/raspi4b.c| 70 +
 include/hw/arm/raspi_platform.h | 11 ++
 include/hw/display/bcm2835_fb.h |  2 +
 8 files changed, 119 insertions(+), 14 deletions(-)
 create mode 100644 hw/arm/raspi4b.c

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index ed38a08a57..a0bbe76f26 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -108,6 +108,7 @@ static void raspi_peripherals_base_init(Object *obj)
 /* Framebuffer */
 object_initialize_child(obj, "fb", >fb, TYPE_BCM2835_FB);
 object_property_add_alias(obj, "vcram-size", OBJECT(>fb), "vcram-size");
+object_property_add_alias(obj, "vcram-base", OBJECT(>fb), "vcram-base");
 
 object_property_add_const_link(OBJECT(>fb), "dma-mr",
OBJECT(>gpu_bus_mr));
@@ -229,7 +230,7 @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, 
Error **errp)
 Object *obj;
 MemoryRegion *ram;
 Error *err = NULL;
-uint64_t ram_size, vcram_size;
+uint64_t ram_size, vcram_size, vcram_base;
 int n;
 
 obj = object_property_get_link(OBJECT(dev), "ram", _abort);
@@ -333,11 +334,21 @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
-if (!object_property_set_uint(OBJECT(>fb), "vcram-base",
-  ram_size - vcram_size, errp)) {
+vcram_base = object_property_get_uint(OBJECT(s), "vcram-base", );
+if (err) {
+error_propagate(errp, err);
 return;
 }
 
+if (vcram_base == 0) {
+vcram_base = ram_size - vcram_size;
+}
+vcram_base = MIN(vcram_base, UPPER_RAM_BASE - vcram_size);
+
+if (!object_property_set_uint(OBJECT(>fb), "vcram-base", vcram_base,
+  errp)) {
+return;
+}
 if (!sysbus_realize(SYS_BUS_DEVICE(>fb), errp)) {
 return;
 }
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 7e4c60dd80..db191661f2 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -66,6 +66,8 @@ static void bcm283x_init(Object *obj)
   "command-line");
 object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
   "vcram-size");
+object_property_add_alias(obj, "vcram-base", OBJECT(>peripherals),
+  "vcram-base");
 }
 
 bool bcm283x_common_realize(DeviceState *dev, BCMSocPeripheralBaseState *ps,
diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index 332e906a84..ddb7c5f757 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -54,6 +54,8 @@ static void bcm2838_init(Object *obj)
   "board-rev");
 object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
   "vcram-size");
+object_property_add_alias(obj, "vcram-base", OBJECT(>peripherals),
+  "vcram-base");
 object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
   "command-line");
 
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 1390a9d7b5..6808135c1f 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -30,7 +30,7 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: 
files('allwinner-a10.c', 'cubi
 arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 
'orangepi.c'))
 arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 
'bananapi_m2u.c'))
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
-arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: 
files('bcm2838.c'))
+arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: 
files('bcm2838.c', 'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 7d04734cd2..8b1a046912 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -18,6 +18,7 @@
 #include "qapi/error.h"
 #include "hw/arm/boot.h"
 #include "hw/arm/bcm2836.h"
+#include "hw/arm/bcm2838.h"
 #include "hw/arm/raspi_platform.h"
 #include "hw/registerfields.h"
 #include "qemu/error-report.h"
@@ -61,6 +62,7 @@ typedef enum RaspiPro

[PATCH v5 16/41] Add RPi4 RNG200

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c |   4 +
 hw/arm/bcm2838_peripherals.c |  14 +
 hw/arm/raspi4b.c |   1 -
 hw/misc/bcm2838_rng200.c | 405 +++
 hw/misc/meson.build  |   1 +
 hw/misc/trace-events |   9 +
 include/hw/arm/bcm2838_peripherals.h |   2 +
 include/hw/misc/bcm2838_rng200.h |  43 +++
 8 files changed, 478 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/bcm2838_rng200.c
 create mode 100644 include/hw/misc/bcm2838_rng200.h

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index 481b262b02..c330322bd5 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -205,6 +205,10 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(_base->dwc2), 0,
qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_DWC2));
 
+/* Connect RNG200 to the interrupt controller */
+sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0,
+   qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_RNG200));
+
 /* Connect DMA 0-6 to the interrupt controller */
 for (int n = GIC_SPI_INTERRUPT_DMA_0; n <= GIC_SPI_INTERRUPT_DMA_6; n++) {
 sysbus_connect_irq(SYS_BUS_DEVICE(_base->dma),
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 7e86ebb555..6b4c840c5b 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -34,6 +34,9 @@ static void bcm2838_peripherals_init(Object *obj)
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* Random Number Generator */
+object_initialize_child(obj, "rng200", >rng200, TYPE_BCM2838_RNG200);
+
 /* PCIe Host Bridge */
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
@@ -88,6 +91,17 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCM2838_VC_PERI_LOW_BASE,
 >peri_low_mr_alias, 1);
 
+/* Random Number Generator */
+if (!sysbus_realize(SYS_BUS_DEVICE(>rng200), errp)) {
+return;
+}
+memory_region_add_subregion(
+_base->peri_mr, RNG_OFFSET,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng200), 0));
+sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0,
+qdev_get_gpio_in_named(DEVICE(_base->ic), BCM2835_IC_GPU_IRQ,
+   INTERRUPT_RNG));
+
 /* Extended Mass Media Controller 2 */
 object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
  _abort);
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 2431b0b8c3..3c71fa9a9a 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -67,7 +67,6 @@ static void raspi4_modify_dtb(const struct arm_boot_info 
*info, void *fdt)
 
 /* Temporarily disable following devices until they are implemented */
 const char *nodes_to_remove[] = {
-"brcm,bcm2711-rng200",
 "brcm,bcm2711-thermal",
 "brcm,bcm2711-genet-v5",
 };
diff --git a/hw/misc/bcm2838_rng200.c b/hw/misc/bcm2838_rng200.c
new file mode 100644
index 00..84ed723a1c
--- /dev/null
+++ b/hw/misc/bcm2838_rng200.c
@@ -0,0 +1,405 @@
+/*
+ * BCM2838 Random Number Generator emulation
+ *
+ * Copyright (C) 2022 Sergey Pushkarev 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qom/object_interfaces.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "hw/misc/bcm2838_rng200.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+/* RNG200 registers */
+REG32(RNG_CTRL,   0x00)
+FIELD(RNG_CTRL, RBG_ENABLE,   0 , 1)
+FIELD(RNG_CTRL, RSVD, 1 , 12)
+FIELD(RNG_CTRL, DIV, 13 , 8)
+
+REG32(RNG_SOFT_RESET,0x04)
+REG32(RBG_SOFT_RESET,0x08)
+REG32(RNG_TOTAL_BIT_COUNT,   0x0C)
+REG32(RNG_TOTAL_BIT_COUNT_THRESHOLD, 0x10)
+
+REG32(RNG_INT_STATUS,   0x18)
+FIELD(RNG_INT_STATUS, TOTAL_BITS_COUNT_IRQ, 0, 1)
+FIELD(RNG_INT_STATUS, RSVD0,1, 4)
+FIELD(RNG_INT_STATUS, NIST_FAIL_IRQ,5, 1)
+FIELD(RNG_INT_STATUS, RSVD1,6, 11)
+FIELD(RNG_INT_STATUS, STARTUP_TRANSITIONS_MET_IRQ,  17, 1)
+FIELD(RNG_INT_STATUS, RSVD2,18, 13)
+FIELD(RNG_INT_STATUS, MASTER_FAIL_LOCKOUT_IRQ,  30, 1)
+
+REG32(RNG_INT_ENABLE,   0x1C)
+FIELD(RNG_INT_ENABLE,

[PATCH v5 35/41] Add mailbox tests tags. Part 3

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 78 +++
 1 file changed, 78 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index b4f7b7b314..d753f17fb2 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -446,6 +446,84 @@ DECLARE_TAG_TYPE(TAG_GET_DMA_CHANNELS_t,
 uint32_t mask;
 });
 
+DECLARE_TAG_TYPE(TAG_GET_THROTTLED_t,
+struct {},
+struct {
+uint32_t throttled;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_NUM_DISPLAYS_t,
+struct {},
+struct {
+uint32_t num_displays;
+});
+
+DECLARE_TAG_TYPE(TAG_FRAMEBUFFER_GET_DISPLAY_SETTINGS_t,
+struct {},
+struct {
+uint32_t display_num;
+uint32_t phys_width;
+uint32_t phys_height;
+uint32_t bpp;
+uint16_t pitch;
+uint32_t virt_width;
+uint32_t virt_height;
+uint16_t virt_width_offset;
+uint32_t virt_height_offset;
+uint32_t fb_bus_address_lo;
+uint32_t fb_bus_address_hi;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_GPIO_CONFIG_t,
+struct {
+uint32_t gpio_num;
+},
+struct {
+uint32_t zero;
+uint32_t direction;
+uint32_t polarity;
+uint32_t term_en;
+uint32_t term_pull_up;
+});
+
+
+DECLARE_TAG_TYPE(TAG_SET_GPIO_CONFIG_t,
+struct {
+uint32_t gpio_num;
+uint32_t direction;
+uint32_t polarity;
+uint32_t term_en;
+uint32_t term_pull_up;
+uint32_t state;
+},
+struct {
+uint32_t zero;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_GPIO_STATE_t,
+struct {
+uint32_t gpio_num;
+},
+struct {
+uint32_t zero;
+uint32_t state;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_GPIO_STATE_t,
+struct {
+uint32_t gpio_num;
+uint32_t state;
+},
+struct {
+uint32_t zero;
+});
+
+DECLARE_TAG_TYPE(TAG_VCHIQ_INIT_t,
+struct {},
+struct {
+uint32_t zero;
+});
+
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
 void mbox1_write_message(uint8_t channel, uint32_t msg_addr);
-- 
2.34.1




[PATCH v5 09/41] Add GPIO and SD to BCM2838 periph

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 143 +++
 include/hw/arm/bcm2838_peripherals.h |   8 ++
 2 files changed, 151 insertions(+)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 06110c724f..55ae56733f 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -15,22 +15,56 @@
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
+/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
+#define BCM2835_SDHC_CAPAREG 0x52134b4
+
 static void bcm2838_peripherals_init(Object *obj)
 {
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(obj);
 BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_GET_CLASS(obj);
+BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(obj);
 
 /* Lower memory region for peripheral devices (exported to the Soc) */
 memory_region_init(>peri_low_mr, obj, "bcm2838-peripherals",
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* Extended Mass Media Controller 2 */
+object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
+
+/* GPIO */
+object_initialize_child(obj, "gpio", >gpio, TYPE_BCM2838_GPIO);
+
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhci",
+   OBJECT(_base->sdhci.sdbus));
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhost",
+   OBJECT(_base->sdhost.sdbus));
+
+object_initialize_child(obj, "mmc_irq_orgate", >mmc_irq_orgate,
+TYPE_OR_IRQ);
+object_property_set_int(OBJECT(>mmc_irq_orgate), "num-lines", 2,
+_abort);
+
+object_initialize_child(obj, "dma_7_8_irq_orgate", >dma_7_8_irq_orgate,
+TYPE_OR_IRQ);
+object_property_set_int(OBJECT(>dma_7_8_irq_orgate), "num-lines", 2,
+_abort);
+
+object_initialize_child(obj, "dma_9_10_irq_orgate", 
>dma_9_10_irq_orgate,
+TYPE_OR_IRQ);
+object_property_set_int(OBJECT(>dma_9_10_irq_orgate), "num-lines", 2,
+_abort);
 }
 
 static void bcm2838_peripherals_realize(DeviceState *dev, Error **errp)
 {
+DeviceState *mmc_irq_orgate;
+DeviceState *dma_7_8_irq_orgate;
+DeviceState *dma_9_10_irq_orgate;
+MemoryRegion *mphi_mr;
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(dev);
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+int n;
 
 bcm_soc_peripherals_common_realize(dev, errp);
 
@@ -42,6 +76,115 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCM2838_VC_PERI_LOW_BASE,
 >peri_low_mr_alias, 1);
 
+/* Extended Mass Media Controller 2 */
+object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
+ _abort);
+object_property_set_uint(OBJECT(>emmc2), "capareg",
+ BCM2835_SDHC_CAPAREG, _abort);
+object_property_set_bool(OBJECT(>emmc2), "pending-insert-quirk", true,
+ _abort);
+if (!sysbus_realize(SYS_BUS_DEVICE(>emmc2), errp)) {
+return;
+}
+
+memory_region_add_subregion(_base->peri_mr, EMMC2_OFFSET,
+
sysbus_mmio_get_region(SYS_BUS_DEVICE(>emmc2),
+0));
+
+/* According to DTS, EMMC and EMMC2 share one irq */
+if (!qdev_realize(DEVICE(>mmc_irq_orgate), NULL, errp)) {
+return;
+}
+
+mmc_irq_orgate = DEVICE(>mmc_irq_orgate);
+sysbus_connect_irq(SYS_BUS_DEVICE(>emmc2), 0,
+   qdev_get_gpio_in(mmc_irq_orgate, 0));
+
+sysbus_connect_irq(SYS_BUS_DEVICE(_base->sdhci), 0,
+   qdev_get_gpio_in(mmc_irq_orgate, 1));
+
+   /* Connect EMMC and EMMC2 to the interrupt controller */
+qdev_connect_gpio_out(mmc_irq_orgate, 0,
+  qdev_get_gpio_in_named(DEVICE(_base->ic),
+ BCM2835_IC_GPU_IRQ,
+ INTERRUPT_ARASANSDIO));
+
+/* Connect DMA 0-6 to the interrupt controller */
+for (n = 0; n < 7; n++) {
+sysbus_connect_irq(SYS_BUS_DEVICE(_base->dma), n,
+   qdev_get_gpio_in_named(DEVICE(_base->ic),
+  BCM2835_IC_GPU_IRQ,
+  GPU_INTERRUPT_DMA0 + n));
+}
+
+   /* According to DTS, DMA 7 and 8 share one irq

[PATCH v5 36/41] Add mailbox property tests. Part 1

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.c|   1 -
 tests/qtest/bcm2838-mbox-property-test.c | 207 +++
 tests/qtest/meson.build  |   2 +-
 3 files changed, 208 insertions(+), 2 deletions(-)
 create mode 100644 tests/qtest/bcm2838-mbox-property-test.c

diff --git a/tests/qtest/bcm2838-mailbox.c b/tests/qtest/bcm2838-mailbox.c
index 1efd3c628a..0928a3dff8 100644
--- a/tests/qtest/bcm2838-mailbox.c
+++ b/tests/qtest/bcm2838-mailbox.c
@@ -11,7 +11,6 @@
 #include "hw/registerfields.h"
 #include "libqtest-single.h"
 #include "bcm2838-mailbox.h"
-#include "hw/arm/raspberrypi-fw-defs.h"
 
 REG32(MBOX_EXCHNG_REG,  0)
 FIELD(MBOX_EXCHNG_REG, CHANNEL, 0, 4)
diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
new file mode 100644
index 00..acb421915b
--- /dev/null
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -0,0 +1,207 @@
+/*
+ * Tests set for BCM2838 mailbox property interface.
+ *
+ * Copyright (c) 2022 Auriga
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/registerfields.h"
+#include "libqtest-single.h"
+#include "bcm2838-mailbox.h"
+#include "hw/arm/raspberrypi-fw-defs.h"
+
+REG32(MBOX_SIZE_STAT,  0)
+FIELD(MBOX_SIZE_STAT, SIZE,0, 31)
+FIELD(MBOX_SIZE_STAT, SUCCESS, 31, 1)
+
+REG32(SET_POWER_STATE_CMD,0)
+FIELD(SET_POWER_STATE_CMD, EN,0, 1)
+FIELD(SET_POWER_STATE_CMD, WAIT,  1, 1)
+
+REG32(GET_CLOCK_STATE_CMD,0)
+FIELD(GET_CLOCK_STATE_CMD, EN,0, 1)
+FIELD(GET_CLOCK_STATE_CMD, NPRES, 1, 1)
+
+#define MBOX_TEST_MESSAGE_ADDRESS 0x1000
+
+#define TEST_TAG(x) RPI_FWREQ_ ## x
+#define TEST_TAG_TYPE(x) TAG_##x##_t
+
+#define TEST_FN_NAME(test, subtest) \
+test ## _ ## subtest ## _test
+
+#define SETUP_FN_NAME(test, subtest) \
+test ## _ ## subtest ## _setup
+
+#define CHECK_FN_NAME(test, subtest) \
+test ## _ ## subtest ## _spec_check
+
+#define DECLARE_TEST_CASE_SETUP(testname, ...)  \
+void SETUP_FN_NAME(testname, __VA_ARGS__)   \
+ (TEST_TAG_TYPE(testname) * tag)
+
+/**/
+#define DECLARE_TEST_CASE(testname, ...)   
\
+__attribute__((weak))  
\
+void SETUP_FN_NAME(testname, __VA_ARGS__)  
\
+  (TEST_TAG_TYPE(testname) * tag); 
\
+static void CHECK_FN_NAME(testname, __VA_ARGS__)   
\
+ (TEST_TAG_TYPE(testname) *tag);   
\
+static void TEST_FN_NAME(testname, __VA_ARGS__)(void) {
\
+struct {   
\
+MboxBufHeader header;  
\
+TEST_TAG_TYPE(testname) tag;   
\
+uint32_t end_tag;  
\
+} mailbox_buffer = { 0 };  
\
+   
\
+QTestState *qts = qtest_init("-machine raspi4b-2g");   
\
+   
\
+mailbox_buffer.header.size = sizeof(mailbox_buffer);   
\
+mailbox_buffer.header.req_resp_code = MBOX_PROCESS_REQUEST;
\
+   
\
+mailbox_buffer.tag.id = TEST_TAG(testname);
\
+mailbox_buffer.tag.value_buffer_size = MAX(
\
+sizeof(mailbox_buffer.tag.request.value),  
\
+sizeof(mailbox_buffer.tag.response.value));
\
+mailbox_buffer.tag.request.zero = 0;   
\
+   
\
+mailbox_buffer.end_tag = RPI_FWREQ_PROPERTY_END;   
\
+   
\
+if (SETUP_FN_NAME(testname, __VA_ARGS__)) {
\
+SETUP_FN_NAME(testname, __VA_ARGS__)(_buffer.tag); 
\
+}  
\
+   
\
+qtest_memwrite(qts, MBOX_

[PATCH v5 40/41] Append added properties to mailbox test

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index c96a9ba3f3..ff7c347e7c 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -270,6 +270,12 @@ DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, ANY) {
 tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
 }
 
+/**/
+DECLARE_TEST_CASE(GET_CLOCKS) {
+g_assert_cmphex(tag->response.value.root_clock, ==, CLOCK_ID_ROOT);
+g_assert_cmphex(tag->response.value.arm_clock, ==, CLOCK_ID_ARM);
+}
+
 
/**/
 DECLARE_TEST_CASE(GET_TEMPERATURE) {
 g_assert_cmphex(tag->response.value.temperature_id, ==, 
TEMPERATURE_ID_SOC);
@@ -536,6 +542,11 @@ DECLARE_TEST_CASE(GET_COMMAND_LINE) {
 /* No special checks are needed for this test case */
 }
 
+/**/
+DECLARE_TEST_CASE(GET_THROTTLED) {
+g_assert_cmpint(tag->response.value.throttled, ==, 0);
+}
+
 
/**/
 DECLARE_TEST_CASE(FRAMEBUFFER_GET_NUM_DISPLAYS) {
 g_assert_cmpint(tag->response.value.num_displays, ==, 1);
@@ -549,6 +560,11 @@ DECLARE_TEST_CASE_SETUP(FRAMEBUFFER_SET_PITCH) {
 tag->request.value.pitch = DUMMY_VALUE;
 }
 
+/**/
+DECLARE_TEST_CASE(VCHIQ_INIT) {
+g_assert_cmpint(tag->response.value.zero, ==, 0);
+}
+
 
/**/
 int main(int argc, char **argv)
 {
@@ -572,6 +588,7 @@ int main(int argc, char **argv)
 QTEST_ADD_TEST_CASE(GET_CLOCK_RATE, ANY);
 QTEST_ADD_TEST_CASE(GET_MAX_CLOCK_RATE, ANY);
 QTEST_ADD_TEST_CASE(GET_MIN_CLOCK_RATE, ANY);
+QTEST_ADD_TEST_CASE(GET_CLOCKS);
 QTEST_ADD_TEST_CASE(GET_TEMPERATURE);
 QTEST_ADD_TEST_CASE(GET_MAX_TEMPERATURE);
 QTEST_ADD_TEST_CASE(FRAMEBUFFER_ALLOCATE);
@@ -607,6 +624,8 @@ int main(int argc, char **argv)
 QTEST_ADD_TEST_CASE(GET_COMMAND_LINE);
 QTEST_ADD_TEST_CASE(FRAMEBUFFER_GET_NUM_DISPLAYS);
 QTEST_ADD_TEST_CASE(FRAMEBUFFER_SET_PITCH);
+QTEST_ADD_TEST_CASE(GET_THROTTLED);
+QTEST_ADD_TEST_CASE(VCHIQ_INIT);
 
 return g_test_run();
 }
-- 
2.34.1




[PATCH v5 04/41] Introduce BCM2838 SoC

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c | 98 
 hw/arm/bcm2838_peripherals.c | 72 
 hw/arm/meson.build   |  2 +
 include/hw/arm/bcm2838.h | 29 
 include/hw/arm/bcm2838_peripherals.h | 36 ++
 5 files changed, 237 insertions(+)
 create mode 100644 hw/arm/bcm2838.c
 create mode 100644 hw/arm/bcm2838_peripherals.c
 create mode 100644 include/hw/arm/bcm2838.h
 create mode 100644 include/hw/arm/bcm2838_peripherals.h

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
new file mode 100644
index 00..05281e247f
--- /dev/null
+++ b/hw/arm/bcm2838.c
@@ -0,0 +1,98 @@
+/*
+ * BCM2838 SoC emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/arm/raspi_platform.h"
+#include "hw/sysbus.h"
+#include "hw/arm/bcm2838.h"
+#include "trace.h"
+
+#define VIRTUAL_PMU_IRQ 7
+
+static void bcm2838_init(Object *obj)
+{
+BCM2838State *s = BCM2838(obj);
+
+object_initialize_child(obj, "peripherals", >peripherals,
+TYPE_BCM2838_PERIPHERALS);
+object_property_add_alias(obj, "board-rev", OBJECT(>peripherals),
+  "board-rev");
+object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
+  "vcram-size");
+object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
+  "command-line");
+}
+
+static void bcm2838_realize(DeviceState *dev, Error **errp)
+{
+int n;
+BCM2838State *s = BCM2838(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc_base = BCM283X_BASE_GET_CLASS(dev);
+BCM2838PeripheralState *ps = BCM2838_PERIPHERALS(>peripherals);
+BCMSocPeripheralBaseState *ps_base =
+BCM_SOC_PERIPHERALS_BASE(>peripherals);
+
+if (!bcm283x_common_realize(dev, ps_base, errp)) {
+return;
+}
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(ps), 1, BCM2838_PERI_LOW_BASE, 1);
+
+/* bcm2836 interrupt controller (and mailboxes, etc.) */
+if (!sysbus_realize(SYS_BUS_DEVICE(_base->control), errp)) {
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc_base->ctrl_base);
+
+/* Create cores */
+for (n = 0; n < bc_base->core_count; n++) {
+
+object_property_set_int(OBJECT(_base->cpu[n].core), "mp-affinity",
+(bc_base->clusterid << 8) | n, _abort);
+
+/* start powered off if not enabled */
+object_property_set_bool(OBJECT(_base->cpu[n].core),
+ "start-powered-off",
+ n >= s_base->enabled_cpus, _abort);
+
+if (!qdev_realize(DEVICE(_base->cpu[n].core), NULL, errp)) {
+return;
+}
+}
+}
+
+static void bcm2838_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+BCM283XBaseClass *bc_base = BCM283X_BASE_CLASS(oc);
+
+bc_base->cpu_type = ARM_CPU_TYPE_NAME("cortex-a72");
+bc_base->core_count = BCM283X_NCPUS;
+bc_base->peri_base = 0xfe00;
+bc_base->ctrl_base = 0xff80;
+bc_base->clusterid = 0x0;
+dc->realize = bcm2838_realize;
+}
+
+static const TypeInfo bcm2838_type = {
+.name   = TYPE_BCM2838,
+.parent = TYPE_BCM283X_BASE,
+.instance_size  = sizeof(BCM2838State),
+.instance_init  = bcm2838_init,
+.class_size = sizeof(BCM283XBaseClass),
+.class_init = bcm2838_class_init,
+};
+
+static void bcm2838_register_types(void)
+{
+type_register_static(_type);
+}
+
+type_init(bcm2838_register_types);
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
new file mode 100644
index 00..06110c724f
--- /dev/null
+++ b/hw/arm/bcm2838_peripherals.c
@@ -0,0 +1,72 @@
+/*
+ * BCM2838 peripherals emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/arm/raspi_platform.h"
+#include "hw/arm/bcm2838_peripherals.h"
+
+/* Lower peripheral base address on the VC (GPU) system bus */
+#define BCM2838_VC_PERI_LOW_BASE 0x7c00
+
+static void bcm2838_peripherals_init(Object *obj)
+{
+BCM2838PeripheralState *s = BCM2838_PERIPHERALS(obj);
+BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_GET_CLASS(obj);
+
+/* Lower memory region for peripheral devices (exported to the Soc) */
+memory_region_init(>peri_low_mr, ob

[PATCH v5 03/41] Split out raspi machine common part

2024-02-18 Thread Sergey Kambalin
Pre-setup for raspberry pi 4 introduction

Signed-off-by: Sergey Kambalin 
---
 hw/arm/raspi.c  | 112 ++--
 include/hw/arm/raspi_platform.h |  21 ++
 2 files changed, 85 insertions(+), 48 deletions(-)

diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index af866ebce2..7d04734cd2 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -18,6 +18,7 @@
 #include "qapi/error.h"
 #include "hw/arm/boot.h"
 #include "hw/arm/bcm2836.h"
+#include "hw/arm/raspi_platform.h"
 #include "hw/registerfields.h"
 #include "qemu/error-report.h"
 #include "hw/boards.h"
@@ -25,6 +26,9 @@
 #include "hw/arm/boot.h"
 #include "qom/object.h"
 
+#define TYPE_RASPI_MACHINE  MACHINE_TYPE_NAME("raspi-common")
+OBJECT_DECLARE_SIMPLE_TYPE(RaspiMachineState, RASPI_MACHINE)
+
 #define SMPBOOT_ADDR0x300 /* this should leave enough space for ATAGS */
 #define MVBAR_ADDR  0x400 /* secure vectors */
 #define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
@@ -37,25 +41,10 @@
 
 struct RaspiMachineState {
 /*< private >*/
-MachineState parent_obj;
+RaspiBaseMachineState parent_obj;
 /*< public >*/
 BCM283XState soc;
-struct arm_boot_info binfo;
-};
-typedef struct RaspiMachineState RaspiMachineState;
-
-struct RaspiMachineClass {
-/*< private >*/
-MachineClass parent_obj;
-/*< public >*/
-uint32_t board_rev;
 };
-typedef struct RaspiMachineClass RaspiMachineClass;
-
-#define TYPE_RASPI_MACHINE   MACHINE_TYPE_NAME("raspi-common")
-DECLARE_OBJ_CHECKERS(RaspiMachineState, RaspiMachineClass,
- RASPI_MACHINE, TYPE_RASPI_MACHINE)
-
 
 /*
  * Board revision codes:
@@ -83,6 +72,11 @@ static const struct {
 [PROCESSOR_ID_BCM2837] = {TYPE_BCM2837, BCM283X_NCPUS},
 };
 
+static void raspi_base_machine_init(MachineState *machine,
+ BCM283XBaseState *soc);
+static void raspi_machine_class_common_init(MachineClass *mc,
+ uint32_t board_rev);
+
 static uint64_t board_ram_size(uint32_t board_rev)
 {
 assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
@@ -200,13 +194,12 @@ static void reset_secondary(ARMCPU *cpu, const struct 
arm_boot_info *info)
 cpu_set_pc(cs, info->smp_loader_start);
 }
 
-static void setup_boot(MachineState *machine, RaspiProcessorId processor_id,
-   size_t ram_size)
+static void setup_boot(MachineState *machine, ARMCPU *cpu,
+   RaspiProcessorId processor_id, size_t ram_size)
 {
-RaspiMachineState *s = RASPI_MACHINE(machine);
+RaspiBaseMachineState *s = RASPI_BASE_MACHINE(machine);
 int r;
 
-s->binfo.board_id = MACH_TYPE_BCM2708;
 s->binfo.ram_size = ram_size;
 
 if (processor_id <= PROCESSOR_ID_BCM2836) {
@@ -252,13 +245,13 @@ static void setup_boot(MachineState *machine, 
RaspiProcessorId processor_id,
 s->binfo.firmware_loaded = true;
 }
 
-arm_load_kernel(>soc.parent_obj.cpu[0].core, machine, >binfo);
+arm_load_kernel(cpu, machine, >binfo);
 }
 
-static void raspi_machine_init(MachineState *machine)
+static void raspi_base_machine_init(MachineState *machine,
+ BCM283XBaseState *soc)
 {
-RaspiMachineClass *mc = RASPI_MACHINE_GET_CLASS(machine);
-RaspiMachineState *s = RASPI_MACHINE(machine);
+RaspiBaseMachineClass *mc = RASPI_BASE_MACHINE_GET_CLASS(machine);
 uint32_t board_rev = mc->board_rev;
 uint64_t ram_size = board_ram_size(board_rev);
 uint32_t vcram_size;
@@ -279,19 +272,17 @@ static void raspi_machine_init(MachineState *machine)
 machine->ram, 0);
 
 /* Setup the SOC */
-object_initialize_child(OBJECT(machine), "soc", >soc,
-board_soc_type(board_rev));
-object_property_add_const_link(OBJECT(>soc), "ram", 
OBJECT(machine->ram));
-object_property_set_int(OBJECT(>soc), "board-rev", board_rev,
+object_property_add_const_link(OBJECT(soc), "ram", OBJECT(machine->ram));
+object_property_set_int(OBJECT(soc), "board-rev", board_rev,
 _abort);
-object_property_set_str(OBJECT(>soc), "command-line",
+object_property_set_str(OBJECT(soc), "command-line",
 machine->kernel_cmdline, _abort);
-qdev_realize(DEVICE(>soc), NULL, _fatal);
+qdev_realize(DEVICE(soc), NULL, _fatal);
 
 /* Create and plug in the SD cards */
 di = drive_get(IF_SD, 0, 0);
 blk = di ? blk_by_legacy_dinfo(di) : NULL;
-bus = qdev_get_child_bus(DEVICE(>soc), "sd-bus");
+bus = qdev_get_child_bus(DEVICE(soc), "sd-bus");
 if (bus == NULL) {
 error_report(&qu

[PATCH v5 02/41] Split out common part of peripherals

2024-02-18 Thread Sergey Kambalin
Pre-setup for BCM2838 introduction

Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2835_peripherals.c | 198 +++
 hw/arm/bcm2836.c |  24 ++--
 include/hw/arm/bcm2835_peripherals.h |  29 +++-
 include/hw/arm/bcm2836.h |   3 +-
 4 files changed, 154 insertions(+), 100 deletions(-)

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index d5573fd954..ed38a08a57 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -30,9 +30,9 @@
 #define SEPARATE_DMA_IRQ_MAX 10
 #define ORGATED_DMA_IRQ_COUNT 4
 
-static void create_unimp(BCM2835PeripheralState *ps,
- UnimplementedDeviceState *uds,
- const char *name, hwaddr ofs, hwaddr size)
+void create_unimp(BCMSocPeripheralBaseState *ps,
+  UnimplementedDeviceState *uds,
+  const char *name, hwaddr ofs, hwaddr size)
 {
 object_initialize_child(OBJECT(ps), name, uds, TYPE_UNIMPLEMENTED_DEVICE);
 qdev_prop_set_string(DEVICE(uds), "name", name);
@@ -45,9 +45,36 @@ static void create_unimp(BCM2835PeripheralState *ps,
 static void bcm2835_peripherals_init(Object *obj)
 {
 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
+BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(obj);
+
+/* Random Number Generator */
+object_initialize_child(obj, "rng", >rng, TYPE_BCM2835_RNG);
+
+/* Thermal */
+object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2835_THERMAL);
+
+/* GPIO */
+object_initialize_child(obj, "gpio", >gpio, TYPE_BCM2835_GPIO);
+
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhci",
+   OBJECT(_base->sdhci.sdbus));
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhost",
+   OBJECT(_base->sdhost.sdbus));
+
+/* Gated DMA interrupts */
+object_initialize_child(obj, "orgated-dma-irq",
+_base->orgated_dma_irq, TYPE_OR_IRQ);
+object_property_set_int(OBJECT(_base->orgated_dma_irq), "num-lines",
+ORGATED_DMA_IRQ_COUNT, _abort);
+}
+
+static void raspi_peripherals_base_init(Object *obj)
+{
+BCMSocPeripheralBaseState *s = BCM_SOC_PERIPHERALS_BASE(obj);
+BCMSocPeripheralBaseClass *bc = BCM_SOC_PERIPHERALS_BASE_GET_CLASS(obj);
 
 /* Memory region for peripheral devices, which we export to our parent */
-memory_region_init(>peri_mr, obj,"bcm2835-peripherals", 0x100);
+memory_region_init(>peri_mr, obj, "bcm2835-peripherals", bc->peri_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_mr);
 
 /* Internal memory region for peripheral bus addresses (not exported) */
@@ -98,9 +125,6 @@ static void bcm2835_peripherals_init(Object *obj)
 object_property_add_const_link(OBJECT(>property), "dma-mr",
OBJECT(>gpu_bus_mr));
 
-/* Random Number Generator */
-object_initialize_child(obj, "rng", >rng, TYPE_BCM2835_RNG);
-
 /* Extended Mass Media Controller */
 object_initialize_child(obj, "sdhci", >sdhci, TYPE_SYSBUS_SDHCI);
 
@@ -110,25 +134,9 @@ static void bcm2835_peripherals_init(Object *obj)
 /* DMA Channels */
 object_initialize_child(obj, "dma", >dma, TYPE_BCM2835_DMA);
 
-object_initialize_child(obj, "orgated-dma-irq",
->orgated_dma_irq, TYPE_OR_IRQ);
-object_property_set_int(OBJECT(>orgated_dma_irq), "num-lines",
-ORGATED_DMA_IRQ_COUNT, _abort);
-
 object_property_add_const_link(OBJECT(>dma), "dma-mr",
OBJECT(>gpu_bus_mr));
 
-/* Thermal */
-object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2835_THERMAL);
-
-/* GPIO */
-object_initialize_child(obj, "gpio", >gpio, TYPE_BCM2835_GPIO);
-
-object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhci",
-   OBJECT(>sdhci.sdbus));
-object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhost",
-   OBJECT(>sdhost.sdbus));
-
 /* Mphi */
 object_initialize_child(obj, "mphi", >mphi, TYPE_BCM2835_MPHI);
 
@@ -152,7 +160,72 @@ static void bcm2835_peripherals_init(Object *obj)
 
 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
 {
+MemoryRegion *mphi_mr;
 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev);
+BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+int n;
+
+bcm_soc_peripherals_common_realize(dev, errp);
+
+/* Extended Mass Media Controller */
+sysbus_connect_irq(SYS_BUS_DEVICE(_base

[PATCH v5 11/41] Temporarily disable unimplemented rpi4b devices

2024-02-18 Thread Sergey Kambalin
This commit adds RPi4B device tree modifications:
- disable pcie, rng200, thermal sensor and genet devices
  (they're going to be re-enabled in the following commits)
- create additional memory region in device tree
  if RAM amount exceeds VC base address.

Signed-off-by: Sergey Kambalin 
---
 hw/arm/raspi.c  |  5 +--
 hw/arm/raspi4b.c| 62 +
 include/hw/arm/raspi_platform.h |  4 +++
 3 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 8b1a046912..a7a662f40d 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -37,9 +37,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(RaspiMachineState, RASPI_MACHINE)
 #define FIRMWARE_ADDR_3 0x8 /* Pi 3 loads kernel.img here by default */
 #define SPINTABLE_ADDR  0xd8 /* Pi 3 bootloader spintable */
 
-/* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
-#define MACH_TYPE_BCM2708   3138
-
 struct RaspiMachineState {
 /*< private >*/
 RaspiBaseMachineState parent_obj;
@@ -75,7 +72,7 @@ static const struct {
 [PROCESSOR_ID_BCM2838] = {TYPE_BCM2838, BCM283X_NCPUS},
 };
 
-static uint64_t board_ram_size(uint32_t board_rev)
+uint64_t board_ram_size(uint32_t board_rev)
 {
 assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
 return 256 * MiB << FIELD_EX32(board_rev, REV_CODE, MEMORY_SIZE);
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 36a4593928..49dec6e53a 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -21,6 +21,7 @@
 #include "hw/arm/boot.h"
 #include "qom/object.h"
 #include "hw/arm/bcm2838.h"
+#include 
 
 #define TYPE_RASPI4B_MACHINE MACHINE_TYPE_NAME("raspi4b-2g")
 OBJECT_DECLARE_SIMPLE_TYPE(Raspi4bMachineState, RASPI4B_MACHINE)
@@ -30,6 +31,66 @@ struct Raspi4bMachineState {
 BCM2838State soc;
 };
 
+/*
+ * Add second memory region if board RAM amount exceeds VC base address
+ * (see https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf
+ * 1.2 Address Map)
+ */
+static int raspi_add_memory_node(void *fdt, hwaddr mem_base, hwaddr mem_len)
+{
+int ret;
+uint32_t acells, scells;
+char *nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
+
+acells = qemu_fdt_getprop_cell(fdt, "/", "#address-cells",
+   NULL, _fatal);
+scells = qemu_fdt_getprop_cell(fdt, "/", "#size-cells",
+   NULL, _fatal);
+if (acells == 0 || scells == 0) {
+fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 
0)\n");
+ret = -1;
+} else {
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
+ret = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
+   acells, mem_base,
+   scells, mem_len);
+}
+
+g_free(nodename);
+return ret;
+}
+
+static void raspi4_modify_dtb(const struct arm_boot_info *info, void *fdt)
+{
+uint64_t ram_size;
+
+/* Temporarily disable following devices until they are implemented */
+const char *nodes_to_remove[] = {
+"brcm,bcm2711-pcie",
+"brcm,bcm2711-rng200",
+"brcm,bcm2711-thermal",
+"brcm,bcm2711-genet-v5",
+};
+
+for (int i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
+const char *dev_str = nodes_to_remove[i];
+
+int offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
+if (offset >= 0) {
+if (!fdt_nop_node(fdt, offset)) {
+warn_report("bcm2711 dtc: %s has been disabled!", dev_str);
+}
+}
+}
+
+ram_size = board_ram_size(info->board_id);
+
+if (info->ram_size > UPPER_RAM_BASE) {
+raspi_add_memory_node(fdt, UPPER_RAM_BASE, ram_size - UPPER_RAM_BASE);
+}
+}
+
 static void raspi4b_machine_init(MachineState *machine)
 {
 Raspi4bMachineState *s = RASPI4B_MACHINE(machine);
@@ -37,6 +98,7 @@ static void raspi4b_machine_init(MachineState *machine)
 RaspiBaseMachineClass *mc = RASPI_BASE_MACHINE_GET_CLASS(machine);
 BCM2838State *soc = >soc;
 
+s_base->binfo.modify_dtb = raspi4_modify_dtb;
 s_base->binfo.board_id = mc->board_rev;
 
 object_initialize_child(OBJECT(machine), "soc", soc,
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
index 45003e2425..0db146e592 100644
--- a/include/hw/arm/raspi_platform.h
+++ b/include/hw/arm/raspi_platform.h
@@ -31,6 +31,9 @@
 #include "hw/boards.h"
 #include "hw/arm/boot.h"
 
+/* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
+#define MACH_TYPE_BCM2708   3138
+
 #define TYPE_RASPI_BASE_MACHINE 

[PATCH v5 00/41] Raspberry Pi 4B machine

2024-02-18 Thread Sergey Kambalin
Introducing Raspberry Pi 4B model.
It contains new BCM2838 SoC, PCIE subsystem,
RNG200, Thermal sensor and Genet network controller.

It can work with recent linux kernels 6.x.x.
Two avocado tests was added to check that.

Unit tests has been made as read/write operations
via mailbox properties.

Genet integration test is under development.

Every single commit
1) builds without errors
2) passes regression tests
3) passes style check*
*the only exception is bcm2838-mbox-property-test.c file
containing heavy macros usage which cause a lot of
false-positives of checkpatch.pl.

I did my best to keep the commits less than 200 changes,
but had to make some of them a bit more in order to
keep their integrity.

This is v5 patchset with the most of v1..v4 comments fixed.


Sergey Kambalin (41):
  Split out common part of BCM283X classes
  Split out common part of peripherals
  Split out raspi machine common part
  Introduce BCM2838 SoC
  Add GIC-400 to BCM2838 SoC
  Add BCM2838 GPIO stub
  Implement BCM2838 GPIO functionality
  Connect SD controller to BCM2838 GPIO
  Add GPIO and SD to BCM2838 periph
  Introduce Raspberry PI 4 machine
  Temporarily disable unimplemented rpi4b devices
  Add memory region for BCM2837 RPiVid ASB
  Add BCM2838 PCIE Root Complex
  Add BCM2838 PCIE host
  Enable BCM2838 PCIE
  Add RPi4 RNG200
  Implement BCM2838 thermal sensor
  Add clock_isp stub
  Add GENET stub
  Add GENET register structs. Part 1
  Add GENET register structs. Part 2
  Add GENET register structs. Part 3
  Add GENET register structs. Part 4
  Add GENET register access macros
  Implement GENET register ops
  Implement GENET MDIO
  Implement GENET TX path
  Implement GENET RX path
  Enable BCM2838 GENET controller
  Add Rpi4b boot tests
  Add mailbox test stub
  Add mailbox test constants
  Add mailbox tests tags. Part 1
  Add mailbox tests tags. Part 2
  Add mailbox tests tags. Part 3
  Add mailbox property tests. Part 1
  Add mailbox property tests. Part 2
  Add mailbox property tests. Part 3
  Add missed BCM2835 properties
  Append added properties to mailbox test
  Add RPi4B to paspi.rst

 docs/system/arm/raspi.rst|   11 +-
 hw/arm/bcm2835_peripherals.c |  215 +++--
 hw/arm/bcm2836.c |  117 ++-
 hw/arm/bcm2838.c |  282 ++
 hw/arm/bcm2838_pcie.c|  295 ++
 hw/arm/bcm2838_peripherals.c |  287 ++
 hw/arm/meson.build   |8 +-
 hw/arm/raspi.c   |  130 +--
 hw/arm/raspi4b.c |  111 +++
 hw/arm/trace-events  |7 +
 hw/gpio/bcm2838_gpio.c   |  390 
 hw/gpio/meson.build  |5 +-
 hw/misc/bcm2835_property.c   |   21 +
 hw/misc/bcm2838_rng200.c |  405 
 hw/misc/bcm2838_thermal.c|   98 ++
 hw/misc/meson.build  |2 +
 hw/misc/trace-events |9 +
 hw/net/bcm2838_genet.c   | 1088 ++
 hw/net/meson.build   |2 +
 hw/net/trace-events  |   16 +
 include/hw/arm/bcm2835_peripherals.h |   29 +-
 include/hw/arm/bcm2836.h |   27 +-
 include/hw/arm/bcm2838.h |   31 +
 include/hw/arm/bcm2838_pcie.h|   75 ++
 include/hw/arm/bcm2838_peripherals.h |   94 ++
 include/hw/arm/raspberrypi-fw-defs.h |   11 +
 include/hw/arm/raspi_platform.h  |   38 +-
 include/hw/display/bcm2835_fb.h  |2 +
 include/hw/gpio/bcm2838_gpio.h   |   45 +
 include/hw/misc/bcm2838_rng200.h |   43 +
 include/hw/misc/bcm2838_thermal.h|   24 +
 include/hw/net/bcm2838_genet.h   |  426 +
 tests/avocado/boot_linux_console.py  |   92 ++
 tests/qtest/bcm2838-mailbox.c|   60 ++
 tests/qtest/bcm2838-mailbox.h|  532 +++
 tests/qtest/bcm2838-mbox-property-test.c |  631 +
 tests/qtest/meson.build  |3 +-
 37 files changed, 5457 insertions(+), 205 deletions(-)
 create mode 100644 hw/arm/bcm2838.c
 create mode 100644 hw/arm/bcm2838_pcie.c
 create mode 100644 hw/arm/bcm2838_peripherals.c
 create mode 100644 hw/arm/raspi4b.c
 create mode 100644 hw/gpio/bcm2838_gpio.c
 create mode 100644 hw/misc/bcm2838_rng200.c
 create mode 100644 hw/misc/bcm2838_thermal.c
 create mode 100644 hw/net/bcm2838_genet.c
 create mode 100644 include/hw/arm/bcm2838.h
 create mode 100644 include/hw/arm/bcm2838_pcie.h
 create mode 100644 include/hw/arm/bcm2838_peripherals.h
 create mode 100644 include/hw/gpio/bcm2838_gpio.h
 create mode 100644 include/hw/misc/bcm2838_rng200.h
 create mode 100644 include/hw/misc/bcm2838_thermal.h
 create mode 100644 include/hw/net/bcm2838_genet.h
 create mode 100644 tests/qtest/bcm2838-mailbox.c
 create mode 100644 tests/qtest/bcm2838-mailbox.h
 create mode 100644 tests/qtest

[PATCH v5 12/41] Add memory region for BCM2837 RPiVid ASB

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 3 +++
 include/hw/arm/bcm2838_peripherals.h | 2 ++
 include/hw/arm/raspi_platform.h  | 2 +-
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 55ae56733f..ca2f37b260 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -185,6 +185,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 sysbus_mmio_get_region(SYS_BUS_DEVICE(>gpio), 0));
 
 object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(>gpio), "sd-bus");
+
+/* BCM2838 RPiVid ASB must be mapped to prevent kernel crash */
+create_unimp(s_base, >asb, "bcm2838-asb", BRDG_OFFSET, 0x24);
 }
 
 static void bcm2838_peripherals_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 86b0d96944..af085934c9 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -69,6 +69,8 @@ struct BCM2838PeripheralState {
 OrIRQState mmc_irq_orgate;
 OrIRQState dma_7_8_irq_orgate;
 OrIRQState dma_9_10_irq_orgate;
+
+UnimplementedDeviceState asb;
 };
 
 struct BCM2838PeripheralClass {
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
index 0db146e592..7bc4807fa5 100644
--- a/include/hw/arm/raspi_platform.h
+++ b/include/hw/arm/raspi_platform.h
@@ -73,7 +73,7 @@ uint64_t board_ram_size(uint32_t board_rev);
 #define MPHI_OFFSET 0x6000   /* Message-based Parallel Host Intf. 
*/
 #define DMA_OFFSET  0x7000   /* DMA controller, channels 0-14 */
 #define ARBA_OFFSET 0x9000
-#define BRDG_OFFSET 0xa000
+#define BRDG_OFFSET 0xa000   /* RPiVid ASB for BCM2838 (BCM2711) */
 #define ARM_OFFSET  0xB000   /* ARM control block */
 #define ARMCTRL_OFFSET  (ARM_OFFSET + 0x000)
 #define ARMCTRL_IC_OFFSET   (ARM_OFFSET + 0x200) /* Interrupt controller */
-- 
2.34.1




[PATCH v5 06/41] Add BCM2838 GPIO stub

2024-02-18 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/gpio/bcm2838_gpio.c | 153 +
 hw/gpio/meson.build|   5 +-
 include/hw/gpio/bcm2838_gpio.h |  40 +
 3 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 hw/gpio/bcm2838_gpio.c
 create mode 100644 include/hw/gpio/bcm2838_gpio.h

diff --git a/hw/gpio/bcm2838_gpio.c b/hw/gpio/bcm2838_gpio.c
new file mode 100644
index 00..a312490bbd
--- /dev/null
+++ b/hw/gpio/bcm2838_gpio.c
@@ -0,0 +1,153 @@
+/*
+ * Raspberry Pi (BCM2838) GPIO Controller
+ * This implementation is based on bcm2835_gpio (hw/gpio/bcm2835_gpio.c)
+ *
+ * Copyright (c) 2022 Auriga LLC
+ *
+ * Authors:
+ *  Lotosh, Aleksey 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "hw/gpio/bcm2838_gpio.h"
+
+#define GPFSEL0   0x00
+#define GPFSEL1   0x04
+#define GPFSEL2   0x08
+#define GPFSEL3   0x0C
+#define GPFSEL4   0x10
+#define GPFSEL5   0x14
+#define GPSET00x1C
+#define GPSET10x20
+#define GPCLR00x28
+#define GPCLR10x2C
+#define GPLEV00x34
+#define GPLEV10x38
+#define GPEDS00x40
+#define GPEDS10x44
+#define GPREN00x4C
+#define GPREN10x50
+#define GPFEN00x58
+#define GPFEN10x5C
+#define GPHEN00x64
+#define GPHEN10x68
+#define GPLEN00x70
+#define GPLEN10x74
+#define GPAREN0   0x7C
+#define GPAREN1   0x80
+#define GPAFEN0   0x88
+#define GPAFEN1   0x8C
+
+#define GPIO_PUP_PDN_CNTRL_REG0 0xE4
+#define GPIO_PUP_PDN_CNTRL_REG1 0xE8
+#define GPIO_PUP_PDN_CNTRL_REG2 0xEC
+#define GPIO_PUP_PDN_CNTRL_REG3 0xF0
+
+#define RESET_VAL_CNTRL_REG0 0xAAA9
+#define RESET_VAL_CNTRL_REG1 0xA0AA
+#define RESET_VAL_CNTRL_REG2 0x50AAA95A
+#define RESET_VAL_CNTRL_REG3 0x0005
+
+#define BYTES_IN_WORD4
+
+static uint64_t bcm2838_gpio_read(void *opaque, hwaddr offset, unsigned size)
+{
+uint64_t value = 0;
+
+qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+
+return value;
+}
+
+static void bcm2838_gpio_write(void *opaque, hwaddr offset, uint64_t value,
+   unsigned size)
+{
+qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+}
+
+static void bcm2838_gpio_reset(DeviceState *dev)
+{
+BCM2838GpioState *s = BCM2838_GPIO(dev);
+
+s->lev0 = 0;
+s->lev1 = 0;
+
+memset(s->fsel, 0, sizeof(s->fsel));
+
+s->pup_cntrl_reg[0] = RESET_VAL_CNTRL_REG0;
+s->pup_cntrl_reg[1] = RESET_VAL_CNTRL_REG1;
+s->pup_cntrl_reg[2] = RESET_VAL_CNTRL_REG2;
+s->pup_cntrl_reg[3] = RESET_VAL_CNTRL_REG3;
+}
+
+static const MemoryRegionOps bcm2838_gpio_ops = {
+.read = bcm2838_gpio_read,
+.write = bcm2838_gpio_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_bcm2838_gpio = {
+.name = "bcm2838_gpio",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT8_ARRAY(fsel, BCM2838GpioState, BCM2838_GPIO_NUM),
+VMSTATE_UINT32(lev0, BCM2838GpioState),
+VMSTATE_UINT32(lev1, BCM2838GpioState),
+VMSTATE_UINT8(sd_fsel, BCM2838GpioState),
+VMSTATE_UINT32_ARRAY(pup_cntrl_reg, BCM2838GpioState,
+ GPIO_PUP_PDN_CNTRL_NUM),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void bcm2838_gpio_init(Object *obj)
+{
+BCM2838GpioState *s = BCM2838_GPIO(obj);
+DeviceState *dev = DEVICE(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem, obj, _gpio_ops, s,
+  "bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
+sysbus_init_mmio(sbd, >iomem);
+qdev_init_gpio_out(dev, s->out, BCM2838_GPIO_NUM);
+}
+
+static void bcm2838_gpio_realize(DeviceState *dev, Error **errp)
+{
+/* Temporary stub. Do nothing */
+}
+
+static void bcm2838_gpio_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->vmsd = _bcm2838_gpio;
+dc->realize = _gpio_realize;
+dc->reset = _gpio_reset;
+}
+
+static const TypeInfo bcm2838_gpio_info = {
+.name  = TYPE_BCM2838_GPIO,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(BCM2838GpioState),
+.instance_init = bcm2838_gpio_init,
+.class_init= bcm2838_gpio_class_init,
+};
+
+static void bcm2838_gpio_register_types(void)
+{
+type_register_static(_gpio_info);
+}
+
+type_init(bcm2838_gpio_register_types)
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
index

[PATCH v4 27/45] Add GENET register access macros

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 include/hw/net/bcm2838_genet.h | 76 ++
 1 file changed, 76 insertions(+)

diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 94c2f3ebca..e7a76cda81 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -22,9 +22,85 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_DMA_RING_CNT  17
 #define BCM2838_GENET_DMA_RING_DEFAULT  (BCM2838_GENET_DMA_RING_CNT - 1)
 
+#define BCM2838_GENET_HFB_FILTER_REGS offsetof(BCM2838GenetRegs, hfb)
+#define BCM2838_GENET_HFB_FILTER_REG(reg) (BCM2838_GENET_HFB_FILTER_REGS \
+   + offsetof(BCM2838GenetRegsHfb, 
reg))
 #define BCM2838_GENET_HFB_FILTER_CNT  48
 #define BCM2838_GENET_HFB_FILTER_SIZE 128
 
+#define BCM2838_GENET_INTRL0_REG(reg)   (offsetof(BCM2838GenetRegs, intrl0) \
++ offsetof(BCM2838GenetRegsIntrl0, 
reg))
+#define BCM2838_GENET_INTRL0_SETBCM2838_GENET_INTRL0_REG(set)
+#define BCM2838_GENET_INTRL0_CLEAR  BCM2838_GENET_INTRL0_REG(clear)
+#define BCM2838_GENET_INTRL0_MASK_SET   BCM2838_GENET_INTRL0_REG(mask_set)
+#define BCM2838_GENET_INTRL0_MASK_CLEAR BCM2838_GENET_INTRL0_REG(mask_clear)
+
+#define BCM2838_GENET_INTRL1_REG(reg)   (offsetof(BCM2838GenetRegs, intrl1) \
++ offsetof(BCM2838GenetRegsIntrl1, 
reg))
+#define BCM2838_GENET_INTRL1_SETBCM2838_GENET_INTRL1_REG(set)
+#define BCM2838_GENET_INTRL1_CLEAR  BCM2838_GENET_INTRL1_REG(clear)
+#define BCM2838_GENET_INTRL1_MASK_SET   BCM2838_GENET_INTRL1_REG(mask_set)
+#define BCM2838_GENET_INTRL1_MASK_CLEAR BCM2838_GENET_INTRL1_REG(mask_clear)
+
+#define BCM2838_GENET_UMAC_REG(reg) (offsetof(BCM2838GenetRegs, umac) \
+ + offsetof(BCM2838GenetRegsUmac, reg))
+#define BCM2838_GENET_UMAC_CMD  BCM2838_GENET_UMAC_REG(cmd)
+#define BCM2838_GENET_UMAC_MAC0 BCM2838_GENET_UMAC_REG(mac0)
+#define BCM2838_GENET_UMAC_MAC1 BCM2838_GENET_UMAC_REG(mac1)
+#define BCM2838_GENET_UMAC_MDIO_CMD BCM2838_GENET_UMAC_REG(mdio_cmd)
+
+#define BCM2838_GENET_TDMA_REGS offsetof(BCM2838GenetRegs, tdma)
+#define BCM2838_GENET_TDMA_REG(reg) (BCM2838_GENET_TDMA_REGS \
+ + offsetof(BCM2838GenetRegsTdma, reg))
+#define BCM2838_GENET_TDMA_RINGSBCM2838_GENET_TDMA_REG(rings)
+#define BCM2838_GENET_TDMA_RING_CFG BCM2838_GENET_TDMA_REG(ring_cfg)
+#define BCM2838_GENET_TDMA_CTRL BCM2838_GENET_TDMA_REG(ctrl)
+
+#define BCM2838_GENET_RDMA_REGS offsetof(BCM2838GenetRegs, rdma)
+#define BCM2838_GENET_RDMA_REG(reg) (BCM2838_GENET_RDMA_REGS \
+ + offsetof(BCM2838GenetRegsRdma, reg))
+#define BCM2838_GENET_RDMA_RINGSBCM2838_GENET_RDMA_REG(rings)
+#define BCM2838_GENET_RDMA_RING_CFG BCM2838_GENET_RDMA_REG(ring_cfg)
+#define BCM2838_GENET_RDMA_CTRL BCM2838_GENET_RDMA_REG(ctrl)
+
+#define BCM2838_GENET_TRING_REG(reg)offsetof(BCM2838GenetTdmaRing, reg)
+#define BCM2838_GENET_TRING_WRITE_PTR BCM2838_GENET_TRING_REG(write_ptr)
+#define BCM2838_GENET_TRING_WRITE_PTR_HI BCM2838_GENET_TRING_REG(write_ptr_hi)
+#define BCM2838_GENET_TRING_PROD_INDEX BCM2838_GENET_TRING_REG(prod_index)
+#define BCM2838_GENET_TRING_CONS_INDEX BCM2838_GENET_TRING_REG(cons_index)
+#define BCM2838_GENET_TRING_RING_BUF_SIZE 
BCM2838_GENET_TRING_REG(ring_buf_size)
+#define BCM2838_GENET_TRING_RING_START_ADDR BCM2838_GENET_TRING_REG(start_addr)
+#define BCM2838_GENET_TRING_RING_START_ADDR_HI 
BCM2838_GENET_TRING_REG(start_addr_hi)
+#define BCM2838_GENET_TRING_RING_END_ADDR BCM2838_GENET_TRING_REG(end_addr)
+#define BCM2838_GENET_TRING_RING_END_ADDR_HI 
BCM2838_GENET_TRING_REG(end_addr_hi)
+#define BCM2838_GENET_TRING_RING_MBUF_DONE_TRESH 
BCM2838_GENET_TRING_REG(mbuf_done_tresh)
+#define BCM2838_GENET_TRING_RING_FLOW_PERIOD 
BCM2838_GENET_TRING_REG(flow_period)
+#define BCM2838_GENET_TRING_RING_READ_PTR BCM2838_GENET_TRING_REG(read_ptr)
+#define BCM2838_GENET_TRING_RING_READ_PTR_HI 
BCM2838_GENET_TRING_REG(read_ptr_hi)
+
+#define BCM2838_GENET_RRING_REG(reg)offsetof(BCM2838GenetRdmaRing, reg)
+#define BCM2838_GENET_RRING_WRITE_PTR BCM2838_GENET_RRING_REG(write_ptr)
+#define BCM2838_GENET_RRING_WRITE_PTR_HI BCM2838_GENET_RRING_REG(write_ptr_hi)
+#define BCM2838_GENET_RRING_PROD_INDEX BCM2838_GENET_RRING_REG(prod_index)
+#define BCM2838_GENET_RRING_CONS_INDEX BCM2838_GENET_RRING_REG(cons_index)
+#define BCM2838_GENET_RRING_RING_BUF_SIZE 
BCM2838_GENET_RRING_REG(ring_buf_size)
+#define BCM2838_GENET_RRING_RING_START_ADDR BCM2838_GENET_RRING_REG(start_addr)
+#define BCM2838_GENET_RRING_RING_START_ADDR_HI 
BCM2838_GENET_RRING_REG(start_addr_hi)
+#define BCM2838_GENET_RRING_RING_END_ADDR BCM2838_GENET_RRING_REG(end_addr)
+#define BCM2838_GENET_RRING_RING_END_ADDR_HI

[PATCH v4 32/45] Enable BCM2838 GENET controller

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 16 
 hw/arm/raspi4b.c | 17 -
 include/hw/arm/bcm2838_peripherals.h |  2 ++
 3 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 65a659c15c..d962999daf 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -47,6 +47,15 @@ static void bcm2838_peripherals_init(Object *obj)
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
 
+/* Gigabit Ethernet */
+object_initialize_child(obj, "genet", >genet, TYPE_BCM2838_GENET);
+for (int i = 0; i < nb_nics; i++) {
+if ((nd_table[i].used && nd_table[i].model) && 
!strcmp(nd_table[i].model, "bcmgenet")) {
+qdev_set_nic_properties(DEVICE(>genet), _table[i]);
+break;
+}
+}
+
 /* Extended Mass Media Controller 2 */
 object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
 
@@ -231,6 +240,13 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
 >pcie_mmio_alias);
 
+/* Gigabit Ethernet */
+if (!sysbus_realize(SYS_BUS_DEVICE(>genet), errp)) {
+return;
+}
+regs_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>genet), 0);
+memory_region_add_subregion(>peri_low_mr, GENET_OFFSET, regs_mr);
+
 create_unimp(s_base, >clkisp, "bcm2835-clkisp", CLOCK_ISP_OFFSET,
  CLOCK_ISP_SIZE);
 
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index fda27d36cb..8aa8dfb087 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -64,23 +64,6 @@ static int raspi_add_memory_node(void *fdt, hwaddr mem_base, 
hwaddr mem_len)
 
 static void raspi4_modify_dtb(const struct arm_boot_info *info, void *fdt)
 {
-
-/* Temporarily disable following devices until they are implemented*/
-const char *to_be_removed_from_dt_as_wa[] = {
-"brcm,bcm2711-genet-v5",
-};
-
-for (int i = 0; i < ARRAY_SIZE(to_be_removed_from_dt_as_wa); i++) {
-const char *dev_str = to_be_removed_from_dt_as_wa[i];
-
-int offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
-if (offset >= 0) {
-if (!fdt_nop_node(fdt, offset)) {
-warn_report("bcm2711 dtc: %s has been disabled!", dev_str);
-}
-}
-}
-
 uint64_t ram_size = board_ram_size(info->board_id);
 
 if (info->ram_size > UPPER_RAM_BASE) {
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 20b7d1eb67..1cfcf5dcce 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -13,6 +13,7 @@
 #include "hw/misc/bcm2838_rng200.h"
 #include "hw/misc/bcm2838_thermal.h"
 #include "hw/arm/bcm2838_pcie.h"
+#include "hw/net/bcm2838_genet.h"
 #include "hw/sd/sdhci.h"
 #include "hw/gpio/bcm2838_gpio.h"
 
@@ -73,6 +74,7 @@ struct BCM2838PeripheralState {
 UnimplementedDeviceState clkisp;
 BCM2838PcieHostState pcie_host;
 BCM2838GpioState gpio;
+BCM2838GenetState genet;
 
 OrIRQState mmc_irq_orgate;
 OrIRQState dma_7_8_irq_orgate;
-- 
2.34.1




[PATCH v4 45/45] Add RPi4B to paspi4.rst

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 docs/system/arm/raspi.rst | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/docs/system/arm/raspi.rst b/docs/system/arm/raspi.rst
index 922fe375a6..db9e0949ef 100644
--- a/docs/system/arm/raspi.rst
+++ b/docs/system/arm/raspi.rst
@@ -1,5 +1,5 @@
-Raspberry Pi boards (``raspi0``, ``raspi1ap``, ``raspi2b``, ``raspi3ap``, 
``raspi3b``)
-==
+Raspberry Pi boards (``raspi0``, ``raspi1ap``, ``raspi2b``, ``raspi3ap``, 
``raspi3b``, ``raspi4b-2g``)
+==
 
 
 QEMU provides models of the following Raspberry Pi boards:
@@ -12,12 +12,13 @@ QEMU provides models of the following Raspberry Pi boards:
   Cortex-A53 (4 cores), 512 MiB of RAM
 ``raspi3b``
   Cortex-A53 (4 cores), 1 GiB of RAM
-
+``raspi4b-2g``
+  Cortex-A72 (4 cores), 2 GiB of RAM
 
 Implemented devices
 ---
 
- * ARM1176JZF-S, Cortex-A7 or Cortex-A53 CPU
+ * ARM1176JZF-S, Cortex-A7, Cortex-A53 or Cortex-A72 CPU
  * Interrupt controller
  * DMA controller
  * Clock and reset controller (CPRMAN)
@@ -33,6 +34,8 @@ Implemented devices
  * USB2 host controller (DWC2 and MPHI)
  * MailBox controller (MBOX)
  * VideoCore firmware (property)
+ * PCIE Root Port (raspi4b-2g)
+ * GENET Ethernet Controller (raspi4b-2g)
 
 
 Missing devices
-- 
2.34.1




[PATCH v4 25/45] Add GENET register structs. Part 3

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 88 ++
 include/hw/net/bcm2838_genet.h | 88 ++
 2 files changed, 176 insertions(+)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 9a99f34c4a..be899b68f8 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -145,6 +145,94 @@ FIELD(GENET_RDMA_LENGTH_STATUS, OWN,15, 1)
 FIELD(GENET_RDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
 FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
 
+REG32(GENET_TDMA_LENGTH_STATUS, 0)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_0_3,   0, 4)
+FIELD(GENET_TDMA_LENGTH_STATUS, DO_CSUM,4, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, OW_CRC, 5, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, APPEND_CRC, 6, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_7_8,   7, 2)
+FIELD(GENET_TDMA_LENGTH_STATUS, UNDERRUN,   9, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_10_11, 10, 2)
+FIELD(GENET_TDMA_LENGTH_STATUS, WRAP,   12, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, SOP,13, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, EOP,14, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, OWN,15, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
+
+REG16(GENET_PHY_BMCR,0)
+FIELD(GENET_PHY_BMCR, RSVD_0_5,  0, 6)
+FIELD(GENET_PHY_BMCR, SPEED1000, 6, 1)
+FIELD(GENET_PHY_BMCR, CTST,  7, 1)
+FIELD(GENET_PHY_BMCR, FULLDPLX,  8, 1)
+FIELD(GENET_PHY_BMCR, ANRESTART, 9, 1)
+FIELD(GENET_PHY_BMCR, ISOLATE,   10, 1)
+FIELD(GENET_PHY_BMCR, PDOWN, 11, 1)
+FIELD(GENET_PHY_BMCR, AENABLE,   12, 1)
+FIELD(GENET_PHY_BMCR, SPEED100,  13, 1)
+FIELD(GENET_PHY_BMCR, LOOPBACK,  14, 1)
+FIELD(GENET_PHY_BMCR, RESET, 15, 1)
+
+REG16(GENET_PHY_BMSR,   0)
+FIELD(GENET_PHY_BMSR, ERCAP,0, 1)
+FIELD(GENET_PHY_BMSR, JCD,  1, 1)
+FIELD(GENET_PHY_BMSR, LSTATUS,  2, 1)
+FIELD(GENET_PHY_BMSR, ANEGCAPABLE,  3, 1)
+FIELD(GENET_PHY_BMSR, RFAULT,   4, 1)
+FIELD(GENET_PHY_BMSR, ANEGCOMPLETE, 5, 1)
+FIELD(GENET_PHY_BMSR, RSVD_6_7, 6, 2)
+FIELD(GENET_PHY_BMSR, ESTATEN,  8, 1)
+FIELD(GENET_PHY_BMSR, _100HALF2,9, 1)
+FIELD(GENET_PHY_BMSR, _100FULL2,10, 1)
+FIELD(GENET_PHY_BMSR, _10HALF,  11, 1)
+FIELD(GENET_PHY_BMSR, _10FULL,  12, 1)
+FIELD(GENET_PHY_BMSR, _100HALF, 13, 1)
+FIELD(GENET_PHY_BMSR, _100FULL, 14, 1)
+FIELD(GENET_PHY_BMSR, _10BASE4, 15, 1)
+
+REG16(GENET_PHY_LPA,   0)
+FIELD(GENET_PHY_LPA, SLCT, 0, 5)
+FIELD(GENET_PHY_LPA, _10HALF_1000XFULL,5, 1)
+FIELD(GENET_PHY_LPA, _10FULL_1000XHALF,6, 1)
+FIELD(GENET_PHY_LPA, _100HALF_1000XPAUSE,  7, 1)
+FIELD(GENET_PHY_LPA, _100FULL_1000XPAUSE_ASYM, 8, 1)
+FIELD(GENET_PHY_LPA, _100BASE4,9, 1)
+FIELD(GENET_PHY_LPA, PAUSE_CAP,10, 1)
+FIELD(GENET_PHY_LPA, PAUSE_ASYM,   11, 1)
+FIELD(GENET_PHY_LPA, RSVD_12,  12, 1)
+FIELD(GENET_PHY_LPA, RFAULT,   13, 1)
+FIELD(GENET_PHY_LPA, LPACK,14, 1)
+FIELD(GENET_PHY_LPA, NPAGE,15, 1)
+
+REG16(GENET_PHY_STAT_1000,0)
+FIELD(GENET_PHY_STAT_1000, RSVD_0_9,  0, 10)
+FIELD(GENET_PHY_STAT_1000, HALF,  10, 1)
+FIELD(GENET_PHY_STAT_1000, FULL,  11, 1)
+FIELD(GENET_PHY_STAT_1000, REMRXOK,   12, 1)
+FIELD(GENET_PHY_STAT_1000, LOCALRXOK, 13, 1)
+FIELD(GENET_PHY_STAT_1000, MSRES, 14, 1)
+FIELD(GENET_PHY_STAT_1000, MSFAIL,15, 1)
+
+REG16(GENET_PHY_AUX_CTRL_0,  0)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_ID_MASK, 0, 3)
+FIELD(GENET_PHY_AUX_CTRL_0, RSVD_3,  3, 1)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_DATA,4, 8)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_ID,  12, 3)
+FIELD(GENET_PHY_AUX_CTRL_0, MISC_WREN,   15, 1)
+
+REG16(GENET_PHY_AUX_CTRL_1,   0)
+FIELD(GENET_PHY_AUX_CTRL_1, RSVD_0_3, 0, 4)
+FIELD(GENET_PHY_AUX_CTRL_1, REG_DATA, 4, 12)
+
+REG16(GENET_PHY_SHADOW,   0)
+FIELD(GENET_PHY_SHADOW, REG_DATA, 0, 10)
+FIELD(GENET_PHY_SHADOW, REG_ID,   10, 5)
+FIELD(GENET_PHY_SHADOW, WR,   15, 1)
+
+REG16(GENET_PHY_EXP_SEL,   0)
+FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
+FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
+
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
 uint64_t value = ~0;
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 736b4d1757..1bd004785a 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -22,6 +22,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_DMA_RING_CNT  17
 #define BCM2838_GENET_DMA_RING_DEFAULT  (BCM2838_GENET_DMA_RING_CNT - 1)
 
+#define BCM2838_GENET_HFB_FILTER_CNT  48
+#define BCM2838_GENET_HFB_FILTER_SIZE 128
+
 typedef struct {
 uint32_t rev_ctrl;
 uint32_t port_ctrl;
@@ -169,6 +172,53 @@ typedef struct {
 uint32_t reserved_0x10D0[972];
 } BCM2838GenetRegsRdma

[PATCH v4 16/45] Enable BCM2838 PCIE

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_pcie.c|  3 +++
 hw/arm/bcm2838_peripherals.c | 26 ++
 hw/arm/meson.build   |  7 ---
 hw/arm/raspi4b.c |  1 -
 include/hw/arm/bcm2838_peripherals.h |  3 +++
 5 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c
index 75146d6c2e..8e046d0ac7 100644
--- a/hw/arm/bcm2838_pcie.c
+++ b/hw/arm/bcm2838_pcie.c
@@ -239,6 +239,9 @@ static void bcm2838_pcie_root_reg_reset(PCIDevice *dev)
 }
 
 static void bcm2838_pcie_root_realize(PCIDevice *dev, Error **errp) {
+BCM2838PcieRootClass *brpc = BCM2838_PCIE_ROOT_GET_CLASS(dev);
+
+brpc->parent_realize(dev, errp);
 bcm2838_pcie_root_reg_reset(dev);
 }
 
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index d3b42cf25b..ee06214715 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -12,6 +12,11 @@
 #include "hw/arm/raspi_platform.h"
 #include "hw/arm/bcm2838_peripherals.h"
 
+#define PCIE_RC_OFFSET  0x150
+#define PCIE_MMIO_OFFSET0xc000
+#define PCIE_MMIO_ARM_OFFSET0x6
+#define PCIE_MMIO_SIZE  0x4000
+
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
@@ -29,6 +34,10 @@ static void bcm2838_peripherals_init(Object *obj)
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* PCIe Host Bridge */
+object_initialize_child(obj, "pcie-host", >pcie_host,
+TYPE_BCM2838_PCIE_HOST);
+
 /* Extended Mass Media Controller 2 */
 object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
 
@@ -61,6 +70,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 MemoryRegion *mphi_mr;
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(dev);
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+MemoryRegion *regs_mr;
+MemoryRegion *mmio_mr;
+
 int n;
 
 bcm_soc_peripherals_common_realize(dev, errp);
@@ -172,6 +184,20 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
  BCM2838_MPHI_SIZE);
 memory_region_add_subregion(_base->peri_mr, BCM2838_MPHI_OFFSET,
 >mphi_mr_alias);
+/* PCIe Root Complex */
+if (!sysbus_realize(SYS_BUS_DEVICE(>pcie_host), errp)) {
+return;
+}
+/* RC registers region */
+regs_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>pcie_host), 0);
+memory_region_add_subregion(>peri_low_mr, PCIE_RC_OFFSET, regs_mr);
+/* MMIO region */
+mmio_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>pcie_host), 1);
+memory_region_init_alias(>pcie_mmio_alias, OBJECT(>pcie_host),
+ "pcie-mmio", mmio_mr, PCIE_MMIO_OFFSET,
+ PCIE_MMIO_SIZE);
+memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
+>pcie_mmio_alias);
 
 /* GPIO */
 if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index b26ed13c6f..69d199b73e 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -41,7 +41,6 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: 
files('allwinner-r40.c', 'bana
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
 arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: files(
   'bcm2838.c',
-  'bcm2838_pcie.c',
   'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
@@ -72,8 +71,10 @@ arm_ss.add(when: 'CONFIG_XEN', if_true: files('xen_arm.c'))
 
 system_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
 system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
-system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c'))
-system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2838_peripherals.c'))
+system_ss.add(when: 'CONFIG_RASPI', if_true: files(
+'bcm2835_peripherals.c',
+'bcm2838_peripherals.c',
+'bcm2838_pcie.c'))
 system_ss.add(when: 'CONFIG_TOSA', if_true: files('tosa.c'))
 
 hw_arch += {'arm': arm_ss}
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 10376b62dc..2e8474e1c5 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -67,7 +67,6 @@ static void raspi4_modify_dtb(const struct arm_boot_info 
*info, void *fdt)
 
 /* Temporarily disable following devices until they are implemented*/
 const char *to_be_removed_from_dt_as_wa[] = {
-"brcm,bcm2711-pcie",
 "brcm,bcm2711-rng200",
 "brcm,bcm2711-thermal",

[PATCH v4 04/45] Introduce BCM2838 SoC

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c | 100 +++
 hw/arm/bcm2838_peripherals.c |  72 +++
 hw/arm/meson.build   |   2 +
 include/hw/arm/bcm2838.h |  29 
 include/hw/arm/bcm2838_peripherals.h |  36 ++
 5 files changed, 239 insertions(+)
 create mode 100644 hw/arm/bcm2838.c
 create mode 100644 hw/arm/bcm2838_peripherals.c
 create mode 100644 include/hw/arm/bcm2838.h
 create mode 100644 include/hw/arm/bcm2838_peripherals.h

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
new file mode 100644
index 00..c61c59661b
--- /dev/null
+++ b/hw/arm/bcm2838.c
@@ -0,0 +1,100 @@
+/*
+ * BCM2838 SoC emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/arm/raspi_platform.h"
+#include "hw/sysbus.h"
+#include "hw/arm/bcm2838.h"
+#include "trace.h"
+
+#define VIRTUAL_PMU_IRQ 7
+
+static void bcm2838_init(Object *obj)
+{
+BCM2838State *s = BCM2838(obj);
+
+object_initialize_child(obj, "peripherals", >peripherals,
+TYPE_BCM2838_PERIPHERALS);
+object_property_add_alias(obj, "board-rev", OBJECT(>peripherals),
+  "board-rev");
+object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
+  "vcram-size");
+object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
+  "command-line");
+}
+
+static void bcm2838_realize(DeviceState *dev, Error **errp)
+{
+int n;
+BCM2838State *s = BCM2838(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc_base = BCM283X_BASE_GET_CLASS(dev);
+BCM2838PeripheralState *ps = BCM2838_PERIPHERALS(>peripherals);
+BCMSocPeripheralBaseState *ps_base =
+BCM_SOC_PERIPHERALS_BASE(>peripherals);
+
+if (!bcm283x_common_realize(dev, ps_base, errp)) {
+return;
+}
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(ps), 1, BCM2838_PERI_LOW_BASE, 1);
+
+/* bcm2836 interrupt controller (and mailboxes, etc.) */
+if (!sysbus_realize(SYS_BUS_DEVICE(_base->control), errp)) {
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc_base->ctrl_base);
+
+/* Create cores */
+for (n = 0; n < bc_base->core_count; n++) {
+/* TODO: this should be converted to a property of ARM_CPU */
+s_base->cpu[n].core.mp_affinity = (bc_base->clusterid << 8) | n;
+
+/* start powered off if not enabled */
+if (!object_property_set_bool(OBJECT(_base->cpu[n].core),
+  "start-powered-off",
+  n >= s_base->enabled_cpus,
+  errp)) {
+return;
+}
+
+if (!qdev_realize(DEVICE(_base->cpu[n].core), NULL, errp)) {
+return;
+}
+}
+}
+
+static void bcm2838_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+BCM283XBaseClass *bc_base = BCM283X_BASE_CLASS(oc);
+
+bc_base->cpu_type = ARM_CPU_TYPE_NAME("cortex-a72");
+bc_base->core_count = BCM283X_NCPUS;
+bc_base->peri_base = 0xfe00;
+bc_base->ctrl_base = 0xff80;
+bc_base->clusterid = 0x0;
+dc->realize = bcm2838_realize;
+}
+
+static const TypeInfo bcm2838_type = {
+.name   = TYPE_BCM2838,
+.parent = TYPE_BCM283X_BASE,
+.instance_size  = sizeof(BCM2838State),
+.instance_init  = bcm2838_init,
+.class_size = sizeof(BCM283XBaseClass),
+.class_init = bcm2838_class_init,
+};
+
+static void bcm2838_register_types(void)
+{
+type_register_static(_type);
+}
+
+type_init(bcm2838_register_types);
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
new file mode 100644
index 00..06110c724f
--- /dev/null
+++ b/hw/arm/bcm2838_peripherals.c
@@ -0,0 +1,72 @@
+/*
+ * BCM2838 peripherals emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/arm/raspi_platform.h"
+#include "hw/arm/bcm2838_peripherals.h"
+
+/* Lower peripheral base address on the VC (GPU) system bus */
+#define BCM2838_VC_PERI_LOW_BASE 0x7c00
+
+static void bcm2838_peripherals_init(Object *obj)
+{
+BCM2838PeripheralState *s = BCM2838_PERIPHERALS(obj);
+BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_GET_CLASS(obj);
+
+/* Lower memory region for per

[PATCH v4 39/45] Add mailbox tests tags. Part 3

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 78 +++
 1 file changed, 78 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 49668668da..2b140a5d32 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -514,6 +514,84 @@ DECLARE_TAG_TYPE(TAG_GET_DMA_CHANNELS_t,
 uint32_t mask;
 });
 
+DECLARE_TAG_TYPE(TAG_GET_THROTTLED_t,
+struct {},
+struct {
+uint32_t throttled;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_NUM_DISPLAYS_t,
+struct {},
+struct {
+uint32_t num_displays;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_DISPLAY_SETTINGS_t,
+struct {},
+struct {
+uint32_t display_num;
+uint32_t phys_width;
+uint32_t phys_height;
+uint32_t bpp;
+uint16_t pitch;
+uint32_t virt_width;
+uint32_t virt_height;
+uint16_t virt_width_offset;
+uint32_t virt_height_offset;
+uint32_t fb_bus_address_lo;
+uint32_t fb_bus_address_hi;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_GPIO_CONFIG_t,
+struct {
+uint32_t gpio_num;
+},
+struct {
+uint32_t zero;
+uint32_t direction;
+uint32_t polarity;
+uint32_t term_en;
+uint32_t term_pull_up;
+});
+
+
+DECLARE_TAG_TYPE(TAG_SET_GPIO_CONFIG_t,
+struct {
+uint32_t gpio_num;
+uint32_t direction;
+uint32_t polarity;
+uint32_t term_en;
+uint32_t term_pull_up;
+uint32_t state;
+},
+struct {
+uint32_t zero;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_GPIO_STATE_t,
+struct {
+uint32_t gpio_num;
+},
+struct {
+uint32_t zero;
+uint32_t state;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_GPIO_STATE_t,
+struct {
+uint32_t gpio_num;
+uint32_t state;
+},
+struct {
+uint32_t zero;
+});
+
+DECLARE_TAG_TYPE(TAG_INITIALIZE_VCHIQ_t,
+struct {},
+struct {
+uint32_t zero;
+});
+
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
 void mbox1_write_message(uint8_t channel, uint32_t msg_addr);
-- 
2.34.1




[PATCH v4 43/45] Add missed BCM2835 properties

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2835_property.c   | 47 
 include/hw/arm/raspberrypi-fw-defs.h | 12 ++-
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index ff55a4e2cd..dfeb793b3e 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -19,6 +19,9 @@
 #include "trace.h"
 #include "hw/arm/raspi_platform.h"
 
+#define RPI_EXP_GPIO_BASE   128
+#define VCHI_BUSADDR_SIZE   sizeof(uint32_t)
+
 /* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
 
 static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
@@ -138,6 +141,13 @@ static void 
bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 resplen = 8;
 break;
 
+case RPI_FWREQ_GET_CLOCKS:
+/* TODO: add more clock IDs if needed */
+stl_le_phys(>dma_as, value + 12, 0);
+stl_le_phys(>dma_as, value + 16, RPI_FIRMWARE_ARM_CLK_ID);
+resplen = 8;
+break;
+
 case RPI_FWREQ_SET_CLOCK_RATE:
 case RPI_FWREQ_SET_MAX_CLOCK_RATE:
 case RPI_FWREQ_SET_MIN_CLOCK_RATE:
@@ -276,6 +286,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState 
*s, uint32_t value)
 stl_le_phys(>dma_as, value + 12, 0);
 resplen = 4;
 break;
+
 case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
 stl_le_phys(>dma_as, value + 12, 1);
 resplen = 4;
@@ -301,6 +312,42 @@ static void 
bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 resplen);
 break;
 
+case RPI_FWREQ_GET_THROTTLED:
+stl_le_phys(>dma_as, value + 12, 0);
+resplen = 4;
+break;
+
+case RPI_FWREQ_FRAMEBUFFER_SET_PITCH:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_FRAMEBUFFER_SET_PITCH "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_GET_GPIO_CONFIG:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_GET_GPIO_CONFIG "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_SET_GPIO_CONFIG:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_SET_GPIO_CONFIG "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_GET_GPIO_STATE:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_GET_GPIO_STATE "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_SET_GPIO_STATE:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_SET_GPIO_STATE "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_VCHIQ_INIT:
+stl_le_phys(>dma_as,
+value + offsetof(rpi_firmware_prop_request_t, payload),
+0);
+resplen = VCHI_BUSADDR_SIZE;
+break;
 default:
 qemu_log_mask(LOG_UNIMP,
   "bcm2835_property: unhandled tag 0x%08x\n", tag);
diff --git a/include/hw/arm/raspberrypi-fw-defs.h 
b/include/hw/arm/raspberrypi-fw-defs.h
index 4551fe7450..ded7a22f02 100644
--- a/include/hw/arm/raspberrypi-fw-defs.h
+++ b/include/hw/arm/raspberrypi-fw-defs.h
@@ -101,7 +101,6 @@ enum rpi_firmware_property_tag {
 RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
 RPI_FWREQ_FRAMEBUFFER_SET_DISPLAY_NUM =0x00048013,
 RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS =   0x00040013,
-RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_SETTINGS =   0x00040014,
 RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
 RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT =  0x00044004,
 RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
@@ -160,4 +159,15 @@ enum rpi_firmware_clk_id {
 RPI_FIRMWARE_NUM_CLK_ID,
 };
 
+struct rpi_firmware_property_tag_header {
+uint32_t tag;
+uint32_t buf_size;
+uint32_t req_resp_size;
+};
+
+typedef struct rpi_firmware_prop_request {
+struct rpi_firmware_property_tag_header hdr;
+uint8_t payload[0];
+} rpi_firmware_prop_request_t;
+
 #endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */
-- 
2.34.1




[PATCH v4 44/45] Append added properties to mailbox test

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 22 --
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index 1b4a2ed9cb..3a2e7f9194 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -269,6 +269,12 @@ DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, ANY) {
 tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
 }
 
+/**/
+DECLARE_TEST_CASE(GET_CLOCKS) {
+g_assert_cmphex(tag->response.value.root_clock, ==, CLOCK_ID_ROOT);
+g_assert_cmphex(tag->response.value.arm_clock, ==, CLOCK_ID_ARM);
+}
+
 
/**/
 DECLARE_TEST_CASE(GET_TEMPERATURE) {
 g_assert_cmphex(tag->response.value.temperature_id, ==, 
TEMPERATURE_ID_SOC);
@@ -535,17 +541,19 @@ DECLARE_TEST_CASE(GET_COMMANDLINE) {
 /* No special checks are needed for this test case */
 }
 
+/**/
+DECLARE_TEST_CASE(GET_THROTTLED) {
+g_assert_cmpint(tag->response.value.throttled, ==, 0);
+}
+
 
/**/
 DECLARE_TEST_CASE(GET_NUM_DISPLAYS) {
 g_assert_cmpint(tag->response.value.num_displays, ==, 1);
 }
 
 
/**/
-DECLARE_TEST_CASE(SET_PITCH) {
-/* No special checks are needed for this test case */
-}
-DECLARE_TEST_CASE_SETUP(SET_PITCH) {
-tag->request.value.pitch = DUMMY_VALUE;
+DECLARE_TEST_CASE(INITIALIZE_VCHIQ) {
+g_assert_cmpint(tag->response.value.zero, ==, 0);
 }
 
 
/**/
@@ -571,6 +579,7 @@ int main(int argc, char **argv)
 QTEST_ADD_TEST_CASE(GET_CLOCK_RATE, ANY);
 QTEST_ADD_TEST_CASE(GET_MAX_CLOCK_RATE, ANY);
 QTEST_ADD_TEST_CASE(GET_MIN_CLOCK_RATE, ANY);
+QTEST_ADD_TEST_CASE(GET_CLOCKS);
 QTEST_ADD_TEST_CASE(GET_TEMPERATURE);
 QTEST_ADD_TEST_CASE(GET_MAX_TEMPERATURE);
 QTEST_ADD_TEST_CASE(ALLOCATE_BUFFER);
@@ -604,8 +613,9 @@ int main(int argc, char **argv)
 QTEST_ADD_TEST_CASE(SET_OVERSCAN);
 QTEST_ADD_TEST_CASE(GET_DMA_CHANNELS);
 QTEST_ADD_TEST_CASE(GET_COMMANDLINE);
+QTEST_ADD_TEST_CASE(GET_THROTTLED);
 QTEST_ADD_TEST_CASE(GET_NUM_DISPLAYS);
-QTEST_ADD_TEST_CASE(SET_PITCH);
+QTEST_ADD_TEST_CASE(INITIALIZE_VCHIQ);
 
 return g_test_run();
 }
-- 
2.34.1




[PATCH v4 34/45] Add Rpi4b boot tests

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/avocado/boot_linux_console.py | 92 +
 1 file changed, 92 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index 6eab515718..b5c090ae64 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -501,6 +501,98 @@ def test_arm_raspi2_initrd(self):
 # Wait for VM to shut down gracefully
 self.vm.wait()
 
+def test_arm_raspi4(self):
+"""
+:avocado: tags=arch:aarch64
+:avocado: tags=machine:raspi4b-2g
+:avocado: tags=device:pl011
+:avocado: tags=accel:tcg
+:avocado: tags=rpi4b
+
+The kernel can be rebuilt using the kernel source referenced
+and following the instructions on the on:
+https://www.raspberrypi.org/documentation/linux/kernel/building.md
+"""
+
+deb_url = ('http://archive.raspberrypi.org/debian/'
+'pool/main/r/raspberrypi-firmware/'
+'raspberrypi-kernel_1.20230106-1_arm64.deb')
+deb_hash = '08dc55696535b18a6d4fe6fa10d4c0d905cbb2ed'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
+dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'earlycon=pl011,mmio32,0xfe201000 ' +
+   'console=ttyAMA0,115200 ' +
+   'root=/dev/mmcblk1p2 rootwait ' +
+   'dwc_otg.fiq_fsm_enable=0')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line,
+ '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
+ '-device', 'usb-kbd,bus=xhci.0')
+self.vm.launch()
+console_pattern = 'Kernel command line: %s' % kernel_command_line
+self.wait_for_console_pattern(console_pattern)
+console_pattern = 'Product: QEMU USB Keyboard'
+self.wait_for_console_pattern(console_pattern)
+
+
+def test_arm_raspi4_initrd(self):
+"""
+:avocado: tags=arch:aarch64
+:avocado: tags=machine:raspi4b-2g
+:avocado: tags=device:pl011
+:avocado: tags=accel:tcg
+:avocado: tags=rpi4b
+
+The kernel can be rebuilt using the kernel source referenced
+and following the instructions on the on:
+https://www.raspberrypi.org/documentation/linux/kernel/building.md
+"""
+deb_url = ('http://archive.raspberrypi.org/debian/'
+'pool/main/r/raspberrypi-firmware/'
+'raspberrypi-kernel_1.20230106-1_arm64.deb')
+deb_hash = '08dc55696535b18a6d4fe6fa10d4c0d905cbb2ed'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
+dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
+
+initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
+  '86b2be1384d41c8c388e63078a847f1e1c4cb1de/rootfs/'
+  'arm64/rootfs.cpio.gz')
+initrd_hash = 'f3d4f9fa92a49aa542f1b44d34be77bbf8ca5b9d'
+initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
+archive.gzip_uncompress(initrd_path_gz, initrd_path)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'earlycon=pl011,mmio32,0xfe201000 ' +
+   'console=ttyAMA0,115200 ' +
+   'panic=-1 noreboot ' +
+   'dwc_otg.fiq_fsm_enable=0')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
+ '-device', 'usb-kbd,bus=xhci.0',
+ '-no-reboot')
+self.vm.launch()
+self.wait_for_console_pattern('Boot successful.')
+
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+'BCM2835')
+exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+'cprman@7e101000')
+exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System 
halted')
+# TODO: Raspberry Pi4 doesn't shut down properly with recent kernels
+# Wait for VM to shut down gracefully
+  

[PATCH v4 30/45] Implement GENET TX path

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 221 -
 include/hw/net/bcm2838_genet.h |  17 +++
 2 files changed, 237 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 1fae3ecbc2..4c9b39a3ca 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -234,6 +234,13 @@ REG16(GENET_PHY_EXP_SEL,   0)
 FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
 FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
 
+REG32(GENET_TX_CSUM_INFO,0)
+FIELD(GENET_TX_CSUM_INFO, OFFSET,0, 15)
+FIELD(GENET_TX_CSUM_INFO, PROTO_UDP, 15, 1)
+FIELD(GENET_TX_CSUM_INFO, START, 16, 15)
+FIELD(GENET_TX_CSUM_INFO, LV,30, 1)
+
+
 static void bcm2838_genet_set_qemu_mac(BCM2838GenetState *s)
 {
 const MACAddr *addr = >nic_conf.macaddr;
@@ -387,6 +394,218 @@ static uint64_t bcm2838_genet_mdio_cmd(BCM2838GenetState 
*s, uint64_t cmd)
 return cmd;
 }
 
+static void bcm2838_genet_xmit_packet(NetClientState *s, void *packet,
+  size_t size)
+{
+uint8_t *buf = packet + sizeof(BCM2838GenetXmitStatus);
+size_t len = size;
+uint16_t len_type = 0;
+
+len -= sizeof(BCM2838GenetXmitStatus);
+net_checksum_calculate(buf, len, CSUM_ALL);
+
+memcpy(_type, [12], sizeof(len_type));
+len_type = ntohs(len_type);
+if (len_type < MAX_PAYLOAD_SIZE) {
+len_type = len;
+len_type = htons(len_type);
+memcpy([12], _type, sizeof(len_type));
+}
+
+qemu_send_packet(s, buf, len);
+}
+
+static uint64_t bcm2838_genet_tx(BCM2838GenetState *s, unsigned int ring_index,
+ uint32_t prod_index,
+ uint32_t cons_index)
+{
+const unsigned int DESC_SIZE_WORDS
+= sizeof(BCM2838GenetTdmaDesc) / sizeof(uint32_t);
+const uint64_t RING_START_ADDR
+= ((uint64_t)s->regs.tdma.rings[ring_index].start_addr_hi << 32)
++ s->regs.tdma.rings[ring_index].start_addr;
+const uint64_t RING_END_ADDR
+= ((uint64_t)s->regs.tdma.rings[ring_index].end_addr_hi << 32)
++ s->regs.tdma.rings[ring_index].end_addr;
+
+hwaddr data_addr;
+uint64_t desc_index;
+uint32_t desc_status = 0;
+uint32_t buflength = 0;
+uint64_t num_descs = 0;
+uint64_t read_ptr
+= ((uint64_t)s->regs.tdma.rings[ring_index].read_ptr_hi << 32)
++ s->regs.tdma.rings[ring_index].read_ptr;
+off_t packet_off = 0;
+
+uint32_t prod_index_fld = FIELD_EX32(prod_index,
+ GENET_DMA_PROD_INDEX, INDEX);
+uint32_t cons_index_fld = FIELD_EX32(cons_index,
+GENET_DMA_CONS_INDEX, INDEX);
+
+while (cons_index_fld != prod_index_fld) {
+desc_index = read_ptr / DESC_SIZE_WORDS;
+if (desc_index >= BCM2838_GENET_DMA_DESC_CNT) {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: invalid TX descriptor index %" PRIu64 " (exceeds %u)\n",
+__func__, desc_index, BCM2838_GENET_DMA_DESC_CNT - 1);
+break;
+}
+desc_status = s->regs.tdma.descs[desc_index].length_status;
+data_addr = ((uint64_t)s->regs.tdma.descs[desc_index].address_hi << 32)
++ s->regs.tdma.descs[desc_index].address_lo;
+trace_bcm2838_genet_tx(ring_index, desc_index, desc_status,
+   data_addr);
+
+if (FIELD_EX32(desc_status, GENET_RDMA_LENGTH_STATUS, SOP) != 0) {
+packet_off = 0;
+}
+
+buflength = FIELD_EX32(desc_status,
+   GENET_RDMA_LENGTH_STATUS, BUFLENGTH);
+
+/* TODO: Add address_space_read() return value check */
+address_space_read(>dma_as, data_addr,
+MEMTXATTRS_UNSPECIFIED,
+s->tx_packet + packet_off,
+buflength);
+packet_off += buflength;
+
+if (FIELD_EX32(desc_status, GENET_RDMA_LENGTH_STATUS, EOP) != 0) {
+bcm2838_genet_xmit_packet(qemu_get_queue(s->nic), s->tx_packet,
+ packet_off);
+packet_off = 0;
+}
+
+num_descs++;
+cons_index_fld++;
+s->regs.tdma.descs[desc_index].length_status =
+FIELD_DP32(s->regs.tdma.descs[desc_index].length_status,
+   GENET_RDMA_LENGTH_STATUS, OWN, 1);
+read_ptr = read_ptr == RING_END_ADDR + 1 - DESC_SIZE_WORDS
+? RING_START_ADDR : read_ptr + DESC_SIZE_WORDS;
+}
+
+s->regs.tdma.rings[ring_index].read_ptr = read_ptr;
+s->regs.tdma.rings[ring_index].read_ptr_hi = read_ptr >> 32;
+
+return num_descs;
+}
+
+static bool bcm2838_ge

[PATCH v4 17/45] Add RNG200 skeleton

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2838_rng200.c | 152 +++
 hw/misc/meson.build  |   1 +
 hw/misc/trace-events |   9 ++
 include/hw/misc/bcm2838_rng200.h |  51 +++
 4 files changed, 213 insertions(+)
 create mode 100644 hw/misc/bcm2838_rng200.c
 create mode 100644 include/hw/misc/bcm2838_rng200.h

diff --git a/hw/misc/bcm2838_rng200.c b/hw/misc/bcm2838_rng200.c
new file mode 100644
index 00..8f64e6a20f
--- /dev/null
+++ b/hw/misc/bcm2838_rng200.c
@@ -0,0 +1,152 @@
+/*
+ * BCM2838 Random Number Generator emulation
+ *
+ * Copyright (C) 2022 Sergey Pushkarev 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "hw/misc/bcm2838_rng200.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static const VMStateDescription vmstate_bcm2838_rng200_regs = {
+.name = "bcm2838_rng200_regs",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(ctrl, BCM2838_rng_regs_t),
+VMSTATE_UINT32(int_status, BCM2838_rng_regs_t),
+VMSTATE_UINT32(fifo_count, BCM2838_rng_regs_t),
+VMSTATE_UINT32(fifo_count_threshold, BCM2838_rng_regs_t),
+VMSTATE_UINT32(total_bit_count_threshold, BCM2838_rng_regs_t),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static const VMStateDescription vmstate_bcm2838_rng200 = {
+.name = "bcm2838_rng200",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(rbg_period, BCM2838Rng200State),
+VMSTATE_UINT32(rng_fifo_cap, BCM2838Rng200State),
+VMSTATE_BOOL(use_timer, BCM2838Rng200State),
+
+VMSTATE_STRUCT(regs, BCM2838Rng200State, 0, 
vmstate_bcm2838_rng200_regs,
+   BCM2838_rng_regs_t),
+
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void bcm2838_rng200_rng_reset(BCM2838Rng200State *state)
+{
+state->regs.ctrl = 0;
+
+trace_bcm2838_rng200_rng_soft_reset();
+}
+
+static uint64_t bcm2838_rng200_read(void *opaque, hwaddr offset,
+unsigned size)
+{
+uint32_t res = 0;
+
+/* will be implemented in upcoming commits */
+return res;
+}
+
+static void bcm2838_rng200_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+/* will be implemented in upcoming commits */
+}
+
+static const MemoryRegionOps bcm2838_rng200_ops = {
+.read = bcm2838_rng200_read,
+.write = bcm2838_rng200_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void bcm2838_rng200_realize(DeviceState *dev, Error **errp)
+{
+BCM2838Rng200State *s = BCM2838_RNG200(dev);
+
+if (s->rng == NULL) {
+Object *default_backend = object_new(TYPE_RNG_BUILTIN);
+
+object_property_add_child(OBJECT(dev), "default-backend",
+  default_backend);
+object_unref(default_backend);
+
+object_property_set_link(OBJECT(dev), "rng", default_backend,
+ errp);
+}
+
+sysbus_init_irq(SYS_BUS_DEVICE(dev), >irq);
+}
+
+static void bcm2838_rng200_init(Object *obj)
+{
+BCM2838Rng200State *s = BCM2838_RNG200(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+s->rbg_period = 250;
+s->use_timer = true;
+
+s->rng_fifo_cap = 128;
+
+s->clock = qdev_init_clock_in(DEVICE(s), "rbg-clock",
+  NULL, s,
+  ClockPreUpdate);
+if (s->clock == NULL) {
+error_setg(_fatal, "Failed to init RBG clock");
+return;
+}
+
+memory_region_init_io(>iomem, obj, _rng200_ops, s,
+  TYPE_BCM2838_RNG200, 0x28);
+sysbus_init_mmio(sbd, >iomem);
+}
+
+static void bcm2838_rng200_reset(DeviceState *dev)
+{
+BCM2838Rng200State *s = BCM2838_RNG200(dev);
+bcm2838_rng200_rng_reset(s);
+}
+
+static Property bcm2838_rng200_properties[] = {
+DEFINE_PROP_LINK("rng", BCM2838Rng200State, rng,
+ TYPE_RNG_BACKEND, RngBackend *),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void bcm2838_rng200_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = bcm2838_rng200_realize;
+dc->reset = bcm2838_rng200_reset;
+dc->vmsd = _bcm2838_rng200;
+
+device_class_set_props(dc, bcm2838_rng200_properties);
+}
+
+static const TypeInfo bcm2838_rng200_info = {
+.name  = TYPE_BCM2838_RNG200,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(BCM2838Rng200State),
+.class_init= bcm2838_rng200_

[PATCH v4 20/45] Implement BCM2838 thermal sensor

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 27 ++--
 hw/arm/raspi4b.c |  1 -
 hw/misc/bcm2838_thermal.c| 98 
 hw/misc/meson.build  |  3 +-
 include/hw/arm/bcm2838_peripherals.h |  2 +
 include/hw/misc/bcm2838_thermal.h| 24 +++
 6 files changed, 147 insertions(+), 8 deletions(-)
 create mode 100644 hw/misc/bcm2838_thermal.c
 create mode 100644 include/hw/misc/bcm2838_thermal.h

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 7c489c8e8a..e9c6d47ba6 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -37,6 +37,9 @@ static void bcm2838_peripherals_init(Object *obj)
 /* Random Number Generator */
 object_initialize_child(obj, "rng200", >rng200, TYPE_BCM2838_RNG200);
 
+/* Thermal */
+object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2838_THERMAL);
+
 /* PCIe Host Bridge */
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
@@ -75,6 +78,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
 MemoryRegion *regs_mr;
 MemoryRegion *mmio_mr;
+MemoryRegion *rng200_mr;
+MemoryRegion *thermal_mr;
+qemu_irq rng_200_irq;
 
 int n;
 
@@ -92,12 +98,20 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 if (!sysbus_realize(SYS_BUS_DEVICE(>rng200), errp)) {
 return;
 }
-memory_region_add_subregion(
-_base->peri_mr, RNG_OFFSET,
-sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng200), 0));
-sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0,
-qdev_get_gpio_in_named(DEVICE(_base->ic), BCM2835_IC_GPU_IRQ,
-   INTERRUPT_RNG));
+rng200_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng200), 0);
+memory_region_add_subregion(_base->peri_mr, RNG_OFFSET, rng200_mr);
+
+rng_200_irq = qdev_get_gpio_in_named(DEVICE(_base->ic),
+ BCM2835_IC_GPU_IRQ, INTERRUPT_RNG);
+sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0, rng_200_irq);
+
+
+/* THERMAL */
+if (!sysbus_realize(SYS_BUS_DEVICE(>thermal), errp)) {
+return;
+}
+thermal_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>thermal), 0);
+memory_region_add_subregion( >peri_low_mr, 0x15D2000, thermal_mr);
 
 /* Extended Mass Media Controller 2 */
 object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
@@ -198,6 +212,7 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
  BCM2838_MPHI_SIZE);
 memory_region_add_subregion(_base->peri_mr, BCM2838_MPHI_OFFSET,
 >mphi_mr_alias);
+
 /* PCIe Root Complex */
 if (!sysbus_realize(SYS_BUS_DEVICE(>pcie_host), errp)) {
 return;
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 7b5385b8dd..fda27d36cb 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -67,7 +67,6 @@ static void raspi4_modify_dtb(const struct arm_boot_info 
*info, void *fdt)
 
 /* Temporarily disable following devices until they are implemented*/
 const char *to_be_removed_from_dt_as_wa[] = {
-"brcm,bcm2711-thermal",
 "brcm,bcm2711-genet-v5",
 };
 
diff --git a/hw/misc/bcm2838_thermal.c b/hw/misc/bcm2838_thermal.c
new file mode 100644
index 00..2301f657d0
--- /dev/null
+++ b/hw/misc/bcm2838_thermal.c
@@ -0,0 +1,98 @@
+/*
+ * BCM2838 dummy thermal sensor
+ *
+ * Copyright (C) 2022 Maksim Kopusov 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/misc/bcm2838_thermal.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+REG32(STAT, 0x200)
+FIELD(STAT, DATA, 0, 10)
+FIELD(STAT, VALID_1, 10, 1)
+FIELD(STAT, VALID_2, 16, 1)
+
+#define BCM2838_THERMAL_SIZE 0xf00
+
+#define THERMAL_OFFSET_C 410040
+#define THERMAL_COEFF  (-487.0f)
+#define MILLIDEGREE_COEFF 1000
+
+static uint16_t bcm2838_thermal_temp2adc(int temp_C)
+{
+return (temp_C * MILLIDEGREE_COEFF - THERMAL_OFFSET_C) / THERMAL_COEFF;
+}
+
+static uint64_t bcm2838_thermal_read(void *opaque, hwaddr addr, unsigned size)
+{
+uint32_t val = 0;
+
+switch (addr) {
+case A_STAT:
+/* Temperature is always 25°C */
+val = FIELD_DP32(val, STAT, DATA, bcm2838_thermal_temp2adc(25));
+val = FIELD_DP32(val, STAT, VALID_1, 1);
+val = FIELD_DP32(val, STAT, VALID_2, 1);
+
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "%s can't access addr: 0x%"

[PATCH v4 18/45] Add RNG200 RNG and RBG

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2838_rng200.c | 292 +--
 include/hw/misc/bcm2838_rng200.h |  10 +-
 2 files changed, 275 insertions(+), 27 deletions(-)

diff --git a/hw/misc/bcm2838_rng200.c b/hw/misc/bcm2838_rng200.c
index 8f64e6a20f..f91ea0754c 100644
--- a/hw/misc/bcm2838_rng200.c
+++ b/hw/misc/bcm2838_rng200.c
@@ -8,25 +8,56 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "qapi/error.h"
 #include "hw/qdev-properties.h"
 #include "hw/misc/bcm2838_rng200.h"
+#include "hw/registerfields.h"
 #include "migration/vmstate.h"
 #include "trace.h"
 
-static const VMStateDescription vmstate_bcm2838_rng200_regs = {
-.name = "bcm2838_rng200_regs",
-.version_id = 1,
-.minimum_version_id = 1,
-.fields = (VMStateField[]) {
-VMSTATE_UINT32(ctrl, BCM2838_rng_regs_t),
-VMSTATE_UINT32(int_status, BCM2838_rng_regs_t),
-VMSTATE_UINT32(fifo_count, BCM2838_rng_regs_t),
-VMSTATE_UINT32(fifo_count_threshold, BCM2838_rng_regs_t),
-VMSTATE_UINT32(total_bit_count_threshold, BCM2838_rng_regs_t),
-VMSTATE_END_OF_LIST()
-}
-};
+/* RNG200 registers */
+REG32(RNG_CTRL,   0x00)
+FIELD(RNG_CTRL, RBG_ENABLE,   0 , 1)
+FIELD(RNG_CTRL, RSVD, 1 , 12)
+FIELD(RNG_CTRL, DIV, 13 , 8)
+
+REG32(RNG_SOFT_RESET,0x04)
+REG32(RBG_SOFT_RESET,0x08)
+REG32(RNG_TOTAL_BIT_COUNT,   0x0C)
+REG32(RNG_TOTAL_BIT_COUNT_THRESHOLD, 0x10)
+
+REG32(RNG_INT_STATUS,   0x18)
+FIELD(RNG_INT_STATUS, TOTAL_BITS_COUNT_IRQ, 0, 1)
+FIELD(RNG_INT_STATUS, RSVD0,1, 4)
+FIELD(RNG_INT_STATUS, NIST_FAIL_IRQ,5, 1)
+FIELD(RNG_INT_STATUS, RSVD1,6, 11)
+FIELD(RNG_INT_STATUS, STARTUP_TRANSITIONS_MET_IRQ,  17, 1)
+FIELD(RNG_INT_STATUS, RSVD2,18, 13)
+FIELD(RNG_INT_STATUS, MASTER_FAIL_LOCKOUT_IRQ,  30, 1)
+
+REG32(RNG_INT_ENABLE,   0x1C)
+FIELD(RNG_INT_ENABLE, TOTAL_BITS_COUNT_IRQ, 0, 1)
+FIELD(RNG_INT_ENABLE, RSVD0,1, 4)
+FIELD(RNG_INT_ENABLE, NIST_FAIL_IRQ,5, 1)
+FIELD(RNG_INT_ENABLE, RSVD1,6, 11)
+FIELD(RNG_INT_ENABLE, STARTUP_TRANSITIONS_MET_IRQ,  17, 1)
+FIELD(RNG_INT_ENABLE, RSVD2,18, 13)
+FIELD(RNG_INT_ENABLE, MASTER_FAIL_LOCKOUT_IRQ,  30, 1)
+
+REG32(RNG_FIFO_DATA, 0x20)
+
+REG32(RNG_FIFO_COUNT,  0x24)
+FIELD(RNG_FIFO_COUNT, COUNT,   0, 8)
+FIELD(RNG_FIFO_COUNT, THRESHOLD,   8, 8)
+
+
+#define RNG_WARM_UP_PERIOD_ELAPSED   17
+
+#define SOFT_RESET1
+#define IRQ_PENDING   1
+
+#define BCM2838_RNG200_PTIMER_POLICY (PTIMER_POLICY_CONTINUOUS_TRIGGER)
 
 static const VMStateDescription vmstate_bcm2838_rng200 = {
 .name = "bcm2838_rng200",
@@ -37,33 +68,253 @@ static const VMStateDescription vmstate_bcm2838_rng200 = {
 VMSTATE_UINT32(rng_fifo_cap, BCM2838Rng200State),
 VMSTATE_BOOL(use_timer, BCM2838Rng200State),
 
-VMSTATE_STRUCT(regs, BCM2838Rng200State, 0, 
vmstate_bcm2838_rng200_regs,
-   BCM2838_rng_regs_t),
+VMSTATE_ARRAY(regs, BCM2838Rng200State, N_BCM2838_RNG200_REGS, 0,
+  vmstate_info_uint32, uint32_t),
 
 VMSTATE_END_OF_LIST()
 }
 };
 
-static void bcm2838_rng200_rng_reset(BCM2838Rng200State *state)
+static bool is_rbg_enabled(BCM2838Rng200State *s)
+{
+return FIELD_EX32(s->regs[R_RNG_CTRL], RNG_CTRL, RBG_ENABLE);
+}
+
+static void increment_bit_counter_by(BCM2838Rng200State *s, uint32_t inc_val) {
+s->regs[R_RNG_TOTAL_BIT_COUNT] += inc_val;
+}
+
+static void bcm2838_rng200_update_irq(BCM2838Rng200State *s)
+{ 
+qemu_set_irq(s->irq,
+!!(s->regs[R_RNG_INT_ENABLE] & s->regs[R_RNG_INT_STATUS]));
+}
+
+static void bcm2838_rng200_update_fifo(void *opaque, const void *buf,
+   size_t size)
 {
-state->regs.ctrl = 0;
+BCM2838Rng200State *s = (BCM2838Rng200State *)opaque;
+Fifo8 *fifo = >fifo;
+size_t num = MIN(size, fifo8_num_free(fifo));
+uint32_t num_bits = num * 8;
+uint32_t bit_threshold_left = 0;
+uint32_t bit_count = 0;
+uint32_t bit_count_thld = 0;
+uint32_t fifo_thld = 0;
+
+increment_bit_counter_by(s, num_bits);
+
+bit_count = s->regs[R_RNG_TOTAL_BIT_COUNT];
+bit_count_thld = s->regs[R_RNG_TOTAL_BIT_COUNT_THRESHOLD];
+
+bit_threshold_left = (bit_count < bit_count_thld)
+   ? bit_count_thld - bit_count
+   : 0;
+
+if (bit_threshold_left < num_bits) {
+num_bits -= bit_threshold_left;
+} else {
+ 

[PATCH v4 01/45] Split out common part of BCM283X classes

2023-12-07 Thread Sergey Kambalin
Pre setup for BCM2838 introduction

Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2836.c | 102 ++-
 hw/arm/raspi.c   |   2 +-
 include/hw/arm/bcm2836.h |  26 +-
 3 files changed, 83 insertions(+), 47 deletions(-)

diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 166dc896c0..66a2b57b38 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -29,12 +29,12 @@ struct BCM283XClass {
 };
 
 static Property bcm2836_enabled_cores_property =
-DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
+DEFINE_PROP_UINT32("enabled-cpus", BCM283XBaseState, enabled_cpus, 0);
 
-static void bcm2836_init(Object *obj)
+static void bcm283x_base_init(Object *obj)
 {
-BCM283XState *s = BCM283X(obj);
-BCM283XClass *bc = BCM283X_GET_CLASS(obj);
+BCM283XBaseState *s = BCM283X_BASE(obj);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(obj);
 int n;
 
 for (n = 0; n < bc->core_count; n++) {
@@ -50,6 +50,11 @@ static void bcm2836_init(Object *obj)
 object_initialize_child(obj, "control", >control,
 TYPE_BCM2836_CONTROL);
 }
+}
+
+static void bcm283x_init(Object *obj)
+{
+BCM283XState *s = BCM283X(obj);
 
 object_initialize_child(obj, "peripherals", >peripherals,
 TYPE_BCM2835_PERIPHERALS);
@@ -61,10 +66,11 @@ static void bcm2836_init(Object *obj)
   "vcram-size");
 }
 
-static bool bcm283x_common_realize(DeviceState *dev, Error **errp)
+bool bcm283x_common_realize(DeviceState *dev, Error **errp)
 {
 BCM283XState *s = BCM283X(dev);
-BCM283XClass *bc = BCM283X_GET_CLASS(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
 Object *obj;
 
 /* common peripherals from bcm2835 */
@@ -77,96 +83,98 @@ static bool bcm283x_common_realize(DeviceState *dev, Error 
**errp)
 return false;
 }
 
-object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(>peripherals),
-  "sd-bus");
+object_property_add_alias(OBJECT(s_base), "sd-bus",
+  OBJECT(>peripherals), "sd-bus");
 
-sysbus_mmio_map_overlap(SYS_BUS_DEVICE(>peripherals), 0,
-bc->peri_base, 1);
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(>peripherals),
+0, bc->peri_base, 1);
 return true;
 }
 
 static void bcm2835_realize(DeviceState *dev, Error **errp)
 {
 BCM283XState *s = BCM283X(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
 
 if (!bcm283x_common_realize(dev, errp)) {
 return;
 }
 
-if (!qdev_realize(DEVICE(>cpu[0].core), NULL, errp)) {
+if (!qdev_realize(DEVICE(_base->cpu[0].core), NULL, errp)) {
 return;
 }
 
 /* Connect irq/fiq outputs from the interrupt controller. */
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
-qdev_get_gpio_in(DEVICE(>cpu[0].core), ARM_CPU_IRQ));
+qdev_get_gpio_in(DEVICE(_base->cpu[0].core), ARM_CPU_IRQ));
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
-qdev_get_gpio_in(DEVICE(>cpu[0].core), ARM_CPU_FIQ));
+qdev_get_gpio_in(DEVICE(_base->cpu[0].core), ARM_CPU_FIQ));
 }
 
 static void bcm2836_realize(DeviceState *dev, Error **errp)
 {
-BCM283XState *s = BCM283X(dev);
-BCM283XClass *bc = BCM283X_GET_CLASS(dev);
 int n;
+BCM283XState *s = BCM283X(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
 
 if (!bcm283x_common_realize(dev, errp)) {
 return;
 }
 
 /* bcm2836 interrupt controller (and mailboxes, etc.) */
-if (!sysbus_realize(SYS_BUS_DEVICE(>control), errp)) {
+if (!sysbus_realize(SYS_BUS_DEVICE(_base->control), errp)) {
 return;
 }
 
-sysbus_mmio_map(SYS_BUS_DEVICE(>control), 0, bc->ctrl_base);
+sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc->ctrl_base);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
-qdev_get_gpio_in_named(DEVICE(>control), "gpu-irq", 0));
+qdev_get_gpio_in_named(DEVICE(_base->control), "gpu-irq", 0));
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
-qdev_get_gpio_in_named(DEVICE(>control), "gpu-fiq", 0));
+qdev_get_gpio_in_named(DEVICE(_base->control), "gpu-fiq", 0));
 
 for (n = 0; n < BCM283X_NCPUS; n++) {
 /* TODO: this should be converted to a property of ARM_CPU */
-s->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n;
+s_base->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n;
 
 /* set periphbase/CBAR value for CPU-local re

[PATCH v4 03/45] Split out raspi machine common part

2023-12-07 Thread Sergey Kambalin
Pre-setup for raspberry pi 4 introduction

Signed-off-by: Sergey Kambalin 
---
 hw/arm/raspi.c  | 112 ++--
 include/hw/arm/raspi_platform.h |  21 ++
 2 files changed, 85 insertions(+), 48 deletions(-)

diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index af866ebce2..7d04734cd2 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -18,6 +18,7 @@
 #include "qapi/error.h"
 #include "hw/arm/boot.h"
 #include "hw/arm/bcm2836.h"
+#include "hw/arm/raspi_platform.h"
 #include "hw/registerfields.h"
 #include "qemu/error-report.h"
 #include "hw/boards.h"
@@ -25,6 +26,9 @@
 #include "hw/arm/boot.h"
 #include "qom/object.h"
 
+#define TYPE_RASPI_MACHINE  MACHINE_TYPE_NAME("raspi-common")
+OBJECT_DECLARE_SIMPLE_TYPE(RaspiMachineState, RASPI_MACHINE)
+
 #define SMPBOOT_ADDR0x300 /* this should leave enough space for ATAGS */
 #define MVBAR_ADDR  0x400 /* secure vectors */
 #define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
@@ -37,25 +41,10 @@
 
 struct RaspiMachineState {
 /*< private >*/
-MachineState parent_obj;
+RaspiBaseMachineState parent_obj;
 /*< public >*/
 BCM283XState soc;
-struct arm_boot_info binfo;
-};
-typedef struct RaspiMachineState RaspiMachineState;
-
-struct RaspiMachineClass {
-/*< private >*/
-MachineClass parent_obj;
-/*< public >*/
-uint32_t board_rev;
 };
-typedef struct RaspiMachineClass RaspiMachineClass;
-
-#define TYPE_RASPI_MACHINE   MACHINE_TYPE_NAME("raspi-common")
-DECLARE_OBJ_CHECKERS(RaspiMachineState, RaspiMachineClass,
- RASPI_MACHINE, TYPE_RASPI_MACHINE)
-
 
 /*
  * Board revision codes:
@@ -83,6 +72,11 @@ static const struct {
 [PROCESSOR_ID_BCM2837] = {TYPE_BCM2837, BCM283X_NCPUS},
 };
 
+static void raspi_base_machine_init(MachineState *machine,
+ BCM283XBaseState *soc);
+static void raspi_machine_class_common_init(MachineClass *mc,
+ uint32_t board_rev);
+
 static uint64_t board_ram_size(uint32_t board_rev)
 {
 assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
@@ -200,13 +194,12 @@ static void reset_secondary(ARMCPU *cpu, const struct 
arm_boot_info *info)
 cpu_set_pc(cs, info->smp_loader_start);
 }
 
-static void setup_boot(MachineState *machine, RaspiProcessorId processor_id,
-   size_t ram_size)
+static void setup_boot(MachineState *machine, ARMCPU *cpu,
+   RaspiProcessorId processor_id, size_t ram_size)
 {
-RaspiMachineState *s = RASPI_MACHINE(machine);
+RaspiBaseMachineState *s = RASPI_BASE_MACHINE(machine);
 int r;
 
-s->binfo.board_id = MACH_TYPE_BCM2708;
 s->binfo.ram_size = ram_size;
 
 if (processor_id <= PROCESSOR_ID_BCM2836) {
@@ -252,13 +245,13 @@ static void setup_boot(MachineState *machine, 
RaspiProcessorId processor_id,
 s->binfo.firmware_loaded = true;
 }
 
-arm_load_kernel(>soc.parent_obj.cpu[0].core, machine, >binfo);
+arm_load_kernel(cpu, machine, >binfo);
 }
 
-static void raspi_machine_init(MachineState *machine)
+static void raspi_base_machine_init(MachineState *machine,
+ BCM283XBaseState *soc)
 {
-RaspiMachineClass *mc = RASPI_MACHINE_GET_CLASS(machine);
-RaspiMachineState *s = RASPI_MACHINE(machine);
+RaspiBaseMachineClass *mc = RASPI_BASE_MACHINE_GET_CLASS(machine);
 uint32_t board_rev = mc->board_rev;
 uint64_t ram_size = board_ram_size(board_rev);
 uint32_t vcram_size;
@@ -279,19 +272,17 @@ static void raspi_machine_init(MachineState *machine)
 machine->ram, 0);
 
 /* Setup the SOC */
-object_initialize_child(OBJECT(machine), "soc", >soc,
-board_soc_type(board_rev));
-object_property_add_const_link(OBJECT(>soc), "ram", 
OBJECT(machine->ram));
-object_property_set_int(OBJECT(>soc), "board-rev", board_rev,
+object_property_add_const_link(OBJECT(soc), "ram", OBJECT(machine->ram));
+object_property_set_int(OBJECT(soc), "board-rev", board_rev,
 _abort);
-object_property_set_str(OBJECT(>soc), "command-line",
+object_property_set_str(OBJECT(soc), "command-line",
 machine->kernel_cmdline, _abort);
-qdev_realize(DEVICE(>soc), NULL, _fatal);
+qdev_realize(DEVICE(soc), NULL, _fatal);
 
 /* Create and plug in the SD cards */
 di = drive_get(IF_SD, 0, 0);
 blk = di ? blk_by_legacy_dinfo(di) : NULL;
-bus = qdev_get_child_bus(DEVICE(>soc), "sd-bus");
+bus = qdev_get_child_bus(DEVICE(soc), "sd-bus");
 if (bus == NULL) {
 error_report(&qu

  1   2   3   4   >