From 0a2ec927645ad3f61bbd68e69fb2781fb5ddc149 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Tue, 9 Mar 2021 15:37:57 +0100 Subject: [PATCH 01/21] Add dtb files --- dtb/bcm2708-rpi-b-plus.dtb | Bin 0 -> 25870 bytes dtb/bcm2708-rpi-b-rev1.dtb | Bin 0 -> 25218 bytes dtb/bcm2708-rpi-b.dtb | Bin 0 -> 25607 bytes dtb/bcm2708-rpi-zero-w.dtb | Bin 0 -> 26545 bytes dtb/bcm2708-rpi-zero.dtb | Bin 0 -> 25352 bytes dtb/bcm2709-rpi-2-b.dtb | Bin 0 -> 26745 bytes dtb/bcm2710-rpi-2-b.dtb | Bin 0 -> 26894 bytes 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100755 dtb/bcm2708-rpi-b-plus.dtb create mode 100755 dtb/bcm2708-rpi-b-rev1.dtb create mode 100755 dtb/bcm2708-rpi-b.dtb create mode 100755 dtb/bcm2708-rpi-zero-w.dtb create mode 100755 dtb/bcm2708-rpi-zero.dtb create mode 100644 dtb/bcm2709-rpi-2-b.dtb create mode 100755 dtb/bcm2710-rpi-2-b.dtb diff --git a/dtb/bcm2708-rpi-b-plus.dtb b/dtb/bcm2708-rpi-b-plus.dtb new file mode 100755 index 0000000000000000000000000000000000000000..76741fb7219c627f898ae323ff72de6eaa39f363 GIT binary patch literal 25870 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
5`X@K71zZCOV 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 Ab^rhX literal 0 HcmV?d00001 diff --git a/dtb/bcm2708-rpi-zero-w.dtb b/dtb/bcm2708-rpi-zero-w.dtb new file mode 100755 index 0000000000000000000000000000000000000000..6fcca98c1899ca7d8ca49d6d69fd216bc1e2add7 GIT binary patch literal 26545 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 X`lVpM-R4VjdELu6=9Ch5Q_24U4cXbb literal 0 HcmV?d00001 diff --git a/dtb/bcm2708-rpi-zero.dtb b/dtb/bcm2708-rpi-zero.dtb new file mode 100755 index 0000000000000000000000000000000000000000..7c079896ec4dd8b0ad1dc4c33bee2cc93f9f1a95 GIT binary patch literal 25352 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 OzGWC=ObNT8<^KYW|B!$H literal 0 HcmV?d00001 diff --git a/dtb/bcm2710-rpi-2-b.dtb b/dtb/bcm2710-rpi-2-b.dtb new file mode 100755 index 0000000000000000000000000000000000000000..f44321ac7b4db47f2dab8e7fc0003e55d0589a0a GIT binary patch literal 26894 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 Date: Tue, 9 Mar 2021 18:37:32 +0100 Subject: [PATCH 02/21] Add board option to makefile; Add linking of dtb into binary --- src/kernel/Makefile | 36 +++++++++++++++++++++--------------- src/kernel/linker/kernel.ld | 11 +++++++++-- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 5fc4c28a..764166f3 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -16,10 +16,6 @@ LDFLAGS += -nostartfiles -fcommon -nolibc # PI_CFLAGS = -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s -nostartfiles # variables to define in the preprocessor. -# amount of memory the PMM should try to allocate, may or may not match the actual amount of -# memory in the system. Stuff will crash if this number is more than the actual amount of -# memory. TODO: autodetect this at boot -MEMORY = 1G LOG_LEVEL ?= 4 # Available options: @@ -33,7 +29,20 @@ SOURCEDIR = src BUILDDIR = build # every directory named `include` will have its contents autoincluded INCLUDEDIR = include + + +BOARD = raspi2 + +ifeq ($(BOARD),raspi2) +MEMORY = 1G CPU = cortex-a7 +DTB = $(CURDIR)/../../dtb/bcm2708-rpi-zero.dtb +else ifeq ($(BOARD),raspi0) +MEMORY = 512M +CPU = arm1176 +DTB = $(CURDIR)/../../dtb/bcm2709-rpi-2-b.dtb +endif + # Seeds the random order in which tests are run. TESTS_SEED = $(shell date '+%s') @@ -94,37 +103,34 @@ configure: configure_qemu configure_toolchain build: $(BUILDDIR)/kernel.elf configure | builddir -build_pi: $(BUILDDIR)/kernelPi.img | builddir +build_pi: $(BUILDDIR)/kernel.img | builddir test: build configure | builddir #${QEMU} -M versatilepb -cpu arm1176 -sd $(BUILDDIR)/card.sd -m $(MEMORY) -nographic -semihosting -kernel build/flash.bin -append "-load 0x410000 0x14000" - ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M raspi2 -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting + ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M $(BOARD) -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting run: build configure | builddir # nographic to turn off the gui # monitor none to disable stdio monitoring so # serial stdio works #${QEMU} -M versatilepb -cpu arm1176 -sd $(BUILDDIR)/card.sd -m $(MEMORY) -nographic -semihosting -monitor none -serial stdio -kernel build/flash.bin -append "-load 0x410000 0x14000" - ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M raspi2 -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting + ${QEMU} -kernel $(BUILDDIR)/kernel.elf -serial stdio -monitor none -M $(BOARD) -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting debug: build configure | builddir - ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M raspi2 -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting -S -s + ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M $(BOARD) -cpu $(CPU) -nographic -semihosting -S -s start_debug: build configure | builddir $(GDB) -ex "target remote localhost:1234" -ex "symbol-file $(BUILDDIR)/kernel.sym" $(BUILDDIR)/kernel.elf: $(OBJECT_FILES) | builddir - $(LD) -T linker/kernel.ld $(LDFLAGS) -Wl,-Map,kernel.map $^ -o $@ + $(OBJCOPY) -I binary -O elf32-littlearm $(DTB) $(BUILDDIR)/dtb.o + $(LD) -T linker/kernel.ld $(LDFLAGS) -Wl,-Map,kernel.map $^ $(BUILDDIR)/dtb.o -o $@ $(OBJCOPY) --only-keep-debug $(BUILDDIR)/kernel.elf $(BUILDDIR)/kernel.sym $(OBJCOPY) --strip-debug $(BUILDDIR)/kernel.elf -# Begin Pi Make -# (aka, building for a real pi. TODO: This is mostly untested) -$(BUILDDIR)/kernelPi.elf: $(C_OBJECT_FILES) | builddir - $(CC) -T kernelPi.ld -O2 $(PI_CFLAGS) $^ -o $@ -$(BUILDDIR)/kernelPi.img: $(BUILDDIR)/kernelPi.elf | builddir - $(OBJCOPY) $< -O binary $@ +$(BUILDDIR)/kernel.img: $(BUILDDIR)/kernel.elf | builddir + $(OBJCOPY) $< -O binary $@(Z # End Pi Make builddir: diff --git a/src/kernel/linker/kernel.ld b/src/kernel/linker/kernel.ld index 1c9c8265..d8a616ae 100644 --- a/src/kernel/linker/kernel.ld +++ b/src/kernel/linker/kernel.ld @@ -10,12 +10,19 @@ SECTIONS .boot : { */startup.o (.text) */startup.o (.data) - */startup.o (.bss) + */startup.o (.bss) */stacks.o (.text) */memory.o (.text) - */memory.o (.data) + */memory.o (.data) } __BOOT_END = .; + __DTB_START = .; + .dtb : { + */dtb.o (.data) + } + + __DTB_END = .; + . += __KERNEL_VIRTUAL_OFFSET; __KERNEL_BASE = .; From e2615d58014886c113ee4392fa39b5915d9b7695 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Tue, 9 Mar 2021 18:43:19 +0100 Subject: [PATCH 03/21] Add board configuration documentation --- src/kernel/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kernel/README.md b/src/kernel/README.md index c6d9e471..bbd97e10 100644 --- a/src/kernel/README.md +++ b/src/kernel/README.md @@ -5,15 +5,15 @@ The [makefile](Makefile) in this directory contains a number of configuration op | Configuration opion | description | | --- | --- | | CFLAGS | Flags given to the c compiler | -| MEMORY | The amount of memory given to qemu. Until memory detection works, must be `1G` | | DEFINITIONS | These are variables given to the c preprocessor. Options for these are listed below. | | KERNEL_PARAMS | Currently not supported and outdated | | SOURCEDIR | The name of the directory containing the sourcecode. | | BUILDDIR | The name of the directory containing object files and binaries | | INCLUDEDIR | Any directory in SOURCEDIR with this name, will be globally included in every c file. This means they can be included with `#include ` instead of `#include "something.h"`. | +| BOARD | The board which will be emulated by QEMU. Can be `raspi0` or `raspi2`. | | TEST_MAIN_FILE | The name of the file generated to contain all [tests](src/test/README.md). | | TESTS_SEED | The seed used to randomize the order in which the tests are run. | -| CPU | The cpu type emulated by qemu. Supported cpu types are the `arm1176` and `cortex-a7`| + ## Definitions From 96d8050feed0bfeb139ea9e3bddd4296bb4ecae6 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Tue, 9 Mar 2021 19:18:15 +0100 Subject: [PATCH 04/21] Move dtb files to kernel directory --- src/kernel/Makefile | 4 ++-- {dtb => src/kernel/dtb}/bcm2708-rpi-b-plus.dtb | Bin {dtb => src/kernel/dtb}/bcm2708-rpi-b-rev1.dtb | Bin {dtb => src/kernel/dtb}/bcm2708-rpi-b.dtb | Bin {dtb => src/kernel/dtb}/bcm2708-rpi-zero-w.dtb | Bin {dtb => src/kernel/dtb}/bcm2708-rpi-zero.dtb | Bin {dtb => src/kernel/dtb}/bcm2709-rpi-2-b.dtb | Bin {dtb => src/kernel/dtb}/bcm2710-rpi-2-b.dtb | Bin 8 files changed, 2 insertions(+), 2 deletions(-) rename {dtb => src/kernel/dtb}/bcm2708-rpi-b-plus.dtb (100%) rename {dtb => src/kernel/dtb}/bcm2708-rpi-b-rev1.dtb (100%) rename {dtb => src/kernel/dtb}/bcm2708-rpi-b.dtb (100%) rename {dtb => src/kernel/dtb}/bcm2708-rpi-zero-w.dtb (100%) rename {dtb => src/kernel/dtb}/bcm2708-rpi-zero.dtb (100%) rename {dtb => src/kernel/dtb}/bcm2709-rpi-2-b.dtb (100%) rename {dtb => src/kernel/dtb}/bcm2710-rpi-2-b.dtb (100%) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 764166f3..7605968c 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -36,11 +36,11 @@ BOARD = raspi2 ifeq ($(BOARD),raspi2) MEMORY = 1G CPU = cortex-a7 -DTB = $(CURDIR)/../../dtb/bcm2708-rpi-zero.dtb +DTB = $(CURDIR)/dtb/bcm2708-rpi-zero.dtb else ifeq ($(BOARD),raspi0) MEMORY = 512M CPU = arm1176 -DTB = $(CURDIR)/../../dtb/bcm2709-rpi-2-b.dtb +DTB = $(CURDIR)/dtb/bcm2709-rpi-2-b.dtb endif diff --git a/dtb/bcm2708-rpi-b-plus.dtb b/src/kernel/dtb/bcm2708-rpi-b-plus.dtb similarity index 100% rename from dtb/bcm2708-rpi-b-plus.dtb rename to src/kernel/dtb/bcm2708-rpi-b-plus.dtb diff --git a/dtb/bcm2708-rpi-b-rev1.dtb b/src/kernel/dtb/bcm2708-rpi-b-rev1.dtb similarity index 100% rename from dtb/bcm2708-rpi-b-rev1.dtb rename to src/kernel/dtb/bcm2708-rpi-b-rev1.dtb diff --git a/dtb/bcm2708-rpi-b.dtb b/src/kernel/dtb/bcm2708-rpi-b.dtb similarity index 100% rename from dtb/bcm2708-rpi-b.dtb rename to src/kernel/dtb/bcm2708-rpi-b.dtb diff --git a/dtb/bcm2708-rpi-zero-w.dtb b/src/kernel/dtb/bcm2708-rpi-zero-w.dtb similarity index 100% rename from dtb/bcm2708-rpi-zero-w.dtb rename to src/kernel/dtb/bcm2708-rpi-zero-w.dtb diff --git a/dtb/bcm2708-rpi-zero.dtb b/src/kernel/dtb/bcm2708-rpi-zero.dtb similarity index 100% rename from dtb/bcm2708-rpi-zero.dtb rename to src/kernel/dtb/bcm2708-rpi-zero.dtb diff --git a/dtb/bcm2709-rpi-2-b.dtb b/src/kernel/dtb/bcm2709-rpi-2-b.dtb similarity index 100% rename from dtb/bcm2709-rpi-2-b.dtb rename to src/kernel/dtb/bcm2709-rpi-2-b.dtb diff --git a/dtb/bcm2710-rpi-2-b.dtb b/src/kernel/dtb/bcm2710-rpi-2-b.dtb similarity index 100% rename from dtb/bcm2710-rpi-2-b.dtb rename to src/kernel/dtb/bcm2710-rpi-2-b.dtb From 2df8f6ae5f579b130917f4b07ac0c51f35f8eedc Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Sat, 13 Mar 2021 20:41:57 +0100 Subject: [PATCH 05/21] Add raspberry pi zero dumped device tree --- src/kernel/dtb/bcm2708-rpi-zero-dumped.dtb | Bin 0 -> 26521 bytes src/kernel/dtb/bcm2708-rpi-zero-dumped.dts | 1252 ++++++++++++++++++++ 2 files changed, 1252 insertions(+) create mode 100644 src/kernel/dtb/bcm2708-rpi-zero-dumped.dtb create mode 100644 src/kernel/dtb/bcm2708-rpi-zero-dumped.dts diff --git a/src/kernel/dtb/bcm2708-rpi-zero-dumped.dtb b/src/kernel/dtb/bcm2708-rpi-zero-dumped.dtb new file mode 100644 index 0000000000000000000000000000000000000000..8f66b1318ad17b864fdcacf1c9ce6131130bdd85 GIT binary patch literal 26521 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 wL8BY5uP2QJO@~^B+(v6z=ig2`VLNH`yF1<1z; + interrupt-parent = < 0x01 >; + #address-cells = < 0x01 >; + #size-cells = < 0x01 >; + + reserved-memory { + ranges; + #address-cells = < 0x01 >; + #size-cells = < 0x01 >; + phandle = < 0x29 >; + + linux,cma { + reusable; + compatible = "shared-dma-pool"; + size = < 0x4000000 >; + phandle = < 0x2a >; + linux,cma-default; + }; + }; + + clocks { + + clk-osc { + compatible = "fixed-clock"; + #clock-cells = < 0x00 >; + phandle = < 0x03 >; + clock-output-names = "osc"; + clock-frequency = < 0x124f800 >; + }; + + clk-usb { + compatible = "fixed-clock"; + #clock-cells = < 0x00 >; + phandle = < 0x14 >; + clock-output-names = "otg"; + clock-frequency = < 0x1c9c3800 >; + }; + }; + + memory@0 { + device_type = "memory"; + reg = < 0x00 0x1c000000 >; + }; + + __overrides__ { + cam0-led-ctrl; + i2c1 = "\0\0\0 status"; + i2c_vc = [ 00 00 00 0e 73 74 61 74 75 73 00 00 00 00 1f 73 74 61 74 75 73 00 ]; + sd_overclock = "\0\0\0$brcm,overclock-50:0"; + sdio_overclock = "\0\0\0%brcm,overclock-50:0\0\0\0\0&brcm,overclock-50:0"; + i2c0_baudrate = [ 00 00 00 0e 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00 ]; + sd_pio_limit = "\0\0\0$brcm,pio-limit:0"; + act_led_trigger = "\0\0\0(linux,default-trigger"; + audio = "\0\0\0!status"; + sd_debug = "\0\0\0$brcm,debug"; + cam0-pwdn-ctrl; + cache_line_size; + cam0-led; + i2c1_baudrate = "\0\0\0 clock-frequency:0"; + spi = [ 00 00 00 1e 73 74 61 74 75 73 00 ]; + i2c_arm = "\0\0\0 status"; + uart0 = [ 00 00 00 1b 73 74 61 74 75 73 00 ]; + i2c2_iknowwhatimdoing = [ 00 00 00 16 73 74 61 74 75 73 00 ]; + i2s = [ 00 00 00 1d 73 74 61 74 75 73 00 ]; + i2c0 = [ 00 00 00 0e 73 74 61 74 75 73 00 00 00 00 1f 73 74 61 74 75 73 00 ]; + arm_freq; + watchdog = "\0\0\0\"status"; + i2c_baudrate = "\0\0\0 clock-frequency:0"; + i2c_vc_baudrate = [ 00 00 00 0e 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00 ]; + sd_poll_once = "\0\0\0$non-removable?"; + axiperf = "\0\0\0'status"; + act_led_activelow = "\0\0\0(gpios:8"; + i2c2_baudrate = [ 00 00 00 16 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00 ]; + sd_force_pio = "\0\0\0$brcm,force-pio?"; + cam0-pwdn; + uart1 = [ 00 00 00 1c 73 74 61 74 75 73 00 ]; + i2c_arm_baudrate = "\0\0\0 clock-frequency:0"; + random = "\0\0\0#status"; + act_led_gpio = "\0\0\0(gpios:4"; + i2c = "\0\0\0 status"; + }; + + arm-pmu { + compatible = "arm,arm1176-pmu"; + }; + + cam1_reg { + compatible = "regulator-fixed"; + enable-active-high; + gpio = < 0x0d 0x29 0x00 >; + status = "disabled"; + phandle = < 0x78 >; + regulator-name = "cam1-reg"; + }; + + system { + linux,serial = < 0x00 0x8d8ca77a >; + linux,revision = < 0x900093 >; + }; + + __symbols__ { + uart0_gpio14 = "/soc/gpio@7e200000/uart0_gpio14"; + pwm = "/soc/pwm@7e20c000"; + gpclk1_gpio5 = "/soc/gpio@7e200000/gpclk1_gpio5"; + clk_usb = "/clocks/clk-usb"; + pixelvalve0 = "/soc/pixelvalve@7e206000"; + uart0_ctsrts_gpio30 = "/soc/gpio@7e200000/uart0_ctsrts_gpio30"; + uart1_ctsrts_gpio16 = "/soc/gpio@7e200000/uart1_ctsrts_gpio16"; + uart0_gpio32 = "/soc/gpio@7e200000/uart0_gpio32"; + intc = "/soc/interrupt-controller@7e00b200"; + spi2 = "/soc/spi@7e2150c0"; + i2c0if = "/soc/i2c@7e205000"; + jtag_gpio4 = "/soc/gpio@7e200000/jtag_gpio4"; + dsi1 = "/soc/dsi@7e700000"; + clocks = "/soc/cprman@7e101000"; + i2c1 = "/soc/i2c@7e804000"; + i2c_vc = "/soc/i2c0mux/i2c@0"; + alt0 = "/soc/gpio@7e200000/alt0"; + firmwarekms = "/soc/firmwarekms@7e600000"; + smi = "/soc/smi@7e600000"; + uart1_ctsrts_gpio42 = "/soc/gpio@7e200000/uart1_ctsrts_gpio42"; + spi0 = "/soc/spi@7e204000"; + thermal = "/soc/thermal@7e212000"; + vdd_5v0_reg = "/fixedregulator_5v0"; + vchiq = "/soc/mailbox@7e00b840"; + sdhost = "/soc/mmc@7e202000"; + aux = "/soc/aux@7e215000"; + gpio = "/soc/gpio@7e200000"; + gpclk0_gpio4 = "/soc/gpio@7e200000/gpclk0_gpio4"; + pwm0_gpio12 = "/soc/gpio@7e200000/pwm0_gpio12"; + pwm1_gpio19 = "/soc/gpio@7e200000/pwm1_gpio19"; + sdhci = "/soc/mmc@7e300000"; + pwm0_gpio40 = "/soc/gpio@7e200000/pwm0_gpio40"; + gpclk2_gpio43 = "/soc/gpio@7e200000/gpclk2_gpio43"; + cam1_reg = "/cam1_reg"; + dpi = "/soc/dpi@7e208000"; + vcsm = "/soc/vcsm"; + v3d = "/soc/v3d@7ec00000"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + vdd_3v3_reg = "/fixedregulator_3v3"; + uart1_ctsrts_gpio30 = "/soc/gpio@7e200000/uart1_ctsrts_gpio30"; + gpioout = "/soc/gpio@7e200000/gpioout"; + dma = "/soc/dma@7e007000"; + spidev1 = "/soc/spi@7e204000/spidev@1"; + mmcnr = "/soc/mmcnr@7e300000"; + spi0_gpio35 = "/soc/gpio@7e200000/spi0_gpio35"; + vc4 = "/soc/gpu"; + firmware_clocks = "/soc/firmware/clocks"; + pwm1_gpio45 = "/soc/gpio@7e200000/pwm1_gpio45"; + pcm_gpio28 = "/soc/gpio@7e200000/pcm_gpio28"; + dpi_gpio0 = "/soc/gpio@7e200000/dpi_gpio0"; + power = "/soc/power"; + soc = "/soc"; + i2c0_gpio0 = "/soc/gpio@7e200000/i2c0_gpio0"; + pcm_gpio18 = "/soc/gpio@7e200000/pcm_gpio18"; + leds = "/leds"; + system_timer = "/soc/timer@7e003000"; + csi1 = "/soc/csi@7e801000"; + i2s_pins = "/soc/gpio@7e200000/i2s"; + firmware = "/soc/firmware"; + mmc = "/soc/mmc@7e300000"; + dpi_18bit_gpio2 = "/soc/gpio@7e200000/dpi_18bit_gpio2"; + usbphy = "/phy"; + pixelvalve1 = "/soc/pixelvalve@7e207000"; + spi = "/soc/spi@7e204000"; + spi0_pins = "/soc/gpio@7e200000/spi0_pins"; + i2c_arm = "/soc/i2c@7e804000"; + clk_osc = "/clocks/clk-osc"; + uart0 = "/soc/serial@7e201000"; + pwm1_gpio13 = "/soc/gpio@7e200000/pwm1_gpio13"; + i2c1_pins = "/soc/gpio@7e200000/i2c1"; + rmem = "/reserved-memory"; + cpu_thermal = "/thermal-zones/cpu-thermal"; + fb = "/soc/fb"; + pwm1_gpio41 = "/soc/gpio@7e200000/pwm1_gpio41"; + txp = "/soc/txp@7e004000"; + dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0"; + spi0_gpio7 = "/soc/gpio@7e200000/spi0_gpio7"; + i2c2 = "/soc/i2c@7e805000"; + i2c1_gpio44 = "/soc/gpio@7e200000/i2c1_gpio44"; + cma = "/reserved-memory/linux,cma"; + i2c0_gpio28 = "/soc/gpio@7e200000/i2c0_gpio28"; + i2c_slave_gpio18 = "/soc/gpio@7e200000/i2c_slave_gpio18"; + i2s = "/soc/i2s@7e203000"; + emmc_gpio48 = "/soc/gpio@7e200000/emmc_gpio48"; + spi1 = "/soc/spi@7e215080"; + usb = "/soc/usb@7e980000"; + dsi0 = "/soc/dsi@7e209000"; + i2c1_gpio2 = "/soc/gpio@7e200000/i2c1_gpio2"; + uart0_ctsrts_gpio38 = "/soc/gpio@7e200000/uart0_ctsrts_gpio38"; + pm = "/soc/watchdog@7e100000"; + audio_pins = "/soc/gpio@7e200000/audio_pins"; + i2c0 = "/soc/i2c0mux/i2c@0"; + spi1_gpio16 = "/soc/gpio@7e200000/spi1_gpio16"; + i2c0mux = "/soc/i2c0mux"; + i2c_csi_dsi = "/soc/i2c0mux/i2c@1"; + i2c0_pins = "/soc/gpio@7e200000/i2c0"; + watchdog = "/soc/watchdog@7e100000"; + jtag_gpio22 = "/soc/gpio@7e200000/jtag_gpio22"; + spi2_gpio40 = "/soc/gpio@7e200000/spi2_gpio40"; + vec = "/soc/vec@7e806000"; + i2c0_gpio44 = "/soc/gpio@7e200000/i2c0_gpio44"; + axiperf = "/soc/axiperf"; + spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins"; + sound = "/soc/sound"; + hvs = "/soc/hvs@7e400000"; + uart0_ctsrts_gpio16 = "/soc/gpio@7e200000/uart0_ctsrts_gpio16"; + act_led = "/leds/act"; + gpclk2_gpio6 = "/soc/gpio@7e200000/gpclk2_gpio6"; + spidev0 = "/soc/spi@7e204000/spidev@0"; + sdhost_gpio48 = "/soc/gpio@7e200000/sdhost_gpio48"; + emmc_gpio34 = "/soc/gpio@7e200000/emmc_gpio34"; + gpclk1_gpio44 = "/soc/gpio@7e200000/gpclk1_gpio44"; + uart1_gpio14 = "/soc/gpio@7e200000/uart1_gpio14"; + uart0_gpio36 = "/soc/gpio@7e200000/uart0_gpio36"; + uart1_gpio32 = "/soc/gpio@7e200000/uart1_gpio32"; + hdmi = "/soc/hdmi@7e902000"; + pixelvalve2 = "/soc/pixelvalve@7e807000"; + pwm0_gpio18 = "/soc/gpio@7e200000/pwm0_gpio18"; + gpclk1_gpio42 = "/soc/gpio@7e200000/gpclk1_gpio42"; + mailbox = "/soc/mailbox@7e00b880"; + uart1_gpio40 = "/soc/gpio@7e200000/uart1_gpio40"; + emmc_gpio22 = "/soc/gpio@7e200000/emmc_gpio22"; + uart1 = "/soc/serial@7e215040"; + csi0 = "/soc/csi@7e800000"; + random = "/soc/rng@7e104000"; + i2c = "/soc/i2c@7e804000"; + }; + + soc { + compatible = "simple-bus"; + ranges = < 0x7e000000 0x20000000 0x2000000 >; + #address-cells = < 0x01 >; + #size-cells = < 0x01 >; + phandle = < 0x2c >; + dma-ranges = < 0x80000000 0x00 0x20000000 >; + + serial@7e201000 { + compatible = "arm,pl011\0arm,primecell"; + clocks = < 0x07 0x13 0x07 0x14 >; + clock-names = "uartclk\0apb_pclk"; + status = "okay"; + interrupts = < 0x02 0x19 >; + skip-init; + phandle = < 0x1b >; + arm,primecell-periphid = < 0x241011 >; + reg = < 0x7e201000 0x200 >; + cts-event-workaround; + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + status = "disabled"; + interrupts = < 0x02 0x0e >; + phandle = < 0x68 >; + reg = < 0x7e207000 0x100 >; + }; + + cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + clocks = < 0x03 0x04 0x00 0x04 0x01 0x04 0x02 0x05 0x00 0x05 0x01 0x05 0x02 >; + firmware = < 0x06 >; + #clock-cells = < 0x01 >; + phandle = < 0x07 >; + reg = < 0x7e101000 0x2000 >; + }; + + csi@7e801000 { + power-domains = < 0x11 0x0d >; + compatible = "brcm,bcm2835-unicam"; + clocks = < 0x07 0x2e 0x18 0x04 >; + clock-names = "lp\0vpu"; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x02 0x07 >; + brcm,num-data-lanes = < 0x02 >; + #size-cells = < 0x00 >; + #clock-cells = < 0x01 >; + phandle = < 0x70 >; + reg = < 0x7e801000 0x800 0x7e802004 0x04 >; + }; + + thermal@7e212000 { + compatible = "brcm,bcm2835-thermal"; + clocks = < 0x07 0x1b >; + #thermal-sensor-cells = < 0x00 >; + status = "okay"; + phandle = < 0x02 >; + reg = < 0x7e212000 0x08 >; + }; + + hvs@7e400000 { + compatible = "brcm,bcm2835-hvs"; + status = "disabled"; + interrupts = < 0x02 0x01 >; + phandle = < 0x64 >; + reg = < 0x7e400000 0x6000 >; + }; + + gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + gpio-controller; + #interrupt-cells = < 0x02 >; + interrupts = < 0x02 0x11 0x02 0x12 >; + phandle = < 0x0d >; + reg = < 0x7e200000 0xb4 >; + #gpio-cells = < 0x02 >; + pinctrl-names = "default"; + interrupt-controller; + + uart0_gpio14 { + brcm,pins = < 0x0e 0x0f >; + phandle = < 0x42 >; + brcm,function = < 0x04 >; + }; + + gpclk1_gpio5 { + brcm,pins = < 0x05 >; + phandle = < 0x33 >; + brcm,function = < 0x04 >; + }; + + uart0_ctsrts_gpio30 { + brcm,pins = < 0x1e 0x1f >; + phandle = < 0x44 >; + brcm,pull = < 0x02 0x00 >; + brcm,function = < 0x07 >; + }; + + uart1_ctsrts_gpio16 { + brcm,pins = < 0x10 0x11 >; + phandle = < 0x49 >; + brcm,function = < 0x02 >; + }; + + uart0_gpio32 { + brcm,pins = < 0x20 0x21 >; + phandle = < 0x45 >; + brcm,pull = < 0x00 0x02 >; + brcm,function = < 0x07 >; + }; + + jtag_gpio4 { + brcm,pins = < 0x04 0x05 0x06 0x0c 0x0d >; + phandle = < 0x4f >; + brcm,function = < 0x02 >; + }; + + i2c1 { + brcm,pins = < 0x02 0x03 >; + phandle = < 0x13 >; + brcm,function = < 0x04 >; + }; + + alt0 { + brcm,pins = < 0x04 0x05 0x07 0x08 0x09 0x0a 0x0b >; + phandle = < 0x5a >; + brcm,function = < 0x04 >; + }; + + uart1_ctsrts_gpio42 { + brcm,pins = < 0x2a 0x2b >; + phandle = < 0x4d >; + brcm,function = < 0x02 >; + }; + + gpclk0_gpio4 { + brcm,pins = < 0x04 >; + phandle = < 0x32 >; + brcm,function = < 0x04 >; + }; + + pwm0_gpio12 { + brcm,pins = < 0x0c >; + phandle = < 0x50 >; + brcm,function = < 0x04 >; + }; + + pwm1_gpio19 { + brcm,pins = < 0x13 >; + phandle = < 0x54 >; + brcm,function = < 0x02 >; + }; + + pwm0_gpio40 { + brcm,pins = < 0x28 >; + phandle = < 0x52 >; + brcm,function = < 0x04 >; + }; + + gpclk2_gpio43 { + brcm,pins = < 0x2b >; + phandle = < 0x37 >; + brcm,pull = < 0x00 >; + brcm,function = < 0x04 >; + }; + + uart1_ctsrts_gpio30 { + brcm,pins = < 0x1e 0x1f >; + phandle = < 0x4b >; + brcm,function = < 0x02 >; + }; + + gpioout { + brcm,pins = < 0x06 >; + phandle = < 0x59 >; + brcm,function = < 0x01 >; + }; + + spi0_gpio35 { + brcm,pins = < 0x23 0x24 0x25 0x26 0x27 >; + phandle = < 0x3f >; + brcm,function = < 0x04 >; + }; + + pwm1_gpio45 { + brcm,pins = < 0x2d >; + phandle = < 0x56 >; + brcm,function = < 0x04 >; + }; + + pcm_gpio28 { + brcm,pins = < 0x1c 0x1d 0x1e 0x1f >; + phandle = < 0x3d >; + brcm,function = < 0x06 >; + }; + + dpi_gpio0 { + brcm,pins = < 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b >; + phandle = < 0x2f >; + brcm,function = < 0x06 >; + }; + + i2c0_gpio0 { + brcm,pins = < 0x00 0x01 >; + phandle = < 0x0f >; + brcm,function = < 0x04 >; + }; + + pcm_gpio18 { + brcm,pins = < 0x12 0x13 0x14 0x15 >; + phandle = < 0x3c >; + brcm,function = < 0x04 >; + }; + + dpi_18bit_gpio2 { + brcm,pins = < 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 >; + phandle = < 0x58 >; + brcm,function = < 0x06 >; + }; + + spi0_pins { + brcm,pins = < 0x09 0x0a 0x0b >; + phandle = < 0x0b >; + brcm,function = < 0x04 >; + }; + + pwm1_gpio13 { + brcm,pins = < 0x0d >; + phandle = < 0x53 >; + brcm,function = < 0x04 >; + }; + + pwm1_gpio41 { + brcm,pins = < 0x29 >; + phandle = < 0x55 >; + brcm,function = < 0x04 >; + }; + + dpi_18bit_gpio0 { + brcm,pins = < 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 >; + phandle = < 0x57 >; + brcm,function = < 0x06 >; + }; + + spi0_gpio7 { + brcm,pins = < 0x07 0x08 0x09 0x0a 0x0b >; + phandle = < 0x3e >; + brcm,function = < 0x04 >; + }; + + i2c1_gpio44 { + brcm,pins = < 0x2c 0x2d >; + phandle = < 0x3a >; + brcm,function = < 0x06 >; + }; + + i2c0_gpio28 { + brcm,pins = < 0x1c 0x1d >; + phandle = < 0x10 >; + brcm,function = < 0x04 >; + }; + + i2c_slave_gpio18 { + brcm,pins = < 0x12 0x13 0x14 0x15 >; + phandle = < 0x4e >; + brcm,function = < 0x07 >; + }; + + i2s { + brcm,pins = < 0x12 0x13 0x14 0x15 >; + phandle = < 0x0a >; + brcm,function = < 0x04 >; + }; + + emmc_gpio48 { + brcm,pins = < 0x30 0x31 0x32 0x33 0x34 0x35 >; + phandle = < 0x17 >; + brcm,function = < 0x07 >; + }; + + i2c1_gpio2 { + brcm,pins = < 0x02 0x03 >; + phandle = < 0x39 >; + brcm,function = < 0x04 >; + }; + + uart0_ctsrts_gpio38 { + brcm,pins = < 0x26 0x27 >; + phandle = < 0x47 >; + brcm,function = < 0x06 >; + }; + + audio_pins { + brcm,pins; + phandle = < 0x1a >; + brcm,function; + }; + + i2c0 { + brcm,pins = < 0x00 0x01 >; + phandle = < 0x5b >; + brcm,function = < 0x04 >; + }; + + spi1_gpio16 { + brcm,pins = < 0x10 0x11 0x12 0x13 0x14 0x15 >; + phandle = < 0x40 >; + brcm,function = < 0x03 >; + }; + + jtag_gpio22 { + brcm,pins = < 0x16 0x17 0x18 0x19 0x1a 0x1b >; + phandle = < 0x3b >; + brcm,function = < 0x03 >; + }; + + spi2_gpio40 { + brcm,pins = < 0x28 0x29 0x2a 0x2b 0x2c 0x2d >; + phandle = < 0x41 >; + brcm,function = < 0x03 >; + }; + + i2c0_gpio44 { + brcm,pins = < 0x2c 0x2d >; + phandle = < 0x38 >; + brcm,function = < 0x05 >; + }; + + spi0_cs_pins { + brcm,pins = < 0x08 0x07 >; + phandle = < 0x0c >; + brcm,function = < 0x01 >; + }; + + uart0_ctsrts_gpio16 { + brcm,pins = < 0x10 0x11 >; + phandle = < 0x43 >; + brcm,function = < 0x07 >; + }; + + gpclk2_gpio6 { + brcm,pins = < 0x06 >; + phandle = < 0x36 >; + brcm,function = < 0x04 >; + }; + + sdhost_gpio48 { + brcm,pins = < 0x30 0x31 0x32 0x33 0x34 0x35 >; + phandle = < 0x09 >; + brcm,function = < 0x04 >; + }; + + emmc_gpio34 { + brcm,pins = < 0x22 0x23 0x24 0x25 0x26 0x27 >; + phandle = < 0x31 >; + brcm,pull = < 0x00 0x02 0x02 0x02 0x02 0x02 >; + brcm,function = < 0x07 >; + }; + + gpclk1_gpio44 { + brcm,pins = < 0x2c >; + phandle = < 0x35 >; + brcm,function = < 0x04 >; + }; + + uart1_gpio14 { + brcm,pins = < 0x0e 0x0f >; + phandle = < 0x48 >; + brcm,function = < 0x02 >; + }; + + uart0_gpio36 { + brcm,pins = < 0x24 0x25 >; + phandle = < 0x46 >; + brcm,function = < 0x06 >; + }; + + uart1_gpio32 { + brcm,pins = < 0x20 0x21 >; + phandle = < 0x4a >; + brcm,function = < 0x02 >; + }; + + pwm0_gpio18 { + brcm,pins = < 0x12 >; + phandle = < 0x51 >; + brcm,function = < 0x02 >; + }; + + gpclk1_gpio42 { + brcm,pins = < 0x2a >; + phandle = < 0x34 >; + brcm,function = < 0x04 >; + }; + + uart1_gpio40 { + brcm,pins = < 0x28 0x29 >; + phandle = < 0x4c >; + brcm,function = < 0x02 >; + }; + + emmc_gpio22 { + brcm,pins = < 0x16 0x17 0x18 0x19 0x1a 0x1b >; + phandle = < 0x30 >; + brcm,function = < 0x07 >; + }; + }; + + pixelvalve@7e807000 { + compatible = "brcm,bcm2835-pixelvalve2"; + status = "disabled"; + interrupts = < 0x02 0x0a >; + phandle = < 0x69 >; + reg = < 0x7e807000 0x100 >; + }; + + v3d@7ec00000 { + power-domains = < 0x11 0x0a >; + compatible = "brcm,vc4-v3d"; + status = "disabled"; + interrupts = < 0x01 0x0a >; + phandle = < 0x6b >; + reg = < 0x7ec00000 0x1000 >; + }; + + gpu { + compatible = "brcm,bcm2835-vc4"; + status = "disabled"; + phandle = < 0x6c >; + }; + + mmc@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + clocks = < 0x07 0x1c >; + status = "disabled"; + interrupts = < 0x02 0x1e >; + brcm,overclock-50 = < 0x00 >; + bus-width = < 0x04 >; + dma-names = "rx-tx"; + phandle = < 0x25 >; + reg = < 0x7e300000 0x100 >; + pinctrl-0 = < 0x17 >; + dmas = < 0x08 0x0b >; + pinctrl-names = "default"; + }; + + spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + clocks = < 0x07 0x14 >; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x02 0x16 >; + cs-gpios = < 0x0d 0x08 0x01 0x0d 0x07 0x01 >; + #size-cells = < 0x00 >; + dma-names = "tx\0rx"; + phandle = < 0x1e >; + reg = < 0x7e204000 0x200 >; + pinctrl-0 = < 0x0b 0x0c >; + dmas = < 0x08 0x06 0x08 0x07 >; + pinctrl-names = "default"; + + spidev@1 { + compatible = "spidev"; + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + phandle = < 0x5d >; + reg = < 0x01 >; + spi-max-frequency = < 0x7735940 >; + }; + + spidev@0 { + compatible = "spidev"; + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + phandle = < 0x5c >; + reg = < 0x00 >; + spi-max-frequency = < 0x7735940 >; + }; + }; + + i2c@7e804000 { + compatible = "brcm,bcm2835-i2c"; + clocks = < 0x07 0x14 >; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x02 0x15 >; + #size-cells = < 0x00 >; + phandle = < 0x20 >; + reg = < 0x7e804000 0x1000 >; + clock-frequency = < 0x186a0 >; + pinctrl-0 = < 0x13 >; + pinctrl-names = "default"; + }; + + vcsm { + compatible = "raspberrypi,bcm2835-vcsm"; + firmware = < 0x06 >; + status = "okay"; + phandle = < 0x73 >; + }; + + timer@7e003000 { + compatible = "brcm,bcm2835-system-timer"; + interrupts = < 0x01 0x00 0x01 0x01 0x01 0x02 0x01 0x03 >; + phandle = < 0x2d >; + reg = < 0x7e003000 0x1000 >; + clock-frequency = < 0xf4240 >; + }; + + i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; + clocks = < 0x07 0x1f >; + #sound-dai-cells = < 0x00 >; + status = "disabled"; + dma-names = "tx\0rx"; + phandle = < 0x1d >; + reg = < 0x7e203000 0x24 >; + pinctrl-0 = < 0x0a >; + dmas = < 0x08 0x02 0x08 0x03 >; + pinctrl-names = "default"; + }; + + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + #mbox-cells = < 0x00 >; + interrupts = < 0x00 0x01 >; + phandle = < 0x19 >; + reg = < 0x7e00b880 0x40 >; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = < 0x7e200000 0x1000 >; + }; + + vec@7e806000 { + power-domains = < 0x11 0x07 >; + compatible = "brcm,bcm2835-vec"; + clocks = < 0x07 0x18 >; + status = "disabled"; + interrupts = < 0x02 0x1b >; + phandle = < 0x65 >; + reg = < 0x7e806000 0x1000 >; + }; + + power { + compatible = "raspberrypi,bcm2835-power"; + firmware = < 0x06 >; + phandle = < 0x11 >; + #power-domain-cells = < 0x01 >; + }; + + pixelvalve@7e206000 { + compatible = "brcm,bcm2835-pixelvalve0"; + status = "disabled"; + interrupts = < 0x02 0x0d >; + phandle = < 0x67 >; + reg = < 0x7e206000 0x100 >; + }; + + csi@7e800000 { + power-domains = < 0x11 0x0c >; + compatible = "brcm,bcm2835-unicam"; + clocks = < 0x07 0x2d 0x18 0x04 >; + clock-names = "lp\0vpu"; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x02 0x06 >; + #size-cells = < 0x00 >; + #clock-cells = < 0x01 >; + phandle = < 0x6f >; + reg = < 0x7e800000 0x800 0x7e802000 0x04 >; + }; + + mailbox@7e00b840 { + compatible = "brcm,bcm2835-vchiq"; + interrupts = < 0x00 0x02 >; + phandle = < 0x71 >; + reg = < 0x7e00b840 0x3c >; + + bcm2835_audio { + brcm,pwm-channels = < 0x08 >; + compatible = "brcm,bcm2835-audio"; + brcm,disable-headphones = < 0x01 >; + status = "okay"; + phandle = < 0x21 >; + pinctrl-0 = < 0x1a >; + pinctrl-names = "default"; + }; + }; + + firmware { + compatible = "raspberrypi,bcm2835-firmware\0simple-mfd"; + #address-cells = < 0x01 >; + mboxes = < 0x19 >; + #size-cells = < 0x01 >; + phandle = < 0x06 >; + dma-ranges; + + clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = < 0x01 >; + phandle = < 0x18 >; + }; + }; + + dsi@7e209000 { + power-domains = < 0x11 0x11 >; + compatible = "brcm,bcm2835-dsi0"; + clocks = < 0x07 0x20 0x07 0x2f 0x07 0x31 >; + clock-names = "phy\0escape\0pixel"; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x02 0x04 >; + #size-cells = < 0x00 >; + #clock-cells = < 0x01 >; + phandle = < 0x04 >; + reg = < 0x7e209000 0x78 >; + clock-output-names = "dsi0_byte\0dsi0_ddr2\0dsi0_ddr"; + }; + + mmcnr@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + clocks = < 0x07 0x1c >; + status = "disabled"; + interrupts = < 0x02 0x1e >; + brcm,overclock-50 = < 0x00 >; + dma-names = "rx-tx"; + phandle = < 0x26 >; + reg = < 0x7e300000 0x100 >; + dmas = < 0x08 0x0b >; + non-removable; + }; + + fb { + compatible = "brcm,bcm2708-fb"; + firmware = < 0x06 >; + status = "okay"; + phandle = < 0x72 >; + }; + + dpi@7e208000 { + compatible = "brcm,bcm2835-dpi"; + clocks = < 0x07 0x14 0x07 0x2c >; + clock-names = "core\0pixel"; + status = "disabled"; + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + phandle = < 0x60 >; + reg = < 0x7e208000 0x8c >; + }; + + mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + clocks = < 0x07 0x14 >; + brcm,pio-limit = < 0x01 >; + status = "okay"; + interrupts = < 0x02 0x18 >; + brcm,overclock-50 = < 0x00 >; + bus-width = < 0x04 >; + dma-names = "rx-tx"; + phandle = < 0x24 >; + reg = < 0x7e202000 0x100 >; + pinctrl-0 = < 0x09 >; + dmas = < 0x08 0x2000000d >; + pinctrl-names = "default"; + }; + + i2c0mux { + compatible = "i2c-mux-pinctrl"; + pinctrl-1 = < 0x10 >; + status = "disabled"; + #address-cells = < 0x01 >; + i2c-parent = < 0x0e >; + #size-cells = < 0x00 >; + phandle = < 0x1f >; + pinctrl-0 = < 0x0f >; + pinctrl-names = "i2c0\0i2c_csi_dsi"; + + i2c@0 { + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + phandle = < 0x5e >; + reg = < 0x00 >; + }; + + i2c@1 { + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + phandle = < 0x5f >; + reg = < 0x01 >; + }; + }; + + hdmi@7e902000 { + power-domains = < 0x11 0x05 >; + compatible = "brcm,bcm2835-hdmi"; + clocks = < 0x07 0x10 0x07 0x19 >; + reg-names = "hdmi\0hd"; + clock-names = "pixel\0hdmi"; + ddc = < 0x16 >; + status = "disabled"; + interrupts = < 0x02 0x08 0x02 0x09 >; + dma-names = "audio-rx"; + phandle = < 0x6a >; + hpd-gpios = < 0x0d 0x2e 0x01 >; + reg = < 0x7e902000 0x600 0x7e808000 0x100 >; + dmas = < 0x08 0x9000011 >; + }; + + pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + clocks = < 0x07 0x1e >; + status = "disabled"; + assigned-clock-rates = < 0x989680 >; + assigned-clocks = < 0x07 0x1e >; + phandle = < 0x63 >; + reg = < 0x7e20c000 0x28 >; + #pwm-cells = < 0x02 >; + }; + + watchdog@7e100000 { + compatible = "brcm,bcm2835-pm\0brcm,bcm2835-pm-wdt"; + clocks = < 0x07 0x15 0x07 0x1d 0x07 0x17 0x07 0x16 >; + #reset-cells = < 0x01 >; + clock-names = "v3d\0peri_image\0h264\0isp"; + system-power-controller; + phandle = < 0x22 >; + reg = < 0x7e100000 0x114 0x7e00a000 0x24 >; + #power-domain-cells = < 0x01 >; + }; + + interrupt-controller@7e00b200 { + compatible = "brcm,bcm2835-armctrl-ic"; + #interrupt-cells = < 0x02 >; + phandle = < 0x01 >; + reg = < 0x7e00b200 0x200 >; + interrupt-controller; + }; + + aux@7e215000 { + compatible = "brcm,bcm2835-aux"; + clocks = < 0x07 0x14 >; + #clock-cells = < 0x01 >; + phandle = < 0x12 >; + reg = < 0x7e215000 0x08 >; + }; + + dsi@7e700000 { + power-domains = < 0x11 0x12 >; + compatible = "brcm,bcm2835-dsi1"; + clocks = < 0x07 0x23 0x07 0x30 0x07 0x32 >; + clock-names = "phy\0escape\0pixel"; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x02 0x0c >; + #size-cells = < 0x00 >; + #clock-cells = < 0x01 >; + phandle = < 0x05 >; + reg = < 0x7e700000 0x8c >; + clock-output-names = "dsi1_byte\0dsi1_ddr2\0dsi1_ddr"; + }; + + axiperf { + compatible = "brcm,bcm2835-axiperf"; + firmware = < 0x06 >; + status = "disabled"; + phandle = < 0x27 >; + reg = < 0x7e009800 0x100 0x7ee08000 0x100 >; + }; + + sound { + status = "disabled"; + phandle = < 0x74 >; + }; + + i2c@7e205000 { + compatible = "brcm,bcm2835-i2c"; + clocks = < 0x07 0x14 >; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x02 0x15 >; + #size-cells = < 0x00 >; + phandle = < 0x0e >; + reg = < 0x7e205000 0x200 >; + clock-frequency = < 0x186a0 >; + }; + + txp@7e004000 { + compatible = "brcm,bcm2835-txp"; + status = "disabled"; + interrupts = < 0x01 0x0b >; + phandle = < 0x2e >; + reg = < 0x7e004000 0x20 >; + }; + + serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + clocks = < 0x12 0x00 >; + status = "disabled"; + interrupts = < 0x01 0x1d >; + skip-init; + phandle = < 0x1c >; + reg = < 0x7e215040 0x40 >; + }; + + dma@7e007000 { + #dma-cells = < 0x01 >; + compatible = "brcm,bcm2835-dma"; + brcm,dma-channel-mask = < 0x7f35 >; + interrupts = < 0x01 0x10 0x01 0x11 0x01 0x12 0x01 0x13 0x01 0x14 0x01 0x15 0x01 0x16 0x01 0x17 0x01 0x18 0x01 0x19 0x01 0x1a 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1c >; + phandle = < 0x08 >; + reg = < 0x7e007000 0xf00 >; + interrupt-names = "dma0\0dma1\0dma2\0dma3\0dma4\0dma5\0dma6\0dma7\0dma8\0dma9\0dma10\0dma11\0dma12\0dma13\0dma14\0dma-shared-all"; + }; + + i2c@7e805000 { + compatible = "brcm,bcm2835-i2c"; + clocks = < 0x07 0x14 >; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x02 0x15 >; + #size-cells = < 0x00 >; + phandle = < 0x16 >; + reg = < 0x7e805000 0x1000 >; + clock-frequency = < 0x186a0 >; + }; + + spi@7e215080 { + compatible = "brcm,bcm2835-aux-spi"; + clocks = < 0x12 0x01 >; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x01 0x1d >; + #size-cells = < 0x00 >; + phandle = < 0x61 >; + reg = < 0x7e215080 0x40 >; + }; + + firmwarekms@7e600000 { + compatible = "raspberrypi,rpi-firmware-kms"; + status = "disabled"; + interrupts = < 0x02 0x10 >; + brcm,firmware = < 0x06 >; + phandle = < 0x6d >; + reg = < 0x7e600000 0x100 >; + }; + + rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + interrupts = < 0x02 0x1d >; + phandle = < 0x23 >; + reg = < 0x7e104000 0x10 >; + }; + + usb@7e980000 { + power-domains = < 0x11 0x06 >; + compatible = "brcm,bcm2835-usb"; + clocks = < 0x14 >; + clock-names = "otg"; + phy-names = "usb2-phy"; + g-rx-fifo-size = < 0x22e >; + status = "okay"; + #address-cells = < 0x01 >; + interrupts = < 0x01 0x09 0x02 0x00 >; + #size-cells = < 0x00 >; + phandle = < 0x66 >; + phys = < 0x15 >; + reg = < 0x7e980000 0x10000 0x7e006000 0x1000 >; + dr_mode = "otg"; + g-tx-fifo-size = < 0x200 0x200 0x200 0x200 0x200 0x100 0x100 >; + interrupt-names = "usb\0soft"; + g-np-tx-fifo-size = < 0x20 >; + }; + + smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + clocks = < 0x07 0x2a >; + status = "disabled"; + interrupts = < 0x02 0x10 >; + assigned-clock-rates = < 0x7735940 >; + dma-names = "rx-tx"; + assigned-clocks = < 0x07 0x2a >; + phandle = < 0x6e >; + reg = < 0x7e600000 0x100 >; + dmas = < 0x08 0x04 >; + }; + + spi@7e2150c0 { + compatible = "brcm,bcm2835-aux-spi"; + clocks = < 0x12 0x02 >; + status = "disabled"; + #address-cells = < 0x01 >; + interrupts = < 0x01 0x1d >; + #size-cells = < 0x00 >; + phandle = < 0x62 >; + reg = < 0x7e2150c0 0x40 >; + }; + }; + + leds { + compatible = "gpio-leds"; + phandle = < 0x75 >; + + act { + gpios = < 0x0d 0x2f 0x01 >; + label = "led0"; + phandle = < 0x28 >; + default-state = "keep"; + linux,default-trigger = "actpwr"; + }; + }; + + aliases { + intc = "/soc/interrupt-controller@7e00b200"; + i2c10 = "/soc/i2c0mux/i2c@1"; + spi2 = "/soc/spi@7e2150c0"; + i2c1 = "/soc/i2c@7e804000"; + i2c_vc = "/soc/i2c0mux/i2c@0"; + spi0 = "/soc/spi@7e204000"; + thermal = "/soc/thermal@7e212000"; + sdhost = "/soc/mmc@7e202000"; + aux = "/soc/aux@7e215000"; + gpio = "/soc/gpio@7e200000"; + mmc1 = "/soc/mmc@7e300000"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + dma = "/soc/dma@7e007000"; + soc = "/soc"; + leds = "/leds"; + mmc = "/soc/mmc@7e300000"; + serial1 = "/soc/serial@7e215040"; + i2c_arm = "/soc/i2c@7e804000"; + uart0 = "/soc/serial@7e201000"; + fb = "/soc/fb"; + i2c2 = "/soc/i2c@7e805000"; + i2s = "/soc/i2s@7e203000"; + spi1 = "/soc/spi@7e215080"; + usb = "/soc/usb@7e980000"; + i2c0 = "/soc/i2c0mux/i2c@0"; + watchdog = "/soc/watchdog@7e100000"; + axiperf = "/soc/axiperf"; + mmc0 = "/soc/mmc@7e202000"; + sound = "/soc/sound"; + mailbox = "/soc/mailbox@7e00b880"; + uart1 = "/soc/serial@7e215040"; + random = "/soc/rng@7e104000"; + i2c = "/soc/i2c@7e804000"; + serial0 = "/soc/serial@7e201000"; + }; + + chosen { + bootargs = "coherent_pool=1M snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 bcm2708_fb.fbwidth=656 bcm2708_fb.fbheight=416 bcm2708_fb.fbswap=1 smsc95xx.macaddr=B8:27:EB:8C:A7:7A vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000 console=tty1 root=PARTUUID=fa464734-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait modules-load=dwc2,g_ether"; + rpi-boardrev-ext = < 0x00 >; + kaslr-seed = < 0xedafdc48 0xf3ce1b3e >; + + bootloader { + }; + }; + + thermal-zones { + + cpu-thermal { + thermal-sensors = < 0x02 >; + polling-delay = < 0x3e8 >; + polling-delay-passive = < 0x00 >; + coefficients = < 0xfffffde6 0x635d8 >; + phandle = < 0x2b >; + + cooling-maps { + }; + }; + }; + + phy { + compatible = "usb-nop-xceiv"; + phandle = < 0x15 >; + #phy-cells = < 0x00 >; + }; + + fixedregulator_3v3 { + compatible = "regulator-fixed"; + phandle = < 0x76 >; + regulator-min-microvolt = < 0x325aa0 >; + regulator-max-microvolt = < 0x325aa0 >; + regulator-always-on; + regulator-name = "3v3"; + }; + + cpus { + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + + cpu@0 { + compatible = "arm,arm1176jzf-s"; + device_type = "cpu"; + reg = < 0x00 >; + }; + }; + + fixedregulator_5v0 { + compatible = "regulator-fixed"; + phandle = < 0x77 >; + regulator-min-microvolt = < 0x4c4b40 >; + regulator-max-microvolt = < 0x4c4b40 >; + regulator-always-on; + regulator-name = "5v0"; + }; + + axi { + + vc_mem { + reg = < 0x1ec00000 0x20000000 0x40000000 >; + }; + }; +}; From 4a29658c6c91d5bb47e06565dbff728b829fec2f Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Sat, 13 Mar 2021 20:48:17 +0100 Subject: [PATCH 06/21] Fix raspi0 core being disabled --- src/kernel/src/common/startup.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/src/common/startup.s b/src/kernel/src/common/startup.s index 7d92b32d..64a8ecdf 100644 --- a/src/kernel/src/common/startup.s +++ b/src/kernel/src/common/startup.s @@ -6,7 +6,7 @@ _Reset: // Disable other cores mrc p15, #0, r1, c0, c0, #5 and r1, r1, #3 - cmp r1, #0 + cmp r1, #3 bne loop ldr sp, =EARLY_KERNEL_STACK_TOP // Set the kernel/SVC stack From ce0916b2834a0b39da94d2fd1d4acc15e4f5ebf9 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Sun, 14 Mar 2021 08:59:43 +0100 Subject: [PATCH 07/21] Fix timer tests failing --- src/kernel/src/drivers/chipset/bcm2836/bcm2836.c | 2 +- src/kernel/src/drivers/chipset/bcm2836/timer.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c b/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c index dfdd6587..29cc0ed9 100644 --- a/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c +++ b/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c @@ -6,7 +6,7 @@ #include void bcm2836_irq_handler() { - volatile const uint32_t pending = bcm2836_registers_base->Core0IRQSource; + volatile const uint32_t pending = bcm2836_registers_base->Core3IRQSource; switch (pending) { // Generic timers diff --git a/src/kernel/src/drivers/chipset/bcm2836/timer.c b/src/kernel/src/drivers/chipset/bcm2836/timer.c index 43de5671..9e641865 100644 --- a/src/kernel/src/drivers/chipset/bcm2836/timer.c +++ b/src/kernel/src/drivers/chipset/bcm2836/timer.c @@ -99,20 +99,20 @@ void bcm2836_timer_init() { const uint32_t freq = get_frequency(); INFO("System counter frequency: %u kHz\n", freq / 1000); - bcm2836_registers_base->Core0TimersInterruptControl = PHYSICAL_SECURE_TIMER; + bcm2836_registers_base->Core3TimersInterruptControl = PHYSICAL_SECURE_TIMER; // Init priority queue scheduled_timers = prq_create(); // Initially there are no timers set yet, so the interrupt is masked - mask_and_enable_timer(); + mask_and_enable_timer(); } void timer_handle_interrupt() { volatile const uint64_t current_count = get_phy_count(); // Begin of critical section, disable timer interrupts - bcm2836_registers_base->Core0TimersInterruptControl = 0; + bcm2836_registers_base->Core3TimersInterruptControl = 0; // Process all timers that are not in the future, if any prq_node * next_timer_node = prq_peek(scheduled_timers); @@ -153,7 +153,7 @@ void timer_handle_interrupt() { } // End of critical section, re-enable timer interrupts - bcm2836_registers_base->Core0TimersInterruptControl = PHYSICAL_SECURE_TIMER; + bcm2836_registers_base->Core3TimersInterruptControl = PHYSICAL_SECURE_TIMER; } static TimerHandle schedule_timer(TimerCallback callback, uint32_t delay_ms, bool periodic) { @@ -178,7 +178,7 @@ static TimerHandle schedule_timer(TimerCallback callback, uint32_t delay_ms, boo new_timer_node->data = new_timer; // Begin of critical section, disable timer interrupts - bcm2836_registers_base->Core0TimersInterruptControl = 0; + bcm2836_registers_base->Core3TimersInterruptControl = 0; prq_enqueue(scheduled_timers, new_timer_node); @@ -188,7 +188,7 @@ static TimerHandle schedule_timer(TimerCallback callback, uint32_t delay_ms, boo unmask_and_enable_timer(); // End of critical section, re-enable timer interrupts - bcm2836_registers_base->Core0TimersInterruptControl = PHYSICAL_SECURE_TIMER; + bcm2836_registers_base->Core3TimersInterruptControl = PHYSICAL_SECURE_TIMER; return new_timer->handle; } From 43ba07fd123d3113ec6579fee23e0d4e6bb5ce70 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Sun, 14 Mar 2021 19:26:37 +0100 Subject: [PATCH 08/21] Remove old memory detection mechanism; Add use of embedded dtb --- src/kernel/src/common/start.c | 13 ++++++++++--- src/kernel/src/common/startup.s | 8 ++------ src/kernel/src/vm/vm2.c | 16 ++++------------ 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/kernel/src/common/start.c b/src/kernel/src/common/start.c index 4341615c..a6d08334 100644 --- a/src/kernel/src/common/start.c +++ b/src/kernel/src/common/start.c @@ -6,11 +6,18 @@ #include #include #include +#include + +extern size_t __DTB_START[]; /// Entrypoint for the C part of the kernel. /// This function is called by the assembly located in [startup.s]. /// The MMU has already been initialized here but only the first MiB of the kernel has been mapped. -void start(uint32_t * p_bootargs, size_t memory_size) { +void start(uint32_t * p_bootargs, void * dtb) { + if (dtb == NULL) { + dtb = __DTB_START; // DTB not passed by bootloader, we are in QEMU. Use Embedded DTB. + } + // Before this point, all code has to be hardware independent. // After this point, code can request the hardware info struct to find out what // Code should be ran. @@ -19,7 +26,7 @@ void start(uint32_t * p_bootargs, size_t memory_size) { // Initialize the chipset and enable uart init_chipset(); - INFO("Detected memory size: 0x%x Bytes", memory_size); + INFO("Detected memory size: 0x%x Bytes", 0x1000000); INFO("Started chipset specific handlers"); // just cosmetic (and for debugging) @@ -32,7 +39,7 @@ void start(uint32_t * p_bootargs, size_t memory_size) { // was temporary and has to be replaced here. // This will actually map the whole kernel in memory and initialize the physicalMemoryManager. INFO("Initializing the physical and virtual memory managers."); - vm2_start(memory_size); + vm2_start(0x1000000); INFO("Setting up interrupt vector tables"); // Set up the exception handlers. diff --git a/src/kernel/src/common/startup.s b/src/kernel/src/common/startup.s index 64a8ecdf..d6cbf450 100644 --- a/src/kernel/src/common/startup.s +++ b/src/kernel/src/common/startup.s @@ -11,9 +11,6 @@ _Reset: ldr sp, =EARLY_KERNEL_STACK_TOP // Set the kernel/SVC stack - // Detect memory size - bl detect_memory - push {r0-r11} @@ -71,9 +68,8 @@ _Reset: // Setup stacks bl stacks - // Pop everything except r1, which will hold the memory size. - pop {r0} - pop {r2-r11} + pop {r0-r11} + mov r1, r2 // Jumpt to the start of the kernel bl start diff --git a/src/kernel/src/vm/vm2.c b/src/kernel/src/vm/vm2.c index bd8c3004..5e4c3230 100644 --- a/src/kernel/src/vm/vm2.c +++ b/src/kernel/src/vm/vm2.c @@ -90,18 +90,10 @@ void vm2_set_user_pagetable(struct L1PageTable * l1) { // Starts the actual MMU after this function we live in Virtual Memory void vm2_start(size_t detected_size) { - size_t available_RAM; - - switch (get_hardwareinfo()->boardType) { - case RaspberryPiZero: - available_RAM = 512 * Mebibyte; - break; - case RaspBerryPiTwo: - available_RAM = 1 * Gibibyte; - break; - default: - available_RAM = detected_size; - } + size_t available_RAM = detected_size; + + + INFO("Using memory size 0x%x", available_RAM); From d94a02e275ee9529b714f0333b4dfab3d56dfd86 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Sun, 14 Mar 2021 20:11:40 +0100 Subject: [PATCH 09/21] Add dtb struct; Add check for dtb magic number --- src/kernel/src/common/dtb.c | 22 ++++++++++++++++++++ src/kernel/src/common/include/dtb.h | 31 +++++++++++++++++++++++++++++ src/kernel/src/common/start.c | 11 +++++++--- 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 src/kernel/src/common/dtb.c create mode 100644 src/kernel/src/common/include/dtb.h diff --git a/src/kernel/src/common/dtb.c b/src/kernel/src/common/dtb.c new file mode 100644 index 00000000..ef0bd39b --- /dev/null +++ b/src/kernel/src/common/dtb.c @@ -0,0 +1,22 @@ +#include + +// DTB is in big endian, so it must be converted to little endian +static inline uint32_t fix_endian(uint32_t num){ + char *ptr = (char*)# + int ret; + + ret = ptr[0] << 24; + ret |= ptr[1] << 16; + ret |= ptr[2] << 8; + ret |= ptr[3]; + + return ret; +} + +void dtb_get_property(struct DTHeader* dtb_h, char* path, char* property){ + if(fix_endian(dtb_h->magic)!=0xd00dfeed){ + FATAL("Wrong dtb header %x", dtb_h->magic); + } +} + + diff --git a/src/kernel/src/common/include/dtb.h b/src/kernel/src/common/include/dtb.h new file mode 100644 index 00000000..a3cb8cb5 --- /dev/null +++ b/src/kernel/src/common/include/dtb.h @@ -0,0 +1,31 @@ +#ifndef DTB_H +#define PMM_H + +#include +#include + +struct DTHeader { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}; + +enum StructureToken { + FDT_BEGIN_NODE = 0x1, + FDT_END_NODE = 0x2, + FDT_PROP = 0x3, + FDT_NOP = 0x4, + FDT_END = 0x9, +}; + +void dtb_get_property(struct DTHeader* dtbh, char* path, char* property); + + +#endif diff --git a/src/kernel/src/common/start.c b/src/kernel/src/common/start.c index a6d08334..5458ad8a 100644 --- a/src/kernel/src/common/start.c +++ b/src/kernel/src/common/start.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -6,16 +8,16 @@ #include #include #include -#include extern size_t __DTB_START[]; /// Entrypoint for the C part of the kernel. /// This function is called by the assembly located in [startup.s]. /// The MMU has already been initialized here but only the first MiB of the kernel has been mapped. -void start(uint32_t * p_bootargs, void * dtb) { +void start(uint32_t * p_bootargs, struct DTHeader * dtb) { if (dtb == NULL) { - dtb = __DTB_START; // DTB not passed by bootloader, we are in QEMU. Use Embedded DTB. + dtb = (struct DTHeader *) + __DTB_START; // DTB not passed by bootloader, we are in QEMU. Use Embedded DTB. } // Before this point, all code has to be hardware independent. @@ -26,6 +28,9 @@ void start(uint32_t * p_bootargs, void * dtb) { // Initialize the chipset and enable uart init_chipset(); + dtb_get_property(dtb, "", ""); + + INFO("Detected memory size: 0x%x Bytes", 0x1000000); INFO("Started chipset specific handlers"); From e695e4e7ae5eec297133c65080ce11af9d906ac5 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Tue, 16 Mar 2021 17:10:11 +0100 Subject: [PATCH 10/21] Add first implementation of dtb parser --- src/kernel/src/common/dtb.c | 114 ++++++++++++++++++++++++---- src/kernel/src/common/include/dtb.h | 12 ++- 2 files changed, 110 insertions(+), 16 deletions(-) diff --git a/src/kernel/src/common/dtb.c b/src/kernel/src/common/dtb.c index ef0bd39b..75cf8ec1 100644 --- a/src/kernel/src/common/dtb.c +++ b/src/kernel/src/common/dtb.c @@ -1,22 +1,108 @@ #include +#include + // DTB is in big endian, so it must be converted to little endian -static inline uint32_t fix_endian(uint32_t num){ - char *ptr = (char*)# - int ret; - - ret = ptr[0] << 24; - ret |= ptr[1] << 16; - ret |= ptr[2] << 8; - ret |= ptr[3]; - - return ret; +static inline uint32_t fix_endian(const uint32_t num) { + char * ptr = (char *)# + int ret; + + ret = ptr[0] << 24; + ret |= ptr[1] << 16; + ret |= ptr[2] << 8; + ret |= ptr[3]; + + return ret; +} + +// Aligns the given pointer to 4 bytes. +static inline void * align_pointer(void * pointer) { + return (void *)(((size_t)pointer + 31) & 31); +} + + +// Advances past the begin node and returns name of the node +char * parse_begin_node(void ** curr_address) { + *curr_address += sizeof(uint32_t); + char * string_address = (char *)*curr_address; + *curr_address += strlen((string_address)); + *curr_address = align_pointer(*curr_address); + return string_address; } -void dtb_get_property(struct DTHeader* dtb_h, char* path, char* property){ - if(fix_endian(dtb_h->magic)!=0xd00dfeed){ - FATAL("Wrong dtb header %x", dtb_h->magic); - } +// Counts the number of characters until the next slash +uint32_t get_chars_to_slash(char * string) { + for (uint32_t i = 0;; i++) { + if (string[i] == '/' || string[i] == '\0') return i; + } + return 0; } +// Returns a structure corresponding to the requested property in the DTB +struct DTProp* dtb_get_property(struct DTHeader * dtb_h, char * path, char * property) { + if (fix_endian(dtb_h->magic) != 0xd00dfeed) { FATAL("Wrong dtb header %x", dtb_h->magic); } + uint32_t current_level = 0; + uint32_t next_level = 1; + + void * curr_address = (void *)dtb_h + fix_endian(dtb_h->off_dt_struct); + + while (curr_address < (void *)dtb_h + fix_endian(dtb_h->off_dt_struct) + fix_endian(dtb_h->size_dt_struct)) { + switch (fix_endian(*(uint32_t *)curr_address)) { + case FDT_BEGIN_NODE: { + char * node_name = parse_begin_node(&curr_address); + + if (strlen(path) == 0) { // Properties precede nodes. If we find a property in the + // path where it should be, we are lost. + return NULL; + } + + current_level++; + if (current_level == next_level) { // Avoid looking at nodes which don't match the nesting level we're looking for in the path + uint32_t chars_to_slash = get_chars_to_slash(path); + uint32_t node_name_size = strlen(node_name); + if (strlen(node_name) == 0 || + strncmp( + path, + node_name, + chars_to_slash < node_name_size ? chars_to_slash : node_name_size)) { + next_level++; + path += chars_to_slash; // Advance path past the slash + if (path[0] == '/') path++; + } + } + + break; + } + case FDT_END_NODE: { + curr_address += sizeof(uint32_t); + current_level--; + if (strlen(path) == 0) { return NULL; } // We have exited the path we were looking for + break; + } + case FDT_PROP: + curr_address += sizeof(uint32_t); + struct DTProp* prop = (struct DTProp*)curr_address; + if(strlen(path)==0) { + // We are in the node that we looking for. Time to check if this is the property we were looking for + char* prop_name = (char*)(dtb_h + fix_endian(dtb_h->off_dt_strings) + fix_endian(prop->nameoff)); + if(strcmp(prop_name, property)){ + // Found it! + return prop; + } + } + // Skip over the property data + curr_address += sizeof(struct DTProp) + fix_endian(prop->len); + curr_address = align_pointer(curr_address); + break; + case FDT_NOP: + curr_address += sizeof(uint32_t); + break; + case FDT_END: + return NULL; + break; + } + } + + return NULL; +} diff --git a/src/kernel/src/common/include/dtb.h b/src/kernel/src/common/include/dtb.h index a3cb8cb5..62da4beb 100644 --- a/src/kernel/src/common/include/dtb.h +++ b/src/kernel/src/common/include/dtb.h @@ -1,8 +1,11 @@ +// https://devicetree-specification.readthedocs.io/en/v0.1/flattened-format.html + #ifndef DTB_H -#define PMM_H +#define DTB_H #include #include +#include struct DTHeader { uint32_t magic; @@ -17,6 +20,11 @@ struct DTHeader { uint32_t size_dt_struct; }; +struct DTProp { + uint32_t len; + uint32_t nameoff; +}; + enum StructureToken { FDT_BEGIN_NODE = 0x1, FDT_END_NODE = 0x2, @@ -25,7 +33,7 @@ enum StructureToken { FDT_END = 0x9, }; -void dtb_get_property(struct DTHeader* dtbh, char* path, char* property); +struct DTProp* dtb_get_property(struct DTHeader * dtb_h, char * path, char * property); #endif From 859b505dcbfac5f88f2caa63bf0fb0a80dc0e62e Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Tue, 16 Mar 2021 21:21:34 +0100 Subject: [PATCH 11/21] Fix bugs in dtb parser, now functional --- src/kernel/Makefile | 2 +- src/kernel/linker/kernel.ld | 14 +++++++------- src/kernel/src/common/dtb.c | 12 ++++++------ src/kernel/src/common/start.c | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 7605968c..535354db 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -36,7 +36,7 @@ BOARD = raspi2 ifeq ($(BOARD),raspi2) MEMORY = 1G CPU = cortex-a7 -DTB = $(CURDIR)/dtb/bcm2708-rpi-zero.dtb +DTB = $(CURDIR)/dtb/bcm2708-rpi-zero-dumped.dtb else ifeq ($(BOARD),raspi0) MEMORY = 512M CPU = arm1176 diff --git a/src/kernel/linker/kernel.ld b/src/kernel/linker/kernel.ld index d8a616ae..2cac69b1 100644 --- a/src/kernel/linker/kernel.ld +++ b/src/kernel/linker/kernel.ld @@ -6,22 +6,22 @@ __BOOT_ADDRESS = 0x8000; SECTIONS { . = __BOOT_ADDRESS; + + + __BOOT_START = .; .boot : { */startup.o (.text) */startup.o (.data) - */startup.o (.bss) + */startup.o (.bss) + __DTB_START = .; + */dtb.o (.data) */stacks.o (.text) */memory.o (.text) */memory.o (.data) } __BOOT_END = .; - __DTB_START = .; - .dtb : { - */dtb.o (.data) - } - - __DTB_END = .; + . += __KERNEL_VIRTUAL_OFFSET; diff --git a/src/kernel/src/common/dtb.c b/src/kernel/src/common/dtb.c index 75cf8ec1..21e18eb0 100644 --- a/src/kernel/src/common/dtb.c +++ b/src/kernel/src/common/dtb.c @@ -17,7 +17,7 @@ static inline uint32_t fix_endian(const uint32_t num) { // Aligns the given pointer to 4 bytes. static inline void * align_pointer(void * pointer) { - return (void *)(((size_t)pointer + 31) & 31); + return (void *)(((size_t)pointer + 3) & ~3); } @@ -25,7 +25,7 @@ static inline void * align_pointer(void * pointer) { char * parse_begin_node(void ** curr_address) { *curr_address += sizeof(uint32_t); char * string_address = (char *)*curr_address; - *curr_address += strlen((string_address)); + *curr_address += strlen(string_address)+1; *curr_address = align_pointer(*curr_address); return string_address; } @@ -39,7 +39,7 @@ uint32_t get_chars_to_slash(char * string) { } -// Returns a structure corresponding to the requested property in the DTB +// Performs an allocation-free traversal to find the requested property in the DTB struct DTProp* dtb_get_property(struct DTHeader * dtb_h, char * path, char * property) { if (fix_endian(dtb_h->magic) != 0xd00dfeed) { FATAL("Wrong dtb header %x", dtb_h->magic); } uint32_t current_level = 0; @@ -65,7 +65,7 @@ struct DTProp* dtb_get_property(struct DTHeader * dtb_h, char * path, char * pro strncmp( path, node_name, - chars_to_slash < node_name_size ? chars_to_slash : node_name_size)) { + chars_to_slash < node_name_size ? chars_to_slash : node_name_size)==0) { next_level++; path += chars_to_slash; // Advance path past the slash if (path[0] == '/') path++; @@ -85,8 +85,8 @@ struct DTProp* dtb_get_property(struct DTHeader * dtb_h, char * path, char * pro struct DTProp* prop = (struct DTProp*)curr_address; if(strlen(path)==0) { // We are in the node that we looking for. Time to check if this is the property we were looking for - char* prop_name = (char*)(dtb_h + fix_endian(dtb_h->off_dt_strings) + fix_endian(prop->nameoff)); - if(strcmp(prop_name, property)){ + char* prop_name = (char*)((void*)dtb_h + fix_endian(dtb_h->off_dt_strings) + fix_endian(prop->nameoff)); + if(strcmp(prop_name, property)==0){ // Found it! return prop; } diff --git a/src/kernel/src/common/start.c b/src/kernel/src/common/start.c index 5458ad8a..4538b8e1 100644 --- a/src/kernel/src/common/start.c +++ b/src/kernel/src/common/start.c @@ -28,7 +28,7 @@ void start(uint32_t * p_bootargs, struct DTHeader * dtb) { // Initialize the chipset and enable uart init_chipset(); - dtb_get_property(dtb, "", ""); + struct DTProp* property = dtb_get_property(dtb, "/memory", "reg"); INFO("Detected memory size: 0x%x Bytes", 0x1000000); From 17796270eda217f10baeece972958c8db0f95b34 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Wed, 17 Mar 2021 10:04:28 +0100 Subject: [PATCH 12/21] Add dtb memory detection; Overhaul hardware detection using DTB --- src/kernel/Makefile | 4 +- src/kernel/src/common/dtb.c | 76 ++++++++++++------- src/kernel/src/common/hardwareinfo.c | 42 +++++++--- src/kernel/src/common/include/dtb.h | 16 ++++ src/kernel/src/common/include/hardwareinfo.h | 5 +- src/kernel/src/common/start.c | 20 +++-- .../drivers/chipset/bcm2835/include/bcm2835.h | 8 ++ 7 files changed, 125 insertions(+), 46 deletions(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 535354db..c3f32760 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -36,11 +36,11 @@ BOARD = raspi2 ifeq ($(BOARD),raspi2) MEMORY = 1G CPU = cortex-a7 -DTB = $(CURDIR)/dtb/bcm2708-rpi-zero-dumped.dtb +DTB = $(CURDIR)/dtb/bcm2709-rpi-2-b.dtb else ifeq ($(BOARD),raspi0) MEMORY = 512M CPU = arm1176 -DTB = $(CURDIR)/dtb/bcm2709-rpi-2-b.dtb +DTB = $(CURDIR)/dtb/bcm2708-rpi-zero-dumped.dtb endif diff --git a/src/kernel/src/common/dtb.c b/src/kernel/src/common/dtb.c index 21e18eb0..bce3fe05 100644 --- a/src/kernel/src/common/dtb.c +++ b/src/kernel/src/common/dtb.c @@ -17,7 +17,7 @@ static inline uint32_t fix_endian(const uint32_t num) { // Aligns the given pointer to 4 bytes. static inline void * align_pointer(void * pointer) { - return (void *)(((size_t)pointer + 3) & ~3); + return (void *)(((size_t)pointer + 3) & ~3); } @@ -25,7 +25,7 @@ static inline void * align_pointer(void * pointer) { char * parse_begin_node(void ** curr_address) { *curr_address += sizeof(uint32_t); char * string_address = (char *)*curr_address; - *curr_address += strlen(string_address)+1; + *curr_address += strlen(string_address) + 1; *curr_address = align_pointer(*curr_address); return string_address; } @@ -40,14 +40,15 @@ uint32_t get_chars_to_slash(char * string) { // Performs an allocation-free traversal to find the requested property in the DTB -struct DTProp* dtb_get_property(struct DTHeader * dtb_h, char * path, char * property) { +struct DTProp * dtb_get_property(struct DTHeader * dtb_h, char * path, char * property) { if (fix_endian(dtb_h->magic) != 0xd00dfeed) { FATAL("Wrong dtb header %x", dtb_h->magic); } uint32_t current_level = 0; uint32_t next_level = 1; void * curr_address = (void *)dtb_h + fix_endian(dtb_h->off_dt_struct); - while (curr_address < (void *)dtb_h + fix_endian(dtb_h->off_dt_struct) + fix_endian(dtb_h->size_dt_struct)) { + while (curr_address < + (void *)dtb_h + fix_endian(dtb_h->off_dt_struct) + fix_endian(dtb_h->size_dt_struct)) { switch (fix_endian(*(uint32_t *)curr_address)) { case FDT_BEGIN_NODE: { char * node_name = parse_begin_node(&curr_address); @@ -58,16 +59,17 @@ struct DTProp* dtb_get_property(struct DTHeader * dtb_h, char * path, char * pro } current_level++; - if (current_level == next_level) { // Avoid looking at nodes which don't match the nesting level we're looking for in the path + if (current_level == next_level) { // Avoid looking at nodes which don't match the + // nesting level we're looking for in the path uint32_t chars_to_slash = get_chars_to_slash(path); uint32_t node_name_size = strlen(node_name); if (strlen(node_name) == 0 || - strncmp( - path, - node_name, - chars_to_slash < node_name_size ? chars_to_slash : node_name_size)==0) { + strncmp(path, + node_name, + chars_to_slash < node_name_size ? chars_to_slash + : node_name_size) == 0) { next_level++; - path += chars_to_slash; // Advance path past the slash + path += chars_to_slash; // Advance path past the slash if (path[0] == '/') path++; } } @@ -77,32 +79,54 @@ struct DTProp* dtb_get_property(struct DTHeader * dtb_h, char * path, char * pro case FDT_END_NODE: { curr_address += sizeof(uint32_t); current_level--; - if (strlen(path) == 0) { return NULL; } // We have exited the path we were looking for + if (strlen(path) == 0) { + return NULL; + } // We have exited the path we were looking for break; } case FDT_PROP: - curr_address += sizeof(uint32_t); - struct DTProp* prop = (struct DTProp*)curr_address; - if(strlen(path)==0) { - // We are in the node that we looking for. Time to check if this is the property we were looking for - char* prop_name = (char*)((void*)dtb_h + fix_endian(dtb_h->off_dt_strings) + fix_endian(prop->nameoff)); - if(strcmp(prop_name, property)==0){ - // Found it! - return prop; - } - } - // Skip over the property data - curr_address += sizeof(struct DTProp) + fix_endian(prop->len); - curr_address = align_pointer(curr_address); + curr_address += sizeof(uint32_t); + struct DTProp * prop = (struct DTProp *)curr_address; + if (strlen(path) == 0) { + // We are in the node that we looking for. Time to check if this is the property + // we were looking for + char * prop_name = (char *)((void *)dtb_h + fix_endian(dtb_h->off_dt_strings) + + fix_endian(prop->nameoff)); + if (strcmp(prop_name, property) == 0) { + // Found it! + return prop; + } + } + // Skip over the property data + curr_address += sizeof(struct DTProp) + fix_endian(prop->len); + curr_address = align_pointer(curr_address); break; case FDT_NOP: - curr_address += sizeof(uint32_t); + curr_address += sizeof(uint32_t); break; case FDT_END: - return NULL; + return NULL; break; } } return NULL; } + +// Wraps a property containing 2 uint32's, also fixing the endianness of the elements. +struct DTProp2UInt dtb_wrap_2uint_prop(struct DTHeader * dtb_h, struct DTProp * prop) { + assert(fix_endian(prop->len) == 8); + struct DTProp2UInt wrapped = { + (char *)((void *)dtb_h + fix_endian(dtb_h->off_dt_strings) + fix_endian(prop->nameoff)), + fix_endian(*((uint32_t *)prop + 2)), + fix_endian(*((uint32_t *)prop + 3))}; + return wrapped; +} + +struct DTPropString dtb_wrap_string_prop(struct DTHeader * dtb_h, struct DTProp * prop) { + struct DTPropString wrapped = { + (char *)((void *)dtb_h + fix_endian(dtb_h->off_dt_strings) + fix_endian(prop->nameoff)), + fix_endian(prop->len), + (char *)(prop + 1)}; + return wrapped; +} diff --git a/src/kernel/src/common/hardwareinfo.c b/src/kernel/src/common/hardwareinfo.c index a5cdcfa7..e84c8079 100644 --- a/src/kernel/src/common/hardwareinfo.c +++ b/src/kernel/src/common/hardwareinfo.c @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -7,7 +9,21 @@ static HardwareInfo hardware_info; -BoardType detect_boardtype() { +BoardType detect_boardtype(struct DTHeader * dtb_h) { + struct DTProp * prop = dtb_get_property(dtb_h, "/", "model"); + assert(prop != NULL); + struct DTPropString prop_str = dtb_wrap_string_prop(dtb_h, prop); + + if (strncmp(prop_str.val, "Raspberry Pi 2", strlen("Raspberry Pi 2")) == 0) { + return RaspBerryPiTwo; + } else if (strncmp(prop_str.val, "Raspberry Pi Zero", strlen("Raspberry Pi Zero")) == 0) { + return RaspberryPiZero; + } else { + FATAL("Unknown boardtype"); + } +} + +CpuType detect_cputype() { uint32_t reg; // read system register @@ -17,18 +33,18 @@ BoardType detect_boardtype() { switch (type) { case 0xB76: - return RaspberryPiZero; // bcm2835 + return ARM1176; // bcm2835 case 0xC07: - return RaspBerryPiTwo; // bcm2836 + return CortexA7; // bcm2836 default: - FATAL("Unknown boardtype"); + FATAL("Unknown cputype"); } } // TODO: detect hardware info. // Such as: CPU and RAM size. -void init_hardwareinfo() { - BoardType boardType = detect_boardtype(); +void init_hardwareinfo(struct DTHeader * dtb_h) { + BoardType boardType = detect_boardtype(dtb_h); size_t peripheral_base_address; size_t peripheral_region_size; switch (boardType) { @@ -36,14 +52,17 @@ void init_hardwareinfo() { peripheral_base_address = BCM2836_PERIPHERALS_PHYSICAL_BASE; peripheral_region_size = 21 * Mebibyte; break; + case RaspberryPiZero: + peripheral_base_address = BCM2835_PERIPHERALS_PHYSICAL_BASE; + peripheral_region_size = 18 * Mebibyte; default: FATAL("Peripheral address for board type not implemented"); - } + } hardware_info = (HardwareInfo){ - .cpuType = ARM1176, + .cpuType = detect_cputype(), .boardType = boardType, .peripheral_base_address = peripheral_base_address, - .peripheral_region_size = peripheral_region_size, + .peripheral_region_size = peripheral_region_size, }; } @@ -79,6 +98,7 @@ void print_hardwareinfo() { } bool address_in_reserved_region(size_t address) { - return ((address - KERNEL_VIRTUAL_OFFSET) >= get_hardwareinfo()->peripheral_base_address && - (address - KERNEL_VIRTUAL_OFFSET) < get_hardwareinfo()->peripheral_base_address + get_hardwareinfo()->peripheral_region_size); + return ((address - KERNEL_VIRTUAL_OFFSET) >= get_hardwareinfo()->peripheral_base_address && + (address - KERNEL_VIRTUAL_OFFSET) < get_hardwareinfo()->peripheral_base_address + + get_hardwareinfo()->peripheral_region_size); } diff --git a/src/kernel/src/common/include/dtb.h b/src/kernel/src/common/include/dtb.h index 62da4beb..6783f10b 100644 --- a/src/kernel/src/common/include/dtb.h +++ b/src/kernel/src/common/include/dtb.h @@ -25,6 +25,18 @@ struct DTProp { uint32_t nameoff; }; +struct DTProp2UInt { + char* name; + uint32_t first; + uint32_t second; +}; + +struct DTPropString { + char* name; + uint32_t len; + char* val; +}; + enum StructureToken { FDT_BEGIN_NODE = 0x1, FDT_END_NODE = 0x2, @@ -35,5 +47,9 @@ enum StructureToken { struct DTProp* dtb_get_property(struct DTHeader * dtb_h, char * path, char * property); +struct DTProp2UInt dtb_wrap_2uint_prop(struct DTHeader* dtb_h,struct DTProp* prop); + +struct DTPropString dtb_wrap_string_prop(struct DTHeader* dtb_h,struct DTProp* prop); + #endif diff --git a/src/kernel/src/common/include/hardwareinfo.h b/src/kernel/src/common/include/hardwareinfo.h index ef6243b3..000489bc 100644 --- a/src/kernel/src/common/include/hardwareinfo.h +++ b/src/kernel/src/common/include/hardwareinfo.h @@ -3,6 +3,7 @@ #include #include +#include typedef enum CpuType { ARM1176, CortexA7 } CpuType; @@ -19,13 +20,13 @@ typedef struct HardwareInfo { // Initialize the global hardware info struct. After this is ran, the get_hardwareinfo // function can be used to retrieve it. -void init_hardwareinfo(); +void init_hardwareinfo(struct DTHeader* dtb_h); // Get a pointer to the hardwareinfo struct. This is a global struct containing information // about the cpu type, and board/chipset type. May be expanded to contain more useful info. HardwareInfo * get_hardwareinfo(); void print_hardwareinfo(); -BoardType detect_boardtype(); +BoardType detect_boardtype(struct DTHeader* dtb_h); // Checks whether given address is in area occupied by MMIO bool address_in_reserved_region(size_t address); diff --git a/src/kernel/src/common/start.c b/src/kernel/src/common/start.c index 4538b8e1..458a07e7 100644 --- a/src/kernel/src/common/start.c +++ b/src/kernel/src/common/start.c @@ -23,20 +23,30 @@ void start(uint32_t * p_bootargs, struct DTHeader * dtb) { // Before this point, all code has to be hardware independent. // After this point, code can request the hardware info struct to find out what // Code should be ran. - init_hardwareinfo(); + init_hardwareinfo(dtb); // Initialize the chipset and enable uart init_chipset(); - struct DTProp* property = dtb_get_property(dtb, "/memory", "reg"); + struct DTProp * mem_prop = dtb_get_property(dtb, "/memory", "reg"); + assert(mem_prop != NULL); // Failed to find memory node in the DTB + struct DTProp2UInt memory_prop = dtb_wrap_2uint_prop( + dtb, mem_prop); // First element is address and second element is size of available memory + assert(memory_prop.first == 0); // There can be multiple memory declarations in the DTB, but + // we're assuming there's only 1, and it starts at address 0 - INFO("Detected memory size: 0x%x Bytes", 0x1000000); + if (memory_prop.second == 0) { + memory_prop.second = Gibibyte; + INFO("DTB reports 0 RAM, setting size to 1 GB"); + } + + + INFO("Detected memory size: 0x%x Bytes", memory_prop.second); INFO("Started chipset specific handlers"); // just cosmetic (and for debugging) print_hardwareinfo(); - detect_boardtype(); // start proper virtual and physical memory management. // Even though we already enabled the mmu in startup.s to @@ -44,7 +54,7 @@ void start(uint32_t * p_bootargs, struct DTHeader * dtb) { // was temporary and has to be replaced here. // This will actually map the whole kernel in memory and initialize the physicalMemoryManager. INFO("Initializing the physical and virtual memory managers."); - vm2_start(0x1000000); + vm2_start(memory_prop.second); INFO("Setting up interrupt vector tables"); // Set up the exception handlers. diff --git a/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h b/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h index 7400b920..11c21df7 100644 --- a/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h +++ b/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h @@ -2,3 +2,11 @@ // We want to have bcm2835 for being able to boot on an actual Pi Zero/B+ // TODO: new pis (raspberry pi zero w) may have an entirely different chipset again (not bcm2835 or 36). // to boot it another implementation must exist. + +#ifndef BCM2835_H +#define BCM2835_H + + +#define BCM2835_PERIPHERALS_PHYSICAL_BASE 0x3F000000 + +#endif From 5b2322c8b39c004970b1fc124da4e439d0a940dc Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Sat, 20 Mar 2021 10:26:32 +0100 Subject: [PATCH 13/21] Add first implementation BCM2835 support --- src/kernel/src/common/hardwareinfo.c | 1 + .../src/drivers/chipset/bcm2835/bcm2835.c | 31 +++ .../drivers/chipset/bcm2835/include/bcm2835.h | 33 +++- .../drivers/chipset/bcm2835/include/timer.h | 43 ++++ .../drivers/chipset/bcm2835/include/uart.h | 10 + .../src/drivers/chipset/bcm2835/timer.c | 183 ++++++++++++++++++ src/kernel/src/drivers/chipset/bcm2835/uart.c | 30 +++ .../src/drivers/chipset/bcm2836/bcm2836.c | 4 +- .../drivers/chipset/bcm2836/include/uart.h | 35 +--- .../drivers/chipset/bcm2836/test/timer_test.c | 2 +- .../src/drivers/chipset/bcm2836/timer.c | 2 +- src/kernel/src/drivers/chipset/bcm2836/uart.c | 70 +------ src/kernel/src/drivers/chipset/chipset.c | 5 + src/kernel/src/drivers/uart/include/pl011.h | 41 ++++ src/kernel/src/drivers/uart/pl011.c | 84 ++++++++ 15 files changed, 466 insertions(+), 108 deletions(-) create mode 100644 src/kernel/src/drivers/chipset/bcm2835/include/timer.h create mode 100644 src/kernel/src/drivers/chipset/bcm2835/include/uart.h create mode 100644 src/kernel/src/drivers/chipset/bcm2835/timer.c create mode 100644 src/kernel/src/drivers/chipset/bcm2835/uart.c create mode 100644 src/kernel/src/drivers/uart/include/pl011.h create mode 100644 src/kernel/src/drivers/uart/pl011.c diff --git a/src/kernel/src/common/hardwareinfo.c b/src/kernel/src/common/hardwareinfo.c index 63d354db..dc1db184 100644 --- a/src/kernel/src/common/hardwareinfo.c +++ b/src/kernel/src/common/hardwareinfo.c @@ -57,6 +57,7 @@ void init_hardwareinfo(struct DTHeader * dtb_h) { case RaspberryPiZero: peripheral_base_address = BCM2835_PERIPHERALS_PHYSICAL_BASE; peripheral_region_size = 18 * Mebibyte; + break; default: FATAL("Peripheral address for board type not implemented"); } diff --git a/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c b/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c index 0c353e4f..9c6ad918 100644 --- a/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c +++ b/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c @@ -1 +1,32 @@ #include +#include +#include + +#include "timer.h" +#include "uart.h" + +volatile UartDevice bcm2835_uart; + +void bcm2835_irq_handler() {} + +void bcm2835_fiq_handler() {} + +void bcm2835_init() { + chipset.schedule_timer_periodic = &bcm2835_schedule_timer_periodic; + chipset.schedule_timer_once = &bcm2835_schedule_timer_once; + chipset.deschedule_timer = &bcm2835_deschedule_timer; + chipset.handle_irq = &bcm2835_irq_handler; + chipset.handle_fiq = &bcm2835_fiq_handler; + chipset.late_init = &bcm2835_late_init; + chipset.uart = &bcm2835_uart; + + bcm2835_peripheral_base = vm2_map_peripheral(BCM2835_PERIPHERALS_PHYSICAL_BASE, 16); + bcm2835_int_registers_base = (BCM2835InterruptRegisters *)(bcm2835_peripheral_base + 0xB000); + bcm2835_timer_registers_base = (BCM2835SystemTimerRegisters *)(bcm2835_peripheral_base + 0x3000); + + bcm2835_uart_init(&bcm2835_uart); +} + +void bcm2835_late_init() { + bcm2835_timer_init(); +} diff --git a/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h b/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h index 11c21df7..003461f6 100644 --- a/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h +++ b/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h @@ -1,12 +1,35 @@ -// TODO: Implement. -// We want to have bcm2835 for being able to boot on an actual Pi Zero/B+ -// TODO: new pis (raspberry pi zero w) may have an entirely different chipset again (not bcm2835 or 36). -// to boot it another implementation must exist. +// https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/BCM2835-ARM-Peripherals.pdf #ifndef BCM2835_H #define BCM2835_H +#include -#define BCM2835_PERIPHERALS_PHYSICAL_BASE 0x3F000000 +#define BCM2835_PERIPHERALS_PHYSICAL_BASE 0x20000000 + +// 0x7E00B200 +typedef struct BCM2835InterruptRegisters { + uint32_t IRQBasicPending; + uint32_t IRQPending1; + uint32_t IRQPending2; + uint32_t FIQControl; + uint32_t EnableIRQ1; + uint32_t EnableIRQ2; + uint32_t EnableBasicIRQ; + uint32_t DisableIRQ1; + uint32_t DisableIRQ2; + uint32_t DisableBasicIRQ; +} BCM2835InterruptRegisters; +enum BasicInterruptSource { + TIMER_IRQ = (1<<0), +}; + +void bcm2835_init(); +void bcm2835_late_init(); + +__attribute__((__common__)) size_t bcm2835_peripheral_base; +__attribute__((__common__)) volatile struct BCM2835InterruptRegisters * bcm2835_int_registers_base; #endif + + diff --git a/src/kernel/src/drivers/chipset/bcm2835/include/timer.h b/src/kernel/src/drivers/chipset/bcm2835/include/timer.h new file mode 100644 index 00000000..ee8563bf --- /dev/null +++ b/src/kernel/src/drivers/chipset/bcm2835/include/timer.h @@ -0,0 +1,43 @@ +#ifndef TIMER_BCM2835_H +#define TIMER_BCM2835_H + +#include +#include +#define SYSTEM_TIMER_FREQ 1000000 + +/* + * System Timer driver for BCM2835 + */ + +typedef struct BCM2835SystemTimerRegisters { + + uint32_t ControlStatus; + uint32_t CounterLower; + uint32_t CounterHigher; + uint32_t Compare0; + uint32_t Compare1; + uint32_t Compare2; + uint32_t Compare3; + +} BCM2835SystemTimerRegisters; + +enum ControlStatus { + Match3 = 0x1 << 16, + Match2 = 0x1 << 12, + Match1 = 0x1 << 8, + Match0 = 0x1 << 4, +}; + +void bcm2835_timer_init(); + +void bcm2835_timer_handle_interrupt(); + +TimerHandle bcm2835_schedule_timer_once(TimerCallback callback, uint32_t delay_ms); + +TimerHandle bcm2835_schedule_timer_periodic(TimerCallback callback, uint32_t delay_ms); + +void bcm2835_deschedule_timer(TimerHandle handle); + +__attribute__((__common__)) volatile struct BCM2835SystemTimerRegisters * bcm2835_timer_registers_base; + +#endif diff --git a/src/kernel/src/drivers/chipset/bcm2835/include/uart.h b/src/kernel/src/drivers/chipset/bcm2835/include/uart.h new file mode 100644 index 00000000..5b033957 --- /dev/null +++ b/src/kernel/src/drivers/chipset/bcm2835/include/uart.h @@ -0,0 +1,10 @@ +#ifndef UART_BCM2835_H +#define UART_BCM2835_H + +// Generic UART +#include "../../include/uart.h" + + +void bcm2835_uart_init(volatile UartDevice *device); + +#endif diff --git a/src/kernel/src/drivers/chipset/bcm2835/timer.c b/src/kernel/src/drivers/chipset/bcm2835/timer.c new file mode 100644 index 00000000..e48c50f6 --- /dev/null +++ b/src/kernel/src/drivers/chipset/bcm2835/timer.c @@ -0,0 +1,183 @@ +#include "timer.h" + +#include +#include +#include +#include +#include +#include + +typedef struct ScheduledTimer { + uint64_t scheduled_count; + TimerHandle handle; + TimerCallback callback; + uint32_t periodic_delay; +} ScheduledTimer; + +typedef union LittleEndianUint64 { + uint64_t dword; + struct { + uint32_t low_word; + uint32_t high_word; + }; +} LittleEndianUint64; + +// Internal implementation functions +static uint32_t get_frequency(); +static void mask_and_enable_timer(); +static uint64_t get_phy_count(); +static void set_phy_timer_cmp_val(uint32_t); +static ScheduledTimer * get_prq_node_data(prq_node *); +static TimerHandle schedule_timer(TimerCallback, uint32_t, bool); + +static prq_handle * scheduled_timers; + +/* + * Gives the frequency of the counter in Hz + */ +static inline uint32_t get_frequency() { + return SYSTEM_TIMER_FREQ; +} + + +static inline void mask_and_enable_timer() { + // Set compare value to 0 + bcm2835_timer_registers_base->Compare0 = 0; +} + +static inline uint64_t get_phy_count() { + return bcm2835_timer_registers_base->Compare0; +} + + + +static inline void set_phy_timer_cmp_val(uint32_t val) { + bcm2835_timer_registers_base->Compare0=val; +} + +static inline ScheduledTimer * get_prq_node_data(prq_node * node) { + return (ScheduledTimer *)node->data; +} + +void bcm2835_timer_init() { + const uint32_t freq = SYSTEM_TIMER_FREQ; + INFO("System counter frequency: %u kHz\n", freq / 1000); + + bcm2835_int_registers_base->DisableBasicIRQ = TIMER_IRQ; + + + // Init priority queue + scheduled_timers = prq_create(); + + + bcm2835_int_registers_base->EnableBasicIRQ = TIMER_IRQ; +} + +void bcm2835_timer_handle_interrupt() { + volatile const uint64_t current_count = get_phy_count(); + + // Begin of critical section, disable timer interrupts + bcm2835_int_registers_base->DisableBasicIRQ = TIMER_IRQ; + + // Process all timers that are not in the future, if any + prq_node * next_timer_node = prq_peek(scheduled_timers); + while (next_timer_node != NULL && + get_prq_node_data(next_timer_node)->scheduled_count <= current_count) { + prq_dequeue(scheduled_timers); + ScheduledTimer * const next_timer = get_prq_node_data(next_timer_node); + + next_timer->callback(); + + // If the timer is not periodic, it is removed + if (next_timer->periodic_delay == 0) { + kfree(next_timer); + prq_free_node(next_timer_node); + } + // If the timer is periodic, it is updated and added to the queue again + else { + // TODO: Avoid duplicating code in `schedule_timer` + const uint64_t scheduled_count = next_timer->scheduled_count; + next_timer->scheduled_count = scheduled_count + next_timer->periodic_delay; + assert(scheduled_count <= INT32_MAX); + next_timer_node->priority = scheduled_count; + + prq_enqueue(scheduled_timers, next_timer_node); + } + + next_timer_node = prq_peek(scheduled_timers); + } + + // If there are no more scheduled timers in queue, mask interrupts until one is added again + if (next_timer_node == NULL) { + mask_and_enable_timer(); + } + // If there still are, set compare val to next one + else { + set_phy_timer_cmp_val(get_prq_node_data(next_timer_node)->scheduled_count); + } + + // End of critical section, re-enable timer interrupts + bcm2835_int_registers_base->EnableBasicIRQ= TIMER_IRQ; +} + +static TimerHandle schedule_timer(TimerCallback callback, uint32_t delay_ms, bool periodic) { + assert(callback != NULL); + assert(delay_ms > 0); + + const uint64_t count_offset = (get_frequency() / 1000) * delay_ms; + volatile const uint64_t scheduled_count = get_phy_count() + count_offset; + + ScheduledTimer * const new_timer = kmalloc(sizeof(ScheduledTimer)); + prq_node * const new_timer_node = prq_create_node(); + + new_timer->scheduled_count = scheduled_count; + new_timer->callback = callback; + assert(sizeof(TimerHandle) >= sizeof(prq_node *)); + new_timer->handle = (TimerHandle)new_timer_node; + // 0 means the timer is not periodic + new_timer->periodic_delay = periodic ? count_offset : 0; + // TODO: Find better way of doing this + assert(scheduled_count <= INT32_MAX); + new_timer_node->priority = scheduled_count; + new_timer_node->data = new_timer; + + // Begin of critical section, disable timer interrupts + bcm2835_int_registers_base->DisableBasicIRQ = TIMER_IRQ; + + prq_enqueue(scheduled_timers, new_timer_node); + + set_phy_timer_cmp_val(get_prq_node_data(prq_peek(scheduled_timers))->scheduled_count); + + + // End of critical section, re-enable timer interrupts + bcm2835_int_registers_base->EnableBasicIRQ = TIMER_IRQ; + + return new_timer->handle; +} + +TimerHandle bcm2835_schedule_timer_once(TimerCallback callback, uint32_t delay_ms) { + return schedule_timer(callback, delay_ms, false); +} + +TimerHandle bcm2835_schedule_timer_periodic(TimerCallback callback, uint32_t delay_ms) { + return schedule_timer(callback, delay_ms, true); +} + +void bcm2835_deschedule_timer(TimerHandle handle) { + assert(sizeof(prq_node *) >= sizeof(TimerHandle)); + prq_node * const timer_node = (prq_node *)handle; + + prq_remove(scheduled_timers, timer_node); + kfree(get_prq_node_data(timer_node)); + prq_free_node(timer_node); + + prq_node * const next_timer_node = prq_peek(scheduled_timers); + // If there are no more scheduled timers in queue, mask interrupts until one is added again + if (next_timer_node == NULL) { + mask_and_enable_timer(); + } + // If there still are, set compare val to next one + else { + set_phy_timer_cmp_val(get_prq_node_data(next_timer_node)->scheduled_count); + } +} diff --git a/src/kernel/src/drivers/chipset/bcm2835/uart.c b/src/kernel/src/drivers/chipset/bcm2835/uart.c new file mode 100644 index 00000000..a25711a3 --- /dev/null +++ b/src/kernel/src/drivers/chipset/bcm2835/uart.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include "uart.h" +#include + +static UartInterface * BCM2835_UART0_ADDRESS; +static UartInterface * BCM2835_UART1_ADDRESS; +static UartInterface * BCM2835_UART2_ADDRESS; +static UartInterface * BCM2835_UART3_ADDRESS; + +void bcm2835_uart_init(volatile UartDevice *device) { + BCM2835_UART0_ADDRESS = (UartInterface *)(bcm2835_peripheral_base + 0x201000); + BCM2835_UART1_ADDRESS = (UartInterface *)(bcm2835_peripheral_base + 0x202000); + BCM2835_UART2_ADDRESS = (UartInterface *)(bcm2835_peripheral_base + 0x203000); + BCM2835_UART3_ADDRESS = (UartInterface *)(bcm2835_peripheral_base + 0x204000); + + device->length = 4; + device->devices[0] = BCM2835_UART0_ADDRESS; + device->devices[1] = BCM2835_UART1_ADDRESS; + device->devices[2] = BCM2835_UART2_ADDRESS; + device->devices[3] = BCM2835_UART3_ADDRESS; + + device->getc = pl011_uart_getc; + device->putc = pl011_uart_putc; + device->on_message = pl011_uart_on_message; + + +} diff --git a/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c b/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c index 83c5dfda..712f44e4 100644 --- a/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c +++ b/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c @@ -1,8 +1,8 @@ // https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf #include #include -#include -#include "uart.h" +#include "./include/timer.h" +#include "./include/uart.h" #include volatile UartDevice bcm2836_uart; diff --git a/src/kernel/src/drivers/chipset/bcm2836/include/uart.h b/src/kernel/src/drivers/chipset/bcm2836/include/uart.h index b7e9feb6..bdd45177 100644 --- a/src/kernel/src/drivers/chipset/bcm2836/include/uart.h +++ b/src/kernel/src/drivers/chipset/bcm2836/include/uart.h @@ -2,42 +2,9 @@ #define UART_BCM2836_H // Generic UART -#include "../include/uart.h" -#include +#include "../../include/uart.h" -// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf -// Section 3.2: Summary of registers -// https://balau82.wordpress.com/2010/11/30/emulating-arm-pl011-serial-ports/ -// This struct is memory mapped. I call them registers but they all live in memory. -struct UartInterface { - uint32_t DR; // Data Register - uint32_t RSR_ECR; // Receive Status Register / Error Clear Register - uint8_t reserved1[0x10]; // Reserved - const uint32_t FR; // Flag Register - uint8_t reserved2[0x4]; // Reserved - uint32_t LPR; // IrDA low power counter Register - uint32_t IBRD; // Integer Baud Rate Register - uint32_t FBRD; // Fractional Baud Rate Register - uint32_t LCR_H; // Line Control Register - uint32_t CR; // Control Register - uint32_t IFLS; // Interrupt FIFO Level Select Register - uint32_t IMSC; // Interrupt Mask Set/Clear Register - const uint32_t RIS; // Raw Interrupt Status Register - const uint32_t MIS; // Masked Interrupt Status Register - uint32_t ICR; // Interrupt Clear Register - uint32_t DMACR; // DMA Control Register -}; void bcm2836_uart_init(volatile UartDevice *device); -void uart_write_byte(volatile UartInterface *interface, volatile uint8_t value); -uint8_t uart_get_byte(volatile UartInterface *device); - -void bcm2836_uart_putc(volatile UartDevice *device, char c, int uartchannel); -char bcm2836_uart_getc(volatile UartDevice *device, int uartchannel); - -void bcm2836_uart_on_message(volatile UartDevice *device, UartCallback callback, - int uartchannel); - - #endif diff --git a/src/kernel/src/drivers/chipset/bcm2836/test/timer_test.c b/src/kernel/src/drivers/chipset/bcm2836/test/timer_test.c index 037cee92..15cfb9aa 100644 --- a/src/kernel/src/drivers/chipset/bcm2836/test/timer_test.c +++ b/src/kernel/src/drivers/chipset/bcm2836/test/timer_test.c @@ -1,4 +1,4 @@ -#include +#include "../include/timer.h" #include static int callback_count_1; diff --git a/src/kernel/src/drivers/chipset/bcm2836/timer.c b/src/kernel/src/drivers/chipset/bcm2836/timer.c index 9e641865..7f32c102 100644 --- a/src/kernel/src/drivers/chipset/bcm2836/timer.c +++ b/src/kernel/src/drivers/chipset/bcm2836/timer.c @@ -1,4 +1,4 @@ -#include +#include "./include/timer.h" #include #include #include diff --git a/src/kernel/src/drivers/chipset/bcm2836/uart.c b/src/kernel/src/drivers/chipset/bcm2836/uart.c index 67f8ee5d..f09e9b7b 100644 --- a/src/kernel/src/drivers/chipset/bcm2836/uart.c +++ b/src/kernel/src/drivers/chipset/bcm2836/uart.c @@ -2,7 +2,8 @@ #include #include #include -#include +#include "uart.h" +#include /* // raspberry pi zero, 1, b+ etc @@ -20,37 +21,6 @@ volatile UartInterface * const UART1_ADDRESS = (volatile UartInterface *)0x101f2 volatile UartInterface * const UART2_ADDRESS = (volatile UartInterface *)0x101f3000; */ - -// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf -// uart flag register masks -// (FR) -#define RI (1 << 8) // Ring Indicator -#define TXFE (1 << 7) // Transmit fifo empty -#define RXFF (1 << 6) // Receive fifo full -#define TXFF (1 << 5) // Transmit fifo full -#define RXFE (1 << 4) // Receive fifo empty -#define BUSY (1 << 3) // UART busy, set while uart is sending something -#define DCD (1 << 2) // Data carrier detect -#define DSR (1 << 1) // Data set ready -#define CTS (1 << 0) // Clear to send - -// Uart interrupt masks. When a mask is set, this action causes an interrupt -// (IMSC) -#define OEIM (1 << 10) // Overrun error -#define BEIM (1 << 9) // Break error -#define PEIM (1 << 8) // Parity error -#define FEIM (1 << 7) // Framing error -#define RTIM (1 << 6) // Receive timeout -#define TXIM (1 << 5) // Transmit -#define RXIM (1 << 4) // Receive -#define DSRMIM (1 << 3) // nUARTDSR Modem -#define DCDMIM (1 << 2) // nUARTDCD Modem -#define CTCMIM (1 << 1) // nUARTCTS Modem -#define RIMIM (1 << 0) // nUARTRI Modem - -// (CR) -//#define CTSEn () // CTS Hardware Control Enable - static UartInterface * BCM2836_UART0_ADDRESS; static UartInterface * BCM2836_UART1_ADDRESS; static UartInterface * BCM2836_UART2_ADDRESS; @@ -68,39 +38,9 @@ void bcm2836_uart_init(volatile UartDevice *device) { device->devices[2] = BCM2836_UART2_ADDRESS; device->devices[3] = BCM2836_UART3_ADDRESS; - device->getc = bcm2836_uart_getc; - device->putc = bcm2836_uart_putc; - device->on_message = bcm2836_uart_on_message; + device->getc = pl011_uart_getc; + device->putc = pl011_uart_putc; + device->on_message = pl011_uart_on_message; } - -void uart_write_byte(volatile UartInterface * interface, - volatile uint8_t value) { - // while (interface->FR & TXFF ) { - // asm volatile ("nop"); - // } - while (interface->FR & (1 << 5)) - ; - - interface->DR = (uint32_t)value; -} - - -uint8_t uart_get_byte(volatile UartInterface *interface) { - while (interface->FR & (1 << 4)) - ; - return interface->DR; -} - -char bcm2836_uart_getc(volatile UartDevice *device, int uartchannel) { - return uart_get_byte(device->devices[uartchannel]); -} - -void bcm2836_uart_putc(volatile UartDevice *device, char c, int uartchannel) { - uart_write_byte(device->devices[uartchannel], c); -} - -void bcm2836_uart_on_message(volatile UartDevice *device, - UartCallback callback, - int uartchannel) {} diff --git a/src/kernel/src/drivers/chipset/chipset.c b/src/kernel/src/drivers/chipset/chipset.c index 1383058c..f651b8e5 100644 --- a/src/kernel/src/drivers/chipset/chipset.c +++ b/src/kernel/src/drivers/chipset/chipset.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -24,6 +25,10 @@ void init_chipset() { case RaspBerryPiTwo: bcm2836_init(); break; + + case RaspberryPiZero: + bcm2835_init(); + break; default: { FATAL("Board type not supported for interrupts \n"); } diff --git a/src/kernel/src/drivers/uart/include/pl011.h b/src/kernel/src/drivers/uart/include/pl011.h new file mode 100644 index 00000000..0f9847cf --- /dev/null +++ b/src/kernel/src/drivers/uart/include/pl011.h @@ -0,0 +1,41 @@ +#ifndef PL011_H +#define PL011_H + +// Generic UART +#include "../../chipset/include/uart.h" +#include + +// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf +// Section 3.2: Summary of registers +// https://balau82.wordpress.com/2010/11/30/emulating-arm-pl011-serial-ports/ +// This struct is memory mapped. I call them registers but they all live in memory. +struct UartInterface { + uint32_t DR; // Data Register + uint32_t RSR_ECR; // Receive Status Register / Error Clear Register + uint8_t reserved1[0x10]; // Reserved + const uint32_t FR; // Flag Register + uint8_t reserved2[0x4]; // Reserved + uint32_t LPR; // IrDA low power counter Register + uint32_t IBRD; // Integer Baud Rate Register + uint32_t FBRD; // Fractional Baud Rate Register + uint32_t LCR_H; // Line Control Register + uint32_t CR; // Control Register + uint32_t IFLS; // Interrupt FIFO Level Select Register + uint32_t IMSC; // Interrupt Mask Set/Clear Register + const uint32_t RIS; // Raw Interrupt Status Register + const uint32_t MIS; // Masked Interrupt Status Register + uint32_t ICR; // Interrupt Clear Register + uint32_t DMACR; // DMA Control Register +}; + +void pl011_write_byte(volatile UartInterface *interface, volatile uint8_t value); +uint8_t pl011_get_byte(volatile UartInterface *device); + +void pl011_uart_putc(volatile UartDevice *device, char c, int uartchannel); +char pl011_uart_getc(volatile UartDevice *device, int uartchannel); + +void pl011_uart_on_message(volatile UartDevice *device, UartCallback callback, + int uartchannel); + + +#endif diff --git a/src/kernel/src/drivers/uart/pl011.c b/src/kernel/src/drivers/uart/pl011.c new file mode 100644 index 00000000..0c150356 --- /dev/null +++ b/src/kernel/src/drivers/uart/pl011.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include + +/* +// raspberry pi zero, 1, b+ etc +volatile UartInterface * const UART0_ADDRESS = (volatile UartInterface *)0x20201000; +volatile UartInterface * const UART1_ADDRESS = (volatile UartInterface *)0x20202000; +volatile UartInterface * const UART2_ADDRESS = (volatile UartInterface *)0x20203000; + +// raspberry pi 4: +volatile UartInterface * const UART0_ADDRESS = (volatile UartInterface *)0xfe201000; +volatile UartInterface * const UART1_ADDRESS = (volatile UartInterface *)0xfe202000; +volatile UartInterface * const UART2_ADDRESS = (volatile UartInterface *)0xfe203000; + VersatilePB +volatile UartInterface * const UART0_ADDRESS = (volatile UartInterface *)0x101f1000; +volatile UartInterface * const UART1_ADDRESS = (volatile UartInterface *)0x101f2000; +volatile UartInterface * const UART2_ADDRESS = (volatile UartInterface *)0x101f3000; +*/ + + +// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf +// uart flag register masks +// (FR) +#define RI (1 << 8) // Ring Indicator +#define TXFE (1 << 7) // Transmit fifo empty +#define RXFF (1 << 6) // Receive fifo full +#define TXFF (1 << 5) // Transmit fifo full +#define RXFE (1 << 4) // Receive fifo empty +#define BUSY (1 << 3) // UART busy, set while uart is sending something +#define DCD (1 << 2) // Data carrier detect +#define DSR (1 << 1) // Data set ready +#define CTS (1 << 0) // Clear to send + +// Uart interrupt masks. When a mask is set, this action causes an interrupt +// (IMSC) +#define OEIM (1 << 10) // Overrun error +#define BEIM (1 << 9) // Break error +#define PEIM (1 << 8) // Parity error +#define FEIM (1 << 7) // Framing error +#define RTIM (1 << 6) // Receive timeout +#define TXIM (1 << 5) // Transmit +#define RXIM (1 << 4) // Receive +#define DSRMIM (1 << 3) // nUARTDSR Modem +#define DCDMIM (1 << 2) // nUARTDCD Modem +#define CTCMIM (1 << 1) // nUARTCTS Modem +#define RIMIM (1 << 0) // nUARTRI Modem + +// (CR) +//#define CTSEn () // CTS Hardware Control Enable + + + + +void pl011_uart_write_byte(volatile UartInterface * interface, + volatile uint8_t value) { + // while (interface->FR & TXFF ) { + // asm volatile ("nop"); + // } + while (interface->FR & (1 << 5)) + ; + + interface->DR = (uint32_t)value; +} + + +uint8_t pl011_uart_get_byte(volatile UartInterface *interface) { + while (interface->FR & (1 << 4)) + ; + return interface->DR; +} + +char pl011_uart_getc(volatile UartDevice *device, int uartchannel) { + return pl011_uart_get_byte(device->devices[uartchannel]); +} + +void pl011_uart_putc(volatile UartDevice *device, char c, int uartchannel) { + return pl011_uart_write_byte(device->devices[uartchannel], c); +} + +void pl011_uart_on_message(volatile UartDevice *device, + UartCallback callback, + int uartchannel) {} From b88563df89da637d6e3ed9ee9d0c1eed2578f884 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Sat, 20 Mar 2021 10:33:03 +0100 Subject: [PATCH 14/21] Fix wrong address used for interrupt registers --- src/kernel/src/drivers/chipset/bcm2835/bcm2835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c b/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c index 9c6ad918..8d4b1f6a 100644 --- a/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c +++ b/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c @@ -21,7 +21,7 @@ void bcm2835_init() { chipset.uart = &bcm2835_uart; bcm2835_peripheral_base = vm2_map_peripheral(BCM2835_PERIPHERALS_PHYSICAL_BASE, 16); - bcm2835_int_registers_base = (BCM2835InterruptRegisters *)(bcm2835_peripheral_base + 0xB000); + bcm2835_int_registers_base = (BCM2835InterruptRegisters *)(bcm2835_peripheral_base + 0xB200); bcm2835_timer_registers_base = (BCM2835SystemTimerRegisters *)(bcm2835_peripheral_base + 0x3000); bcm2835_uart_init(&bcm2835_uart); From 2c6c6cc75fe351501ed8a33ef9c991d69830a3d7 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Sat, 20 Mar 2021 10:36:37 +0100 Subject: [PATCH 15/21] Refactor timer test to use chipset functions --- .../drivers/chipset/bcm2836/test/timer_test.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/kernel/src/drivers/chipset/bcm2836/test/timer_test.c b/src/kernel/src/drivers/chipset/bcm2836/test/timer_test.c index 15cfb9aa..00bd99e7 100644 --- a/src/kernel/src/drivers/chipset/bcm2836/test/timer_test.c +++ b/src/kernel/src/drivers/chipset/bcm2836/test/timer_test.c @@ -15,7 +15,7 @@ static void test_callback_2() { TEST_CREATE(test_timer_cb_called, { callback_count_1 = 0; - bcm2836_schedule_timer_once(test_callback_1, 50); + chipset.schedule_timer_once(test_callback_1, 50); DEBUG("If the test gets stuck here, the timer callback was never called"); while (callback_count_1 != 1); }) @@ -23,26 +23,26 @@ TEST_CREATE(test_timer_cb_called, { TEST_CREATE(test_timer_cancel, { callback_count_1 = 0; - TimerHandle const handle = bcm2836_schedule_timer_once(test_callback_1, 50); - bcm2836_deschedule_timer(handle); + TimerHandle const handle = chipset.schedule_timer_once(test_callback_1, 50); + chipset.deschedule_timer(handle); ASSERT_EQ(callback_count_1, 0); }) TEST_CREATE(test_timer_periodic_cb_called, { callback_count_1 = 0; - TimerHandle const handle = bcm2836_schedule_timer_periodic(test_callback_1, 50); - DEBUG("If the test gets stuck here, the timer callback was not called the required number of times"); + TimerHandle const handle = chipset.schedule_timer_periodic(test_callback_1, 50); + DEBUG("If the test gets stuck here, the timer callback was not called the requirxed number of times"); while (callback_count_1 != 10); - bcm2836_deschedule_timer(handle); + chipset.deschedule_timer(handle); }) TEST_CREATE(test_timer_order, { callback_count_1 = 0; callback_count_2 = 0; - bcm2836_schedule_timer_once(test_callback_1, 50); - bcm2836_schedule_timer_once(test_callback_2, 100); + chipset.schedule_timer_once(test_callback_1, 50); + chipset.schedule_timer_once(test_callback_2, 100); DEBUG("If the test gets stuck here, one of the timer callbacks was never called"); while (callback_count_1 != 1); ASSERT_EQ(callback_count_2, 0); From 4f96a82a8dafdc7ee2bd8ecc4f87b98c7411de3f Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Sat, 20 Mar 2021 22:06:37 +0100 Subject: [PATCH 16/21] Fix system timer implementation; Fix failing test on raspi0 --- .../src/drivers/chipset/bcm2835/bcm2835.c | 9 ++++++- .../drivers/chipset/bcm2835/include/bcm2835.h | 6 +++-- .../drivers/chipset/bcm2835/include/timer.h | 8 +++--- .../src/drivers/chipset/bcm2835/timer.c | 25 +++++++++++-------- .../src/drivers/chipset/bcm2836/bcm2836.c | 1 - src/kernel/src/vm/test/test_pagealloc2.c | 12 ++++++--- 6 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c b/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c index 8d4b1f6a..05bcf131 100644 --- a/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c +++ b/src/kernel/src/drivers/chipset/bcm2835/bcm2835.c @@ -7,7 +7,14 @@ volatile UartDevice bcm2835_uart; -void bcm2835_irq_handler() {} +void bcm2835_irq_handler() { + volatile const uint32_t pending = bcm2835_timer_registers_base->ControlStatus; + + if(pending&Match1){ + bcm2835_timer_registers_base->ControlStatus |= Match1; + bcm2835_timer_handle_interrupt(); + } +} void bcm2835_fiq_handler() {} diff --git a/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h b/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h index 003461f6..3ba9e899 100644 --- a/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h +++ b/src/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h @@ -20,10 +20,12 @@ typedef struct BCM2835InterruptRegisters { uint32_t DisableIRQ2; uint32_t DisableBasicIRQ; } BCM2835InterruptRegisters; -enum BasicInterruptSource { - TIMER_IRQ = (1<<0), + +enum IRQ1Source { + SysTimerCMP1 = 1 << 1, }; + void bcm2835_init(); void bcm2835_late_init(); diff --git a/src/kernel/src/drivers/chipset/bcm2835/include/timer.h b/src/kernel/src/drivers/chipset/bcm2835/include/timer.h index ee8563bf..6a0c5832 100644 --- a/src/kernel/src/drivers/chipset/bcm2835/include/timer.h +++ b/src/kernel/src/drivers/chipset/bcm2835/include/timer.h @@ -22,10 +22,10 @@ typedef struct BCM2835SystemTimerRegisters { } BCM2835SystemTimerRegisters; enum ControlStatus { - Match3 = 0x1 << 16, - Match2 = 0x1 << 12, - Match1 = 0x1 << 8, - Match0 = 0x1 << 4, + Match3 = 0x1 << 3, + Match2 = 0x1 << 2, + Match1 = 0x1 << 1, + Match0 = 0x1 << 0, }; void bcm2835_timer_init(); diff --git a/src/kernel/src/drivers/chipset/bcm2835/timer.c b/src/kernel/src/drivers/chipset/bcm2835/timer.c index e48c50f6..f5a8958a 100644 --- a/src/kernel/src/drivers/chipset/bcm2835/timer.c +++ b/src/kernel/src/drivers/chipset/bcm2835/timer.c @@ -41,18 +41,20 @@ static inline uint32_t get_frequency() { static inline void mask_and_enable_timer() { - // Set compare value to 0 - bcm2835_timer_registers_base->Compare0 = 0; + // Set compare value to 0 + bcm2835_timer_registers_base->Compare1 = 0; + // Disable CMP1 interrupt + bcm2835_int_registers_base->DisableIRQ1 |= SysTimerCMP1; } static inline uint64_t get_phy_count() { - return bcm2835_timer_registers_base->Compare0; + return bcm2835_timer_registers_base->CounterLower; } static inline void set_phy_timer_cmp_val(uint32_t val) { - bcm2835_timer_registers_base->Compare0=val; + bcm2835_timer_registers_base->Compare1=val; } static inline ScheduledTimer * get_prq_node_data(prq_node * node) { @@ -63,21 +65,22 @@ void bcm2835_timer_init() { const uint32_t freq = SYSTEM_TIMER_FREQ; INFO("System counter frequency: %u kHz\n", freq / 1000); - bcm2835_int_registers_base->DisableBasicIRQ = TIMER_IRQ; + + bcm2835_int_registers_base->DisableIRQ1 |= SysTimerCMP1; // Init priority queue scheduled_timers = prq_create(); - bcm2835_int_registers_base->EnableBasicIRQ = TIMER_IRQ; + bcm2835_int_registers_base->EnableIRQ1 |= SysTimerCMP1; } void bcm2835_timer_handle_interrupt() { volatile const uint64_t current_count = get_phy_count(); // Begin of critical section, disable timer interrupts - bcm2835_int_registers_base->DisableBasicIRQ = TIMER_IRQ; + bcm2835_int_registers_base->DisableIRQ1 |= SysTimerCMP1; // Process all timers that are not in the future, if any prq_node * next_timer_node = prq_peek(scheduled_timers); @@ -117,7 +120,8 @@ void bcm2835_timer_handle_interrupt() { } // End of critical section, re-enable timer interrupts - bcm2835_int_registers_base->EnableBasicIRQ= TIMER_IRQ; + bcm2835_int_registers_base->EnableIRQ1 |= SysTimerCMP1; + } static TimerHandle schedule_timer(TimerCallback callback, uint32_t delay_ms, bool periodic) { @@ -142,7 +146,8 @@ static TimerHandle schedule_timer(TimerCallback callback, uint32_t delay_ms, boo new_timer_node->data = new_timer; // Begin of critical section, disable timer interrupts - bcm2835_int_registers_base->DisableBasicIRQ = TIMER_IRQ; + bcm2835_int_registers_base->DisableIRQ1 |= SysTimerCMP1; + prq_enqueue(scheduled_timers, new_timer_node); @@ -150,7 +155,7 @@ static TimerHandle schedule_timer(TimerCallback callback, uint32_t delay_ms, boo // End of critical section, re-enable timer interrupts - bcm2835_int_registers_base->EnableBasicIRQ = TIMER_IRQ; + bcm2835_int_registers_base->EnableIRQ1 |= SysTimerCMP1; return new_timer->handle; } diff --git a/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c b/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c index 712f44e4..5eeb09bc 100644 --- a/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c +++ b/src/kernel/src/drivers/chipset/bcm2836/bcm2836.c @@ -9,7 +9,6 @@ volatile UartDevice bcm2836_uart; void bcm2836_irq_handler() { volatile const uint32_t pending = bcm2836_registers_base->Core3IRQSource; - switch (pending) { // Generic timers case PHYSICAL_SECURE_TIMER: diff --git a/src/kernel/src/vm/test/test_pagealloc2.c b/src/kernel/src/vm/test/test_pagealloc2.c index fa31bb4e..67e9ed9e 100644 --- a/src/kernel/src/vm/test/test_pagealloc2.c +++ b/src/kernel/src/vm/test/test_pagealloc2.c @@ -120,8 +120,12 @@ TEST_CREATE(test_first_free, { }) TEST_CREATE(test_slice_reserved, { - size_t address = get_hardwareinfo()->peripheral_base_address + KERNEL_VIRTUAL_OFFSET; - union MemorySlice * slice = (union MemorySlice*) address; - struct MemorySliceInfo * sliceinfo = NULL; - ASSERT_EQ(pmm_get_sliceinfo_for_slice(slice, &sliceinfo), SI_RESERVED_MMIO_MEMORY); + // For a raspi 1, mmio doesn't overlap memory. So this test doesn't make sense there. + // TODO: Find a better solution + if(get_hardwareinfo()->boardType==RaspBerryPiTwo){ + size_t address = get_hardwareinfo()->peripheral_base_address + KERNEL_VIRTUAL_OFFSET; + union MemorySlice * slice = (union MemorySlice*) address; + struct MemorySliceInfo * sliceinfo = NULL; + ASSERT_EQ(pmm_get_sliceinfo_for_slice(slice, &sliceinfo), SI_RESERVED_MMIO_MEMORY); + } }); From b1425cedc5443a5fcd309a411744ddc388cf79dc Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Wed, 24 Mar 2021 14:14:59 +0100 Subject: [PATCH 17/21] Remove unused DTB files --- src/kernel/dtb/bcm2708-rpi-b-plus.dtb | Bin 25870 -> 0 bytes src/kernel/dtb/bcm2708-rpi-b-rev1.dtb | Bin 25218 -> 0 bytes src/kernel/dtb/bcm2708-rpi-b.dtb | Bin 25607 -> 0 bytes src/kernel/dtb/bcm2708-rpi-zero-w.dtb | Bin 26545 -> 0 bytes src/kernel/dtb/bcm2708-rpi-zero.dtb | Bin 25352 -> 0 bytes src/kernel/dtb/bcm2710-rpi-2-b.dtb | Bin 26894 -> 0 bytes 6 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 src/kernel/dtb/bcm2708-rpi-b-plus.dtb delete mode 100755 src/kernel/dtb/bcm2708-rpi-b-rev1.dtb delete mode 100755 src/kernel/dtb/bcm2708-rpi-b.dtb delete mode 100755 src/kernel/dtb/bcm2708-rpi-zero-w.dtb delete mode 100755 src/kernel/dtb/bcm2708-rpi-zero.dtb delete mode 100755 src/kernel/dtb/bcm2710-rpi-2-b.dtb diff --git a/src/kernel/dtb/bcm2708-rpi-b-plus.dtb b/src/kernel/dtb/bcm2708-rpi-b-plus.dtb deleted file mode 100755 index 76741fb7219c627f898ae323ff72de6eaa39f363..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25870 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
5`X@K71zZCOV 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 Ab^rhX diff --git a/src/kernel/dtb/bcm2708-rpi-zero-w.dtb b/src/kernel/dtb/bcm2708-rpi-zero-w.dtb deleted file mode 100755 index 6fcca98c1899ca7d8ca49d6d69fd216bc1e2add7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26545 zcmdU2dyHgRS-;hf+38_dW?^_Nu28ex?9Q@tx2w8)W_pl?b`eBjapWPe0yWiDx4Z97 zJ?_@6>YiR@b|BGBjK~_34FM#`NP-)p0SzH);-ZllOn|6~8i?pWXb2`~M2U*{`+etp z=bn4(R@KaIH1Q<2?s^|h5HgWy6MVd7CicQYrekbFDW}0kAgTY}EpYHbCQ73#P8uY`1V0+N&p5AVC*EZMB zm`bd30@t(Nq;;wn;_8C{ufB~CEMLGyy4a4UtA#Y_WO=38iJNJZA}X-Y!~MS1wBK4y zqe0y4Y@LhN>St;jH3A?IA7NfofT`7MH6LaLFb@b!w;6Y~`JR@>g(sI6Ll8qHBV z?gLD4J_q+V3w(1#ST?E%+2*rwz0I`QANATunR<)3zl-^jli_L#Y`fc(cF*N-Edw@^ z^0+sI*hk4QZ1sD?LBG?928Pfz+c?{P0j`Gx{-8N*?X~;6fFZvg4Czk=X3#Um8(J*< zJs;(dNO@i!n^tIS=efAvCosE7+@}!oZBXuyNqMH5qTC7d{sK%wi|uUH!VlPyYTu%F`s4_Ve{w{&~L~0`&F7@-Gz1TOR!^|1&8c zrQ5)Nev<-3CIaa{g6qqxov1Cn&g30M-d{?cooz$~jyCgGk~iFo23^}3^SZhPFkcs# z=H)nv20N^bpmO>LDWm)-r>sxS0jAR0>!(rA!M_u+Z?*bpE9wm!Nx$E@ul_)FbL~v+ z-rk@wY7U0!ef4VEYd35czBlSMw>wdz)$b_*-G;E)86-dTQ&aNqG@{|oVZaaB5TZ*=)|tJ_2Zfw+z{lI}GJXa!y%Bsa{m?Nk=n zm`&qWS@Po4pVGrNR&kMTq1~z?e5BtqUXyZ6Mxo6InAWY(2Qp}zFGutry)?!V!O3#y zzw-9)fB$>m2#%cj>kKAf`!tiHp86NaJqOiNfuXfmVK| zjSDxU+IOztr;3Y65m*oTmFOx{2vzx2o`gOswla*n)_1zj%(^ckxIc`A>0vsIx}m_c z(6mARlPkiisE&23M2mX`7X$Bl3C~Cqju+Hfc{F(T{aaaDXj?QDah18=w z^7IWaC(J`2UQ5>&(^XuWr*u))%!B<@KG2R+_J=mo43;jTV;yOsqm`g1_drVBxo*PI zr{?J}fXuddDo-Fz{+Tv(9jC0SxFl}_#n)`ynz!^R)?u3MbG&5Wo%y^oU)y*Rar!5l z7TRyJFqQJ5OJLb&^7MBx=rhx&H~8FDq_@00%8^0&q8@+8WaVi1A>@ht#)rlU?Gw-- z%H&m*jNipC^B_F2FXE*g@UDFy(aIm<*WG7vTq~Kx=ceabCq_q(;Rh# zH47thJcja0JBb@4t%d{w%M;Xjwxm#wyW*nGs2}QsIsk6kSwK9rJN8%l{~y4``rt?S zAP>*QbpjXX0~|*8M2AZc7MWV^@+oz$5ft4_?yk z%is*sdA#dvDu?$Dq?d86;Cd;pJ8|8G%cocIk`|UR5O4AF+dgZ{GoCg!S&uNv6V*b0 zMrPS(NgQb|Yn%F^f2KTzr`@F0xl|Kr2~%D@>WA7%GCFX)A;?7B0i(W96r_Kivjx*Tt2=c z-}fuNw2cY(P)IbM$JDzK-&5=p90SBw@F-(!mtMr+Jz;sLuPlxoKD|YpuLgV`r&)bq z9mTnf_zJE`{<(d)^QxJFMuA$r;nqkgP$J5VbrO0NC$PP=`uRr z=HakiNoH(Xhd7GzpuB9k_=>lW<2a8jg%MsjwkuB3QRL+vHjgqjbZl^%@9L0_qD>a* zcyJttOwYAl;wa9^ia35oaqu~?zPTNn>45Xw;8pkm*#FA2pwdbi75(Tt%V~4AhyE?J z`Lb2JX1_pxd|J<^(`b5^(nN349}SVr>CEFn#vX5uF1GV-t>5enMaZ^3=5N9a^+O)Y z==bR=>an4CW!{yy?ZbzW%k-GTTrt`%IIE0m4#DmT`-3os1CTf8hSVmn+Tk+!$78g4bLv{KGD z`kYC75PW9NqbNnTDjS`zRRKF`UPV~)KwKIa_i3lCxVGw!e1TyR=_fpb*nq}~*T?fb z0^q91+q&z+!@k0KDtTdDsbBKSitRujLC_p@PbZyPy>4OyEG4(1PKQN=0WVk^u7Yhr z|@KCO-I-$_M(Fnumxp*fvBid|s?@tD4OR;M?auJh&VVFQWi~ z_^78(n7d2=HVYB7{PT#DDBJ#+zKDbRg8a0O=;ajBVyok?B?T_0ACUQx@FO5`))m*{$FLH{L`kG2l=m-`Sk@<69&X5!c5=a@kvhy% zKf&>Z`eWWT+{w=~wG;4zcY&2(_!w{zx9Sf4%kjd`0+5t)<_F*}L|%wdxiuWPv4?eM z$&PkG9Bd1)bF%(RgpF1jH`=M+ZzkC`bwFRjwk*x_lm+KXJ`c-C6TcdtExS=W6T4~w zm(y(>2?QUXZ!a@sAo$v-@9YK7H)1dR_CYW^`4q+#0D9%tUam6hmvE6D$Tnvilnci& zmca+i)m!~R6eRKGNYti0Ox4>IJqRxmaEol9KH=kho)79JKRyD`GD^BEACD7^hNgLH z_p~eKU59<;-uuE=IayRupR!oBcdC#$p{u!ivUeCnX{(v|k}>6Y|1f_m$!%;O4x>O~ z?e<{J#ejo>xF*R7{LQbR{JFSj8_Em&0(lbIjep9e^c7?WK-6Kdcyc@&S)RPWa>NCO zdDjpx`U|#C{~_&Xb58dO6!CLx%Igm8hnyU;Aj6+rIeB3VX{%4z|fa zxU%^Tvgc^$7SGtY1er-7y7YwCBCSY_eI2=mp=fRhoE#~41S8~Q(oRR#MyuNoMz$X*9v){eg6L7gHK$w zFih*39_!4aoi;DD@9pzbKYnO8V>|#L>M&%qZ!vk1KbpsWD0pq&EIJ-ic;nCcL1>PS zQh#1YB?N6Vxspg)$0hcCr33v-;AZI>F)} z^9Xkh<>dW@g_|YMDf~?IvHEO6U6joeSJ1ZD)_!C@n>?GhmGS-tK-6LI_`Qf^j$h>s zI(Kj?1Fki(?i7BUekdQps(vmZF7%FnZYpqjde7B1Lja-<1Mz@J=;woo!Q);DE}E>Y zj5N|0gEnagH`hLK`+mC0LIg{n=<@|xdam9d?t10(q(kKa{PVjYZ7t;F#RTGE{=+0W z?eCBl2Il)V%jZGcrr0cJf+CagPrwB(FB7hB01$N;EN;kzpJvIYRg!lVtg0-iSn{p> zv(GTi`4I0X?47pFG;NM|%7SBIW-{KFu*7T~AOA57o6 z&2|24@aGJF&hqCRe>VAZoESa-61C*vHu3vArG+vSTFO7!7d$IO znEN(0=@!%BL0e2t`TjT?$EE4ddTG;-XcvP=5>z#niH25J@j6;uCkvtMyxq20M-xlZpS-|(&$QODDud=6&ux-du z${^qQ|3sW}V%vnhhC6Ksak*=mtgDzM6-N;30H;}_22$#dd5F$^Sl$nXx;(AiYg%mJZse(43fs;E?*D^a$QEQH^p^SMY4Y*>d#QY0rt;Z|2i*f~ zeY(`;GdG9hTwmchp4)ReNa9fIgs8-Fgv@p>GFfUn>`+!`3!KO3JbaS=p-13p$qbKHck21x^A6A^FY`9{ocD5-|k5>>y_F4EI!p2SMVwTx{#fK z(i1ICj)nQIJL<))rYzsEO~@C%>nfp+!v9wpQF_Rm;#av7{u*HD(?eYB#|n?Uxq2rF z_KmA@vRDBOpIe^p8pbRc&@qaxRR)EtR$$#LO4VD(u7 z(MsgirEExhrPb-TE*VcmywqWi7Ns}L0B!p@y-<(D$@=6|cuo2T5eHcW*5SC5!>xQ4 z;EJ+Edj8|6>hUIRu`fwG`TcUaZ(#|O@Avzyz4&3~3Qe?YtUr8i3+Y#QdF<~D#IN!u ze+RfKV>{~&%y?UF>%HPw*g}1@Dd|ZzgYt=Ex6UCTlZ7{t7K=;euYEw|!f*Mo^%o%0 z-nh+s02ao`qsl7u14h1PtF+*dOgAUu8dtWDx~R9ZaaZZQtho1EsSt=X<;;0;sf`ri zZltY4pcHwe?nr~F@>d!kvGt^GX8!Cmm%@J9BB`XA{yf;h<96G05+<$9NFVXi^S65S z$it(RmG64xV%Mx|+q|Sph&SF&ZvC(F={1}x;q!KYb-=LKPr}Qs zD5euduskh1WRjW|nqP=KLvvzxLOb}0{+;`|3-8w#M#$5)WNyN5)^OG9=gvO#$WCZH zmBa1c$2&d%8zxuOYrN1%~(^!1dAse&*9o?kvft4(}@D z!+sXNiTqRITc{S(=$V?Ki1c9ovheQ?W~V=BMfi-Q|0-k&z3^{~?7IdBO2SUujfcvT zz&sl;v?~MCjeep$z-#vkbmrckgZRGdsxb7+Nh5W_4k$+nuAM#%$;kQkZ zEyj~Y%Jx*R-wOvg!eO7g-i2MEm$)B9`RM{~*!Ddxk>QemVMGqTK;4@tZvH}TJUUebgxZR(DOe=CPIl3oL22;>iVZ>mg#_3#q*mJ(RE9nc(`p)}ldTM2Ao z+q#2YnF4FYAh6KKO{*oaCELv%Zga+4-uCgumcNBuV9DR>%5W>JJ(y1AR@PU6*KYkg zo0IXya=iXFZlR$H8agGg+16pRHJdct1=z!hu--OOv;9`^vyM44EiVs)->YM`#X6dP zePTPrW423^Cer^~(_uw0O8@Uqg!O5WsgR@P%M*2TFkTP9CowbrW@IPZ)fe8Q|51vE zPqPLOcvzY*fl2dQDy2=xZmDcM^R_?=9Qw%8^Ga|UpP31Uyb`uL0oL1^=zg%E4=^`3-oa6La2~=VDGfx03Z|oGZCt>% z=>8d=`MLD4v^D;bw(>iY^6?L$wcN~G#y?P2c}zR=l)5&4ef* zx$s>}=2@xyBR!>i+PS(|mtXpMBX{>*nV7nMgl27laKBOprymDdI6kw^I&+n>nslxz zX=Yo$Hr`hDA(Cy2edsrhO^kgUWO-jQ^TzRyURaK`i6tEuM@Tbhz0V5X@efFB`KA2_54v`L+DdrCeVOXCEqPxzUA|XD^Of4*xar z>|4Ams5~jSl|}#~upWHJl9>Z**{ZB|ni12$U=4HWTT(xJ3COyzkEMT+{PLH3gu#6C zhR(jmTGrUvzgSmV`mVH-yzEdHQbJRtK2 zRg!p(udM=EamH&&{jyWv?4!b3u#K|-nuFbx6zt+;;bae#fN`>j#ov*fEE~8*z);T^ zO>k&A&jrS*@y)|9X{Kqsk1c$0`6Nec}Fw3M{ltza){Tk+&xG#RNnixa|nqb|fcY=)gCkL9KjI)fpzhGuI* z_L$~yFKV`vJvqmFnKCdGW3C;yqQ>wLJ7?jSYGHEF?uD`^+$Bu``m>jh6pt@y@RcRX zTYFIh9W!c32ZnydLo~MGhNuPc5?Ly3%PU{8U-+1YyhOxlD}5$#11h{RWWu}}lt(xB zHj>EJ8u6uG|KMP+iIcV4eYgaZ>l!2?c!fs4*NTEmgC33+k>896IQ9m(kb}_zP2diP z(&-<#9DT>uX>Mb~wZ3_ybBL^e(maKPTFq;%u-Q3i9;P8WZI(y7@5Ze`f4`42lfC@7 zSDH`L49v;%p`k9^i+A^e0Y53>A@Fzy(oi33?5|-?8|Ts9*^2|W)Q=@v7ss-{i(^?o zw``wVm-iA_YVuPXCZ&t!Qe@XO*Qpa-^LA0J<+?bQmJ!z_X%|JdTYUn#-ionCfh51) z3zO5;To=V+E#hu57IC-Onp;dATlvIl;8-43@Ulu+?er35(3@riHOKC4*o3!WXPYp@ zS#n_vp}YC^922A70AC-uFOdU&z>9`!{HeQ=hMhr}X}0+YPNuw=#5VX*67QTn;o>ya X`lVpM-R4VjdELu6=9Ch5Q_24U4cXbb diff --git a/src/kernel/dtb/bcm2708-rpi-zero.dtb b/src/kernel/dtb/bcm2708-rpi-zero.dtb deleted file mode 100755 index 7c079896ec4dd8b0ad1dc4c33bee2cc93f9f1a95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25352 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 Date: Wed, 24 Mar 2021 14:34:00 +0100 Subject: [PATCH 18/21] Add dtb readme --- src/kernel/dtb/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/kernel/dtb/README.md diff --git a/src/kernel/dtb/README.md b/src/kernel/dtb/README.md new file mode 100644 index 00000000..486de12b --- /dev/null +++ b/src/kernel/dtb/README.md @@ -0,0 +1,21 @@ +# Device Tree Files for QEMU + +In this directory, there are a number of DTB files we use when running the kernel in QEMU. + +## What is a DTB file? +In an ARM board, most peripherals are use via memory-mapped IO, which means there is no standard way to poll what kind of peripherals are present in the system and where in memory to find them. Additionally, there is no way to find out how much memory is present in the system. A Device Tree is the standardized way in which the bootloader communicates to the kernel how the system looks like, including the type of cpu, the amount of memory available, what peripherals can be found and any other details we need to for our kernel to interact with the current board correctly. + +A **DTS** file is the human-readable representation of a device tree, while a **DTB** is a binary version, more suitable for parsing, and usually what you feed into the OS. + +## How does the kernel obtain the DTB file? +One of the responsibilities of a board's bootloader is to load the board's DTB file and pass it to the kernel. Thus on kernel startup, we can expect a pointer to the DTB to be in the `r2` register. + +In QEMU however, there is no provision made for a DTB to be passed to our program. Thus we must work around it, and build the DTB into the kernel, and use this built-in DTB instead. + +## Why use a dumped DTB file? +Certain bootloaders make changes to the board's standard DTB file before passing it to the kernel. For example, the Raspberry Pi Zero's default DTB does not have the memory property filled in. Thus, if we weren't using a dumped DTB, we would not be getting the correct memory value. + +## Further Reading +https://devicetree-specification.readthedocs.io/en/v0.3/ +https://devicetree-specification.readthedocs.io/en/v0.3/flattened-format.html +https://elinux.org/Device_Tree_Usage From 6af63f6cd9cf40e7b85d08a39541ea6f14f6d314 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Wed, 24 Mar 2021 14:34:30 +0100 Subject: [PATCH 19/21] Remove unnecessary memory variable --- src/kernel/Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index a3575b09..69bb7201 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -34,11 +34,9 @@ INCLUDEDIR = include BOARD = raspi2 ifeq ($(BOARD),raspi2) -MEMORY = 1G CPU = cortex-a7 DTB = $(CURDIR)/dtb/bcm2709-rpi-2-b.dtb else ifeq ($(BOARD),raspi0) -MEMORY = 512M CPU = arm1176 DTB = $(CURDIR)/dtb/bcm2708-rpi-zero-dumped.dtb endif @@ -108,7 +106,7 @@ build_pi: $(BUILDDIR)/kernel.img | builddir test: build configure | builddir #${QEMU} -M versatilepb -cpu arm1176 -sd $(BUILDDIR)/card.sd -m $(MEMORY) -nographic -semihosting -kernel build/flash.bin -append "-load 0x410000 0x14000" - ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M $(BOARD) -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting + ${QEMU} -kernel $(BUILDDIR)/kernel.elf -serial stdio -monitor none -M $(BOARD) -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting run: build configure | builddir # nographic to turn off the gui @@ -118,7 +116,7 @@ run: build configure | builddir ${QEMU} -kernel $(BUILDDIR)/kernel.elf -serial stdio -monitor none -M $(BOARD) -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting debug: build configure | builddir - ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M $(BOARD) -cpu $(CPU) -nographic -semihosting -S -s + ${QEMU} -kernel $(BUILDDIR)/kernel.elf -serial stdio -monitor none -M $(BOARD) -cpu $(CPU) -nographic -semihosting -S -s start_debug: build configure | builddir $(GDB) -ex "target remote localhost:1234" -ex "symbol-file $(BUILDDIR)/kernel.sym" From 2830c9068c8485ce354ec8a13fd2992386a8dd7a Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Wed, 24 Mar 2021 14:38:34 +0100 Subject: [PATCH 20/21] Refactore dtb source to use existing ALIGN macro --- src/kernel/src/common/dtb.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/kernel/src/common/dtb.c b/src/kernel/src/common/dtb.c index bce3fe05..0268d7d3 100644 --- a/src/kernel/src/common/dtb.c +++ b/src/kernel/src/common/dtb.c @@ -1,5 +1,6 @@ #include #include +#include // DTB is in big endian, so it must be converted to little endian @@ -15,10 +16,6 @@ static inline uint32_t fix_endian(const uint32_t num) { return ret; } -// Aligns the given pointer to 4 bytes. -static inline void * align_pointer(void * pointer) { - return (void *)(((size_t)pointer + 3) & ~3); -} // Advances past the begin node and returns name of the node @@ -26,7 +23,7 @@ char * parse_begin_node(void ** curr_address) { *curr_address += sizeof(uint32_t); char * string_address = (char *)*curr_address; *curr_address += strlen(string_address) + 1; - *curr_address = align_pointer(*curr_address); + *curr_address = (void*)ALIGN(*curr_address,4); return string_address; } @@ -99,7 +96,7 @@ struct DTProp * dtb_get_property(struct DTHeader * dtb_h, char * path, char * pr } // Skip over the property data curr_address += sizeof(struct DTProp) + fix_endian(prop->len); - curr_address = align_pointer(curr_address); + curr_address = (void*)ALIGN(curr_address,4); break; case FDT_NOP: curr_address += sizeof(uint32_t); From dbf0db54c8bb188d6324c38abf0d43dc8a801f44 Mon Sep 17 00:00:00 2001 From: Francisco Ayala Le Brun Date: Wed, 24 Mar 2021 15:04:00 +0100 Subject: [PATCH 21/21] Move memory detection responsibility to hardware info --- src/kernel/src/common/dtb.c | 3 ++ src/kernel/src/common/hardwareinfo.c | 35 ++++++++++++++++---- src/kernel/src/common/include/hardwareinfo.h | 7 ++-- src/kernel/src/common/start.c | 34 ++++--------------- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/kernel/src/common/dtb.c b/src/kernel/src/common/dtb.c index 0268d7d3..214bab09 100644 --- a/src/kernel/src/common/dtb.c +++ b/src/kernel/src/common/dtb.c @@ -2,6 +2,8 @@ #include #include +extern size_t __DTB_START[]; + // DTB is in big endian, so it must be converted to little endian static inline uint32_t fix_endian(const uint32_t num) { @@ -127,3 +129,4 @@ struct DTPropString dtb_wrap_string_prop(struct DTHeader * dtb_h, struct DTProp (char *)(prop + 1)}; return wrapped; } + diff --git a/src/kernel/src/common/hardwareinfo.c b/src/kernel/src/common/hardwareinfo.c index dc1db184..eae00ec2 100644 --- a/src/kernel/src/common/hardwareinfo.c +++ b/src/kernel/src/common/hardwareinfo.c @@ -1,7 +1,7 @@ -#include #include -#include +#include #include +#include #include #include #include @@ -10,6 +10,8 @@ static HardwareInfo hardware_info; +extern size_t __DTB_START[]; + BoardType detect_boardtype(struct DTHeader * dtb_h) { struct DTProp * prop = dtb_get_property(dtb_h, "/", "model"); assert(prop != NULL); @@ -24,6 +26,22 @@ BoardType detect_boardtype(struct DTHeader * dtb_h) { } } +size_t detect_memory_size(struct DTHeader * dtb_h) { + struct DTProp * mem_prop = dtb_get_property(dtb_h, "/memory", "reg"); + assert(mem_prop != NULL); // Failed to find memory node in the DTB + + struct DTProp2UInt memory_prop = dtb_wrap_2uint_prop( + dtb_h, + mem_prop); // First element is address and second element is size of available memory + assert(memory_prop.first == 0); // There can be multiple memory declarations in the DTB, but + // we're assuming there's only 1, and it starts at address 0 + + if (memory_prop.second == 0) { + memory_prop.second = Gibibyte; // TODO: Dump the Rpi 2 DTB so this is not needed + } + return memory_prop.second; +} + CpuType detect_cputype() { uint32_t reg; @@ -46,7 +64,13 @@ CpuType detect_cputype() { // Such as: CPU and RAM size. void init_hardwareinfo(struct DTHeader * dtb_h) { + if (dtb_h == NULL) { + dtb_h = (struct DTHeader *) + __DTB_START; // DTB not passed by bootloader, we are in QEMU. Use Embedded DTB. + } + BoardType boardType = detect_boardtype(dtb_h); + size_t memory_size = detect_memory_size(dtb_h); size_t peripheral_base_address; size_t peripheral_region_size; switch (boardType) { @@ -57,19 +81,16 @@ void init_hardwareinfo(struct DTHeader * dtb_h) { case RaspberryPiZero: peripheral_base_address = BCM2835_PERIPHERALS_PHYSICAL_BASE; peripheral_region_size = 18 * Mebibyte; - break; + break; default: FATAL("Peripheral address for board type not implemented"); } hardware_info = (HardwareInfo){ .cpuType = detect_cputype(), .boardType = boardType, + .memory_size = memory_size, .peripheral_base_address = peripheral_base_address, - - .peripheral_region_size = peripheral_region_size, - .peripheral_region_size = peripheral_region_size, - }; } diff --git a/src/kernel/src/common/include/hardwareinfo.h b/src/kernel/src/common/include/hardwareinfo.h index 000489bc..18c943d2 100644 --- a/src/kernel/src/common/include/hardwareinfo.h +++ b/src/kernel/src/common/include/hardwareinfo.h @@ -1,9 +1,9 @@ #ifndef HARDWAREINFO_H #define HARDWAREINFO_H +#include #include #include -#include typedef enum CpuType { ARM1176, CortexA7 } CpuType; @@ -14,19 +14,20 @@ typedef enum BoardType { VersatilePB, RaspberryPiZero, RaspBerryPiTwo } BoardTyp typedef struct HardwareInfo { CpuType cpuType; BoardType boardType; + size_t memory_size; size_t peripheral_base_address; size_t peripheral_region_size; } HardwareInfo; // Initialize the global hardware info struct. After this is ran, the get_hardwareinfo // function can be used to retrieve it. -void init_hardwareinfo(struct DTHeader* dtb_h); +void init_hardwareinfo(struct DTHeader * dtb_h); // Get a pointer to the hardwareinfo struct. This is a global struct containing information // about the cpu type, and board/chipset type. May be expanded to contain more useful info. HardwareInfo * get_hardwareinfo(); void print_hardwareinfo(); -BoardType detect_boardtype(struct DTHeader* dtb_h); +BoardType detect_boardtype(struct DTHeader * dtb_h); // Checks whether given address is in area occupied by MMIO bool address_in_reserved_region(size_t address); diff --git a/src/kernel/src/common/start.c b/src/kernel/src/common/start.c index 0b3d4d0a..c5869a4a 100644 --- a/src/kernel/src/common/start.c +++ b/src/kernel/src/common/start.c @@ -1,27 +1,24 @@ #include #include +#include #include #include #include #include #include #include +#include #include -#include #include #include #include #include -#include extern unsigned int user_start; extern unsigned int user_end; #include -extern size_t __DTB_START[]; - - void init() { ProcessControlBlock * pcb = createPCB(0); add(pcb, true); @@ -33,10 +30,10 @@ void init() { // copy the SWI instruction from _userspace_test_program to the allocated page at 0x8000 int userspace_test_program = 0; asm volatile("ldr %0, =_userspace_test_program" : "=r"(userspace_test_program)); - + // TODO size of userspace test program is hardcoded kprintf("userspace test: %x\n", userspace_test_program); - memcpy((void *) available_mem_addr, (void *) userspace_test_program, (size_t) 60); + memcpy((void *)available_mem_addr, (void *)userspace_test_program, (size_t)60); register ProcessControlBlock * r5 asm("r5") = pcb; asm volatile("push {lr}"); @@ -49,11 +46,6 @@ void init() { /// This function is called by the assembly located in [startup.s]. /// The MMU has already been initialized here but only the first MiB of the kernel has been mapped. void start(uint32_t * p_bootargs, struct DTHeader * dtb) { - if (dtb == NULL) { - dtb = (struct DTHeader *) - __DTB_START; // DTB not passed by bootloader, we are in QEMU. Use Embedded DTB. - } - // Before this point, all code has to be hardware independent. // After this point, code can request the hardware info struct to find out what // Code should be ran. @@ -62,21 +54,8 @@ void start(uint32_t * p_bootargs, struct DTHeader * dtb) { // Initialize the chipset and enable uart init_chipset(); - struct DTProp * mem_prop = dtb_get_property(dtb, "/memory", "reg"); - assert(mem_prop != NULL); // Failed to find memory node in the DTB - - struct DTProp2UInt memory_prop = dtb_wrap_2uint_prop( - dtb, mem_prop); // First element is address and second element is size of available memory - assert(memory_prop.first == 0); // There can be multiple memory declarations in the DTB, but - // we're assuming there's only 1, and it starts at address 0 - if (memory_prop.second == 0) { - memory_prop.second = Gibibyte; - INFO("DTB reports 0 RAM, setting size to 1 GB"); - } - - - INFO("Detected memory size: 0x%x Bytes", memory_prop.second); + INFO("Detected memory size: 0x%x Bytes", get_hardwareinfo()->memory_size); INFO("Started chipset specific handlers"); // just cosmetic (and for debugging) @@ -88,7 +67,7 @@ void start(uint32_t * p_bootargs, struct DTHeader * dtb) { // was temporary and has to be replaced here. // This will actually map the whole kernel in memory and initialize the physicalMemoryManager. INFO("Initializing the physical and virtual memory managers."); - vm2_start(memory_prop.second); + vm2_start(get_hardwareinfo()->memory_size); INFO("Setting up interrupt vector tables"); // Set up the exception handlers. @@ -134,4 +113,3 @@ void start(uint32_t * p_bootargs, struct DTHeader * dtb) { SLEEP; } -