summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/bsp/raspberrypi4/family.c24
-rw-r--r--hw/bsp/raspberrypi4/family.mk3
-rw-r--r--hw/mcu/broadcom/bcm2711/boot.s4
-rw-r--r--hw/mcu/broadcom/bcm2711/link.ld16
-rw-r--r--hw/mcu/broadcom/bcm2711/mmu.c58
-rw-r--r--hw/mcu/broadcom/bcm2711/mmu.h44
6 files changed, 132 insertions, 17 deletions
diff --git a/hw/bsp/raspberrypi4/family.c b/hw/bsp/raspberrypi4/family.c
index b2665f42d..6266d5a35 100644
--- a/hw/bsp/raspberrypi4/family.c
+++ b/hw/bsp/raspberrypi4/family.c
@@ -28,6 +28,7 @@
#include "board.h"
#include "io.h"
+#include "mmu.h"
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
@@ -55,6 +56,7 @@ void board_init(void)
gpio_initOutputPinWithPullNone(18);
gpio_setPinOutputBool(18, true);
gpio_initOutputPinWithPullNone(42);
+ setup_mmu_flat_map();
// gpio_initOutputPinWithPullNone(23);
// gpio_initOutputPinWithPullNone(24);
// gpio_initOutputPinWithPullNone(25);
@@ -83,17 +85,17 @@ void board_init(void)
// gpio_setPinOutputBool(25, true);
print();
// gpio_setPinOutputBool(25, false);
- while (true) {
- // for (size_t i = 0; i < 5; i++) {
- for (size_t j = 0; j < 10000000000; j++) {
- __asm__("nop");
- }
- gpio_setPinOutputBool(42, true);
- for (size_t j = 0; j < 10000000000; j++) {
- __asm__("nop");
- }
- gpio_setPinOutputBool(42, false);
- }
+ // while (true) {
+ // // for (size_t i = 0; i < 5; i++) {
+ // for (size_t j = 0; j < 10000000000; j++) {
+ // __asm__("nop");
+ // }
+ // gpio_setPinOutputBool(42, true);
+ // for (size_t j = 0; j < 10000000000; j++) {
+ // __asm__("nop");
+ // }
+ // gpio_setPinOutputBool(42, false);
+ // }
// while (1) uart_update();
}
diff --git a/hw/bsp/raspberrypi4/family.mk b/hw/bsp/raspberrypi4/family.mk
index 2d5c78d22..1547beee1 100644
--- a/hw/bsp/raspberrypi4/family.mk
+++ b/hw/bsp/raspberrypi4/family.mk
@@ -18,8 +18,9 @@ CFLAGS += \
SRC_C += \
src/portable/broadcom/synopsys/dcd_synopsys.c \
+ $(MCU_DIR)/interrupts.c \
$(MCU_DIR)/io.c \
- $(MCU_DIR)/interrupts.c
+ $(MCU_DIR)/mmu.c
CROSS_COMPILE = aarch64-none-elf-
diff --git a/hw/mcu/broadcom/bcm2711/boot.s b/hw/mcu/broadcom/bcm2711/boot.s
index 076b3a76a..dcc588924 100644
--- a/hw/mcu/broadcom/bcm2711/boot.s
+++ b/hw/mcu/broadcom/bcm2711/boot.s
@@ -19,7 +19,7 @@ _start:
adr x0, vectors // load VBAR_EL1 with virtual
// msr vbar_el3, x0 // vector table address
msr vbar_el1, x0 // vector table address
- // msr vbar_el2, x0 // vector table address
+ msr vbar_el2, x0 // vector table address
isb
// Clean the BSS section
@@ -45,6 +45,8 @@ irq_entry
mov x0, #\type
mrs x1, esr_el1
mrs x2, elr_el1
+mrs x3, esr_el2
+mrs x4, elr_el2
b err_hang
.endm
diff --git a/hw/mcu/broadcom/bcm2711/link.ld b/hw/mcu/broadcom/bcm2711/link.ld
index 0d5ebe2ab..43c4e722f 100644
--- a/hw/mcu/broadcom/bcm2711/link.ld
+++ b/hw/mcu/broadcom/bcm2711/link.ld
@@ -1,12 +1,20 @@
SECTIONS
{
. = 0x80000; /* Kernel load address for AArch64 */
- .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
- .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
+ .text : {
+ KEEP(*(.text.boot))
+ *(.text .text.* .gnu.linkonce.t*)
+ }
+ .rodata : {
+ . = ALIGN(4096);
+ *(.rodata .rodata.* .gnu.linkonce.r*)
+ }
PROVIDE(_data = .);
- .data : { *(.data .data.* .gnu.linkonce.d*) }
+ .data : {
+ . = ALIGN(4096);
+ *(.data .data.* .gnu.linkonce.d*)
+ }
.bss (NOLOAD) : {
- . = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
diff --git a/hw/mcu/broadcom/bcm2711/mmu.c b/hw/mcu/broadcom/bcm2711/mmu.c
new file mode 100644
index 000000000..3c20436e6
--- /dev/null
+++ b/hw/mcu/broadcom/bcm2711/mmu.c
@@ -0,0 +1,58 @@
+#include <stdbool.h>
+#include <stdint.h>
+
+
+#include "mmu.h"
+
+// Each entry is a gig.
+volatile uint64_t level_1_table[32] __attribute__((aligned(4096)));
+
+// Third gig has peripherals
+uint64_t level_2_0x0_c000_0000_to_0x1_0000_0000[512] __attribute__((aligned(4096)));
+
+void setup_mmu_flat_map(void) {
+ // Set the first gig to regular access.
+ level_1_table[0] = 0x0000000000000000 |
+ MM_DESCRIPTOR_MAIR_INDEX(MT_NORMAL_NC) |
+ MM_DESCRIPTOR_BLOCK |
+ MM_DESCRIPTOR_VALID;
+ level_1_table[2] = ((uint64_t) level_2_0x0_c000_0000_to_0x1_0000_0000) |
+ MM_DESCRIPTOR_TABLE |
+ MM_DESCRIPTOR_VALID;
+ // Set peripherals to register access.
+ for (uint64_t i = 480; i < 512; i++) {
+ level_2_0x0_c000_0000_to_0x1_0000_0000[i] = (0x00000000c0000000 + (i << 21)) |
+ MM_DESCRIPTOR_EXECUTE_NEVER |
+ MM_DESCRIPTOR_MAIR_INDEX(MT_DEVICE_nGnRnE) |
+ MM_DESCRIPTOR_BLOCK |
+ MM_DESCRIPTOR_VALID;
+ }
+ uint64_t mair = MAIR_VALUE;
+ uint64_t tcr = TCR_VALUE;
+ uint64_t ttbr0 = ((uint64_t) level_1_table) | MM_TTBR_CNP;
+ uint64_t sctlr = 0;
+ __asm__ volatile (
+ // Set MAIR
+ "MSR MAIR_EL2, %[mair]\n\t"
+ // Set TTBR0
+ "MSR TTBR0_EL2, %[ttbr0]\n\t"
+ // Set TCR
+ "MSR TCR_EL2, %[tcr]\n\t"
+ // The ISB forces these changes to be seen before the MMU is enabled.
+ "ISB\n\t"
+ // Read System Control Register configuration data
+ "MRS %[sctlr], SCTLR_EL2\n\t"
+ // Write System Control Register configuration data
+ "ORR %[sctlr], %[sctlr], #1\n\t"
+ // Set [M] bit and enable the MMU.
+ "MSR SCTLR_EL2, %[sctlr]\n\t"
+ // The ISB forces these changes to be seen by the next instruction
+ "ISB"
+ : /* No outputs. */
+ : [mair] "r" (mair),
+ [tcr] "r" (tcr),
+ [ttbr0] "r" (ttbr0),
+ [sctlr] "r" (sctlr)
+ );
+ while (true) {}
+}
diff --git a/hw/mcu/broadcom/bcm2711/mmu.h b/hw/mcu/broadcom/bcm2711/mmu.h
new file mode 100644
index 000000000..9f0a7db49
--- /dev/null
+++ b/hw/mcu/broadcom/bcm2711/mmu.h
@@ -0,0 +1,44 @@
+#pragma once
+
+
+// From: https://github.com/s-matyukevich/raspberry-pi-os/blob/master/docs/lesson06/rpi-os.md
+/*
+ * Memory region attributes:
+ *
+ * n = AttrIndx[2:0]
+ * n MAIR
+ * DEVICE_nGnRnE 000 00000000
+ * NORMAL_NC 001 01000100
+ */
+#define MT_DEVICE_nGnRnE 0x0
+#define MT_NORMAL_NC 0x1
+#define MT_DEVICE_nGnRnE_FLAGS 0x00
+#define MT_NORMAL_NC_FLAGS 0x44
+#define MAIR_VALUE (MT_DEVICE_nGnRnE_FLAGS << (8 * MT_DEVICE_nGnRnE)) | (MT_NORMAL_NC_FLAGS << (8 * MT_NORMAL_NC))
+
+
+#define TCR_T0SZ (64 - 35)
+#define TCR_PS (0x01 << 16) // 36-bit physical address
+#define TCR_TG0_4K (0 << 14)
+#define TCR_SH0_OUTER_SHAREABLE (0x2 << 12)
+#define TCR_VALUE (TCR_T0SZ | TCR_PS | TCR_TG0_4K | TCR_SH0_OUTER_SHAREABLE)
+
+#define ENTRY_TYPE_TABLE_DESCRIPTOR 0x11
+#define ENTRY_TYPE_BLOCK_ENTRY 0x01
+#define ENTRY_TYPE_TABLE_ENTRY 0x11
+#define ENTRY_TYPE_INVALID 0x00
+
+#define MM_DESCRIPTOR_VALID (0x1)
+
+#define MM_DESCRIPTOR_BLOCK (0x0 << 1)
+#define MM_DESCRIPTOR_TABLE (0x1 << 1)
+
+// Block attributes
+#define MM_DESCRIPTOR_EXECUTE_NEVER (0x1ull << 54)
+#define MM_DESCRIPTOR_CONTIGUOUS (0x1ull << 52)
+
+#define MM_DESCRIPTOR_MAIR_INDEX(index) (index << 2)
+
+#define MM_TTBR_CNP (0x1)
+
+void setup_mmu_flat_map(void);