Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 236820fad4 | |||
| 69cc9a2eaa | |||
| 7f256cf3a6 | |||
| f416414b93 | |||
| 0386e3916d | |||
| 31176fb5aa | |||
| 1411f1eed0 | |||
| 4c5309fa15 | |||
| 1012abceec | |||
| a6a6dba155 | |||
| 7f46da9ebd | |||
| 1a87bc3666 | |||
| 4f648142c8 | |||
| 0e979a9e09 | |||
| ed9d7a7145 | |||
| 6b5dd9f673 | |||
| 58dbaddf11 | |||
| 218e391505 | |||
| 2a49c655c2 | |||
| d108494314 | |||
| 195c19e225 | |||
| 21a8361eec | |||
| fd0a3f50ea | |||
| c72c8f88d7 | |||
| e44b616998 | |||
| 7abb950a8f | |||
| 57143f9d8d | |||
| 3491e1a227 | |||
| 61644bdef5 | |||
| e1b905c65a | |||
| 9855142c25 | |||
| bb4e805733 | |||
| ecf1c18240 | |||
| a87c8a7ee2 | |||
| 312458b8f0 | |||
| 33474c10d3 | |||
| e934b4d696 | |||
| 6d8d97d492 | |||
| ca01f57873 | |||
| 9be467d5d5 | |||
| 0c2ebbf7b3 | |||
| cb4c0bc4b0 | |||
| c1b62aef1d | |||
| 6469914be1 | |||
| 131e6adc3d | |||
| 322cb0a958 | |||
| 6552fa8059 | |||
| 0ff48fd520 |
Generated
+69
-27
@@ -25,7 +25,6 @@ dependencies = [
|
||||
name = "abi-lib"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
@@ -33,7 +32,6 @@ dependencies = [
|
||||
name = "abi-serde"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
@@ -407,15 +405,6 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.146"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97117b1434b79833f39a5fabdf82f890bd98c1988334dea1cb67f7e627fa311"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.10"
|
||||
@@ -469,6 +458,7 @@ dependencies = [
|
||||
name = "device-api"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"device-api-macros",
|
||||
"yggdrasil-abi",
|
||||
]
|
||||
@@ -499,7 +489,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "discrete_range_map"
|
||||
version = "0.6.2"
|
||||
source = "git+https://git.alnyan.me/yggdrasil/discrete_range_map.git#6b54882b190b02fb013f22cbe9664f6273e846ae"
|
||||
source = "git+https://git.alnyan.me/yggdrasil/discrete_range_map.git#0c932f7cc7ff55253519e3465ddeea8fe69083be"
|
||||
dependencies = [
|
||||
"btree_monstrousity",
|
||||
"either",
|
||||
@@ -1199,9 +1189,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.169"
|
||||
version = "0.2.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
@@ -1290,9 +1280,8 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.8"
|
||||
source = "git+https://git.alnyan.me/yggdrasil/libm.git#ace5825d9683d2bf4a71c8f18f2c854660c297b2"
|
||||
source = "git+https://git.alnyan.me/yggdrasil/libm.git#78b62c33fc6a56b6c063c19bbffc5224616b7028"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
@@ -1329,7 +1318,6 @@ version = "0.1.0"
|
||||
name = "libyalloc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-core",
|
||||
"yggdrasil-rt",
|
||||
@@ -1353,6 +1341,12 @@ version = "0.4.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.7.4"
|
||||
@@ -1787,7 +1781,20 @@ dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.11.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
@@ -2004,15 +2011,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.16.0"
|
||||
version = "3.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91"
|
||||
checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"getrandom 0.3.1",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"rustix 1.1.3",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
@@ -2388,7 +2394,7 @@ checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f"
|
||||
dependencies = [
|
||||
"either",
|
||||
"home",
|
||||
"rustix",
|
||||
"rustix 0.38.44",
|
||||
"winsafe",
|
||||
]
|
||||
|
||||
@@ -2557,8 +2563,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"rustix",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"rustix 0.38.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2589,6 +2595,7 @@ dependencies = [
|
||||
"semver 1.0.25",
|
||||
"serde",
|
||||
"tar",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"toml",
|
||||
"walkdir",
|
||||
@@ -2657,6 +2664,7 @@ dependencies = [
|
||||
name = "ygg_driver_bsp_bcm283x"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytemuck",
|
||||
"device-api",
|
||||
"device-tree",
|
||||
@@ -2702,6 +2710,25 @@ dependencies = [
|
||||
"yggdrasil-abi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ygg_driver_bsp_sifive"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytemuck",
|
||||
"device-api",
|
||||
"device-tree",
|
||||
"futures-util",
|
||||
"libk",
|
||||
"libk-mm",
|
||||
"libk-util",
|
||||
"log",
|
||||
"static_assertions",
|
||||
"tock-registers",
|
||||
"ygg_driver_net_core",
|
||||
"yggdrasil-abi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ygg_driver_fat32"
|
||||
version = "0.1.0"
|
||||
@@ -2733,6 +2760,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytemuck",
|
||||
"device-api",
|
||||
"kernel-fs",
|
||||
"libk",
|
||||
"libk-mm",
|
||||
@@ -2749,6 +2777,7 @@ name = "ygg_driver_net_igbe"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"device-api",
|
||||
"futures-util",
|
||||
"libk",
|
||||
"libk-mm",
|
||||
"libk-util",
|
||||
@@ -2855,6 +2884,19 @@ dependencies = [
|
||||
"yggdrasil-abi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ygg_driver_serial_8250"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"device-api",
|
||||
"device-tree",
|
||||
"kernel-arch-x86",
|
||||
"libk",
|
||||
"libk-mm",
|
||||
"libk-util",
|
||||
"yggdrasil-abi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ygg_driver_usb"
|
||||
version = "0.1.0"
|
||||
@@ -2968,7 +3010,6 @@ dependencies = [
|
||||
"abi-lib",
|
||||
"abi-serde",
|
||||
"bytemuck",
|
||||
"compiler_builtins",
|
||||
"prettyplease",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
@@ -3019,6 +3060,7 @@ dependencies = [
|
||||
"ygg_driver_bsp_bcm283x",
|
||||
"ygg_driver_bsp_jh7110",
|
||||
"ygg_driver_bsp_riscv",
|
||||
"ygg_driver_bsp_sifive",
|
||||
"ygg_driver_fat32",
|
||||
"ygg_driver_input",
|
||||
"ygg_driver_net_core",
|
||||
@@ -3028,6 +3070,7 @@ dependencies = [
|
||||
"ygg_driver_net_stmmac",
|
||||
"ygg_driver_nvme",
|
||||
"ygg_driver_pci",
|
||||
"ygg_driver_serial_8250",
|
||||
"ygg_driver_usb",
|
||||
"ygg_driver_usb_xhci",
|
||||
"ygg_driver_virtio_blk",
|
||||
@@ -3044,7 +3087,6 @@ dependencies = [
|
||||
"abi-lib",
|
||||
"abi-serde",
|
||||
"cc",
|
||||
"compiler_builtins",
|
||||
"libm",
|
||||
"prettyplease",
|
||||
"rustc-std-workspace-alloc",
|
||||
|
||||
@@ -7,6 +7,7 @@ exclude = [
|
||||
"toolchain",
|
||||
"userspace/dynload-program",
|
||||
"userspace/lib/ygglibc",
|
||||
"userspace",
|
||||
"toolchain-c"
|
||||
]
|
||||
members = [
|
||||
@@ -88,6 +89,7 @@ features = ["no_std_stream"]
|
||||
|
||||
[workspace.lints.rust]
|
||||
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(rust_analyzer)'] }
|
||||
unsafe_op_in_unsafe_fn.level = "deny"
|
||||
[workspace.lints.clippy]
|
||||
derivable_impls = { level = "allow" }
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ Main features
|
||||
-------------
|
||||
|
||||
* Architecture support:
|
||||
* [aarch64](kernel/src/arch/aarch64)
|
||||
* [x86_64](kernel/src/arch/x86_64)
|
||||
* [i686](kernel/src/arch/i686) (Pentium Pro and later)
|
||||
* [aarch64](kernel/arch/aarch64)
|
||||
* [x86_64](kernel/arch/x86_64)
|
||||
* [riscv64](kernel/arch/riscv64)
|
||||
* Core features:
|
||||
* Kernel/userspace preemptive multithreading
|
||||
* Kernel-space multitasking with `async`/`await` runtime
|
||||
@@ -24,6 +24,7 @@ Main features
|
||||
* sysfs
|
||||
* devfs
|
||||
* ext2
|
||||
* fat32 (read-only)
|
||||
* Userspace features:
|
||||
* [Kernel-user ABI](lib/abi-def/yggdrasil.abi) generated from a rust-like description language
|
||||
* Sanitized system calls better suited for use in Rust
|
||||
@@ -33,33 +34,37 @@ Main features
|
||||
* Synchronization primitives through futex-like interface
|
||||
* Unix-like signals and exceptions
|
||||
* [Dynamic loader](userspace/dyn-loader) for linking with shared libraries
|
||||
* Runs DOOM
|
||||
* Hardware features:
|
||||
* PCI Express devices
|
||||
* NVMe drive support (read/write, currently x86_64 only, due to lack of MSI-X support on aarch64/i686).
|
||||
* AHCI SATA drive support (read/write)
|
||||
* NVMe drive support
|
||||
* AHCI SATA drive support
|
||||
* xHCI USB host controller
|
||||
* VirtIO Network + GPU framebuffer support
|
||||
* USB HID keyboards
|
||||
* USB device support
|
||||
* Hub driver
|
||||
* HID keyboards and mice
|
||||
* Mass storage (BBB)
|
||||
* Partial hardware support for aarch64/riscv64 SBCs like StarFive VisionFive 2 and Raspberry Pi 4
|
||||
|
||||
aarch64-specific:
|
||||
|
||||
* PSCI for SMP start-up and power control
|
||||
* PL011 serial port
|
||||
* PL061 GPIO controller
|
||||
* PL031 RTC
|
||||
* ARM generic timer as system/monotonic timer
|
||||
* GICv2 IRQ controller
|
||||
* GICv2 IRQ controller + GICv2m MSI interrupts
|
||||
|
||||
x86-specific:
|
||||
|
||||
* Boot options:
|
||||
* x86_64: UEFI [yboot](https://git.alnyan.me/yggdrasil/yboot)
|
||||
* i686: multiboot/grub
|
||||
* Boot via UEFI [yboot](https://git.alnyan.me/yggdrasil/yboot)
|
||||
* I/O and Local APIC IRQ controllers
|
||||
* PS/2 keyboard
|
||||
* HPET for x86_64
|
||||
* i8253-based timer for i686 or as a fallback timer
|
||||
* i8253 as a fallback timer
|
||||
* COM ports
|
||||
* ACPI, [work in progress](https://github.com/rust-osdev/acpi), mostly broken
|
||||
on real hardware, so currently disabled
|
||||
* ACPI, [work in progress](https://github.com/rust-osdev/acpi)
|
||||
* ACPI shutdown
|
||||
* PCI IRQ pin routing
|
||||
* Events like power button, etc.
|
||||
@@ -122,7 +127,6 @@ General plans (in no particular order)
|
||||
2. Get a full LLVM build to work
|
||||
3. Get rustc to work
|
||||
4. Get self-hosted
|
||||
5. Run doom (?)
|
||||
|
||||
In addition to eternal code cleanup, I've been doing quite a lazy job at that lately...
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
Booting Yggdrasil OS on SiFive HiFive Unmatched Rev B RISC-V board:
|
||||
|
||||
* TODO: proper format for initrd image
|
||||
|
||||
Prerequisites:
|
||||
|
||||
* OpenSBI + u-boot (can use the u-boot from the Freedom U SDK that comes with the board)
|
||||
* yggdrasil-kernel.bin
|
||||
* initrd.img
|
||||
|
||||
Steps:
|
||||
|
||||
1. Copy yggdrasil-kernel.bin and initrd.img into some directory and start a TFTP server there
|
||||
2. Connect to HFU's serial port, ethernet and enter u-boot
|
||||
3. Run the following commands in u-boot:
|
||||
|
||||
### If using DHCP
|
||||
|
||||
=> setenv autoload no
|
||||
=> setenv initrd_addr_r 0x90000000
|
||||
=> dhcp
|
||||
=> tftpboot ${initrd_addr_r} <SERVER IP>:initrd.img
|
||||
=> tftpboot ${loadaddr} <SERVER IP>:yggdrasil-kernel.bin
|
||||
=> tftpboot ${fdt_addr_r} <SERVER IP>:hifive-unmatched-a00.dtb
|
||||
=> fdt resize
|
||||
=> booti ${loadaddr} ${initrd_addr_r}:60000000 ${fdt_addr_r}
|
||||
|
||||
Two-liner (server is 13.0.0.1, board is 13.0.0.2):
|
||||
|
||||
setenv ipaddr 13.0.0.2;setenv initrd_addr_r 0x90000000;tftpboot ${initrd_addr_r} 13.0.0.1:initrd.img;tftpboot ${loadaddr} 13.0.0.1:yggdrasil-kernel.bin;tftpboot ${fdt_addr_r} 13.0.0.1:hifive-unmatched-a00.dtb;fdt resize
|
||||
booti ${loadaddr} ${initrd_addr_r}:60000000 ${fdt_addr_r}
|
||||
|
||||
One-liner without initrd
|
||||
|
||||
setenv ipaddr 13.0.0.2;tftpboot ${loadaddr} 13.0.0.1:yggdrasil-kernel.bin;tftpboot ${fdt_addr_r} 13.0.0.1:hifive-unmatched-a00.dtb;fdt resize;booti ${loadaddr} - ${fdt_addr_r}
|
||||
+3
-2
@@ -33,10 +33,11 @@ $ booti ${loadaddr} ${initrd_addr_r}:<initrd-size> ${fdt_addr_r}
|
||||
|
||||
env set ipaddr 13.0.0.2; env set initrd_addr_r 0x70000000; tftpboot ${initrd_addr_r} 13.0.0.1:initrd.img; tftpboot ${loadaddr} 13.0.0.1:yggdrasil-kernel.bin; load mmc 1:3 ${fdt_addr_r} dtbs/6.6.20-starfive/starfive/${fdtfile}; fdt resize; booti ${loadaddr} ${initrd_addr_r}:60000000 ${fdt_addr_r}
|
||||
|
||||
env set ipaddr 13.0.0.2; env set initrd_addr_r 0x70000000; tftpboot ${initrd_addr_r} 13.0.0.1:initrd.img; tftpboot ${loadaddr} 13.0.0.1:yggdrasil-kernel.bin; tftpboot ${fdt_addr_r} 13.0.0.1:vf2.dtb; fdt resize; booti ${loadaddr} ${initrd_addr_r}:60000000 ${fdt_addr_r}
|
||||
|
||||
#### For DHCP boot with BUILD-MACHINE-IP-ADDR 192.168.88.10
|
||||
|
||||
dhcp
|
||||
dhcp; env set initrd_addr_r 0x70000000; tftpboot ${initrd_addr_r} 192.168.88.10:initrd.img; tftpboot ${loadaddr} 192.168.88.10:yggdrasil-kernel.bin; load mmc 1:3 ${fdt_addr_r} dtbs/6.6.20-starfive/starfive/${fdtfile}; fdt resize; booti ${loadaddr} ${initrd_addr_r}:60000000 ${fdt_addr_r}
|
||||
dhcp; env set initrd_addr_r 0x70000000; tftpboot ${initrd_addr_r} 192.168.88.10:initrd.img; tftpboot ${loadaddr} 192.168.88.10:yggdrasil-kernel.bin; tftpboot ${fdt_addr_r} 192.168.88.10:vf2.dtb; fdt resize; booti ${loadaddr} ${initrd_addr_r}:60000000 ${fdt_addr_r}
|
||||
|
||||
|
||||
Missing drivers:
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
"arch": "aarch64",
|
||||
"os": "none",
|
||||
"abi": "softfloat",
|
||||
"rustc-abi": "softfloat",
|
||||
"llvm-target": "aarch64-unknown-none",
|
||||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
|
||||
"max-atomic-width": 128,
|
||||
"target-pointer-width": "64",
|
||||
"target-pointer-width": 64,
|
||||
"features": "+v8a,+strict-align,-neon,-fp-armv8",
|
||||
|
||||
"disable-redzone": true,
|
||||
|
||||
Binary file not shown.
@@ -264,16 +264,15 @@
|
||||
compatible = "gpio-keys";
|
||||
|
||||
poweroff {
|
||||
gpios = <0x8007 0x03 0x00>;
|
||||
gpios = <&gpio 0x03 0x00>;
|
||||
linux,code = <0x74>;
|
||||
label = "GPIO Key Poweroff";
|
||||
};
|
||||
};
|
||||
|
||||
pl061@9030000 {
|
||||
phandle = <0x8007>;
|
||||
gpio: pl061@9030000 {
|
||||
clock-names = "apb_pclk";
|
||||
clocks = <0x8000>;
|
||||
clocks = <&clk_24mhz>;
|
||||
interrupts = <0x00 0x07 0x04>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <0x02>;
|
||||
@@ -299,15 +298,15 @@
|
||||
|
||||
pl031@9010000 {
|
||||
clock-names = "apb_pclk";
|
||||
clocks = <0x8000>;
|
||||
clocks = <&clk_24mhz>;
|
||||
interrupts = <0x00 0x02 0x04>;
|
||||
reg = <0x00 0x9010000 0x00 0x1000>;
|
||||
compatible = "arm,pl031", "arm,primecell";
|
||||
};
|
||||
|
||||
pl011@9000000 {
|
||||
uart0: pl011@9000000 {
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
clocks = <0x8000 0x8000>;
|
||||
clocks = <&clk_24mhz &clk_24mhz>;
|
||||
interrupts = <0x00 0x01 0x04>;
|
||||
reg = <0x00 0x9000000 0x00 0x1000>;
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
@@ -411,8 +410,7 @@
|
||||
compatible = "arm,armv8-timer", "arm,armv7-timer";
|
||||
};
|
||||
|
||||
apb-pclk {
|
||||
phandle = <0x8000>;
|
||||
clk_24mhz: apb-pclk {
|
||||
clock-output-names = "clk24mhz";
|
||||
clock-frequency = <0x16e3600>;
|
||||
#clock-cells = <0x00>;
|
||||
@@ -0,0 +1,669 @@
|
||||
/dts-v1/;
|
||||
|
||||
#include <aarch64/gicv2.h>
|
||||
|
||||
/memreserve/ 0x0000000000000000 0x0000000000001000;
|
||||
/ {
|
||||
compatible = "raspberrypi,4-model-b", "brcm,bcm2711";
|
||||
model = "Raspberry Pi 4 Model B";
|
||||
#address-cells = <0x02>;
|
||||
#size-cells = <0x01>;
|
||||
interrupt-parent = <&gicv2>;
|
||||
|
||||
aliases {
|
||||
serial0 = "/soc/serial@7e201000";
|
||||
serial1 = "/soc/serial@7e215040";
|
||||
blconfig = "/reserved-memory/nvram@0";
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial1:115200n8";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <0x02>;
|
||||
#size-cells = <0x01>;
|
||||
ranges;
|
||||
|
||||
linux,cma {
|
||||
compatible = "shared-dma-pool";
|
||||
size = <0x4000000>;
|
||||
reusable;
|
||||
linux,cma-default;
|
||||
alloc-ranges = <0x00 0x00 0x40000000>;
|
||||
};
|
||||
|
||||
nvram@0 {
|
||||
compatible = "raspberrypi,bootloader-config", "nvmem-rmem";
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x01>;
|
||||
reg = <0x00 0x00 0x00>;
|
||||
no-map;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x01>;
|
||||
ranges = <0x7e000000 0x00 0xfe000000 0x01800000>,
|
||||
<0x7c000000 0x00 0xfc000000 0x02000000>,
|
||||
<0x40000000 0x00 0xff800000 0x00800000>;
|
||||
dma-ranges = <0xc0000000 0x00 0x00 0x40000000>;
|
||||
|
||||
timer@7e003000 {
|
||||
compatible = "brcm,bcm2835-system-timer";
|
||||
reg = <0x7e003000 0x1000>;
|
||||
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <0xf4240>;
|
||||
};
|
||||
|
||||
txp@7e004000 {
|
||||
compatible = "brcm,bcm2835-txp";
|
||||
reg = <0x7e004000 0x20>;
|
||||
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
dsi0: dsi@7e209000 {
|
||||
compatible = "brcm,bcm2835-dsi0";
|
||||
reg = <0x7e209000 0x78>;
|
||||
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
#clock-cells = <0x01>;
|
||||
clocks = <&cprman 0x20>,
|
||||
<&cprman 0x2f>,
|
||||
<&cprman 0x31>;
|
||||
clock-names = "phy", "escape", "pixel";
|
||||
clock-output-names = "dsi0_byte", "dsi0_ddr2", "dsi0_ddr";
|
||||
status = "disabled";
|
||||
power-domains = <&power 0x11>;
|
||||
};
|
||||
|
||||
dsi1: dsi@7e700000 {
|
||||
compatible = "brcm,bcm2711-dsi1";
|
||||
reg = <0x7e700000 0x8c>;
|
||||
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
#clock-cells = <0x01>;
|
||||
clocks = <&cprman 0x23>,
|
||||
<&cprman 0x30>,
|
||||
<&cprman 0x32>;
|
||||
clock-names = "phy", "escape", "pixel";
|
||||
clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
|
||||
status = "disabled";
|
||||
power-domains = <&power 0x12>;
|
||||
};
|
||||
|
||||
cprman: cprman@7e101000 {
|
||||
compatible = "brcm,bcm2711-cprman";
|
||||
#clock-cells = <0x01>;
|
||||
reg = <0x7e101000 0x2000>;
|
||||
clocks = <&clk_osc>,
|
||||
<&dsi0 0x00>,
|
||||
<&dsi0 0x01>,
|
||||
<&dsi0 0x02>,
|
||||
<&dsi1 0x00>,
|
||||
<&dsi1 0x01>,
|
||||
<&dsi1 0x02>;
|
||||
};
|
||||
|
||||
mbox: mailbox@7e00b880 {
|
||||
compatible = "brcm,bcm2835-mbox";
|
||||
reg = <0x7e00b880 0x40>;
|
||||
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#mbox-cells = <0x00>;
|
||||
};
|
||||
|
||||
gpio: gpio@7e200000 {
|
||||
compatible = "brcm,bcm2711-gpio";
|
||||
reg = <0x7e200000 0xb4>;
|
||||
interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <0x02>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <0x02>;
|
||||
pinctrl-names = "default";
|
||||
bootph-all;
|
||||
|
||||
// UART
|
||||
uart0_ctsrts_gpio30: uart0_ctsrts_gpio30 {
|
||||
brcm,pins = <30>, <31>;
|
||||
brcm,pull = <2>, <0>;
|
||||
brcm,function = <7>;
|
||||
};
|
||||
uart0_gpio32: uart0_gpio32 {
|
||||
brcm,pins = <32>, <33>;
|
||||
brcm,pull = <0>, <2>;
|
||||
brcm,function = <8>;
|
||||
};
|
||||
uart1_gpio14: uart1_gpio14 {
|
||||
brcm,pins = <14>, <15>;
|
||||
brcm,function = <2>;
|
||||
bootph-all;
|
||||
};
|
||||
uart2_gpio: uart2_pins {
|
||||
brcm,pins = <0>, <1>;
|
||||
brcm,function = <3>;
|
||||
brcm,pull = <0>, <2>;
|
||||
};
|
||||
|
||||
// I²C
|
||||
i2c0if_gpio0: i2c0if-gpio0 {
|
||||
brcm,pins = <0>, <1>;
|
||||
brcm,function = <4>;
|
||||
};
|
||||
i2c0if_gpio44: i2c0if-gpio44 {
|
||||
brcm,pins = <44>, <45>;
|
||||
brcm,function = <5>;
|
||||
};
|
||||
i2c1_gpio: i2c1 {
|
||||
brcm,pins = <2>, <3>;
|
||||
brcm,function = <4>;
|
||||
brcm,pull = <2>;
|
||||
};
|
||||
i2c3_gpio: i2c3 {
|
||||
brcm,pins = <4>, <5>;
|
||||
brcm,function = <2>;
|
||||
brcm,pull = <2>;
|
||||
};
|
||||
i2c4_gpio: i2c4 {
|
||||
brcm,pins = <8>, <9>;
|
||||
brcm,function = <2>;
|
||||
brcm,pull = <2>;
|
||||
};
|
||||
i2c5_gpio: i2c5 {
|
||||
brcm,pins = <12>, <13>;
|
||||
brcm,function = <2>;
|
||||
brcm,pull = <2>;
|
||||
};
|
||||
i2c6_gpio: i2c6 {
|
||||
brcm,pins = <22>, <23>;
|
||||
brcm,function = <2>;
|
||||
brcm,pull = <2>;
|
||||
};
|
||||
|
||||
// SPI
|
||||
spi0_gpio: spi0_pins {
|
||||
brcm,pins = <9>, <10>, <11>;
|
||||
brcm,function = <4>;
|
||||
};
|
||||
spi0_cs_gpio: spi0_cs_pins {
|
||||
brcm,pins = <8>, <7>;
|
||||
brcm,function = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
uart0: serial@7e201000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x7e201000 0x200>;
|
||||
interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x13>,
|
||||
<&cprman 0x14>;
|
||||
clock-names = "uartclk",
|
||||
"apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart0_ctsrts_gpio30>, <&uart0_gpio32>;
|
||||
uart-has-rtscts;
|
||||
status = "okay";
|
||||
skip-init;
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
aux: aux@7e215000 {
|
||||
compatible = "brcm,bcm2835-aux";
|
||||
#clock-cells = <0x01>;
|
||||
reg = <0x7e215000 0x08>;
|
||||
clocks = <&cprman 0x14>;
|
||||
};
|
||||
|
||||
uart1: serial@7e215040 {
|
||||
compatible = "brcm,bcm2835-aux-uart";
|
||||
reg = <0x7e215040 0x40>;
|
||||
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&aux 0x00>;
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart1_gpio14>;
|
||||
skip-init;
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
i2c0if: i2c@7e205000 {
|
||||
compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
|
||||
reg = <0x7e205000 0x200>;
|
||||
interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x14>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "disabled";
|
||||
clock-frequency = <0x186a0>;
|
||||
};
|
||||
|
||||
i2c0mux: i2c0mux {
|
||||
compatible = "i2c-mux-pinctrl";
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
i2c-parent = <&i2c0if>;
|
||||
status = "disabled";
|
||||
pinctrl-names = "i2c0", "i2c_csi_dsi";
|
||||
pinctrl-0 = <&i2c0if_gpio0>;
|
||||
pinctrl-1 = <&i2c0if_gpio44>;
|
||||
|
||||
i2c0: i2c@0 {
|
||||
reg = <0x00>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
};
|
||||
|
||||
i2c_csi_dsi: i2c@1 {
|
||||
reg = <0x01>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
};
|
||||
};
|
||||
i2c1: i2c@7e804000 {
|
||||
compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
|
||||
reg = <0x7e804000 0x1000>;
|
||||
interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x14>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_gpio>;
|
||||
clock-frequency = <0x186a0>;
|
||||
};
|
||||
// TODO: memory access crashes on qemu (not implemented?)
|
||||
i2c3: i2c@7e205600 {
|
||||
compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
|
||||
reg = <0x7e205600 0x200>;
|
||||
interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x14>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "disabled";
|
||||
pinctrl-0 = <&i2c3_gpio>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
// TODO: memory access crashes on qemu (not implemented?)
|
||||
i2c4: i2c@7e205800 {
|
||||
compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
|
||||
reg = <0x7e205800 0x200>;
|
||||
interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x14>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "disabled";
|
||||
pinctrl-0 = <&i2c4_gpio>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
// TODO: memory access crashes on qemu (not implemented?)
|
||||
i2c5: i2c@7e205a00 {
|
||||
compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
|
||||
reg = <0x7e205a00 0x200>;
|
||||
interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x14>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "disabled";
|
||||
pinctrl-0 = <&i2c5_gpio>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
// TODO: memory access crashes on qemu (not implemented?)
|
||||
i2c6: i2c@7e205c00 {
|
||||
compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
|
||||
reg = <0x7e205c00 0x200>;
|
||||
interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x14>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "disabled";
|
||||
pinctrl-0 = <&i2c6_gpio>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
spi0: spi@7e204000 {
|
||||
compatible = "brcm,bcm2835-spi";
|
||||
reg = <0x7e204000 0x200>;
|
||||
interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x14>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "okay";
|
||||
dmas = <&dma 0x06>,
|
||||
<&dma 0x07>;
|
||||
dma-names = "tx", "rx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi0_gpio>, <&spi0_cs_gpio>;
|
||||
cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
|
||||
|
||||
spi0_0: spidev@0 {
|
||||
compatible = "spidev";
|
||||
reg = <0x00>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
spi-max-frequency = <125000000>;
|
||||
};
|
||||
|
||||
spi0_1: spidev@1 {
|
||||
compatible = "spidev";
|
||||
reg = <0x01>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
spi-max-frequency = <125000000>;
|
||||
};
|
||||
};
|
||||
|
||||
l1_intc: local_intc@40000000 {
|
||||
compatible = "brcm,bcm2836-l1-intc";
|
||||
reg = <0x40000000 0x100>;
|
||||
};
|
||||
|
||||
gicv2: interrupt-controller@40041000 {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <0x03>;
|
||||
compatible = "arm,gic-400";
|
||||
reg = <0x40041000 0x1000>,
|
||||
<0x40042000 0x2000>,
|
||||
<0x40044000 0x2000>,
|
||||
<0x40046000 0x2000>;
|
||||
interrupts = <GIC_PPI 9 (IRQ_TYPE_LEVEL_HIGH | GIC_CPU_MASK_SIMPLE(4))>;
|
||||
};
|
||||
|
||||
avs_monitor: avs-monitor@7d5d2000 {
|
||||
compatible = "brcm,bcm2711-avs-monitor", "syscon", "simple-mfd";
|
||||
reg = <0x7d5d2000 0xf00>;
|
||||
};
|
||||
|
||||
dma: dma@7e007000 {
|
||||
compatible = "brcm,bcm2835-dma";
|
||||
reg = <0x7e007000 0xb00>;
|
||||
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "dma0",
|
||||
"dma1",
|
||||
"dma2",
|
||||
"dma3",
|
||||
"dma4",
|
||||
"dma5",
|
||||
"dma6",
|
||||
"dma7",
|
||||
"dma8",
|
||||
"dma9",
|
||||
"dma10";
|
||||
#dma-cells = <0x01>;
|
||||
brcm,dma-channel-mask = <0x7f5>;
|
||||
};
|
||||
|
||||
pm_wdt: watchdog@7e100000 {
|
||||
compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
|
||||
#power-domain-cells = <0x01>;
|
||||
#reset-cells = <0x01>;
|
||||
reg = <0x7e100000 0x114>,
|
||||
<0x7e00a000 0x24>,
|
||||
<0x7ec11000 0x20>;
|
||||
clocks = <&cprman 0x15>,
|
||||
<&cprman 0x1d>,
|
||||
<&cprman 0x17>,
|
||||
<&cprman 0x16>;
|
||||
clock-names = "v3d", "peri_image", "h264", "isp";
|
||||
system-power-controller;
|
||||
};
|
||||
|
||||
uart2: serial@7e201400 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x7e201400 0x200>;
|
||||
interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x13>,
|
||||
<&cprman 0x14>;
|
||||
clock-names = "uartclk",
|
||||
"apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
pinctrl-0 = <&uart2_gpio>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart3: serial@7e201600 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x7e201600 0x200>;
|
||||
interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x13>,
|
||||
<&cprman 0x14>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart4: serial@7e201800 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x7e201800 0x200>;
|
||||
interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x13>,
|
||||
<&cprman 0x14>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart5: serial@7e201a00 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x7e201a00 0x200>;
|
||||
interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cprman 0x13>,
|
||||
<&cprman 0x14>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
clk_dvp: clock@7ef00000 {
|
||||
compatible = "brcm,brcm2711-dvp";
|
||||
reg = <0x7ef00000 0x10>;
|
||||
clocks = <&clk_108m>;
|
||||
#clock-cells = <0x01>;
|
||||
#reset-cells = <0x01>;
|
||||
};
|
||||
|
||||
l2_intc: interrupt-controller@7ef00100 {
|
||||
compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc";
|
||||
reg = <0x7ef00100 0x30>;
|
||||
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <0x01>;
|
||||
};
|
||||
|
||||
firmware: firmware {
|
||||
compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x01>;
|
||||
mboxes = <&mbox>;
|
||||
dma-ranges;
|
||||
|
||||
clk_firmware: clocks {
|
||||
compatible = "raspberrypi,firmware-clocks";
|
||||
#clock-cells = <0x01>;
|
||||
};
|
||||
|
||||
gpio_firmware: gpio {
|
||||
compatible = "raspberrypi,firmware-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <0x02>;
|
||||
status = "okay";
|
||||
gpio-line-names = "BT_ON", "WL_ON", "PWR_LED_OFF", "GLOBAL_RESET", "VDD_SD_IO_SEL", "CAM_GPIO", "SD_PWR_ON", "";
|
||||
};
|
||||
|
||||
firmware_reset: reset {
|
||||
compatible = "raspberrypi,firmware-reset";
|
||||
#reset-cells = <0x01>;
|
||||
};
|
||||
};
|
||||
|
||||
power: power {
|
||||
compatible = "raspberrypi,bcm2835-power";
|
||||
firmware = <&firmware>;
|
||||
#power-domain-cells = <0x01>;
|
||||
};
|
||||
|
||||
vchiq: mailbox@7e00b840 {
|
||||
compatible = "brcm,bcm2835-vchiq";
|
||||
reg = <0x7e00b840 0x3c>;
|
||||
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
clocks {
|
||||
clk_osc: clk-osc {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0x00>;
|
||||
clock-output-names = "osc";
|
||||
clock-frequency = <54000000>;
|
||||
};
|
||||
|
||||
clk_usb: clk-usb {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0x00>;
|
||||
clock-output-names = "otg";
|
||||
clock-frequency = <480000000>;
|
||||
};
|
||||
};
|
||||
|
||||
clk_27m: clk-27M {
|
||||
#clock-cells = <0x00>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <27000000>;
|
||||
clock-output-names = "27MHz-clock";
|
||||
};
|
||||
|
||||
clk_108m: clk-108M {
|
||||
#clock-cells = <0x00>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <108000000>;
|
||||
clock-output-names = "108MHz-clock";
|
||||
};
|
||||
|
||||
pmu: arm-pmu {
|
||||
compatible = "arm,cortex-a72-pmu", "arm,armv8-pmuv3";
|
||||
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-affinity = <0x21>,
|
||||
<0x22>,
|
||||
<0x23>,
|
||||
<0x24>;
|
||||
};
|
||||
|
||||
arm_timer: timer {
|
||||
compatible = "arm,armv8-timer";
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 15 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 16 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
arm,cpu-registers-not-fw-configured;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
enable-method = "brcm,bcm2836-smp";
|
||||
|
||||
cpu0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a72";
|
||||
reg = <0x00>;
|
||||
enable-method = "spin-table";
|
||||
cpu-release-addr = <0x00 0xd8>;
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a72";
|
||||
reg = <0x01>;
|
||||
enable-method = "spin-table";
|
||||
cpu-release-addr = <0x00 0xe0>;
|
||||
};
|
||||
|
||||
cpu2: cpu@2 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a72";
|
||||
reg = <0x02>;
|
||||
enable-method = "spin-table";
|
||||
cpu-release-addr = <0x00 0xe8>;
|
||||
};
|
||||
|
||||
cpu3: cpu@3 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a72";
|
||||
reg = <0x03>;
|
||||
enable-method = "spin-table";
|
||||
cpu-release-addr = <0x00 0xf0>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_act: led-act {
|
||||
label = "ACT";
|
||||
default-state = "keep";
|
||||
linux,default-trigger = "heartbeat";
|
||||
gpios = <&gpio 0x2a 0x00>;
|
||||
};
|
||||
|
||||
led_pwr: led-pwr {
|
||||
label = "PWR";
|
||||
gpios = <&gpio_firmware 0x02 0x01>;
|
||||
default-state = "keep";
|
||||
linux,default-trigger = "default-on";
|
||||
};
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00 0x00 0x00>;
|
||||
};
|
||||
|
||||
sd_io_1v8_reg {
|
||||
compatible = "regulator-gpio";
|
||||
regulator-name = "vdd-sd-io";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-settling-time-us = <0x1388>;
|
||||
gpios = <&gpio_firmware 0x04 0x00>;
|
||||
states = <3300000 0x01>,
|
||||
<1800000 0x00>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sd_vcc_reg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc-sd";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
enable-active-high;
|
||||
gpio = <&gpio_firmware 0x06 0x00>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#define GIC_SPI 0
|
||||
#define GIC_PPI 1
|
||||
|
||||
#define GIC_CPU_MASK_RAW(x) ((x) << 8)
|
||||
#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1)
|
||||
|
||||
#define IRQ_TYPE_NONE 0
|
||||
#define IRQ_TYPE_EDGE_RISING 1
|
||||
#define IRQ_TYPE_EDGE_FALLING 2
|
||||
#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)
|
||||
#define IRQ_TYPE_LEVEL_HIGH 4
|
||||
#define IRQ_TYPE_LEVEL_LOW 8
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,319 @@
|
||||
/dts-v1/;
|
||||
|
||||
#define CLK_COREPLL 0
|
||||
#define CLK_DDRPLL 1
|
||||
#define CLK_GEMGXLPLL 2
|
||||
#define CLK_DVFSCOREPLL 3
|
||||
#define CLK_HFPCLKPLL 4
|
||||
#define CLK_CLTXPLL 5
|
||||
#define CLK_TLCLK 6
|
||||
#define CLK_PCLK 7
|
||||
#define CLK_PCIE_AUX 8
|
||||
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000", "sifive,fu740";
|
||||
model = "SiFive HiFive Unmatched";
|
||||
|
||||
aliases {
|
||||
serial0 = "/soc/serial@10010000";
|
||||
serial1 = "/soc/serial@10011000";
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0";
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
timebase-frequency = <1000000>;
|
||||
|
||||
cpu0: cpu@0 {
|
||||
compatible = "sifive,bullet0", "riscv";
|
||||
device_type = "cpu";
|
||||
i-cache-block-size = <64>;
|
||||
i-cache-sets = <128>;
|
||||
i-cache-size = <16384>;
|
||||
next-level-cache = <&ccache>;
|
||||
reg = <0>;
|
||||
riscv,isa = "rv64imac";
|
||||
status = "disabled";
|
||||
|
||||
cpu0_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
|
||||
device_type = "cpu";
|
||||
d-cache-block-size = <64>;
|
||||
d-cache-sets = <64>;
|
||||
d-cache-size = <32768>;
|
||||
i-cache-block-size = <64>;
|
||||
i-cache-sets = <128>;
|
||||
i-cache-size = <32768>;
|
||||
i-tlb-sets = <1>;
|
||||
i-tlb-size = <40>;
|
||||
d-tlb-sets = <1>;
|
||||
d-tlb-size = <40>;
|
||||
mmu-type = "riscv,sv39";
|
||||
next-level-cache = <&ccache>;
|
||||
reg = <1>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
tlb-split;
|
||||
|
||||
cpu1_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
|
||||
cpu2: cpu@2 {
|
||||
compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
|
||||
device_type = "cpu";
|
||||
d-cache-block-size = <64>;
|
||||
d-cache-sets = <64>;
|
||||
d-cache-size = <32768>;
|
||||
i-cache-block-size = <64>;
|
||||
i-cache-sets = <128>;
|
||||
i-cache-size = <32768>;
|
||||
d-tlb-sets = <1>;
|
||||
d-tlb-size = <40>;
|
||||
i-tlb-sets = <1>;
|
||||
i-tlb-size = <40>;
|
||||
mmu-type = "riscv,sv39";
|
||||
next-level-cache = <&ccache>;
|
||||
reg = <2>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
tlb-split;
|
||||
|
||||
cpu2_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
|
||||
cpu3: cpu@3 {
|
||||
compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
|
||||
device_type = "cpu";
|
||||
d-cache-block-size = <64>;
|
||||
d-cache-sets = <64>;
|
||||
d-cache-size = <32768>;
|
||||
i-cache-block-size = <64>;
|
||||
i-cache-sets = <128>;
|
||||
i-cache-size = <32768>;
|
||||
d-tlb-sets = <1>;
|
||||
d-tlb-size = <40>;
|
||||
i-tlb-sets = <1>;
|
||||
i-tlb-size = <40>;
|
||||
mmu-type = "riscv,sv39";
|
||||
next-level-cache = <&ccache>;
|
||||
reg = <3>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
tlb-split;
|
||||
|
||||
cpu3_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
|
||||
cpu4: cpu@4 {
|
||||
compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
|
||||
device_type = "cpu";
|
||||
d-cache-block-size = <64>;
|
||||
d-cache-sets = <64>;
|
||||
d-cache-size = <32768>;
|
||||
i-cache-block-size = <64>;
|
||||
i-cache-sets = <128>;
|
||||
i-cache-size = <32768>;
|
||||
d-tlb-sets = <1>;
|
||||
d-tlb-size = <40>;
|
||||
i-tlb-sets = <1>;
|
||||
i-tlb-size = <40>;
|
||||
mmu-type = "riscv,sv39";
|
||||
next-level-cache = <&ccache>;
|
||||
reg = <4>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
tlb-split;
|
||||
|
||||
cpu4_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
plic: interrupt-controller@c000000 {
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
compatible = "sifive,fu540-c000-plic", "sifive,plic-1.0.0";
|
||||
reg = <0x00 0xc000000 0x00 0x4000000>;
|
||||
riscv,ndev = <69>;
|
||||
interrupt-controller;
|
||||
interrupts-extended = <&cpu0_intc 0xffffffff>,
|
||||
<&cpu1_intc 0xffffffff>,
|
||||
<&cpu1_intc 0x09>,
|
||||
<&cpu2_intc 0xffffffff>,
|
||||
<&cpu2_intc 0x09>,
|
||||
<&cpu3_intc 0xffffffff>,
|
||||
<&cpu3_intc 0x09>,
|
||||
<&cpu4_intc 0xffffffff>,
|
||||
<&cpu4_intc 0x09>;
|
||||
};
|
||||
|
||||
prci: clock-controller@10000000 {
|
||||
compatible = "sifive,fu740-c000-prci";
|
||||
reg = <0x00 0x10000000 0x00 0x1000>;
|
||||
clocks = <&clk_hfclk>, <&clk_rtcclk>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
uart0: serial@10010000 {
|
||||
compatible = "sifive,fu740-c000-uart", "sifive,uart0";
|
||||
reg = <0x00 0x10010000 0x00 0x1000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <39>;
|
||||
clocks = <&prci CLK_PCLK>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
uart1: serial@10011000 {
|
||||
compatible = "sifive,fu740-c000-uart", "sifive,uart0";
|
||||
reg = <0x00 0x10011000 0x00 0x1000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <40>;
|
||||
clocks = <&prci CLK_PCLK>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ccache: cache-controller@2010000 {
|
||||
compatible = "sifive,fu740-c000-ccache", "cache";
|
||||
cache-block-size = <64>;
|
||||
cache-level = <2>;
|
||||
cache-sets = <2048>;
|
||||
cache-size = <0x200000>;
|
||||
cache-unified;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <0x13>, <0x15>, <0x16>, <0x14>;
|
||||
reg = <0x00 0x2010000 0x00 0x1000>;
|
||||
};
|
||||
|
||||
pwm0: pwm@10020000 {
|
||||
compatible = "sifive,fu740-c000-pwm", "sifive,pwm0";
|
||||
reg = <0x00 0x10020000 0x00 0x1000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <44>, <45>, <46>, <47>;
|
||||
clocks = <&prci CLK_PCLK>;
|
||||
#pwm-cells = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pwm1: pwm@10021000 {
|
||||
compatible = "sifive,fu740-c000-pwm", "sifive,pwm0";
|
||||
reg = <0x00 0x10021000 0x00 0x1000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <48>, <49>, <50>, <51>;
|
||||
clocks = <&prci CLK_PCLK>;
|
||||
#pwm-cells = <3>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c0: i2c@10030000 {
|
||||
compatible = "sifive,fu740-c000-i2c", "sifive,i2c0";
|
||||
reg = <0x00 0x10030000 0x00 0x1000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <52>;
|
||||
clocks = <&prci CLK_PCLK>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c1: i2c@10031000 {
|
||||
compatible = "sifive,fu740-c000-i2c", "sifive,i2c0";
|
||||
reg = <0x00 0x10031000 0x00 0x1000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <53>;
|
||||
clocks = <&prci CLK_PCLK>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x00 0x80000000 0x04 0x00>;
|
||||
};
|
||||
|
||||
leds: pwmleds {
|
||||
compatible = "pwm-leds";
|
||||
|
||||
green-d12 {
|
||||
label = "green:d12";
|
||||
pwms = <&pwm0 0 7812500 0x01>;
|
||||
active-low = <1>;
|
||||
max-brightness = <255>;
|
||||
linux,default-trigger = "none";
|
||||
};
|
||||
|
||||
green-d2 {
|
||||
label = "green:d2";
|
||||
pwms = <&pwm0 1 7812500 0x01>;
|
||||
active-low = <1>;
|
||||
max-brightness = <255>;
|
||||
linux,default-trigger = "none";
|
||||
};
|
||||
|
||||
red-d2 {
|
||||
label = "red:d2";
|
||||
pwms = <&pwm0 2 7812500 0x01>;
|
||||
active-low = <0x01>;
|
||||
max-brightness = <0xff>;
|
||||
linux,default-trigger = "none";
|
||||
};
|
||||
|
||||
blue-d2 {
|
||||
label = "blue:d2";
|
||||
pwms = <&pwm0 3 7812500 0x01>;
|
||||
active-low = <1>;
|
||||
max-brightness = <255>;
|
||||
linux,default-trigger = "none";
|
||||
};
|
||||
};
|
||||
|
||||
clk_hfclk: hfclk {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <26000000>;
|
||||
clock-output-names = "hfclk";
|
||||
};
|
||||
|
||||
clk_rtcclk: rtcclk {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <1000000>;
|
||||
clock-output-names = "rtcclk";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,308 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
|
||||
/*
|
||||
* Copyright (C) 2022 Emil Renner Berthing <kernel@esmil.dk>
|
||||
* Copyright (C) 2022 StarFive Technology Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __JH7110_PINFUNC_H__
|
||||
#define __JH7110_PINFUNC_H__
|
||||
|
||||
/*
|
||||
* mux bits:
|
||||
* | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 |
|
||||
* | din | dout | doen | function | gpio nr |
|
||||
*
|
||||
* dout: output signal
|
||||
* doen: output enable signal
|
||||
* din: optional input signal, 0xff = none
|
||||
* function: function selector
|
||||
* gpio nr: gpio number, 0 - 63
|
||||
*/
|
||||
#define GPIOMUX(n, dout, doen, din) ( \
|
||||
(((din) & 0xff) << 24) | \
|
||||
(((dout) & 0xff) << 16) | \
|
||||
(((doen) & 0x3f) << 10) | \
|
||||
((n) & 0x3f))
|
||||
|
||||
#define PINMUX(n, func) ((1 << 10) | (((func) & 0x3) << 8) | ((n) & 0xff))
|
||||
|
||||
/* sys_iomux dout */
|
||||
#define GPOUT_LOW 0
|
||||
#define GPOUT_HIGH 1
|
||||
#define GPOUT_SYS_WAVE511_UART_TX 2
|
||||
#define GPOUT_SYS_CAN0_STBY 3
|
||||
#define GPOUT_SYS_CAN0_TST_NEXT_BIT 4
|
||||
#define GPOUT_SYS_CAN0_TST_SAMPLE_POINT 5
|
||||
#define GPOUT_SYS_CAN0_TXD 6
|
||||
#define GPOUT_SYS_USB_DRIVE_VBUS 7
|
||||
#define GPOUT_SYS_QSPI_CS1 8
|
||||
#define GPOUT_SYS_SPDIF 9
|
||||
#define GPOUT_SYS_HDMI_CEC_SDA 10
|
||||
#define GPOUT_SYS_HDMI_DDC_SCL 11
|
||||
#define GPOUT_SYS_HDMI_DDC_SDA 12
|
||||
#define GPOUT_SYS_WATCHDOG 13
|
||||
#define GPOUT_SYS_I2C0_CLK 14
|
||||
#define GPOUT_SYS_I2C0_DATA 15
|
||||
#define GPOUT_SYS_SDIO0_BACK_END_POWER 16
|
||||
#define GPOUT_SYS_SDIO0_CARD_POWER_EN 17
|
||||
#define GPOUT_SYS_SDIO0_CCMD_OD_PULLUP_EN 18
|
||||
#define GPOUT_SYS_SDIO0_RST 19
|
||||
#define GPOUT_SYS_UART0_TX 20
|
||||
#define GPOUT_SYS_HIFI4_JTAG_TDO 21
|
||||
#define GPOUT_SYS_JTAG_TDO 22
|
||||
#define GPOUT_SYS_PDM_MCLK 23
|
||||
#define GPOUT_SYS_PWM_CHANNEL0 24
|
||||
#define GPOUT_SYS_PWM_CHANNEL1 25
|
||||
#define GPOUT_SYS_PWM_CHANNEL2 26
|
||||
#define GPOUT_SYS_PWM_CHANNEL3 27
|
||||
#define GPOUT_SYS_PWMDAC_LEFT 28
|
||||
#define GPOUT_SYS_PWMDAC_RIGHT 29
|
||||
#define GPOUT_SYS_SPI0_CLK 30
|
||||
#define GPOUT_SYS_SPI0_FSS 31
|
||||
#define GPOUT_SYS_SPI0_TXD 32
|
||||
#define GPOUT_SYS_GMAC_PHYCLK 33
|
||||
#define GPOUT_SYS_I2SRX_BCLK 34
|
||||
#define GPOUT_SYS_I2SRX_LRCK 35
|
||||
#define GPOUT_SYS_I2STX0_BCLK 36
|
||||
#define GPOUT_SYS_I2STX0_LRCK 37
|
||||
#define GPOUT_SYS_MCLK 38
|
||||
#define GPOUT_SYS_TDM_CLK 39
|
||||
#define GPOUT_SYS_TDM_SYNC 40
|
||||
#define GPOUT_SYS_TDM_TXD 41
|
||||
#define GPOUT_SYS_TRACE_DATA0 42
|
||||
#define GPOUT_SYS_TRACE_DATA1 43
|
||||
#define GPOUT_SYS_TRACE_DATA2 44
|
||||
#define GPOUT_SYS_TRACE_DATA3 45
|
||||
#define GPOUT_SYS_TRACE_REF 46
|
||||
#define GPOUT_SYS_CAN1_STBY 47
|
||||
#define GPOUT_SYS_CAN1_TST_NEXT_BIT 48
|
||||
#define GPOUT_SYS_CAN1_TST_SAMPLE_POINT 49
|
||||
#define GPOUT_SYS_CAN1_TXD 50
|
||||
#define GPOUT_SYS_I2C1_CLK 51
|
||||
#define GPOUT_SYS_I2C1_DATA 52
|
||||
#define GPOUT_SYS_SDIO1_BACK_END_POWER 53
|
||||
#define GPOUT_SYS_SDIO1_CARD_POWER_EN 54
|
||||
#define GPOUT_SYS_SDIO1_CLK 55
|
||||
#define GPOUT_SYS_SDIO1_CMD_OD_PULLUP_EN 56
|
||||
#define GPOUT_SYS_SDIO1_CMD 57
|
||||
#define GPOUT_SYS_SDIO1_DATA0 58
|
||||
#define GPOUT_SYS_SDIO1_DATA1 59
|
||||
#define GPOUT_SYS_SDIO1_DATA2 60
|
||||
#define GPOUT_SYS_SDIO1_DATA3 61
|
||||
#define GPOUT_SYS_SDIO1_DATA4 62
|
||||
#define GPOUT_SYS_SDIO1_DATA5 63
|
||||
#define GPOUT_SYS_SDIO1_DATA6 64
|
||||
#define GPOUT_SYS_SDIO1_DATA7 65
|
||||
#define GPOUT_SYS_SDIO1_RST 66
|
||||
#define GPOUT_SYS_UART1_RTS 67
|
||||
#define GPOUT_SYS_UART1_TX 68
|
||||
#define GPOUT_SYS_I2STX1_SDO0 69
|
||||
#define GPOUT_SYS_I2STX1_SDO1 70
|
||||
#define GPOUT_SYS_I2STX1_SDO2 71
|
||||
#define GPOUT_SYS_I2STX1_SDO3 72
|
||||
#define GPOUT_SYS_SPI1_CLK 73
|
||||
#define GPOUT_SYS_SPI1_FSS 74
|
||||
#define GPOUT_SYS_SPI1_TXD 75
|
||||
#define GPOUT_SYS_I2C2_CLK 76
|
||||
#define GPOUT_SYS_I2C2_DATA 77
|
||||
#define GPOUT_SYS_UART2_RTS 78
|
||||
#define GPOUT_SYS_UART2_TX 79
|
||||
#define GPOUT_SYS_SPI2_CLK 80
|
||||
#define GPOUT_SYS_SPI2_FSS 81
|
||||
#define GPOUT_SYS_SPI2_TXD 82
|
||||
#define GPOUT_SYS_I2C3_CLK 83
|
||||
#define GPOUT_SYS_I2C3_DATA 84
|
||||
#define GPOUT_SYS_UART3_TX 85
|
||||
#define GPOUT_SYS_SPI3_CLK 86
|
||||
#define GPOUT_SYS_SPI3_FSS 87
|
||||
#define GPOUT_SYS_SPI3_TXD 88
|
||||
#define GPOUT_SYS_I2C4_CLK 89
|
||||
#define GPOUT_SYS_I2C4_DATA 90
|
||||
#define GPOUT_SYS_UART4_RTS 91
|
||||
#define GPOUT_SYS_UART4_TX 92
|
||||
#define GPOUT_SYS_SPI4_CLK 93
|
||||
#define GPOUT_SYS_SPI4_FSS 94
|
||||
#define GPOUT_SYS_SPI4_TXD 95
|
||||
#define GPOUT_SYS_I2C5_CLK 96
|
||||
#define GPOUT_SYS_I2C5_DATA 97
|
||||
#define GPOUT_SYS_UART5_RTS 98
|
||||
#define GPOUT_SYS_UART5_TX 99
|
||||
#define GPOUT_SYS_SPI5_CLK 100
|
||||
#define GPOUT_SYS_SPI5_FSS 101
|
||||
#define GPOUT_SYS_SPI5_TXD 102
|
||||
#define GPOUT_SYS_I2C6_CLK 103
|
||||
#define GPOUT_SYS_I2C6_DATA 104
|
||||
#define GPOUT_SYS_SPI6_CLK 105
|
||||
#define GPOUT_SYS_SPI6_FSS 106
|
||||
#define GPOUT_SYS_SPI6_TXD 107
|
||||
|
||||
/* aon_iomux dout */
|
||||
#define GPOUT_AON_CLK_32K_OUT 2
|
||||
#define GPOUT_AON_PTC0_PWM4 3
|
||||
#define GPOUT_AON_PTC0_PWM5 4
|
||||
#define GPOUT_AON_PTC0_PWM6 5
|
||||
#define GPOUT_AON_PTC0_PWM7 6
|
||||
#define GPOUT_AON_CLK_GCLK0 7
|
||||
#define GPOUT_AON_CLK_GCLK1 8
|
||||
#define GPOUT_AON_CLK_GCLK2 9
|
||||
|
||||
/* sys_iomux doen */
|
||||
#define GPOEN_ENABLE 0
|
||||
#define GPOEN_DISABLE 1
|
||||
#define GPOEN_SYS_HDMI_CEC_SDA 2
|
||||
#define GPOEN_SYS_HDMI_DDC_SCL 3
|
||||
#define GPOEN_SYS_HDMI_DDC_SDA 4
|
||||
#define GPOEN_SYS_I2C0_CLK 5
|
||||
#define GPOEN_SYS_I2C0_DATA 6
|
||||
#define GPOEN_SYS_HIFI4_JTAG_TDO 7
|
||||
#define GPOEN_SYS_JTAG_TDO 8
|
||||
#define GPOEN_SYS_PWM0_CHANNEL0 9
|
||||
#define GPOEN_SYS_PWM0_CHANNEL1 10
|
||||
#define GPOEN_SYS_PWM0_CHANNEL2 11
|
||||
#define GPOEN_SYS_PWM0_CHANNEL3 12
|
||||
#define GPOEN_SYS_SPI0_NSSPCTL 13
|
||||
#define GPOEN_SYS_SPI0_NSSP 14
|
||||
#define GPOEN_SYS_TDM_SYNC 15
|
||||
#define GPOEN_SYS_TDM_TXD 16
|
||||
#define GPOEN_SYS_I2C1_CLK 17
|
||||
#define GPOEN_SYS_I2C1_DATA 18
|
||||
#define GPOEN_SYS_SDIO1_CMD 19
|
||||
#define GPOEN_SYS_SDIO1_DATA0 20
|
||||
#define GPOEN_SYS_SDIO1_DATA1 21
|
||||
#define GPOEN_SYS_SDIO1_DATA2 22
|
||||
#define GPOEN_SYS_SDIO1_DATA3 23
|
||||
#define GPOEN_SYS_SDIO1_DATA4 24
|
||||
#define GPOEN_SYS_SDIO1_DATA5 25
|
||||
#define GPOEN_SYS_SDIO1_DATA6 26
|
||||
#define GPOEN_SYS_SDIO1_DATA7 27
|
||||
#define GPOEN_SYS_SPI1_NSSPCTL 28
|
||||
#define GPOEN_SYS_SPI1_NSSP 29
|
||||
#define GPOEN_SYS_I2C2_CLK 30
|
||||
#define GPOEN_SYS_I2C2_DATA 31
|
||||
#define GPOEN_SYS_SPI2_NSSPCTL 32
|
||||
#define GPOEN_SYS_SPI2_NSSP 33
|
||||
#define GPOEN_SYS_I2C3_CLK 34
|
||||
#define GPOEN_SYS_I2C3_DATA 35
|
||||
#define GPOEN_SYS_SPI3_NSSPCTL 36
|
||||
#define GPOEN_SYS_SPI3_NSSP 37
|
||||
#define GPOEN_SYS_I2C4_CLK 38
|
||||
#define GPOEN_SYS_I2C4_DATA 39
|
||||
#define GPOEN_SYS_SPI4_NSSPCTL 40
|
||||
#define GPOEN_SYS_SPI4_NSSP 41
|
||||
#define GPOEN_SYS_I2C5_CLK 42
|
||||
#define GPOEN_SYS_I2C5_DATA 43
|
||||
#define GPOEN_SYS_SPI5_NSSPCTL 44
|
||||
#define GPOEN_SYS_SPI5_NSSP 45
|
||||
#define GPOEN_SYS_I2C6_CLK 46
|
||||
#define GPOEN_SYS_I2C6_DATA 47
|
||||
#define GPOEN_SYS_SPI6_NSSPCTL 48
|
||||
#define GPOEN_SYS_SPI6_NSSP 49
|
||||
|
||||
/* aon_iomux doen */
|
||||
#define GPOEN_AON_PTC0_OE_N_4 2
|
||||
#define GPOEN_AON_PTC0_OE_N_5 3
|
||||
#define GPOEN_AON_PTC0_OE_N_6 4
|
||||
#define GPOEN_AON_PTC0_OE_N_7 5
|
||||
|
||||
/* sys_iomux gin */
|
||||
#define GPI_NONE 255
|
||||
|
||||
#define GPI_SYS_WAVE511_UART_RX 0
|
||||
#define GPI_SYS_CAN0_RXD 1
|
||||
#define GPI_SYS_USB_OVERCURRENT 2
|
||||
#define GPI_SYS_SPDIF 3
|
||||
#define GPI_SYS_JTAG_RST 4
|
||||
#define GPI_SYS_HDMI_CEC_SDA 5
|
||||
#define GPI_SYS_HDMI_DDC_SCL 6
|
||||
#define GPI_SYS_HDMI_DDC_SDA 7
|
||||
#define GPI_SYS_HDMI_HPD 8
|
||||
#define GPI_SYS_I2C0_CLK 9
|
||||
#define GPI_SYS_I2C0_DATA 10
|
||||
#define GPI_SYS_SDIO0_CD 11
|
||||
#define GPI_SYS_SDIO0_INT 12
|
||||
#define GPI_SYS_SDIO0_WP 13
|
||||
#define GPI_SYS_UART0_RX 14
|
||||
#define GPI_SYS_HIFI4_JTAG_TCK 15
|
||||
#define GPI_SYS_HIFI4_JTAG_TDI 16
|
||||
#define GPI_SYS_HIFI4_JTAG_TMS 17
|
||||
#define GPI_SYS_HIFI4_JTAG_RST 18
|
||||
#define GPI_SYS_JTAG_TDI 19
|
||||
#define GPI_SYS_JTAG_TMS 20
|
||||
#define GPI_SYS_PDM_DMIC0 21
|
||||
#define GPI_SYS_PDM_DMIC1 22
|
||||
#define GPI_SYS_I2SRX_SDIN0 23
|
||||
#define GPI_SYS_I2SRX_SDIN1 24
|
||||
#define GPI_SYS_I2SRX_SDIN2 25
|
||||
#define GPI_SYS_SPI0_CLK 26
|
||||
#define GPI_SYS_SPI0_FSS 27
|
||||
#define GPI_SYS_SPI0_RXD 28
|
||||
#define GPI_SYS_JTAG_TCK 29
|
||||
#define GPI_SYS_MCLK_EXT 30
|
||||
#define GPI_SYS_I2SRX_BCLK 31
|
||||
#define GPI_SYS_I2SRX_LRCK 32
|
||||
#define GPI_SYS_I2STX1_BCLK 33
|
||||
#define GPI_SYS_I2STX1_LRCK 34
|
||||
#define GPI_SYS_TDM_CLK 35
|
||||
#define GPI_SYS_TDM_RXD 36
|
||||
#define GPI_SYS_TDM_SYNC 37
|
||||
#define GPI_SYS_CAN1_RXD 38
|
||||
#define GPI_SYS_I2C1_CLK 39
|
||||
#define GPI_SYS_I2C1_DATA 40
|
||||
#define GPI_SYS_SDIO1_CD 41
|
||||
#define GPI_SYS_SDIO1_INT 42
|
||||
#define GPI_SYS_SDIO1_WP 43
|
||||
#define GPI_SYS_SDIO1_CMD 44
|
||||
#define GPI_SYS_SDIO1_DATA0 45
|
||||
#define GPI_SYS_SDIO1_DATA1 46
|
||||
#define GPI_SYS_SDIO1_DATA2 47
|
||||
#define GPI_SYS_SDIO1_DATA3 48
|
||||
#define GPI_SYS_SDIO1_DATA4 49
|
||||
#define GPI_SYS_SDIO1_DATA5 50
|
||||
#define GPI_SYS_SDIO1_DATA6 51
|
||||
#define GPI_SYS_SDIO1_DATA7 52
|
||||
#define GPI_SYS_SDIO1_STRB 53
|
||||
#define GPI_SYS_UART1_CTS 54
|
||||
#define GPI_SYS_UART1_RX 55
|
||||
#define GPI_SYS_SPI1_CLK 56
|
||||
#define GPI_SYS_SPI1_FSS 57
|
||||
#define GPI_SYS_SPI1_RXD 58
|
||||
#define GPI_SYS_I2C2_CLK 59
|
||||
#define GPI_SYS_I2C2_DATA 60
|
||||
#define GPI_SYS_UART2_CTS 61
|
||||
#define GPI_SYS_UART2_RX 62
|
||||
#define GPI_SYS_SPI2_CLK 63
|
||||
#define GPI_SYS_SPI2_FSS 64
|
||||
#define GPI_SYS_SPI2_RXD 65
|
||||
#define GPI_SYS_I2C3_CLK 66
|
||||
#define GPI_SYS_I2C3_DATA 67
|
||||
#define GPI_SYS_UART3_RX 68
|
||||
#define GPI_SYS_SPI3_CLK 69
|
||||
#define GPI_SYS_SPI3_FSS 70
|
||||
#define GPI_SYS_SPI3_RXD 71
|
||||
#define GPI_SYS_I2C4_CLK 72
|
||||
#define GPI_SYS_I2C4_DATA 73
|
||||
#define GPI_SYS_UART4_CTS 74
|
||||
#define GPI_SYS_UART4_RX 75
|
||||
#define GPI_SYS_SPI4_CLK 76
|
||||
#define GPI_SYS_SPI4_FSS 77
|
||||
#define GPI_SYS_SPI4_RXD 78
|
||||
#define GPI_SYS_I2C5_CLK 79
|
||||
#define GPI_SYS_I2C5_DATA 80
|
||||
#define GPI_SYS_UART5_CTS 81
|
||||
#define GPI_SYS_UART5_RX 82
|
||||
#define GPI_SYS_SPI5_CLK 83
|
||||
#define GPI_SYS_SPI5_FSS 84
|
||||
#define GPI_SYS_SPI5_RXD 85
|
||||
#define GPI_SYS_I2C6_CLK 86
|
||||
#define GPI_SYS_I2C6_DATA 87
|
||||
#define GPI_SYS_SPI6_CLK 88
|
||||
#define GPI_SYS_SPI6_FSS 89
|
||||
#define GPI_SYS_SPI6_RXD 90
|
||||
|
||||
/* aon_iomux gin */
|
||||
#define GPI_AON_PMU_GPIO_WAKEUP_0 0
|
||||
#define GPI_AON_PMU_GPIO_WAKEUP_1 1
|
||||
#define GPI_AON_PMU_GPIO_WAKEUP_2 2
|
||||
#define GPI_AON_PMU_GPIO_WAKEUP_3 3
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,7 @@
|
||||
#size-cells = <0x00>;
|
||||
timebase-frequency = <0x989680>;
|
||||
|
||||
cpu@0 {
|
||||
cpu0: cpu@0 {
|
||||
phandle = <0x01>;
|
||||
device_type = "cpu";
|
||||
reg = <0x00>;
|
||||
@@ -52,7 +52,7 @@
|
||||
riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
|
||||
mmu-type = "riscv,sv57";
|
||||
|
||||
interrupt-controller {
|
||||
cpu0_intc: interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
interrupt-controller;
|
||||
compatible = "riscv,cpu-intc";
|
||||
@@ -61,11 +61,9 @@
|
||||
};
|
||||
|
||||
cpu-map {
|
||||
|
||||
cluster0 {
|
||||
|
||||
core0 {
|
||||
cpu = <0x01>;
|
||||
cpu = <&cpu0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -186,7 +184,8 @@
|
||||
phandle = <0x03>;
|
||||
riscv,ndev = <0x5f>;
|
||||
reg = <0x00 0xc000000 0x00 0x600000>;
|
||||
interrupts-extended = <0x02 0x0b 0x02 0x09>;
|
||||
interrupts-extended = <&cpu0_intc 0x0b>,
|
||||
<&cpu0_intc 0x09>;
|
||||
interrupt-controller;
|
||||
compatible = "sifive,plic-1.0.0", "riscv,plic0";
|
||||
#address-cells = <0x00>;
|
||||
@@ -194,7 +193,8 @@
|
||||
};
|
||||
|
||||
clint@2000000 {
|
||||
interrupts-extended = <0x02 0x03 0x02 0x07>;
|
||||
interrupts-extended = <&cpu0_intc 0x03>,
|
||||
<&cpu0_intc 0x07>;
|
||||
reg = <0x00 0x2000000 0x00 0x10000>;
|
||||
compatible = "sifive,clint0", "riscv,clint0";
|
||||
};
|
||||
@@ -0,0 +1,252 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <0x02>;
|
||||
#size-cells = <0x02>;
|
||||
compatible = "sifive,hifive-unleashed-a00";
|
||||
model = "SiFive HiFive Unleashed A00";
|
||||
|
||||
chosen {
|
||||
linux,initrd-end = <0x00 0x87688400>;
|
||||
linux,initrd-start = <0x00 0x84200000>;
|
||||
stdout-path = "/soc/serial@10010000";
|
||||
};
|
||||
|
||||
aliases {
|
||||
serial0 = "/soc/serial@10010000";
|
||||
serial1 = "/soc/serial@10011000";
|
||||
ethernet0 = "/soc/ethernet@10090000";
|
||||
};
|
||||
|
||||
gpio-restart {
|
||||
compatible = "gpio-restart";
|
||||
gpios = <&gpio 0x0a 0x01>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
timebase-frequency = <0xf4240>;
|
||||
|
||||
cpu0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0x00>;
|
||||
status = "okay";
|
||||
compatible = "riscv";
|
||||
riscv,isa-extensions = "i", "m", "a", "c", "zicntr", "zicsr", "zifencei", "zihpm", "sdtrig";
|
||||
riscv,isa-base = "rv64i";
|
||||
riscv,isa = "rv64imac_zicntr_zicsr_zifencei_zihpm_sdtrig";
|
||||
|
||||
cpu0_intc: interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
interrupt-controller;
|
||||
compatible = "riscv,cpu-intc";
|
||||
phandle = <0x04>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
device_type = "cpu";
|
||||
reg = <0x01>;
|
||||
status = "okay";
|
||||
compatible = "riscv";
|
||||
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr", "zifencei", "zihpm", "sdtrig";
|
||||
riscv,isa-base = "rv64i";
|
||||
riscv,isa = "rv64imafdc_zicntr_zicsr_zifencei_zihpm_sdtrig";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu1_intc: interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
interrupt-controller;
|
||||
compatible = "riscv,cpu-intc";
|
||||
phandle = <0x03>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x00 0x80000000 0x00 0x8000000>;
|
||||
};
|
||||
|
||||
rtcclk: rtcclk {
|
||||
#clock-cells = <0x00>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <0xf4240>;
|
||||
clock-output-names = "rtcclk";
|
||||
phandle = <0x02>;
|
||||
};
|
||||
|
||||
hfclk: hfclk {
|
||||
#clock-cells = <0x00>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <0x1fca055>;
|
||||
clock-output-names = "hfclk";
|
||||
phandle = <0x01>;
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <0x02>;
|
||||
#size-cells = <0x02>;
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
uart0: serial@10010000 {
|
||||
interrupts = <4>;
|
||||
interrupt-parent = <&plic>;
|
||||
clocks = <&prci 0x03>;
|
||||
reg = <0x00 0x10010000 0x00 0x1000>;
|
||||
compatible = "sifive,uart0";
|
||||
};
|
||||
|
||||
uart1: serial@10011000 {
|
||||
interrupts = <5>;
|
||||
interrupt-parent = <&plic>;
|
||||
clocks = <&prci 0x03>;
|
||||
reg = <0x00 0x10011000 0x00 0x1000>;
|
||||
compatible = "sifive,uart0";
|
||||
};
|
||||
|
||||
pwm0: pwm@10020000 {
|
||||
#pwm-cells = <0>;
|
||||
clocks = <&prci 0x03>;
|
||||
interrupts = <42>, <43>, <44>, <45>;
|
||||
interrupt-parent = <&plic>;
|
||||
reg = <0x00 0x10020000 0x00 0x1000>;
|
||||
compatible = "sifive,pwm0";
|
||||
};
|
||||
|
||||
pwm1: pwm@10021000 {
|
||||
#pwm-cells = <0>;
|
||||
clocks = <&prci 0x03>;
|
||||
interrupts = <46>, <47>, <48>, <49>;
|
||||
interrupt-parent = <&plic>;
|
||||
reg = <0x00 0x10021000 0x00 0x1000>;
|
||||
compatible = "sifive,pwm0";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac0: ethernet@10090000 {
|
||||
#size-cells = <0x00>;
|
||||
#address-cells = <0x01>;
|
||||
local-mac-address = [52 54 00 12 34 56];
|
||||
clock-names = "pclk", "hclk";
|
||||
clocks = <&prci 0x02>, <&prci 0x02>;
|
||||
interrupts = <0x35>;
|
||||
interrupt-parent = <&plic>;
|
||||
phy-handle = <&gmac0_phy>;
|
||||
phy-mode = "gmii";
|
||||
reg-names = "control";
|
||||
reg = <0x00 0x10090000 0x00 0x2000>,
|
||||
<0x00 0x100a0000 0x00 0x1000>;
|
||||
compatible = "sifive,fu540-c000-gem";
|
||||
|
||||
gmac0_phy: ethernet-phy@0 {
|
||||
reg = <0x00>;
|
||||
};
|
||||
};
|
||||
|
||||
// spi@10040000 {
|
||||
// compatible = "sifive,spi0";
|
||||
// reg = <0x00 0x10040000 0x00 0x1000>;
|
||||
// interrupt-parent = <0x06>;
|
||||
// interrupts = <0x33>;
|
||||
// clocks = <0x05 0x03>;
|
||||
// #address-cells = <0x01>;
|
||||
// #size-cells = <0x00>;
|
||||
|
||||
// flash@0 {
|
||||
// compatible = "jedec,spi-nor";
|
||||
// reg = <0x00>;
|
||||
// spi-max-frequency = <0x2faf080>;
|
||||
// m25p,fast-read;
|
||||
// spi-tx-bus-width = <0x04>;
|
||||
// spi-rx-bus-width = <0x04>;
|
||||
// };
|
||||
// };
|
||||
|
||||
// spi@10050000 {
|
||||
// compatible = "sifive,spi0";
|
||||
// reg = <0x00 0x10050000 0x00 0x1000>;
|
||||
// interrupt-parent = <0x06>;
|
||||
// interrupts = <0x06>;
|
||||
// clocks = <0x05 0x03>;
|
||||
// #address-cells = <0x01>;
|
||||
// #size-cells = <0x00>;
|
||||
|
||||
// mmc@0 {
|
||||
// compatible = "mmc-spi-slot";
|
||||
// reg = <0x00>;
|
||||
// spi-max-frequency = <0x1312d00>;
|
||||
// voltage-ranges = <0xce4 0xce4>;
|
||||
// disable-wp;
|
||||
// };
|
||||
// };
|
||||
|
||||
// cache-controller@2010000 {
|
||||
// compatible = "sifive,fu540-c000-ccache";
|
||||
// cache-block-size = <0x40>;
|
||||
// cache-level = <0x02>;
|
||||
// cache-sets = <0x400>;
|
||||
// cache-size = <0x200000>;
|
||||
// cache-unified;
|
||||
// interrupt-parent = <0x06>;
|
||||
// interrupts = <0x01 0x02 0x03>;
|
||||
// reg = <0x00 0x2010000 0x00 0x1000>;
|
||||
// };
|
||||
|
||||
// dma@3000000 {
|
||||
// compatible = "sifive,fu540-c000-pdma";
|
||||
// reg = <0x00 0x3000000 0x00 0x100000>;
|
||||
// interrupt-parent = <0x06>;
|
||||
// interrupts = <0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e>;
|
||||
// #dma-cells = <0x01>;
|
||||
// };
|
||||
|
||||
gpio: gpio@10060000 {
|
||||
compatible = "sifive,gpio0";
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <0x07>, <0x08>, <0x09>, <0x0a>,
|
||||
<0x0b>, <0x0c>, <0x0d>, <0x0e>,
|
||||
<0x0f>, <0x10>, <0x11>, <0x12>,
|
||||
<0x13>, <0x14>, <0x15>, <0x16>;
|
||||
reg = <0x00 0x10060000 0x00 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <0x02>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <0x02>;
|
||||
clocks = <&prci 0x03>;
|
||||
phandle = <0x07>;
|
||||
};
|
||||
|
||||
plic: interrupt-controller@c000000 {
|
||||
phandle = <0x06>;
|
||||
riscv,ndev = <0x35>;
|
||||
reg = <0x00 0xc000000 0x00 0x4000000>;
|
||||
interrupts-extended = <&cpu0_intc 0x0b>, <&cpu1_intc 0x0b>, <&cpu1_intc 0x09>;
|
||||
interrupt-controller;
|
||||
compatible = "sifive,plic-1.0.0", "riscv,plic0";
|
||||
#interrupt-cells = <0x01>;
|
||||
};
|
||||
|
||||
prci: clock-controller@10000000 {
|
||||
compatible = "sifive,fu540-c000-prci";
|
||||
reg = <0x00 0x10000000 0x00 0x1000>;
|
||||
clocks = <&hfclk>, <&rtcclk>;
|
||||
#clock-cells = <0x01>;
|
||||
phandle = <0x05>;
|
||||
};
|
||||
|
||||
// otp@10070000 {
|
||||
// compatible = "sifive,fu540-c000-otp";
|
||||
// reg = <0x00 0x10070000 0x00 0x1000>;
|
||||
// fuse-count = <0x1000>;
|
||||
// };
|
||||
|
||||
clint: clint@2000000 {
|
||||
interrupts-extended = <&cpu0_intc 0x03>, <&cpu0_intc 0x07>, <&cpu1_intc 0x03>, <&cpu1_intc 0x07>;
|
||||
reg = <0x00 0x2000000 0x00 0x10000>;
|
||||
compatible = "sifive,clint0", "riscv,clint0";
|
||||
};
|
||||
};
|
||||
};
|
||||
Binary file not shown.
@@ -68,7 +68,7 @@
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_headphones=0 cgroup_disable=memory numa_policy=interleave";
|
||||
bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_headphones=0 cgroup_disable=memory numa_policy=interleave nvme.max_host_mem_size_mb=0";
|
||||
phandle = <0x54>;
|
||||
};
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
reg = <0x7e00b880 0x40>;
|
||||
interrupts = <0x00 0x21 0x04>;
|
||||
#mbox-cells = <0x00>;
|
||||
phandle = <0x35>;
|
||||
phandle = <0x31>;
|
||||
};
|
||||
|
||||
gpio@7e200000 {
|
||||
@@ -252,7 +252,7 @@
|
||||
i2c0if-gpio0 {
|
||||
brcm,pins = <0x00 0x01>;
|
||||
brcm,function = <0x04>;
|
||||
phandle = <0x33>;
|
||||
phandle = <0x35>;
|
||||
};
|
||||
|
||||
i2c0if-gpio28 {
|
||||
@@ -264,7 +264,7 @@
|
||||
i2c0if-gpio44 {
|
||||
brcm,pins = <0x2c 0x2d>;
|
||||
brcm,function = <0x05>;
|
||||
phandle = <0x34>;
|
||||
phandle = <0x36>;
|
||||
};
|
||||
|
||||
i2c1-gpio2 {
|
||||
@@ -958,64 +958,64 @@
|
||||
};
|
||||
};
|
||||
|
||||
dpi_18bit_cpadhi_gpio0 {
|
||||
brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>;
|
||||
brcm,function = <0x06>;
|
||||
brcm,pull = <0x00>;
|
||||
phandle = <0xb2>;
|
||||
};
|
||||
|
||||
dpi_18bit_cpadhi_gpio2 {
|
||||
brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb3>;
|
||||
};
|
||||
|
||||
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>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb4>;
|
||||
};
|
||||
|
||||
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>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb5>;
|
||||
};
|
||||
|
||||
dpi_16bit_gpio0 {
|
||||
brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb6>;
|
||||
};
|
||||
|
||||
dpi_16bit_gpio2 {
|
||||
brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb7>;
|
||||
};
|
||||
|
||||
dpi_16bit_cpadhi_gpio0 {
|
||||
brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb8>;
|
||||
};
|
||||
|
||||
dpi_16bit_cpadhi_gpio2 {
|
||||
brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb9>;
|
||||
};
|
||||
|
||||
gpioout {
|
||||
brcm,pins = <0x06>;
|
||||
brcm,function = <0x01>;
|
||||
phandle = <0xba>;
|
||||
phandle = <0xb2>;
|
||||
};
|
||||
|
||||
alt0 {
|
||||
brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>;
|
||||
brcm,function = <0x04>;
|
||||
phandle = <0xb3>;
|
||||
};
|
||||
|
||||
dpi_18bit_cpadhi_gpio0 {
|
||||
brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>;
|
||||
brcm,function = <0x06>;
|
||||
brcm,pull = <0x00>;
|
||||
phandle = <0xb4>;
|
||||
};
|
||||
|
||||
dpi_18bit_cpadhi_gpio2 {
|
||||
brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb5>;
|
||||
};
|
||||
|
||||
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>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb6>;
|
||||
};
|
||||
|
||||
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>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb7>;
|
||||
};
|
||||
|
||||
dpi_16bit_gpio0 {
|
||||
brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb8>;
|
||||
};
|
||||
|
||||
dpi_16bit_gpio2 {
|
||||
brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xb9>;
|
||||
};
|
||||
|
||||
dpi_16bit_cpadhi_gpio0 {
|
||||
brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xba>;
|
||||
};
|
||||
|
||||
dpi_16bit_cpadhi_gpio2 {
|
||||
brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>;
|
||||
brcm,function = <0x06>;
|
||||
phandle = <0xbb>;
|
||||
};
|
||||
|
||||
@@ -1131,7 +1131,7 @@
|
||||
brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>;
|
||||
brcm,function = <0x07>;
|
||||
brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>;
|
||||
phandle = <0x31>;
|
||||
phandle = <0x33>;
|
||||
};
|
||||
|
||||
uart2_pins {
|
||||
@@ -1194,17 +1194,17 @@
|
||||
brcm,pins = <0x28 0x29>;
|
||||
brcm,function = <0x04>;
|
||||
brcm,pull = <0x00>;
|
||||
phandle = <0x36>;
|
||||
phandle = <0x32>;
|
||||
};
|
||||
};
|
||||
|
||||
serial@7e201000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
compatible = "arm,pl011-axi";
|
||||
reg = <0x7e201000 0x200>;
|
||||
interrupts = <0x00 0x79 0x04>;
|
||||
clocks = <0x08 0x13 0x08 0x14>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
arm,primecell-periphid = <0x341011>;
|
||||
status = "okay";
|
||||
cts-event-workaround;
|
||||
pinctrl-names = "default";
|
||||
@@ -1295,7 +1295,7 @@
|
||||
#size-cells = <0x00>;
|
||||
status = "disabled";
|
||||
clock-frequency = <0x186a0>;
|
||||
phandle = <0x32>;
|
||||
phandle = <0x34>;
|
||||
};
|
||||
|
||||
dpi@7e208000 {
|
||||
@@ -1404,8 +1404,8 @@
|
||||
compatible = "brcm,bcm2711-hvs";
|
||||
reg = <0x7e400000 0x8000>;
|
||||
interrupts = <0x00 0x61 0x04>;
|
||||
status = "disabled";
|
||||
clocks = <0x14 0x04>;
|
||||
status = "disabled";
|
||||
phandle = <0xc4>;
|
||||
};
|
||||
|
||||
@@ -1424,6 +1424,38 @@
|
||||
phandle = <0x05>;
|
||||
};
|
||||
|
||||
csi@7e800000 {
|
||||
compatible = "brcm,bcm2835-unicam";
|
||||
reg = <0x7e800000 0x800 0x7e802000 0x04>;
|
||||
reg-names = "unicam", "cmi";
|
||||
interrupts = <0x00 0x66 0x04>;
|
||||
brcm,num-data-lanes = <0x02>;
|
||||
status = "disabled";
|
||||
clocks = <0x08 0x2d 0x14 0x04>;
|
||||
clock-names = "lp", "vpu";
|
||||
power-domains = <0x10 0x0c>;
|
||||
phandle = <0x51>;
|
||||
|
||||
port {
|
||||
};
|
||||
};
|
||||
|
||||
csi@7e801000 {
|
||||
compatible = "brcm,bcm2835-unicam";
|
||||
reg = <0x7e801000 0x800 0x7e802004 0x04>;
|
||||
reg-names = "unicam", "cmi";
|
||||
interrupts = <0x00 0x67 0x04>;
|
||||
brcm,num-data-lanes = <0x02>;
|
||||
status = "disabled";
|
||||
clocks = <0x08 0x2e 0x14 0x04>;
|
||||
clock-names = "lp", "vpu";
|
||||
power-domains = <0x10 0x0d>;
|
||||
phandle = <0x50>;
|
||||
|
||||
port {
|
||||
};
|
||||
};
|
||||
|
||||
i2c@7e804000 {
|
||||
compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
|
||||
reg = <0x7e804000 0x1000>;
|
||||
@@ -1446,10 +1478,11 @@
|
||||
#size-cells = <0x00>;
|
||||
clocks = <0x16>;
|
||||
clock-names = "otg";
|
||||
dr_mode = "host";
|
||||
phys = <0x17>;
|
||||
phy-names = "usb2-phy";
|
||||
interrupt-names = "usb", "soft";
|
||||
power-domains = <0x10 0x06>;
|
||||
interrupt-names = "usb", "soft";
|
||||
status = "disabled";
|
||||
phandle = <0xc5>;
|
||||
};
|
||||
@@ -1511,12 +1544,12 @@
|
||||
};
|
||||
|
||||
serial@7e201400 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
compatible = "arm,pl011-axi";
|
||||
reg = <0x7e201400 0x200>;
|
||||
interrupts = <0x00 0x79 0x04>;
|
||||
clocks = <0x08 0x13 0x08 0x14>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
arm,primecell-periphid = <0x341011>;
|
||||
status = "disabled";
|
||||
pinctrl-0 = <0x18>;
|
||||
pinctrl-names = "default";
|
||||
@@ -1524,12 +1557,12 @@
|
||||
};
|
||||
|
||||
serial@7e201600 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
compatible = "arm,pl011-axi";
|
||||
reg = <0x7e201600 0x200>;
|
||||
interrupts = <0x00 0x79 0x04>;
|
||||
clocks = <0x08 0x13 0x08 0x14>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
arm,primecell-periphid = <0x341011>;
|
||||
status = "disabled";
|
||||
pinctrl-0 = <0x19>;
|
||||
pinctrl-names = "default";
|
||||
@@ -1537,12 +1570,12 @@
|
||||
};
|
||||
|
||||
serial@7e201800 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
compatible = "arm,pl011-axi";
|
||||
reg = <0x7e201800 0x200>;
|
||||
interrupts = <0x00 0x79 0x04>;
|
||||
clocks = <0x08 0x13 0x08 0x14>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
arm,primecell-periphid = <0x341011>;
|
||||
status = "disabled";
|
||||
pinctrl-0 = <0x1a>;
|
||||
pinctrl-names = "default";
|
||||
@@ -1550,12 +1583,12 @@
|
||||
};
|
||||
|
||||
serial@7e201a00 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
compatible = "arm,pl011-axi";
|
||||
reg = <0x7e201a00 0x200>;
|
||||
interrupts = <0x00 0x79 0x04>;
|
||||
clocks = <0x08 0x13 0x08 0x14>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
arm,primecell-periphid = <0x241011>;
|
||||
arm,primecell-periphid = <0x341011>;
|
||||
status = "disabled";
|
||||
pinctrl-0 = <0x1b>;
|
||||
pinctrl-names = "default";
|
||||
@@ -1803,113 +1836,9 @@
|
||||
phandle = <0x30>;
|
||||
};
|
||||
|
||||
mmcnr@7e300000 {
|
||||
compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
|
||||
reg = <0x7e300000 0x100>;
|
||||
interrupts = <0x00 0x7e 0x04>;
|
||||
clocks = <0x08 0x1c>;
|
||||
dmas = <0x0c 0x0b>;
|
||||
dma-names = "rx-tx";
|
||||
brcm,overclock-50 = <0x00>;
|
||||
non-removable;
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <0x31>;
|
||||
bus-width = <0x04>;
|
||||
phandle = <0x4d>;
|
||||
};
|
||||
|
||||
firmwarekms@7e600000 {
|
||||
compatible = "raspberrypi,rpi-firmware-kms-2711";
|
||||
reg = <0x7e600000 0x100>;
|
||||
interrupts = <0x00 0x70 0x04>;
|
||||
brcm,firmware = <0x06>;
|
||||
status = "disabled";
|
||||
phandle = <0xdb>;
|
||||
};
|
||||
|
||||
smi@7e600000 {
|
||||
compatible = "brcm,bcm2835-smi";
|
||||
reg = <0x7e600000 0x100>;
|
||||
interrupts = <0x00 0x70 0x04>;
|
||||
clocks = <0x08 0x2a>;
|
||||
assigned-clocks = <0x08 0x2a>;
|
||||
assigned-clock-rates = <0x7735940>;
|
||||
dmas = <0x0c 0x04>;
|
||||
dma-names = "rx-tx";
|
||||
status = "disabled";
|
||||
phandle = <0xdc>;
|
||||
};
|
||||
|
||||
csi@7e800000 {
|
||||
compatible = "brcm,bcm2835-unicam";
|
||||
reg = <0x7e800000 0x800 0x7e802000 0x04>;
|
||||
interrupts = <0x00 0x66 0x04>;
|
||||
clocks = <0x08 0x2d 0x14 0x04>;
|
||||
clock-names = "lp", "vpu";
|
||||
power-domains = <0x10 0x0c>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
#clock-cells = <0x01>;
|
||||
status = "disabled";
|
||||
phandle = <0x51>;
|
||||
};
|
||||
|
||||
csi@7e801000 {
|
||||
compatible = "brcm,bcm2835-unicam";
|
||||
reg = <0x7e801000 0x800 0x7e802004 0x04>;
|
||||
interrupts = <0x00 0x67 0x04>;
|
||||
clocks = <0x08 0x2e 0x14 0x04>;
|
||||
clock-names = "lp", "vpu";
|
||||
power-domains = <0x10 0x0d>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
#clock-cells = <0x01>;
|
||||
status = "disabled";
|
||||
brcm,num-data-lanes = <0x02>;
|
||||
phandle = <0x50>;
|
||||
};
|
||||
|
||||
axiperf {
|
||||
compatible = "brcm,bcm2711-axiperf";
|
||||
reg = <0x7e009800 0x100 0x7ee08000 0x100>;
|
||||
firmware = <0x06>;
|
||||
status = "disabled";
|
||||
phandle = <0x4e>;
|
||||
};
|
||||
|
||||
i2c0mux {
|
||||
compatible = "i2c-mux-pinctrl";
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
i2c-parent = <0x32>;
|
||||
status = "disabled";
|
||||
pinctrl-names = "i2c0", "i2c_csi_dsi";
|
||||
pinctrl-0 = <0x33>;
|
||||
pinctrl-1 = <0x34>;
|
||||
phandle = <0x47>;
|
||||
|
||||
i2c@0 {
|
||||
reg = <0x00>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
phandle = <0xdd>;
|
||||
};
|
||||
|
||||
i2c@1 {
|
||||
reg = <0x01>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
phandle = <0xde>;
|
||||
};
|
||||
};
|
||||
|
||||
firmware {
|
||||
compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x01>;
|
||||
mboxes = <0x35>;
|
||||
dma-ranges;
|
||||
mboxes = <0x31>;
|
||||
phandle = <0x06>;
|
||||
|
||||
clocks {
|
||||
@@ -1935,7 +1864,7 @@
|
||||
|
||||
vcio {
|
||||
compatible = "raspberrypi,vcio";
|
||||
phandle = <0xdf>;
|
||||
phandle = <0xdb>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1951,8 +1880,88 @@
|
||||
reg = <0x7e00b840 0x3c>;
|
||||
interrupts = <0x00 0x22 0x04>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <0x36>;
|
||||
phandle = <0xe0>;
|
||||
pinctrl-0 = <0x32>;
|
||||
phandle = <0xdc>;
|
||||
};
|
||||
|
||||
mmcnr@7e300000 {
|
||||
compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
|
||||
reg = <0x7e300000 0x100>;
|
||||
interrupts = <0x00 0x7e 0x04>;
|
||||
clocks = <0x08 0x1c>;
|
||||
dmas = <0x0c 0x0b>;
|
||||
dma-names = "rx-tx";
|
||||
brcm,overclock-50 = <0x00>;
|
||||
non-removable;
|
||||
status = "okay";
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <0x33>;
|
||||
bus-width = <0x04>;
|
||||
phandle = <0x4d>;
|
||||
|
||||
wifi@1 {
|
||||
reg = <0x01>;
|
||||
compatible = "brcm,bcm4329-fmac";
|
||||
phandle = <0xdd>;
|
||||
};
|
||||
};
|
||||
|
||||
firmwarekms@7e600000 {
|
||||
compatible = "raspberrypi,rpi-firmware-kms-2711";
|
||||
reg = <0x7e600000 0x100>;
|
||||
interrupts = <0x00 0x70 0x04>;
|
||||
brcm,firmware = <0x06>;
|
||||
status = "disabled";
|
||||
phandle = <0xde>;
|
||||
};
|
||||
|
||||
smi@7e600000 {
|
||||
compatible = "brcm,bcm2835-smi";
|
||||
reg = <0x7e600000 0x100>;
|
||||
interrupts = <0x00 0x70 0x04>;
|
||||
clocks = <0x08 0x2a>;
|
||||
assigned-clocks = <0x08 0x2a>;
|
||||
assigned-clock-rates = <0x7735940>;
|
||||
dmas = <0x0c 0x04>;
|
||||
dma-names = "rx-tx";
|
||||
status = "disabled";
|
||||
phandle = <0xdf>;
|
||||
};
|
||||
|
||||
axiperf {
|
||||
compatible = "brcm,bcm2711-axiperf";
|
||||
reg = <0x7e009800 0x100 0x7ee08000 0x100>;
|
||||
firmware = <0x06>;
|
||||
status = "disabled";
|
||||
phandle = <0x4e>;
|
||||
};
|
||||
|
||||
i2c0mux {
|
||||
compatible = "i2c-mux-pinctrl";
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
i2c-parent = <0x34>;
|
||||
status = "disabled";
|
||||
pinctrl-names = "i2c0", "i2c_csi_dsi";
|
||||
pinctrl-0 = <0x35>;
|
||||
pinctrl-1 = <0x36>;
|
||||
phandle = <0x47>;
|
||||
|
||||
i2c@0 {
|
||||
reg = <0x00>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
phandle = <0xe0>;
|
||||
};
|
||||
|
||||
i2c@1 {
|
||||
reg = <0x01>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
phandle = <0xe1>;
|
||||
};
|
||||
};
|
||||
|
||||
gpiomem {
|
||||
@@ -1964,12 +1973,12 @@
|
||||
compatible = "brcm,bcm2708-fb";
|
||||
firmware = <0x06>;
|
||||
status = "okay";
|
||||
phandle = <0xe1>;
|
||||
phandle = <0xe2>;
|
||||
};
|
||||
|
||||
sound {
|
||||
status = "disabled";
|
||||
phandle = <0xe2>;
|
||||
phandle = <0xe3>;
|
||||
};
|
||||
|
||||
nvmem {
|
||||
@@ -1982,7 +1991,7 @@
|
||||
firmware = <0x06>;
|
||||
reg = <0x00 0xa6>;
|
||||
status = "okay";
|
||||
phandle = <0xe3>;
|
||||
phandle = <0xe4>;
|
||||
};
|
||||
|
||||
nvmem_cust {
|
||||
@@ -2035,7 +2044,7 @@
|
||||
compatible = "brcm,bcm2711-vc5";
|
||||
status = "disabled";
|
||||
raspberrypi,firmware = <0x06>;
|
||||
phandle = <0xe4>;
|
||||
phandle = <0xe5>;
|
||||
};
|
||||
|
||||
clk-27M {
|
||||
@@ -2060,7 +2069,7 @@
|
||||
#size-cells = <0x01>;
|
||||
ranges = <0x00 0x7e000000 0x00 0xfe000000 0x1800000>;
|
||||
dma-ranges = <0x00 0xc0000000 0x00 0x00 0x40000000>;
|
||||
phandle = <0xe5>;
|
||||
phandle = <0xe6>;
|
||||
|
||||
mmc@7e340000 {
|
||||
compatible = "brcm,bcm2711-emmc2";
|
||||
@@ -2076,8 +2085,8 @@
|
||||
};
|
||||
};
|
||||
|
||||
arm-pmu {
|
||||
compatible = "arm,cortex-a72-pmu", "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
|
||||
pmu {
|
||||
compatible = "arm,cortex-a72-pmu";
|
||||
interrupts = <0x00 0x10 0x04 0x00 0x11 0x04 0x00 0x12 0x04 0x00 0x13 0x04>;
|
||||
interrupt-affinity = <0x39 0x3a 0x3b 0x3c>;
|
||||
};
|
||||
@@ -2085,14 +2094,13 @@
|
||||
timer {
|
||||
compatible = "arm,armv8-timer";
|
||||
interrupts = <0x01 0x0d 0xf08 0x01 0x0e 0xf08 0x01 0x0b 0xf08 0x01 0x0a 0xf08>;
|
||||
arm,cpu-registers-not-fw-configured;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
enable-method = "brcm,bcm2836-smp";
|
||||
phandle = <0xe6>;
|
||||
phandle = <0xe7>;
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
@@ -2173,9 +2181,9 @@
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <0x02>;
|
||||
#size-cells = <0x02>;
|
||||
ranges = <0x00 0x7c000000 0x00 0xfc000000 0x00 0x3800000 0x00 0x40000000 0x00 0xff800000 0x00 0x800000 0x06 0x00 0x06 0x00 0x00 0x80000000 0x00 0x00 0x00 0x00 0x00 0xfc000000>;
|
||||
ranges = <0x00 0x7c000000 0x00 0xfc000000 0x00 0x3800000 0x00 0x40000000 0x00 0xff800000 0x00 0x800000 0x06 0x00 0x06 0x00 0x00 0x40000000 0x00 0x00 0x00 0x00 0x00 0xfc000000>;
|
||||
dma-ranges = <0x04 0x7c000000 0x00 0xfc000000 0x00 0x3800000 0x00 0x00 0x00 0x00 0x04 0x00>;
|
||||
phandle = <0xe7>;
|
||||
phandle = <0xe8>;
|
||||
|
||||
pcie@7d500000 {
|
||||
compatible = "brcm,bcm2711-pcie";
|
||||
@@ -2190,7 +2198,7 @@
|
||||
interrupt-map = <0x00 0x00 0x00 0x01 0x01 0x00 0x8f 0x04 0x00 0x00 0x00 0x02 0x01 0x00 0x90 0x04 0x00 0x00 0x00 0x03 0x01 0x00 0x91 0x04 0x00 0x00 0x00 0x04 0x01 0x00 0x92 0x04>;
|
||||
msi-controller;
|
||||
msi-parent = <0x3e>;
|
||||
ranges = <0x2000000 0x00 0x80000000 0x06 0x00 0x00 0x80000000>;
|
||||
ranges = <0x2000000 0x00 0xc0000000 0x06 0x00 0x00 0x40000000>;
|
||||
dma-ranges = <0x2000000 0x00 0x00 0x00 0x00 0x00 0xc0000000>;
|
||||
brcm,enable-ssc;
|
||||
phandle = <0x3e>;
|
||||
@@ -2218,7 +2226,7 @@
|
||||
status = "okay";
|
||||
phy-handle = <0x40>;
|
||||
phy-mode = "rgmii-rxid";
|
||||
phandle = <0xe8>;
|
||||
phandle = <0xe9>;
|
||||
|
||||
mdio@e14 {
|
||||
compatible = "brcm,genet-mdio-v5";
|
||||
@@ -2226,7 +2234,7 @@
|
||||
reg-names = "mdio";
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
phandle = <0xe9>;
|
||||
phandle = <0xea>;
|
||||
|
||||
ethernet-phy@1 {
|
||||
reg = <0x01>;
|
||||
@@ -2236,6 +2244,15 @@
|
||||
};
|
||||
};
|
||||
|
||||
codec@7eb10000 {
|
||||
compatible = "brcm,bcm2711-hevc-dec", "raspberrypi,hevc-dec";
|
||||
reg = <0x00 0x7eb00000 0x00 0x10000 0x00 0x7eb10000 0x00 0x1000>;
|
||||
reg-names = "hevc", "intc";
|
||||
interrupts = <0x00 0x62 0x04>;
|
||||
clocks = <0x14 0x0b>;
|
||||
phandle = <0xeb>;
|
||||
};
|
||||
|
||||
dma@7e007b00 {
|
||||
compatible = "brcm,bcm2711-dma";
|
||||
reg = <0x00 0x7e007b00 0x00 0x400>;
|
||||
@@ -2252,33 +2269,41 @@
|
||||
reg = <0x00 0x7e9c0000 0x00 0x100000>;
|
||||
interrupts = <0x00 0xb0 0x04>;
|
||||
power-domains = <0x10 0x06>;
|
||||
phandle = <0xea>;
|
||||
};
|
||||
|
||||
codec@7eb10000 {
|
||||
compatible = "raspberrypi,rpivid-vid-decoder";
|
||||
reg = <0x00 0x7eb10000 0x00 0x1000 0x00 0x7eb00000 0x00 0x10000>;
|
||||
reg-names = "intc", "hevc";
|
||||
interrupts = <0x00 0x62 0x04>;
|
||||
clocks = <0x14 0x0b>;
|
||||
clock-names = "hevc";
|
||||
phandle = <0xec>;
|
||||
};
|
||||
};
|
||||
|
||||
cam1_regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "cam1-reg";
|
||||
enable-active-high;
|
||||
status = "okay";
|
||||
gpio = <0x0b 0x05 0x00>;
|
||||
phandle = <0x53>;
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00 0x00 0x00>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
phandle = <0xed>;
|
||||
|
||||
led-act {
|
||||
label = "ACT";
|
||||
default-state = "off";
|
||||
linux,default-trigger = "mmc0";
|
||||
gpios = <0x07 0x2a 0x00>;
|
||||
phandle = <0x5a>;
|
||||
};
|
||||
|
||||
led-pwr {
|
||||
label = "PWR";
|
||||
gpios = <0x0b 0x02 0x01>;
|
||||
default-state = "off";
|
||||
linux,default-trigger = "default-on";
|
||||
phandle = <0x5b>;
|
||||
};
|
||||
};
|
||||
|
||||
cam1_clk {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0x00>;
|
||||
status = "disabled";
|
||||
phandle = <0xeb>;
|
||||
phandle = <0xee>;
|
||||
};
|
||||
|
||||
cam0_regulator {
|
||||
@@ -2286,14 +2311,14 @@
|
||||
regulator-name = "cam0-reg";
|
||||
enable-active-high;
|
||||
status = "disabled";
|
||||
phandle = <0xec>;
|
||||
phandle = <0xef>;
|
||||
};
|
||||
|
||||
cam0_clk {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0x00>;
|
||||
status = "disabled";
|
||||
phandle = <0xed>;
|
||||
phandle = <0xf0>;
|
||||
};
|
||||
|
||||
cam_dummy_reg {
|
||||
@@ -2316,17 +2341,17 @@
|
||||
uart1 = "", "", "", "Dstatus";
|
||||
i2s = "", "", "", "Estatus";
|
||||
spi = "", "", "", "Fstatus";
|
||||
i2c0 = "", "", "", "2status", "", "", "", "Gstatus";
|
||||
i2c0 = "", "", "", "4status", "", "", "", "Gstatus";
|
||||
i2c1 = "", "", "", "Hstatus";
|
||||
i2c = "", "", "", "Hstatus";
|
||||
i2c_arm = "", "", "", "Hstatus";
|
||||
i2c_vc = "", "", "", "2status", "", "", "", "Gstatus";
|
||||
i2c0_baudrate = "", "", "", "2clock-frequency:0";
|
||||
i2c_vc = "", "", "", "4status", "", "", "", "Gstatus";
|
||||
i2c0_baudrate = "", "", "", "4clock-frequency:0";
|
||||
i2c1_baudrate = "", "", "", "Hclock-frequency:0";
|
||||
i2c_baudrate = "", "", "", "Hclock-frequency:0";
|
||||
i2c_arm_baudrate = "", "", "", "Hclock-frequency:0";
|
||||
i2c_vc_baudrate = "", "", "", "2clock-frequency:0";
|
||||
watchdog = "", "", "", "Istatus";
|
||||
i2c_vc_baudrate = "", "", "", "4clock-frequency:0";
|
||||
watchdog = "", "", "", "Iearly-watchdog?";
|
||||
random = "", "", "", "Jstatus";
|
||||
sd_overclock = "", "", "", "Kbrcm,overclock-50:0";
|
||||
sd_force_pio = "", "", "", "Kbrcm,force-pio?";
|
||||
@@ -2365,32 +2390,15 @@
|
||||
pwr_led_trigger = "", "", "", "[linux,default-trigger";
|
||||
eth_led0 = "", "", "", "@led-modes:0";
|
||||
eth_led1 = "", "", "", "@led-modes:4";
|
||||
eth_max_speed = "", "", "", "@max-speed:0";
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00 0x00 0x00>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
phandle = <0xee>;
|
||||
|
||||
led-act {
|
||||
label = "ACT";
|
||||
default-state = "off";
|
||||
linux,default-trigger = "mmc0";
|
||||
gpios = <0x07 0x2a 0x00>;
|
||||
phandle = <0x5a>;
|
||||
};
|
||||
|
||||
led-pwr {
|
||||
label = "PWR";
|
||||
gpios = <0x0b 0x02 0x01>;
|
||||
default-state = "off";
|
||||
linux,default-trigger = "default-on";
|
||||
phandle = <0x5b>;
|
||||
};
|
||||
regulator-cam1 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "cam1-reg";
|
||||
enable-active-high;
|
||||
gpio = <0x0b 0x05 0x00>;
|
||||
phandle = <0x53>;
|
||||
};
|
||||
|
||||
regulator-sd-io-1v8 {
|
||||
@@ -2424,7 +2432,7 @@
|
||||
regulator-max-microvolt = <0x325aa0>;
|
||||
regulator-min-microvolt = <0x325aa0>;
|
||||
regulator-name = "3v3";
|
||||
phandle = <0xef>;
|
||||
phandle = <0xf1>;
|
||||
};
|
||||
|
||||
fixedregulator_5v0 {
|
||||
@@ -2433,7 +2441,7 @@
|
||||
regulator-max-microvolt = <0x4c4b40>;
|
||||
regulator-min-microvolt = <0x4c4b40>;
|
||||
regulator-name = "5v0";
|
||||
phandle = <0xf0>;
|
||||
phandle = <0xf2>;
|
||||
};
|
||||
|
||||
zone_dma {
|
||||
@@ -2448,7 +2456,7 @@
|
||||
#size-cells = <0x02>;
|
||||
ranges = <0x7c500000 0x00 0xfc500000 0x00 0x3300000 0x40000000 0x00 0xff800000 0x00 0x800000>;
|
||||
dma-ranges = <0x00 0x00 0x00 0x04 0x00>;
|
||||
phandle = <0xf1>;
|
||||
phandle = <0xf3>;
|
||||
|
||||
v3d@7ec04000 {
|
||||
compatible = "brcm,2711-v3d";
|
||||
@@ -2460,7 +2468,7 @@
|
||||
clocks-names = "v3d";
|
||||
interrupts = <0x00 0x4a 0x04>;
|
||||
status = "disabled";
|
||||
phandle = <0xf2>;
|
||||
phandle = <0xf4>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2561,6 +2569,8 @@
|
||||
uart4_ctsrts_gpio10 = "/soc/gpio@7e200000/uart4-ctsrts-gpio10";
|
||||
uart5_gpio12 = "/soc/gpio@7e200000/uart5-gpio12";
|
||||
uart5_ctsrts_gpio14 = "/soc/gpio@7e200000/uart5-ctsrts-gpio14";
|
||||
gpioout = "/soc/gpio@7e200000/gpioout";
|
||||
alt0 = "/soc/gpio@7e200000/alt0";
|
||||
dpi_18bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio0";
|
||||
dpi_18bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio2";
|
||||
dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0";
|
||||
@@ -2569,8 +2579,6 @@
|
||||
dpi_16bit_gpio2 = "/soc/gpio@7e200000/dpi_16bit_gpio2";
|
||||
dpi_16bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio0";
|
||||
dpi_16bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio2";
|
||||
gpioout = "/soc/gpio@7e200000/gpioout";
|
||||
alt0 = "/soc/gpio@7e200000/alt0";
|
||||
spi0_pins = "/soc/gpio@7e200000/spi0_pins";
|
||||
spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins";
|
||||
spi3_pins = "/soc/gpio@7e200000/spi3_pins";
|
||||
@@ -2621,6 +2629,8 @@
|
||||
sdhci = "/soc/mmc@7e300000";
|
||||
hvs = "/soc/hvs@7e400000";
|
||||
dsi1 = "/soc/dsi@7e700000";
|
||||
csi0 = "/soc/csi@7e800000";
|
||||
csi1 = "/soc/csi@7e801000";
|
||||
i2c_arm = "/soc/i2c@7e804000";
|
||||
i2c1 = "/soc/i2c@7e804000";
|
||||
usb = "/soc/usb@7e980000";
|
||||
@@ -2657,17 +2667,6 @@
|
||||
ddc0 = "/soc/i2c@7ef04500";
|
||||
hdmi1 = "/soc/hdmi@7ef05700";
|
||||
ddc1 = "/soc/i2c@7ef09500";
|
||||
mmcnr = "/soc/mmcnr@7e300000";
|
||||
firmwarekms = "/soc/firmwarekms@7e600000";
|
||||
smi = "/soc/smi@7e600000";
|
||||
csi0 = "/soc/csi@7e800000";
|
||||
csi1 = "/soc/csi@7e801000";
|
||||
axiperf = "/soc/axiperf";
|
||||
i2c0mux = "/soc/i2c0mux";
|
||||
i2c_csi_dsi0 = "/soc/i2c0mux/i2c@0";
|
||||
i2c_vc = "/soc/i2c0mux/i2c@0";
|
||||
i2c0 = "/soc/i2c0mux/i2c@0";
|
||||
i2c_csi_dsi = "/soc/i2c0mux/i2c@1";
|
||||
firmware = "/soc/firmware";
|
||||
firmware_clocks = "/soc/firmware/clocks";
|
||||
expgpio = "/soc/firmware/gpio";
|
||||
@@ -2675,6 +2674,16 @@
|
||||
vcio = "/soc/firmware/vcio";
|
||||
power = "/soc/power";
|
||||
vchiq = "/soc/mailbox@7e00b840";
|
||||
mmcnr = "/soc/mmcnr@7e300000";
|
||||
brcmf = "/soc/mmcnr@7e300000/wifi@1";
|
||||
firmwarekms = "/soc/firmwarekms@7e600000";
|
||||
smi = "/soc/smi@7e600000";
|
||||
axiperf = "/soc/axiperf";
|
||||
i2c0mux = "/soc/i2c0mux";
|
||||
i2c_csi_dsi0 = "/soc/i2c0mux/i2c@0";
|
||||
i2c_vc = "/soc/i2c0mux/i2c@0";
|
||||
i2c0 = "/soc/i2c0mux/i2c@0";
|
||||
i2c_csi_dsi = "/soc/i2c0mux/i2c@1";
|
||||
fb = "/soc/fb";
|
||||
sound = "/soc/sound";
|
||||
nvmem_otp = "/soc/nvmem/nvmem_otp";
|
||||
@@ -2699,17 +2708,18 @@
|
||||
genet = "/scb/ethernet@7d580000";
|
||||
genet_mdio = "/scb/ethernet@7d580000/mdio@e14";
|
||||
phy1 = "/scb/ethernet@7d580000/mdio@e14/ethernet-phy@1";
|
||||
hevc_dec = "/scb/codec@7eb10000";
|
||||
dma40 = "/scb/dma@7e007b00";
|
||||
xhci = "/scb/xhci@7e9c0000";
|
||||
cam1_reg = "/cam1_regulator";
|
||||
leds = "/leds";
|
||||
led_act = "/leds/led-act";
|
||||
led_pwr = "/leds/led-pwr";
|
||||
cam1_clk = "/cam1_clk";
|
||||
cam0_regulator = "/cam0_regulator";
|
||||
cam0_clk = "/cam0_clk";
|
||||
cam0_reg = "/cam_dummy_reg";
|
||||
cam_dummy_reg = "/cam_dummy_reg";
|
||||
leds = "/leds";
|
||||
led_act = "/leds/led-act";
|
||||
led_pwr = "/leds/led-pwr";
|
||||
cam1_reg = "/regulator-cam1";
|
||||
sd_io_1v8_reg = "/regulator-sd-io-1v8";
|
||||
sd_vcc_reg = "/regulator-sd-vcc";
|
||||
vdd_3v3_reg = "/fixedregulator_3v3";
|
||||
Binary file not shown.
@@ -0,0 +1,577 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <0x02>;
|
||||
#size-cells = <0x02>;
|
||||
compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000", "sifive,fu740";
|
||||
model = "SiFive HiFive Unmatched";
|
||||
|
||||
aliases {
|
||||
serial0 = "/soc/serial@10010000";
|
||||
serial1 = "/soc/serial@10011000";
|
||||
ethernet0 = "/soc/ethernet@10090000";
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0";
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
timebase-frequency = <0xf4240>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "sifive,bullet0", "riscv";
|
||||
device_type = "cpu";
|
||||
i-cache-block-size = <0x40>;
|
||||
i-cache-sets = <0x80>;
|
||||
i-cache-size = <0x4000>;
|
||||
next-level-cache = <0x01>;
|
||||
reg = <0x00>;
|
||||
riscv,isa = "rv64imac";
|
||||
status = "disabled";
|
||||
|
||||
interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
phandle = <0x02>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
|
||||
d-cache-block-size = <0x40>;
|
||||
d-cache-sets = <0x40>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-tlb-sets = <0x01>;
|
||||
d-tlb-size = <0x28>;
|
||||
device_type = "cpu";
|
||||
i-cache-block-size = <0x40>;
|
||||
i-cache-sets = <0x80>;
|
||||
i-cache-size = <0x8000>;
|
||||
i-tlb-sets = <0x01>;
|
||||
i-tlb-size = <0x28>;
|
||||
mmu-type = "riscv,sv39";
|
||||
next-level-cache = <0x01>;
|
||||
reg = <0x01>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
tlb-split;
|
||||
|
||||
interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
phandle = <0x03>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu@2 {
|
||||
compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
|
||||
d-cache-block-size = <0x40>;
|
||||
d-cache-sets = <0x40>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-tlb-sets = <0x01>;
|
||||
d-tlb-size = <0x28>;
|
||||
device_type = "cpu";
|
||||
i-cache-block-size = <0x40>;
|
||||
i-cache-sets = <0x80>;
|
||||
i-cache-size = <0x8000>;
|
||||
i-tlb-sets = <0x01>;
|
||||
i-tlb-size = <0x28>;
|
||||
mmu-type = "riscv,sv39";
|
||||
next-level-cache = <0x01>;
|
||||
reg = <0x02>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
tlb-split;
|
||||
|
||||
interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
phandle = <0x04>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu@3 {
|
||||
compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
|
||||
d-cache-block-size = <0x40>;
|
||||
d-cache-sets = <0x40>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-tlb-sets = <0x01>;
|
||||
d-tlb-size = <0x28>;
|
||||
device_type = "cpu";
|
||||
i-cache-block-size = <0x40>;
|
||||
i-cache-sets = <0x80>;
|
||||
i-cache-size = <0x8000>;
|
||||
i-tlb-sets = <0x01>;
|
||||
i-tlb-size = <0x28>;
|
||||
mmu-type = "riscv,sv39";
|
||||
next-level-cache = <0x01>;
|
||||
reg = <0x03>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
tlb-split;
|
||||
|
||||
interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
phandle = <0x05>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu@4 {
|
||||
compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
|
||||
d-cache-block-size = <0x40>;
|
||||
d-cache-sets = <0x40>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-tlb-sets = <0x01>;
|
||||
d-tlb-size = <0x28>;
|
||||
device_type = "cpu";
|
||||
i-cache-block-size = <0x40>;
|
||||
i-cache-sets = <0x80>;
|
||||
i-cache-size = <0x8000>;
|
||||
i-tlb-sets = <0x01>;
|
||||
i-tlb-size = <0x28>;
|
||||
mmu-type = "riscv,sv39";
|
||||
next-level-cache = <0x01>;
|
||||
reg = <0x04>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
tlb-split;
|
||||
|
||||
interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
phandle = <0x06>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <0x02>;
|
||||
#size-cells = <0x02>;
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
interrupt-controller@c000000 {
|
||||
#interrupt-cells = <0x01>;
|
||||
#address-cells = <0x00>;
|
||||
compatible = "sifive,fu540-c000-plic", "sifive,plic-1.0.0";
|
||||
reg = <0x00 0xc000000 0x00 0x4000000>;
|
||||
riscv,ndev = <0x45>;
|
||||
interrupt-controller;
|
||||
interrupts-extended = <0x02 0xffffffff 0x03 0xffffffff 0x03 0x09 0x04 0xffffffff 0x04 0x09 0x05 0xffffffff 0x05 0x09 0x06 0xffffffff 0x06 0x09>;
|
||||
phandle = <0x09>;
|
||||
};
|
||||
|
||||
prci: clock-controller@10000000 {
|
||||
compatible = "sifive,fu740-c000-prci";
|
||||
reg = <0x00 0x10000000 0x00 0x1000>;
|
||||
clocks = <&clk_hfclk>, <&clk_rtcclk>;
|
||||
#clock-cells = <0x01>;
|
||||
#reset-cells = <0x01>;
|
||||
};
|
||||
|
||||
serial@10010000 {
|
||||
compatible = "sifive,fu740-c000-uart", "sifive,uart0";
|
||||
reg = <0x00 0x10010000 0x00 0x1000>;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x27>;
|
||||
clocks = <&prci 0x07>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
serial@10011000 {
|
||||
compatible = "sifive,fu740-c000-uart", "sifive,uart0";
|
||||
reg = <0x00 0x10011000 0x00 0x1000>;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x28>;
|
||||
clocks = <&prci 0x07>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c@10030000 {
|
||||
compatible = "sifive,fu740-c000-i2c", "sifive,i2c0";
|
||||
reg = <0x00 0x10030000 0x00 0x1000>;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x34>;
|
||||
clocks = <&prci 0x07>;
|
||||
reg-shift = <0x02>;
|
||||
reg-io-width = <0x01>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "okay";
|
||||
|
||||
temperature-sensor@4c {
|
||||
compatible = "ti,tmp451";
|
||||
reg = <0x4c>;
|
||||
interrupt-parent = <0x0b>;
|
||||
interrupts = <0x06 0x08>;
|
||||
};
|
||||
|
||||
pmic@58 {
|
||||
compatible = "dlg,da9063";
|
||||
reg = <0x58>;
|
||||
interrupt-parent = <0x0b>;
|
||||
interrupts = <0x01 0x08>;
|
||||
interrupt-controller;
|
||||
|
||||
regulators {
|
||||
|
||||
bcore1 {
|
||||
regulator-min-microvolt = <0x100590>;
|
||||
regulator-max-microvolt = <0x100590>;
|
||||
regulator-min-microamp = <0x4c4b40>;
|
||||
regulator-max-microamp = <0x4c4b40>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
bcore2 {
|
||||
regulator-min-microvolt = <0x100590>;
|
||||
regulator-max-microvolt = <0x100590>;
|
||||
regulator-min-microamp = <0x4c4b40>;
|
||||
regulator-max-microamp = <0x4c4b40>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
bpro {
|
||||
regulator-min-microvolt = <0x1b7740>;
|
||||
regulator-max-microvolt = <0x1b7740>;
|
||||
regulator-min-microamp = <0x2625a0>;
|
||||
regulator-max-microamp = <0x2625a0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
bperi {
|
||||
regulator-min-microvolt = <0x100590>;
|
||||
regulator-max-microvolt = <0x100590>;
|
||||
regulator-min-microamp = <0x16e360>;
|
||||
regulator-max-microamp = <0x16e360>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
bmem {
|
||||
regulator-min-microvolt = <0x124f80>;
|
||||
regulator-max-microvolt = <0x124f80>;
|
||||
regulator-min-microamp = <0x2dc6c0>;
|
||||
regulator-max-microamp = <0x2dc6c0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
bio {
|
||||
regulator-min-microvolt = <0x124f80>;
|
||||
regulator-max-microvolt = <0x124f80>;
|
||||
regulator-min-microamp = <0x2dc6c0>;
|
||||
regulator-max-microamp = <0x2dc6c0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo1 {
|
||||
regulator-min-microvolt = <0x1b7740>;
|
||||
regulator-max-microvolt = <0x1b7740>;
|
||||
regulator-min-microamp = <0x186a0>;
|
||||
regulator-max-microamp = <0x186a0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo2 {
|
||||
regulator-min-microvolt = <0x1b7740>;
|
||||
regulator-max-microvolt = <0x1b7740>;
|
||||
regulator-min-microamp = <0x30d40>;
|
||||
regulator-max-microamp = <0x30d40>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo3 {
|
||||
regulator-min-microvolt = <0x325aa0>;
|
||||
regulator-max-microvolt = <0x325aa0>;
|
||||
regulator-min-microamp = <0x30d40>;
|
||||
regulator-max-microamp = <0x30d40>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo4 {
|
||||
regulator-min-microvolt = <0x2625a0>;
|
||||
regulator-max-microvolt = <0x2625a0>;
|
||||
regulator-min-microamp = <0x30d40>;
|
||||
regulator-max-microamp = <0x30d40>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo5 {
|
||||
regulator-min-microvolt = <0x325aa0>;
|
||||
regulator-max-microvolt = <0x325aa0>;
|
||||
regulator-min-microamp = <0x186a0>;
|
||||
regulator-max-microamp = <0x186a0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo6 {
|
||||
regulator-min-microvolt = <0x1b7740>;
|
||||
regulator-max-microvolt = <0x1b7740>;
|
||||
regulator-min-microamp = <0x30d40>;
|
||||
regulator-max-microamp = <0x30d40>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo7 {
|
||||
regulator-min-microvolt = <0x325aa0>;
|
||||
regulator-max-microvolt = <0x325aa0>;
|
||||
regulator-min-microamp = <0x30d40>;
|
||||
regulator-max-microamp = <0x30d40>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo8 {
|
||||
regulator-min-microvolt = <0x325aa0>;
|
||||
regulator-max-microvolt = <0x325aa0>;
|
||||
regulator-min-microamp = <0x30d40>;
|
||||
regulator-max-microamp = <0x30d40>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo9 {
|
||||
regulator-min-microvolt = <0x100590>;
|
||||
regulator-max-microvolt = <0x100590>;
|
||||
regulator-min-microamp = <0x30d40>;
|
||||
regulator-max-microamp = <0x30d40>;
|
||||
};
|
||||
|
||||
ldo10 {
|
||||
regulator-min-microvolt = <0xf4240>;
|
||||
regulator-max-microvolt = <0xf4240>;
|
||||
regulator-min-microamp = <0x493e0>;
|
||||
regulator-max-microamp = <0x493e0>;
|
||||
};
|
||||
|
||||
ldo11 {
|
||||
regulator-min-microvolt = <0x2625a0>;
|
||||
regulator-max-microvolt = <0x2625a0>;
|
||||
regulator-min-microamp = <0x493e0>;
|
||||
regulator-max-microamp = <0x493e0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c@10031000 {
|
||||
compatible = "sifive,fu740-c000-i2c", "sifive,i2c0";
|
||||
reg = <0x00 0x10031000 0x00 0x1000>;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x35>;
|
||||
clocks = <&prci 0x07>;
|
||||
reg-shift = <0x02>;
|
||||
reg-io-width = <0x01>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi@10040000 {
|
||||
compatible = "sifive,fu740-c000-spi", "sifive,spi0";
|
||||
reg = <0x00 0x10040000 0x00 0x1000 0x00 0x20000000 0x00 0x10000000>;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x29>;
|
||||
clocks = <&prci 0x07>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "issi,is25wp256", "jedec,spi-nor";
|
||||
reg = <0x00>;
|
||||
spi-max-frequency = <0x2faf080>;
|
||||
m25p,fast-read;
|
||||
spi-tx-bus-width = <0x04>;
|
||||
spi-rx-bus-width = <0x04>;
|
||||
};
|
||||
};
|
||||
|
||||
spi@10041000 {
|
||||
compatible = "sifive,fu740-c000-spi", "sifive,spi0";
|
||||
reg = <0x00 0x10041000 0x00 0x1000 0x00 0x30000000 0x00 0x10000000>;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x2a>;
|
||||
clocks = <&prci 0x07>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi@10050000 {
|
||||
compatible = "sifive,fu740-c000-spi", "sifive,spi0";
|
||||
reg = <0x00 0x10050000 0x00 0x1000>;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x2b>;
|
||||
clocks = <&prci 0x07>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "okay";
|
||||
|
||||
mmc@0 {
|
||||
compatible = "mmc-spi-slot";
|
||||
reg = <0x00>;
|
||||
spi-max-frequency = <0x1312d00>;
|
||||
voltage-ranges = <0xce4 0xce4>;
|
||||
disable-wp;
|
||||
};
|
||||
};
|
||||
|
||||
macb: ethernet@10090000 {
|
||||
compatible = "sifive,fu540-c000-gem";
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x37>;
|
||||
reg = <0x00 0x10090000 0x00 0x2000 0x00 0x100a0000 0x00 0x1000>;
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
clock-names = "pclk", "hclk";
|
||||
clocks = <&prci 0x02 &prci 0x02>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
status = "okay";
|
||||
phy-mode = "gmii";
|
||||
phy-handle = <0x0c>;
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <0x00>;
|
||||
phandle = <0x0c>;
|
||||
};
|
||||
};
|
||||
|
||||
pwm@10020000 {
|
||||
compatible = "sifive,fu740-c000-pwm", "sifive,pwm0";
|
||||
reg = <0x00 0x10020000 0x00 0x1000>;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x2c 0x2d 0x2e 0x2f>;
|
||||
clocks = <&prci 0x07>;
|
||||
#pwm-cells = <0x03>;
|
||||
status = "okay";
|
||||
phandle = <0x0d>;
|
||||
};
|
||||
|
||||
pwm@10021000 {
|
||||
compatible = "sifive,fu740-c000-pwm", "sifive,pwm0";
|
||||
reg = <0x00 0x10021000 0x00 0x1000>;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x30 0x31 0x32 0x33>;
|
||||
clocks = <&prci 0x07>;
|
||||
#pwm-cells = <0x03>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
cache-controller@2010000 {
|
||||
compatible = "sifive,fu740-c000-ccache", "cache";
|
||||
cache-block-size = <0x40>;
|
||||
cache-level = <0x02>;
|
||||
cache-sets = <0x800>;
|
||||
cache-size = <0x200000>;
|
||||
cache-unified;
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x13 0x15 0x16 0x14>;
|
||||
reg = <0x00 0x2010000 0x00 0x1000>;
|
||||
phandle = <0x01>;
|
||||
};
|
||||
|
||||
gpio@10060000 {
|
||||
compatible = "sifive,fu740-c000-gpio", "sifive,gpio0";
|
||||
interrupt-parent = <0x09>;
|
||||
interrupts = <0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26>;
|
||||
reg = <0x00 0x10060000 0x00 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <0x02>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <0x02>;
|
||||
clocks = <&prci 0x07>;
|
||||
status = "okay";
|
||||
phandle = <0x0b>;
|
||||
};
|
||||
|
||||
pcie@e00000000 {
|
||||
#address-cells = <0x03>;
|
||||
#interrupt-cells = <0x01>;
|
||||
#num-lanes = <0x08>;
|
||||
#size-cells = <0x02>;
|
||||
compatible = "sifive,fu740-pcie";
|
||||
reg = <0x0e 0x00 0x01 0x00 0x0d 0xf0000000 0x00 0x10000000 0x00 0x100d0000 0x00 0x1000>;
|
||||
reg-names = "dbi", "config", "mgmt";
|
||||
device_type = "pci";
|
||||
dma-coherent;
|
||||
bus-range = <0x00 0xff>;
|
||||
ranges = <0x81000000 0x00 0x60080000 0x00 0x60080000 0x00 0x10000 0x82000000 0x00 0x60090000 0x00 0x60090000 0x00 0xff70000 0x82000000 0x00 0x70000000 0x00 0x70000000 0x00 0x1000000 0xc3000000 0x20 0x00 0x20 0x00 0x20 0x00>;
|
||||
num-lanes = <0x08>;
|
||||
interrupts = <0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40>;
|
||||
interrupt-names = "msi", "inta", "intb", "intc", "intd";
|
||||
interrupt-parent = <0x09>;
|
||||
interrupt-map-mask = <0x00 0x00 0x00 0x07>;
|
||||
interrupt-map = <0x00 0x00 0x00 0x01 0x09 0x39 0x00 0x00 0x00 0x02 0x09 0x3a 0x00 0x00 0x00 0x03 0x09 0x3b 0x00 0x00 0x00 0x04 0x09 0x3c>;
|
||||
clock-names = "pcie_aux";
|
||||
clocks = <&prci 0x08>;
|
||||
pwren-gpios = <0x0b 0x05 0x00>;
|
||||
perstn-gpios = <0x0b 0x08 0x00>;
|
||||
resets = <&prci 0x04>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x00 0x80000000 0x04 0x00>;
|
||||
};
|
||||
|
||||
pwmleds {
|
||||
compatible = "pwm-leds";
|
||||
|
||||
green-d12 {
|
||||
label = "green:d12";
|
||||
pwms = <0x0d 0x00 0x773594 0x01>;
|
||||
active-low = <0x01>;
|
||||
max-brightness = <0xff>;
|
||||
linux,default-trigger = "none";
|
||||
};
|
||||
|
||||
green-d2 {
|
||||
label = "green:d2";
|
||||
pwms = <0x0d 0x01 0x773594 0x01>;
|
||||
active-low = <0x01>;
|
||||
max-brightness = <0xff>;
|
||||
linux,default-trigger = "none";
|
||||
};
|
||||
|
||||
red-d2 {
|
||||
label = "red:d2";
|
||||
pwms = <0x0d 0x02 0x773594 0x01>;
|
||||
active-low = <0x01>;
|
||||
max-brightness = <0xff>;
|
||||
linux,default-trigger = "none";
|
||||
};
|
||||
|
||||
blue-d2 {
|
||||
label = "blue:d2";
|
||||
pwms = <0x0d 0x03 0x773594 0x01>;
|
||||
active-low = <0x01>;
|
||||
max-brightness = <0xff>;
|
||||
linux,default-trigger = "none";
|
||||
};
|
||||
};
|
||||
|
||||
clk_hfclk: hfclk {
|
||||
#clock-cells = <0x00>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <26000000>;
|
||||
clock-output-names = "hfclk";
|
||||
};
|
||||
|
||||
clk_rtcclk: rtcclk {
|
||||
#clock-cells = <0x00>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <1000000>;
|
||||
clock-output-names = "rtcclk";
|
||||
};
|
||||
|
||||
gpio-poweroff {
|
||||
compatible = "gpio-poweroff";
|
||||
gpios = <0x0b 0x02 0x01>;
|
||||
};
|
||||
};
|
||||
Binary file not shown.
@@ -0,0 +1,248 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <0x02>;
|
||||
#size-cells = <0x02>;
|
||||
compatible = "sifive,hifive-unleashed-a00";
|
||||
model = "SiFive HiFive Unleashed A00";
|
||||
|
||||
chosen {
|
||||
linux,initrd-end = <0x00 0x87688400>;
|
||||
linux,initrd-start = <0x00 0x84200000>;
|
||||
stdout-path = "/soc/serial@10010000";
|
||||
};
|
||||
|
||||
aliases {
|
||||
serial0 = "/soc/serial@10010000";
|
||||
serial1 = "/soc/serial@10011000";
|
||||
ethernet0 = "/soc/ethernet@10090000";
|
||||
};
|
||||
|
||||
gpio-restart {
|
||||
compatible = "gpio-restart";
|
||||
gpios = <0x07 0x0a 0x01>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
timebase-frequency = <0xf4240>;
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0x00>;
|
||||
status = "okay";
|
||||
compatible = "riscv";
|
||||
riscv,isa-extensions = "i", "m", "a", "c", "zicntr", "zicsr", "zifencei", "zihpm", "sdtrig";
|
||||
riscv,isa-base = "rv64i";
|
||||
riscv,isa = "rv64imac_zicntr_zicsr_zifencei_zihpm_sdtrig";
|
||||
|
||||
interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
interrupt-controller;
|
||||
compatible = "riscv,cpu-intc";
|
||||
phandle = <0x04>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
device_type = "cpu";
|
||||
reg = <0x01>;
|
||||
status = "okay";
|
||||
compatible = "riscv";
|
||||
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr", "zifencei", "zihpm", "sdtrig";
|
||||
riscv,isa-base = "rv64i";
|
||||
riscv,isa = "rv64imafdc_zicntr_zicsr_zifencei_zihpm_sdtrig";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
interrupt-controller {
|
||||
#interrupt-cells = <0x01>;
|
||||
interrupt-controller;
|
||||
compatible = "riscv,cpu-intc";
|
||||
phandle = <0x03>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x00 0x80000000 0x00 0x8000000>;
|
||||
};
|
||||
|
||||
rtcclk {
|
||||
#clock-cells = <0x00>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <0xf4240>;
|
||||
clock-output-names = "rtcclk";
|
||||
phandle = <0x02>;
|
||||
};
|
||||
|
||||
hfclk {
|
||||
#clock-cells = <0x00>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <0x1fca055>;
|
||||
clock-output-names = "hfclk";
|
||||
phandle = <0x01>;
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <0x02>;
|
||||
#size-cells = <0x02>;
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
serial@10010000 {
|
||||
interrupts = <0x04>;
|
||||
interrupt-parent = <0x06>;
|
||||
clocks = <0x05 0x03>;
|
||||
reg = <0x00 0x10010000 0x00 0x1000>;
|
||||
compatible = "sifive,uart0";
|
||||
};
|
||||
|
||||
serial@10011000 {
|
||||
interrupts = <0x05>;
|
||||
interrupt-parent = <0x06>;
|
||||
clocks = <0x05 0x03>;
|
||||
reg = <0x00 0x10011000 0x00 0x1000>;
|
||||
compatible = "sifive,uart0";
|
||||
};
|
||||
|
||||
pwm@10021000 {
|
||||
#pwm-cells = <0x00>;
|
||||
clocks = <0x05 0x03>;
|
||||
interrupts = <0x2e 0x2f 0x30 0x31>;
|
||||
interrupt-parent = <0x06>;
|
||||
reg = <0x00 0x10021000 0x00 0x1000>;
|
||||
compatible = "sifive,pwm0";
|
||||
};
|
||||
|
||||
pwm@10020000 {
|
||||
#pwm-cells = <0x00>;
|
||||
clocks = <0x05 0x03>;
|
||||
interrupts = <0x2a 0x2b 0x2c 0x2d>;
|
||||
interrupt-parent = <0x06>;
|
||||
reg = <0x00 0x10020000 0x00 0x1000>;
|
||||
compatible = "sifive,pwm0";
|
||||
};
|
||||
|
||||
ethernet@10090000 {
|
||||
#size-cells = <0x00>;
|
||||
#address-cells = <0x01>;
|
||||
local-mac-address = [52 54 00 12 34 56];
|
||||
clock-names = "pclk", "hclk";
|
||||
clocks = <0x05 0x02 0x05 0x02>;
|
||||
interrupts = <0x35>;
|
||||
interrupt-parent = <0x06>;
|
||||
phy-handle = <0x08>;
|
||||
phy-mode = "gmii";
|
||||
reg-names = "control";
|
||||
reg = <0x00 0x10090000 0x00 0x2000 0x00 0x100a0000 0x00 0x1000>;
|
||||
compatible = "sifive,fu540-c000-gem";
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <0x00>;
|
||||
phandle = <0x08>;
|
||||
};
|
||||
};
|
||||
|
||||
spi@10040000 {
|
||||
compatible = "sifive,spi0";
|
||||
reg = <0x00 0x10040000 0x00 0x1000>;
|
||||
interrupt-parent = <0x06>;
|
||||
interrupts = <0x33>;
|
||||
clocks = <0x05 0x03>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0x00>;
|
||||
spi-max-frequency = <0x2faf080>;
|
||||
m25p,fast-read;
|
||||
spi-tx-bus-width = <0x04>;
|
||||
spi-rx-bus-width = <0x04>;
|
||||
};
|
||||
};
|
||||
|
||||
spi@10050000 {
|
||||
compatible = "sifive,spi0";
|
||||
reg = <0x00 0x10050000 0x00 0x1000>;
|
||||
interrupt-parent = <0x06>;
|
||||
interrupts = <0x06>;
|
||||
clocks = <0x05 0x03>;
|
||||
#address-cells = <0x01>;
|
||||
#size-cells = <0x00>;
|
||||
|
||||
mmc@0 {
|
||||
compatible = "mmc-spi-slot";
|
||||
reg = <0x00>;
|
||||
spi-max-frequency = <0x1312d00>;
|
||||
voltage-ranges = <0xce4 0xce4>;
|
||||
disable-wp;
|
||||
};
|
||||
};
|
||||
|
||||
cache-controller@2010000 {
|
||||
compatible = "sifive,fu540-c000-ccache";
|
||||
cache-block-size = <0x40>;
|
||||
cache-level = <0x02>;
|
||||
cache-sets = <0x400>;
|
||||
cache-size = <0x200000>;
|
||||
cache-unified;
|
||||
interrupt-parent = <0x06>;
|
||||
interrupts = <0x01 0x02 0x03>;
|
||||
reg = <0x00 0x2010000 0x00 0x1000>;
|
||||
};
|
||||
|
||||
dma@3000000 {
|
||||
compatible = "sifive,fu540-c000-pdma";
|
||||
reg = <0x00 0x3000000 0x00 0x100000>;
|
||||
interrupt-parent = <0x06>;
|
||||
interrupts = <0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e>;
|
||||
#dma-cells = <0x01>;
|
||||
};
|
||||
|
||||
gpio@10060000 {
|
||||
compatible = "sifive,gpio0";
|
||||
interrupt-parent = <0x06>;
|
||||
interrupts = <0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16>;
|
||||
reg = <0x00 0x10060000 0x00 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <0x02>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <0x02>;
|
||||
clocks = <0x05 0x03>;
|
||||
phandle = <0x07>;
|
||||
};
|
||||
|
||||
interrupt-controller@c000000 {
|
||||
phandle = <0x06>;
|
||||
riscv,ndev = <0x35>;
|
||||
reg = <0x00 0xc000000 0x00 0x4000000>;
|
||||
interrupts-extended = <0x04 0x0b 0x03 0x0b 0x03 0x09>;
|
||||
interrupt-controller;
|
||||
compatible = "sifive,plic-1.0.0", "riscv,plic0";
|
||||
#interrupt-cells = <0x01>;
|
||||
};
|
||||
|
||||
clock-controller@10000000 {
|
||||
compatible = "sifive,fu540-c000-prci";
|
||||
reg = <0x00 0x10000000 0x00 0x1000>;
|
||||
clocks = <0x01 0x02>;
|
||||
#clock-cells = <0x01>;
|
||||
phandle = <0x05>;
|
||||
};
|
||||
|
||||
otp@10070000 {
|
||||
compatible = "sifive,fu540-c000-otp";
|
||||
reg = <0x00 0x10070000 0x00 0x1000>;
|
||||
fuse-count = <0x1000>;
|
||||
};
|
||||
|
||||
clint@2000000 {
|
||||
interrupts-extended = <0x04 0x03 0x04 0x07 0x03 0x03 0x03 0x07>;
|
||||
reg = <0x00 0x2000000 0x00 0x10000>;
|
||||
compatible = "sifive,clint0", "riscv,clint0";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"arch": "riscv64",
|
||||
"os": "none",
|
||||
"abi": "softfloat",
|
||||
"cpu": "generic-rv64",
|
||||
"llvm-abiname": "lp64",
|
||||
"llvm-target": "riscv64",
|
||||
"data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
|
||||
"max-atomic-width": 64,
|
||||
"target-pointer-width": "64",
|
||||
"target-pointer-width": 64,
|
||||
"features": "+m,+a,+c",
|
||||
|
||||
"disable-redzone": true,
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
"crt-objects-fallback": "false",
|
||||
"emit-debug-gdb-scripts": false,
|
||||
"llvm-abiname": "lp64",
|
||||
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "ld.lld"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"llvm-target": "x86_64-unknown-linux-gnu",
|
||||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
|
||||
"max-atomic-width": 64,
|
||||
"target-pointer-width": "64",
|
||||
"target-pointer-width": 64,
|
||||
"features": "-avx,-sse,-avx2,+soft-float",
|
||||
|
||||
"disable-redzone": true,
|
||||
|
||||
+3
-1
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "yggdrasil-kernel"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
build = "build.rs"
|
||||
authors = ["Mark Poliakov <mark@alnyan.me>"]
|
||||
|
||||
@@ -35,6 +35,7 @@ ygg_driver_ahci = { path = "driver/block/ahci" }
|
||||
ygg_driver_input = { path = "driver/input" }
|
||||
ygg_driver_usb_xhci.path = "driver/usb/xhci"
|
||||
ygg_driver_net_rtl81xx.path = "driver/net/rtl81xx"
|
||||
ygg_driver_serial_8250.path = "driver/serial/uart8250"
|
||||
|
||||
memfs = { path = "driver/fs/memfs" }
|
||||
ext2 = { path = "driver/fs/ext2" }
|
||||
@@ -66,6 +67,7 @@ ygg_driver_bsp_arm.path = "driver/bsp/arm" # PrimeCell components
|
||||
ygg_driver_bsp_riscv.path = "driver/bsp/riscv"
|
||||
ygg_driver_net_stmmac.path = "driver/net/stmmac"
|
||||
ygg_driver_bsp_jh7110.path = "driver/bsp/jh7110"
|
||||
ygg_driver_bsp_sifive.path = "driver/bsp/sifive"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
yboot-proto.workspace = true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kernel-arch"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[target.'cfg(all(target_os = "none", target_arch = "x86_64"))'.dependencies]
|
||||
kernel-arch-x86_64.path = "x86_64"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kernel-arch-aarch64"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
yggdrasil-abi.workspace = true
|
||||
|
||||
@@ -66,7 +66,7 @@ impl FpContext {
|
||||
///
|
||||
/// It is up to the caller to ensure `this` is a valid pointer to store the FPU context in.
|
||||
pub unsafe fn store(this: *mut Self) {
|
||||
__aarch64_fp_store_context(this as _)
|
||||
unsafe { __aarch64_fp_store_context(this as _) }
|
||||
}
|
||||
|
||||
/// Loads the FPU with the context stored in `this` pointer.
|
||||
@@ -75,7 +75,7 @@ impl FpContext {
|
||||
///
|
||||
/// It is up to the caller to ensure `this` is a valid pointer to load the FPU context from.
|
||||
pub unsafe fn restore(this: *const Self) {
|
||||
__aarch64_fp_restore_context(this as _)
|
||||
unsafe { __aarch64_fp_restore_context(this as _) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,12 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
stack.push(entry as _);
|
||||
stack.push(arg);
|
||||
|
||||
setup_common_context(&mut stack, __aarch64_task_enter_kernel as _, 0, 0);
|
||||
setup_common_context(
|
||||
&mut stack,
|
||||
(__aarch64_task_enter_kernel as *const ()).addr(),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
|
||||
let sp = stack.build();
|
||||
|
||||
@@ -212,7 +217,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
|
||||
setup_common_context(
|
||||
&mut stack,
|
||||
__aarch64_task_enter_user as _,
|
||||
(__aarch64_task_enter_user as *const ()).addr(),
|
||||
ttbr0,
|
||||
context.thread_pointer as _,
|
||||
);
|
||||
@@ -231,9 +236,8 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
}
|
||||
|
||||
unsafe fn enter(&self) -> ! {
|
||||
FpContext::restore(self.fp_context.get());
|
||||
|
||||
__aarch64_enter_task(self.inner.get())
|
||||
unsafe { FpContext::restore(self.fp_context.get()) };
|
||||
unsafe { __aarch64_enter_task(self.inner.get()) }
|
||||
}
|
||||
|
||||
unsafe fn switch(&self, from: &Self) {
|
||||
@@ -241,19 +245,20 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
let src = from.inner.get();
|
||||
|
||||
if dst != src {
|
||||
// Save the old context
|
||||
FpContext::store(from.fp_context.get());
|
||||
// Load next context
|
||||
FpContext::restore(self.fp_context.get());
|
||||
unsafe {
|
||||
// Save the old context
|
||||
FpContext::store(from.fp_context.get());
|
||||
// Load next context
|
||||
FpContext::restore(self.fp_context.get());
|
||||
|
||||
__aarch64_switch_task(self.inner.get(), from.inner.get())
|
||||
__aarch64_switch_task(self.inner.get(), from.inner.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn switch_and_drop(&self, thread: *const ()) {
|
||||
FpContext::restore(self.fp_context.get());
|
||||
|
||||
__aarch64_switch_task_and_drop(self.inner.get(), thread);
|
||||
unsafe { FpContext::restore(self.fp_context.get()) };
|
||||
unsafe { __aarch64_switch_task_and_drop(self.inner.get(), thread) };
|
||||
}
|
||||
|
||||
fn set_thread_pointer(&self, _tp: usize) {
|
||||
@@ -293,7 +298,7 @@ fn setup_common_context(builder: &mut StackBuilder, entry: usize, ttbr0: u64, tp
|
||||
builder.push(0); // x19
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn __aarch64_enter_task(to: *mut TaskContextInner) -> !;
|
||||
fn __aarch64_switch_task(to: *mut TaskContextInner, from: *mut TaskContextInner);
|
||||
fn __aarch64_switch_task_and_drop(to: *mut TaskContextInner, thread: *const ()) -> !;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#![no_std]
|
||||
#![feature(decl_macro)]
|
||||
#![allow(clippy::new_without_default)]
|
||||
|
||||
extern crate alloc;
|
||||
@@ -13,11 +12,11 @@ use aarch64_cpu::{
|
||||
use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||
use device_api::interrupt::LocalInterruptController;
|
||||
use kernel_arch_interface::{
|
||||
Architecture,
|
||||
cpu::{CpuData, CpuImpl, IpiQueue},
|
||||
guard::IrqGuard,
|
||||
task::Scheduler,
|
||||
util::OneTimeInit,
|
||||
Architecture,
|
||||
};
|
||||
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
||||
|
||||
@@ -25,7 +24,7 @@ pub mod context;
|
||||
pub mod mem;
|
||||
|
||||
pub use context::TaskContextImpl;
|
||||
pub use mem::{process::ProcessAddressSpaceImpl, KernelTableManagerImpl};
|
||||
pub use mem::{KernelTableManagerImpl, process::ProcessAddressSpaceImpl};
|
||||
|
||||
pub struct ArchitectureImpl;
|
||||
|
||||
@@ -101,7 +100,7 @@ impl Architecture for ArchitectureImpl {
|
||||
let id = (MPIDR_EL1.get() & 0xFF) as u32;
|
||||
let cpu = Box::leak(Box::new(CpuImpl::<Self, S>::new(id, data)));
|
||||
|
||||
cpu.set_local();
|
||||
unsafe { cpu.set_local() };
|
||||
}
|
||||
|
||||
fn local_cpu() -> *mut () {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use core::ops::Range;
|
||||
|
||||
use aarch64_cpu::registers::{TTBR0_EL1, TTBR1_EL1};
|
||||
use kernel_arch_interface::{mem::DeviceMemoryAttributes, KERNEL_VIRT_OFFSET};
|
||||
use kernel_arch_interface::{KERNEL_VIRT_OFFSET, mem::DeviceMemoryAttributes};
|
||||
use libk_mm_interface::{
|
||||
address::PhysicalAddress,
|
||||
device::{DevicePageManager, DevicePageTableLevel},
|
||||
@@ -10,7 +10,7 @@ use libk_mm_interface::{
|
||||
|
||||
use crate::mem::{
|
||||
auto_lower_address,
|
||||
table::{PageAttributes, PageEntry, PageTable, L1, L2, L3},
|
||||
table::{L1, L2, L3, PageAttributes, PageEntry, PageTable},
|
||||
tlb_flush_range_va,
|
||||
};
|
||||
|
||||
@@ -98,22 +98,26 @@ impl DevicePageTableLevel for L3DeviceMemory {
|
||||
}
|
||||
|
||||
pub unsafe fn setup() {
|
||||
// 0..IDENTITY_SIZE_L1 -> lower RAM region
|
||||
for i in 0..IDENTITY_SIZE_L1 {
|
||||
let phys = PhysicalAddress::from_usize(i << L1::SHIFT);
|
||||
KERNEL_L1[i] = PageEntry::normal_block(phys, PageAttributes::empty());
|
||||
}
|
||||
unsafe {
|
||||
// 0..IDENTITY_SIZE_L1 -> lower RAM region
|
||||
for i in 0..IDENTITY_SIZE_L1 {
|
||||
let phys = PhysicalAddress::from_usize(i << L1::SHIFT);
|
||||
KERNEL_L1[i] = PageEntry::normal_block(phys, PageAttributes::empty());
|
||||
}
|
||||
|
||||
// DEVICE_L1 -> Device L2 table
|
||||
// 0..DEVICE_MAPPING_L3_COUNT -> Device L3 tables -> Device L3 pages
|
||||
// ..512 -> Device L2 pages
|
||||
for i in 0..DEVICE_MAPPING_L3_COUNT {
|
||||
// DEVICE_L1 -> Device L2 table
|
||||
// 0..DEVICE_MAPPING_L3_COUNT -> Device L3 tables -> Device L3 pages
|
||||
// ..512 -> Device L2 pages
|
||||
for i in 0..DEVICE_MAPPING_L3_COUNT {
|
||||
let phys = PhysicalAddress::from_usize(auto_lower_address(
|
||||
&raw const DEVICE_MEMORY.normal.0[i],
|
||||
));
|
||||
DEVICE_MEMORY.large.0[i] = PageEntry::table(phys, PageAttributes::empty());
|
||||
}
|
||||
let phys =
|
||||
PhysicalAddress::from_usize(auto_lower_address(&raw const DEVICE_MEMORY.normal.0[i]));
|
||||
DEVICE_MEMORY.large.0[i] = PageEntry::table(phys, PageAttributes::empty());
|
||||
PhysicalAddress::from_usize(auto_lower_address(&raw const DEVICE_MEMORY.large.0));
|
||||
KERNEL_L1[DEVICE_L1] = PageEntry::table(phys, PageAttributes::empty());
|
||||
}
|
||||
let phys = PhysicalAddress::from_usize(auto_lower_address(&raw const DEVICE_MEMORY.large.0));
|
||||
KERNEL_L1[DEVICE_L1] = PageEntry::table(phys, PageAttributes::empty());
|
||||
}
|
||||
|
||||
pub unsafe fn load() {
|
||||
|
||||
@@ -4,9 +4,9 @@ use aarch64_cpu::{
|
||||
registers::{MAIR_EL1, SCTLR_EL1, TCR_EL1},
|
||||
};
|
||||
use kernel_arch_interface::{
|
||||
KERNEL_VIRT_OFFSET,
|
||||
mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping},
|
||||
sync::IrqSafeSpinlock,
|
||||
KERNEL_VIRT_OFFSET,
|
||||
};
|
||||
use libk_mm_interface::{address::PhysicalAddress, table::EntryLevel};
|
||||
use tock_registers::interfaces::{ReadWriteable, Writeable};
|
||||
@@ -14,7 +14,7 @@ use yggdrasil_abi::error::Error;
|
||||
|
||||
pub use intrinsics::*;
|
||||
|
||||
use crate::{mem::table::L1, ArchitectureImpl};
|
||||
use crate::{ArchitectureImpl, mem::table::L1};
|
||||
|
||||
pub mod fixed;
|
||||
pub mod intrinsics;
|
||||
@@ -52,14 +52,18 @@ impl KernelTableManager for KernelTableManagerImpl {
|
||||
attrs: DeviceMemoryAttributes,
|
||||
) -> Result<RawDeviceMemoryMapping<Self>, Error> {
|
||||
let _lock = KERNEL_MEMORY_LOCK.lock();
|
||||
#[allow(static_mut_refs)]
|
||||
fixed::DEVICE_MEMORY.map_device_pages(PhysicalAddress::from_u64(base), count, attrs)
|
||||
unsafe {
|
||||
#[allow(static_mut_refs)]
|
||||
fixed::DEVICE_MEMORY.map_device_pages(PhysicalAddress::from_u64(base), count, attrs)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn unmap_device_pages(mapping: &RawDeviceMemoryMapping<Self>) {
|
||||
let _lock = KERNEL_MEMORY_LOCK.lock();
|
||||
#[allow(static_mut_refs)]
|
||||
fixed::DEVICE_MEMORY.unmap_device_pages(mapping);
|
||||
unsafe {
|
||||
#[allow(static_mut_refs)]
|
||||
fixed::DEVICE_MEMORY.unmap_device_pages(mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,15 +136,19 @@ unsafe fn enable_mmu() {
|
||||
SCTLR_EL1.modify(SCTLR_EL1::M::Enable);
|
||||
|
||||
// Enable caches
|
||||
enable_icache();
|
||||
enable_dcache();
|
||||
unsafe {
|
||||
enable_icache();
|
||||
enable_dcache();
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn init_lower(bsp: bool) {
|
||||
setup_memory_attributes();
|
||||
if bsp {
|
||||
fixed::setup();
|
||||
unsafe {
|
||||
if bsp {
|
||||
fixed::setup();
|
||||
}
|
||||
fixed::load();
|
||||
enable_mmu();
|
||||
}
|
||||
fixed::load();
|
||||
enable_mmu();
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ use libk_mm_interface::{
|
||||
};
|
||||
use yggdrasil_abi::error::Error;
|
||||
|
||||
use crate::{mem::table::PageEntry, KernelTableManagerImpl};
|
||||
use crate::{KernelTableManagerImpl, mem::table::PageEntry};
|
||||
|
||||
use super::{
|
||||
dc_cvac, ic_iallu,
|
||||
table::{PageAttributes, PageTable, L1, L2, L3},
|
||||
table::{L1, L2, L3, PageAttributes, PageTable},
|
||||
tlb_flush_asid, tlb_flush_vaae1,
|
||||
};
|
||||
|
||||
@@ -97,8 +97,10 @@ impl<TA: TableAllocator> ProcessAddressSpaceManager<TA> for ProcessAddressSpaceI
|
||||
}
|
||||
|
||||
unsafe fn clear(&mut self) {
|
||||
self.l1
|
||||
.drop_range::<TA>(0..((Self::UPPER_LIMIT_PFN * L3::SIZE).page_index::<L1>()));
|
||||
unsafe {
|
||||
self.l1
|
||||
.drop_range::<TA>(0..((Self::UPPER_LIMIT_PFN * L3::SIZE).page_index::<L1>()))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ use crate::KernelTableManagerImpl;
|
||||
use super::dc_cvac;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct PageAttributes: u64 {
|
||||
const PRESENT = 1 << 0;
|
||||
|
||||
@@ -71,8 +71,8 @@ pub struct L3;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum EntryType {
|
||||
Table(PhysicalAddress),
|
||||
Page(PhysicalAddress),
|
||||
Table(PageAttributes, PhysicalAddress),
|
||||
Page(PageAttributes, PhysicalAddress),
|
||||
Invalid,
|
||||
}
|
||||
|
||||
@@ -103,8 +103,8 @@ impl<L: EntryLevel> PageTable<L> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_zeroed<'a, TA: TableAllocator>(
|
||||
) -> Result<PhysicalRefMut<'a, Self, KernelTableManagerImpl>, Error> {
|
||||
pub fn new_zeroed<'a, TA: TableAllocator>()
|
||||
-> Result<PhysicalRefMut<'a, Self, KernelTableManagerImpl>, Error> {
|
||||
let physical = TA::allocate_page_table()?;
|
||||
let mut table =
|
||||
unsafe { PhysicalRefMut::<'a, Self, KernelTableManagerImpl>::map(physical) };
|
||||
@@ -132,7 +132,7 @@ impl<L: EntryLevel> PageTable<L> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let inner = PhysicalRefMut::map(physical);
|
||||
let inner = unsafe { PhysicalRefMut::map(physical) };
|
||||
Some(inner)
|
||||
}
|
||||
}
|
||||
@@ -234,12 +234,16 @@ where
|
||||
let entry = self[index];
|
||||
|
||||
if let Some(table) = entry.as_table() {
|
||||
let mut table_ref: PhysicalRefMut<PageTable<L::NextLevel>, KernelTableManagerImpl> =
|
||||
PhysicalRefMut::map(table);
|
||||
unsafe {
|
||||
let mut table_ref: PhysicalRefMut<
|
||||
PageTable<L::NextLevel>,
|
||||
KernelTableManagerImpl,
|
||||
> = PhysicalRefMut::map(table);
|
||||
|
||||
table_ref.drop_all::<TA>();
|
||||
table_ref.drop_all::<TA>();
|
||||
|
||||
TA::free_page_table(table);
|
||||
TA::free_page_table(table);
|
||||
}
|
||||
} else if entry.is_present() {
|
||||
// Memory must've been cleared beforehand, so no non-table entries must be present
|
||||
panic!(
|
||||
@@ -307,9 +311,14 @@ impl<L: NonTerminalEntryLevel> PageEntry<L> {
|
||||
if !self.is_present() {
|
||||
EntryType::Invalid
|
||||
} else if let Some(table) = self.as_table() {
|
||||
EntryType::Table(table)
|
||||
let attributes = self.attributes();
|
||||
EntryType::Table(attributes, table)
|
||||
} else {
|
||||
EntryType::Page(PhysicalAddress::from_u64(self.0 & !Self::ATTR_MASK))
|
||||
let attributes = self.attributes();
|
||||
EntryType::Page(
|
||||
attributes,
|
||||
PhysicalAddress::from_u64(self.0 & !Self::ATTR_MASK),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -426,8 +435,26 @@ impl From<PageAttributes> for MapAttributes {
|
||||
impl fmt::Display for EntryType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Table(address) => write!(f, "table @ {address:#x}"),
|
||||
Self::Page(address) => write!(f, "page @ {address:#x}"),
|
||||
&Self::Table(attrs, address) => {
|
||||
let mask = match attrs & PageAttributes::AP_ACCESS_MASK {
|
||||
PageAttributes::AP_BOTH_READONLY => "r- r-",
|
||||
PageAttributes::AP_BOTH_READWRITE => "rw rw",
|
||||
PageAttributes::AP_KERNEL_READONLY => "r- --",
|
||||
PageAttributes::AP_KERNEL_READWRITE => "rw --",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
write!(f, "table @ {address:#010x} {mask}")
|
||||
}
|
||||
&Self::Page(attrs, address) => {
|
||||
let mask = match attrs & PageAttributes::AP_ACCESS_MASK {
|
||||
PageAttributes::AP_BOTH_READONLY => "r- r-",
|
||||
PageAttributes::AP_BOTH_READWRITE => "rw rw",
|
||||
PageAttributes::AP_KERNEL_READONLY => "r- --",
|
||||
PageAttributes::AP_KERNEL_READWRITE => "rw --",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
write!(f, "page @ {address:#010x} {mask}")
|
||||
}
|
||||
Self::Invalid => f.write_str("<invalid>"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kernel-arch-hosted"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
kernel-arch-interface.workspace = true
|
||||
|
||||
@@ -7,16 +7,16 @@ use std::{
|
||||
|
||||
use device_api::dma::{DmaAllocation, DmaAllocator};
|
||||
use kernel_arch_interface::{
|
||||
Architecture,
|
||||
cpu::{CpuData, IpiQueue},
|
||||
mem::{
|
||||
DeviceMemoryAttributes, KernelTableManager, PhysicalMemoryAllocator, RawDeviceMemoryMapping,
|
||||
},
|
||||
task::{Scheduler, TaskContext, UserContextInfo},
|
||||
Architecture,
|
||||
};
|
||||
use libk_mm_interface::{
|
||||
address::PhysicalAddress,
|
||||
process::ProcessAddressSpaceManager,
|
||||
process::{PageAttributeUpdate, ProcessAddressSpaceManager},
|
||||
table::{MapAttributes, TableAllocator},
|
||||
};
|
||||
use yggdrasil_abi::{
|
||||
@@ -164,6 +164,14 @@ impl<TA: TableAllocator> ProcessAddressSpaceManager<TA> for ProcessAddressSpaceI
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
unsafe fn update_page_attributes(
|
||||
&mut self,
|
||||
_address: usize,
|
||||
_update: &PageAttributeUpdate,
|
||||
) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn translate(&self, _address: usize) -> Result<(PhysicalAddress, MapAttributes), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kernel-arch-interface"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
yggdrasil-abi.workspace = true
|
||||
|
||||
@@ -7,7 +7,7 @@ use alloc::vec::Vec;
|
||||
use device_api::interrupt::IpiMessage;
|
||||
|
||||
use crate::{
|
||||
guard::IrqGuard, sync::IrqSafeSpinlock, task::Scheduler, util::OneTimeInit, Architecture,
|
||||
Architecture, guard::IrqGuard, sync::IrqSafeSpinlock, task::Scheduler, util::OneTimeInit,
|
||||
};
|
||||
|
||||
#[repr(C, align(0x10))]
|
||||
@@ -94,7 +94,7 @@ impl<A: Architecture, S: Scheduler + 'static> CpuImpl<A, S> {
|
||||
///
|
||||
/// See [Architecture::set_local_cpu].
|
||||
pub unsafe fn set_local(&'static mut self) {
|
||||
A::set_local_cpu(self as *mut _ as *mut _)
|
||||
unsafe { A::set_local_cpu(self as *mut _ as *mut _) }
|
||||
}
|
||||
|
||||
pub fn try_local<'a>() -> Option<LocalCpuImpl<'a, A, S>> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![no_std]
|
||||
#![feature(step_trait, const_trait_impl, never_type, decl_macro)]
|
||||
#![feature(never_type)]
|
||||
#![allow(clippy::new_without_default)]
|
||||
|
||||
use core::ops::Range;
|
||||
|
||||
@@ -86,7 +86,7 @@ impl<A: KernelTableManager> RawDeviceMemoryMapping<A> {
|
||||
size: usize,
|
||||
attrs: DeviceMemoryAttributes,
|
||||
) -> Result<Self, Error> {
|
||||
A::map_device_pages(base, size, attrs)
|
||||
unsafe { A::map_device_pages(base, size, attrs) }
|
||||
}
|
||||
|
||||
/// Consumes the device mapping, leaking its address without deallocating the translation
|
||||
|
||||
@@ -6,7 +6,7 @@ use core::{
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use crate::{guard::IrqGuard, Architecture};
|
||||
use crate::{Architecture, guard::IrqGuard};
|
||||
|
||||
pub struct Spinlock<A: Architecture, T> {
|
||||
value: UnsafeCell<T>,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use core::{arch::global_asm, cell::UnsafeCell, marker::PhantomData};
|
||||
|
||||
use kernel_arch_interface::{
|
||||
Architecture,
|
||||
mem::{KernelTableManager, PhysicalMemoryAllocator},
|
||||
task::{StackBuilder, TaskContext, UserContextInfo},
|
||||
Architecture,
|
||||
};
|
||||
use libk_mm_interface::address::PhysicalAddress;
|
||||
use tock_registers::{
|
||||
@@ -13,9 +13,9 @@ use tock_registers::{
|
||||
use yggdrasil_abi::error::Error;
|
||||
|
||||
use crate::{
|
||||
ArchitectureImpl, PerCpuData,
|
||||
mem::{self},
|
||||
registers::SATP,
|
||||
ArchitectureImpl, PerCpuData,
|
||||
};
|
||||
|
||||
pub const CONTEXT_SIZE: usize = 14 * size_of::<usize>();
|
||||
@@ -86,7 +86,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
stack.push(context.entry);
|
||||
stack.push(context.argument);
|
||||
|
||||
setup_common_context(&mut stack, __rv64_task_enter_user as _);
|
||||
setup_common_context(&mut stack, (__rv64_task_enter_user as *const ()).addr());
|
||||
|
||||
let sp = stack.build();
|
||||
let satp = InMemoryRegister::new(0);
|
||||
@@ -118,7 +118,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
stack.push(entry as _);
|
||||
stack.push(arg);
|
||||
|
||||
setup_common_context(&mut stack, __rv64_task_enter_kernel as _);
|
||||
setup_common_context(&mut stack, (__rv64_task_enter_kernel as *const ()).addr());
|
||||
|
||||
let sp = stack.build();
|
||||
|
||||
|
||||
@@ -11,18 +11,18 @@ use core::{
|
||||
use alloc::{boxed::Box, collections::btree_map::BTreeMap, vec::Vec};
|
||||
use device_api::interrupt::LocalInterruptController;
|
||||
use kernel_arch_interface::{
|
||||
Architecture,
|
||||
cpu::{CpuData, CpuImpl, IpiQueue},
|
||||
sync::IrqSafeSpinlock,
|
||||
task::Scheduler,
|
||||
util::OneTimeInit,
|
||||
Architecture,
|
||||
};
|
||||
use tock_registers::interfaces::{ReadWriteable, Readable};
|
||||
|
||||
use registers::SSTATUS;
|
||||
|
||||
pub mod mem;
|
||||
pub use mem::{process::ProcessAddressSpaceImpl, KernelTableManagerImpl};
|
||||
pub use mem::{KernelTableManagerImpl, process::ProcessAddressSpaceImpl};
|
||||
pub mod context;
|
||||
pub use context::TaskContextImpl;
|
||||
pub mod intrinsics;
|
||||
|
||||
@@ -2,12 +2,11 @@ use kernel_arch_interface::sync::IrqSafeSpinlock;
|
||||
use libk_mm_interface::{address::PhysicalAddress, table::EntryLevel};
|
||||
|
||||
use crate::{
|
||||
mem::{
|
||||
auto_lower_address,
|
||||
table::{PageEntry, PageTable, L1},
|
||||
KERNEL_VIRT_OFFSET,
|
||||
},
|
||||
ArchitectureImpl,
|
||||
mem::{
|
||||
KERNEL_VIRT_OFFSET, auto_lower_address,
|
||||
table::{L1, PageEntry, PageTable},
|
||||
},
|
||||
};
|
||||
|
||||
pub const IDENTITY_SIZE_L1: usize = 64;
|
||||
|
||||
@@ -3,13 +3,13 @@ use kernel_arch_interface::mem::{
|
||||
};
|
||||
use libk_mm_interface::{
|
||||
address::PhysicalAddress,
|
||||
table::{page_index, EntryLevel, EntryLevelExt},
|
||||
table::{EntryLevel, EntryLevelExt, page_index},
|
||||
};
|
||||
use tock_registers::interfaces::Writeable;
|
||||
use yggdrasil_abi::error::Error;
|
||||
|
||||
use crate::{
|
||||
mem::table::{PageTable, L1, L3},
|
||||
mem::table::{L1, L3, PageTable},
|
||||
registers::SATP,
|
||||
};
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ use crate::mem::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
table::{DroppableRange, PageTable, L1, L2, L3},
|
||||
KernelTableManagerImpl, USER_BOUNDARY,
|
||||
table::{DroppableRange, L1, L2, L3, PageTable},
|
||||
};
|
||||
|
||||
pub struct ProcessAddressSpaceImpl<TA: TableAllocator> {
|
||||
|
||||
@@ -10,8 +10,8 @@ use libk_mm_interface::{
|
||||
pointer::{PhysicalRef, PhysicalRefMut},
|
||||
process::PageAttributeUpdate,
|
||||
table::{
|
||||
page_index, EntryLevel, EntryLevelDrop, NextPageTable, NonTerminalEntryLevel,
|
||||
TableAllocator,
|
||||
EntryLevel, EntryLevelDrop, NextPageTable, NonTerminalEntryLevel, TableAllocator,
|
||||
page_index,
|
||||
},
|
||||
};
|
||||
use yggdrasil_abi::error::Error;
|
||||
@@ -109,8 +109,8 @@ impl<L: EntryLevel> PageTable<L> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_zeroed<'a, TA: TableAllocator>(
|
||||
) -> Result<PhysicalRefMut<'a, PageTable<L>, KernelTableManagerImpl>, Error> {
|
||||
pub fn new_zeroed<'a, TA: TableAllocator>()
|
||||
-> Result<PhysicalRefMut<'a, PageTable<L>, KernelTableManagerImpl>, Error> {
|
||||
let physical = TA::allocate_page_table()?;
|
||||
let mut table =
|
||||
unsafe { PhysicalRefMut::<'a, Self, KernelTableManagerImpl>::map(physical) };
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
use device_api::{ResetDevice, device::Device};
|
||||
use yggdrasil_abi::{error::Error, primitive_enum};
|
||||
|
||||
const EXT_HSM: u64 = 0x48534D;
|
||||
const EXT_TIME: u64 = 0x54494D45;
|
||||
const EXT_DBCN: u64 = 0x4442434E;
|
||||
const EXT_SPI: u64 = 0x735049;
|
||||
const EXT_SYSTEM_SHUTDOWN: u64 = 0x53525354;
|
||||
const EXT_SYSTEM_SHUTDOWN_LEGACY: u64 = 0x08;
|
||||
const EXT_SYSTEM_RESET: u64 = 0x53525354;
|
||||
|
||||
primitive_enum! {
|
||||
pub enum Status: i64 {
|
||||
@@ -50,6 +54,20 @@ impl From<i64> for SbiError {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SbiResetMethod;
|
||||
|
||||
impl Device for SbiResetMethod {
|
||||
fn display_name(&self) -> &str {
|
||||
"SBI reset"
|
||||
}
|
||||
}
|
||||
|
||||
impl ResetDevice for SbiResetMethod {
|
||||
unsafe fn reset(&self) -> ! {
|
||||
sbi_system_reset()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[inline(always)]
|
||||
unsafe fn sbi_do_call(
|
||||
@@ -76,11 +94,7 @@ unsafe fn sbi_do_call(
|
||||
);
|
||||
}
|
||||
let a0 = a0 as i64;
|
||||
if a0 == 0 {
|
||||
Ok(a1)
|
||||
} else {
|
||||
Err(a0.into())
|
||||
}
|
||||
if a0 == 0 { Ok(a1) } else { Err(a0.into()) }
|
||||
}
|
||||
|
||||
pub fn sbi_hart_start(hart_id: u64, start_addr: u64, opaque: u64) -> Result<(), Error> {
|
||||
@@ -108,3 +122,14 @@ pub fn sbi_debug_console_write_byte(byte: u8) {
|
||||
pub fn sbi_set_timer(next_event: u64) {
|
||||
unsafe { sbi_do_call(EXT_TIME, 0x00, next_event, 0, 0, 0, 0, 0) }.ok();
|
||||
}
|
||||
|
||||
pub fn sbi_system_reset() -> ! {
|
||||
unsafe { sbi_do_call(EXT_SYSTEM_RESET, 0x00, 0x01, 0x00, 0, 0, 0, 0) }.ok();
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
pub fn sbi_system_shutdown() -> ! {
|
||||
unsafe { sbi_do_call(EXT_SYSTEM_SHUTDOWN, 0x00, 0, 0, 0, 0, 0, 0) }.ok();
|
||||
unsafe { sbi_do_call(EXT_SYSTEM_SHUTDOWN_LEGACY, 0x00, 0, 0, 0, 0, 0, 0) }.ok();
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ cfg_if! {
|
||||
|
||||
pub use imp::{ArchitectureImpl, KernelTableManagerImpl, ProcessAddressSpaceImpl, TaskContextImpl};
|
||||
|
||||
pub use kernel_arch_interface::{guard, mem, sync, task, util, Architecture, KERNEL_VIRT_OFFSET};
|
||||
pub use kernel_arch_interface::{Architecture, KERNEL_VIRT_OFFSET, guard, mem, sync, task, util};
|
||||
|
||||
pub type CpuImpl<S> = kernel_arch_interface::cpu::CpuImpl<ArchitectureImpl, S>;
|
||||
pub type LocalCpuImpl<'a, S> = kernel_arch_interface::cpu::LocalCpuImpl<'a, ArchitectureImpl, S>;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kernel-arch-x86"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
kernel-arch-interface.workspace = true
|
||||
|
||||
@@ -170,36 +170,40 @@ impl CpuFeatureSet for CpuFeatures {
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||
unsafe fn raw_cpuid(eax: u32, result: &mut [u32]) {
|
||||
core::arch::asm!(
|
||||
r#"
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
r#"
|
||||
push %rbx
|
||||
cpuid
|
||||
mov %ebx, {0:e}
|
||||
pop %rbx
|
||||
"#,
|
||||
out(reg) result[0],
|
||||
out("edx") result[1],
|
||||
out("ecx") result[2],
|
||||
in("eax") eax,
|
||||
options(att_syntax)
|
||||
);
|
||||
out(reg) result[0],
|
||||
out("edx") result[1],
|
||||
out("ecx") result[2],
|
||||
in("eax") eax,
|
||||
options(att_syntax)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
||||
unsafe fn raw_cpuid(eax: u32, result: &mut [u32]) {
|
||||
core::arch::asm!(
|
||||
r#"
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
r#"
|
||||
push %ebx
|
||||
cpuid
|
||||
mov %ebx, {0:e}
|
||||
pop %ebx
|
||||
"#,
|
||||
out(reg) result[0],
|
||||
out("edx") result[1],
|
||||
out("ecx") result[2],
|
||||
in("eax") eax,
|
||||
options(att_syntax)
|
||||
);
|
||||
out(reg) result[0],
|
||||
out("edx") result[1],
|
||||
out("ecx") result[2],
|
||||
in("eax") eax,
|
||||
options(att_syntax)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn cpuid_features() -> (EcxFeatures, EdxFeatures, ExtEdxFeatures) {
|
||||
|
||||
+34
-32
@@ -225,42 +225,44 @@ mod imp {
|
||||
offset: gdt_addr,
|
||||
};
|
||||
|
||||
core::arch::asm!(
|
||||
r#"
|
||||
wbinvd
|
||||
lgdt ({0})
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
r#"
|
||||
wbinvd
|
||||
lgdt ({0})
|
||||
|
||||
// Have to use iretq here
|
||||
mov %rsp, %rcx
|
||||
leaq 1f(%rip), %rax
|
||||
// Have to use iretq here
|
||||
mov %rsp, %rcx
|
||||
leaq 1f(%rip), %rax
|
||||
|
||||
// SS:RSP
|
||||
pushq $0x10
|
||||
pushq %rcx
|
||||
// SS:RSP
|
||||
pushq $0x10
|
||||
pushq %rcx
|
||||
|
||||
// RFLAGS
|
||||
pushfq
|
||||
// RFLAGS
|
||||
pushfq
|
||||
|
||||
// CS:RIP
|
||||
pushq $0x08
|
||||
pushq %rax
|
||||
iretq
|
||||
1:
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
// CS:RIP
|
||||
pushq $0x08
|
||||
pushq %rax
|
||||
iretq
|
||||
1:
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
|
||||
mov $0x28, %ax
|
||||
ltr %ax
|
||||
"#,
|
||||
in(reg) &gdtr,
|
||||
out("rax") _,
|
||||
out("rcx") _,
|
||||
options(att_syntax)
|
||||
);
|
||||
mov $0x28, %ax
|
||||
ltr %ax
|
||||
"#,
|
||||
in(reg) &gdtr,
|
||||
out("rax") _,
|
||||
out("rcx") _,
|
||||
options(att_syntax)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes and loads the GDT data structure for the current CPU.
|
||||
@@ -270,7 +272,7 @@ mod imp {
|
||||
/// Intended to be called once per each CPU during their early initialization.
|
||||
pub unsafe fn init() -> usize {
|
||||
let (gdt, tss) = create_gdt();
|
||||
load_gdt(gdt);
|
||||
unsafe { load_gdt(gdt) };
|
||||
(tss as *const Tss).addr()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,9 @@ impl IoPortAccess<u32> for IoPort<u32> {
|
||||
#[inline]
|
||||
pub unsafe fn inb(port: u16) -> u8 {
|
||||
let value: u8;
|
||||
core::arch::asm!("inb %dx, %al", in("dx") port, out("al") value, options(att_syntax));
|
||||
unsafe {
|
||||
core::arch::asm!("inb %dx, %al", in("dx") port, out("al") value, options(att_syntax))
|
||||
};
|
||||
value
|
||||
}
|
||||
|
||||
@@ -88,7 +90,9 @@ pub unsafe fn inb(port: u16) -> u8 {
|
||||
#[inline]
|
||||
pub unsafe fn inw(port: u16) -> u16 {
|
||||
let value: u16;
|
||||
core::arch::asm!("inw %dx, %ax", in("dx") port, out("ax") value, options(att_syntax));
|
||||
unsafe {
|
||||
core::arch::asm!("inw %dx, %ax", in("dx") port, out("ax") value, options(att_syntax))
|
||||
};
|
||||
value
|
||||
}
|
||||
|
||||
@@ -100,7 +104,9 @@ pub unsafe fn inw(port: u16) -> u16 {
|
||||
#[inline]
|
||||
pub unsafe fn inl(port: u16) -> u32 {
|
||||
let value: u32;
|
||||
core::arch::asm!("inl %dx, %eax", in("dx") port, out("eax") value, options(att_syntax));
|
||||
unsafe {
|
||||
core::arch::asm!("inl %dx, %eax", in("dx") port, out("eax") value, options(att_syntax))
|
||||
};
|
||||
value
|
||||
}
|
||||
|
||||
@@ -111,7 +117,9 @@ pub unsafe fn inl(port: u16) -> u32 {
|
||||
/// Provides direct access to port I/O, unsafe.
|
||||
#[inline]
|
||||
pub unsafe fn outb(port: u16, value: u8) {
|
||||
core::arch::asm!("outb %al, %dx", in("dx") port, in("al") value, options(att_syntax));
|
||||
unsafe {
|
||||
core::arch::asm!("outb %al, %dx", in("dx") port, in("al") value, options(att_syntax))
|
||||
};
|
||||
}
|
||||
|
||||
/// Writes a 16-bit value to the I/O port.
|
||||
@@ -121,7 +129,9 @@ pub unsafe fn outb(port: u16, value: u8) {
|
||||
/// Provides direct access to port I/O, unsafe.
|
||||
#[inline]
|
||||
pub unsafe fn outw(port: u16, value: u16) {
|
||||
core::arch::asm!("outw %ax, %dx", in("dx") port, in("ax") value, options(att_syntax));
|
||||
unsafe {
|
||||
core::arch::asm!("outw %ax, %dx", in("dx") port, in("ax") value, options(att_syntax))
|
||||
};
|
||||
}
|
||||
|
||||
/// Writes a 32-bit value to the I/O port.
|
||||
@@ -131,7 +141,9 @@ pub unsafe fn outw(port: u16, value: u16) {
|
||||
/// Provides direct access to port I/O, unsafe.
|
||||
#[inline]
|
||||
pub unsafe fn outl(port: u16, value: u32) {
|
||||
core::arch::asm!("outl %eax, %dx", in("dx") port, in("eax") value, options(att_syntax));
|
||||
unsafe {
|
||||
core::arch::asm!("outl %eax, %dx", in("dx") port, in("eax") value, options(att_syntax))
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#![feature(iter_chain, new_zeroed_alloc, box_as_ptr)]
|
||||
#![feature(box_as_ptr)]
|
||||
#![allow(clippy::new_without_default)]
|
||||
#![no_std]
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kernel-arch-x86_64"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
yggdrasil-abi.workspace = true
|
||||
|
||||
@@ -4,14 +4,14 @@ use kernel_arch_interface::{
|
||||
mem::{KernelTableManager, PhysicalMemoryAllocator},
|
||||
task::{ForkFrame, StackBuilder, TaskContext, TaskFrame, UserContextInfo},
|
||||
};
|
||||
use kernel_arch_x86::registers::{FpuContext, CR3, MSR_IA32_FS_BASE};
|
||||
use kernel_arch_x86::registers::{CR3, FpuContext, MSR_IA32_FS_BASE};
|
||||
use libk_mm_interface::address::PhysicalAddress;
|
||||
use tock_registers::interfaces::Writeable;
|
||||
use yggdrasil_abi::{arch::SavedFrame, error::Error};
|
||||
|
||||
use crate::{
|
||||
mem::{auto_lower_address, fixed},
|
||||
ArchitectureImpl,
|
||||
mem::{auto_lower_address, fixed},
|
||||
};
|
||||
|
||||
/// Frame saved onto the stack when taking an IRQ
|
||||
@@ -255,7 +255,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
type Context = TaskContextImpl<K, PA>;
|
||||
|
||||
unsafe fn fork(&self, address_space: u64) -> Result<TaskContextImpl<K, PA>, Error> {
|
||||
TaskContextImpl::from_syscall_frame(self, address_space)
|
||||
unsafe { TaskContextImpl::from_syscall_frame(self, address_space) }
|
||||
}
|
||||
|
||||
fn set_return_value(&mut self, value: u64) {
|
||||
@@ -405,18 +405,20 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
}
|
||||
|
||||
unsafe fn store_state(&self) {
|
||||
FpuContext::store(self.fpu_context.get());
|
||||
unsafe { FpuContext::store(self.fpu_context.get()) };
|
||||
// No need to save TSS/%cr3/%fs base back into the TCB, only the kernel
|
||||
// can make changes to those
|
||||
}
|
||||
|
||||
unsafe fn load_state(&self) {
|
||||
FpuContext::restore(self.fpu_context.get());
|
||||
// When the task is interrupted from Ring 3, make the CPU load
|
||||
// the top of its kernel stack
|
||||
ArchitectureImpl::set_local_tss_sp0(self.tss_rsp0);
|
||||
MSR_IA32_FS_BASE.set((*self.inner.get()).fs_base as u64);
|
||||
CR3.set_address(self.cr3);
|
||||
unsafe {
|
||||
FpuContext::restore(self.fpu_context.get());
|
||||
// When the task is interrupted from Ring 3, make the CPU load
|
||||
// the top of its kernel stack
|
||||
ArchitectureImpl::set_local_tss_sp0(self.tss_rsp0);
|
||||
MSR_IA32_FS_BASE.set((*self.inner.get()).fs_base as u64);
|
||||
CR3.set_address(self.cr3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,7 +447,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
stack.push(entry as _);
|
||||
stack.push(arg);
|
||||
|
||||
setup_common_context(&mut stack, __x86_64_task_enter_kernel as _);
|
||||
setup_common_context(&mut stack, (__x86_64_task_enter_kernel as *const ()).addr());
|
||||
|
||||
let sp = stack.build();
|
||||
|
||||
@@ -483,7 +485,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
stack.push(context.argument);
|
||||
stack.push(context.stack_pointer);
|
||||
|
||||
setup_common_context(&mut stack, __x86_64_task_enter_user as _);
|
||||
setup_common_context(&mut stack, (__x86_64_task_enter_user as *const ()).addr());
|
||||
|
||||
let sp = stack.build();
|
||||
let rsp0 = stack_base + USER_TASK_PAGES * 0x1000;
|
||||
@@ -506,8 +508,10 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
}
|
||||
|
||||
unsafe fn enter(&self) -> ! {
|
||||
self.load_state();
|
||||
__x86_64_enter_task(self.inner.get())
|
||||
unsafe {
|
||||
self.load_state();
|
||||
__x86_64_enter_task(self.inner.get())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn switch(&self, from: &Self) {
|
||||
@@ -515,14 +519,18 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
return;
|
||||
}
|
||||
|
||||
from.store_state();
|
||||
self.load_state();
|
||||
__x86_64_switch_task(self.inner.get(), from.inner.get())
|
||||
unsafe {
|
||||
from.store_state();
|
||||
self.load_state();
|
||||
__x86_64_switch_task(self.inner.get(), from.inner.get())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn switch_and_drop(&self, thread: *const ()) {
|
||||
self.load_state();
|
||||
__x86_64_switch_and_drop(self.inner.get(), thread)
|
||||
unsafe {
|
||||
self.load_state();
|
||||
__x86_64_switch_and_drop(self.inner.get(), thread)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_thread_pointer(&self, tp: usize) {
|
||||
@@ -561,7 +569,7 @@ fn setup_common_context(builder: &mut StackBuilder, entry: usize) {
|
||||
builder.push(0); // %rbx
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn __x86_64_task_enter_kernel();
|
||||
fn __x86_64_task_enter_user();
|
||||
fn __x86_64_task_enter_from_fork();
|
||||
|
||||
@@ -11,10 +11,10 @@ use core::{
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use device_api::interrupt::{LocalInterruptController, MessageInterruptController};
|
||||
use kernel_arch_interface::{
|
||||
Architecture,
|
||||
cpu::{CpuData, CpuImpl, IpiQueue},
|
||||
task::Scheduler,
|
||||
util::OneTimeInit,
|
||||
Architecture,
|
||||
};
|
||||
use kernel_arch_x86::{cpuid::CpuFeatures, registers::MSR_IA32_KERNEL_GS_BASE};
|
||||
use libk_mm_interface::address::PhysicalAddress;
|
||||
@@ -24,7 +24,7 @@ pub mod context;
|
||||
pub mod mem;
|
||||
|
||||
pub use context::TaskContextImpl;
|
||||
pub use mem::{process::ProcessAddressSpaceImpl, KernelTableManagerImpl};
|
||||
pub use mem::{KernelTableManagerImpl, process::ProcessAddressSpaceImpl};
|
||||
|
||||
pub struct ArchitectureImpl;
|
||||
|
||||
@@ -103,7 +103,7 @@ impl Architecture for ArchitectureImpl {
|
||||
|
||||
unsafe fn set_local_cpu(cpu: *mut ()) {
|
||||
MSR_IA32_KERNEL_GS_BASE.set(cpu as u64);
|
||||
core::arch::asm!("wbinvd; swapgs");
|
||||
unsafe { core::arch::asm!("wbinvd; swapgs") };
|
||||
}
|
||||
|
||||
fn local_cpu() -> *mut () {
|
||||
@@ -127,7 +127,7 @@ impl Architecture for ArchitectureImpl {
|
||||
)));
|
||||
cpu.this = cpu.deref_mut();
|
||||
|
||||
cpu.set_local();
|
||||
unsafe { cpu.set_local() };
|
||||
}
|
||||
|
||||
fn idle_task() -> extern "C" fn(usize) -> ! {
|
||||
@@ -153,10 +153,12 @@ impl Architecture for ArchitectureImpl {
|
||||
|
||||
unsafe fn set_interrupt_mask(mask: bool) -> bool {
|
||||
let old = Self::interrupt_mask();
|
||||
if mask {
|
||||
core::arch::asm!("cli");
|
||||
} else {
|
||||
core::arch::asm!("sti");
|
||||
unsafe {
|
||||
if mask {
|
||||
core::arch::asm!("cli");
|
||||
} else {
|
||||
core::arch::asm!("sti");
|
||||
}
|
||||
}
|
||||
old
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
use core::ops::Range;
|
||||
|
||||
use kernel_arch_interface::{mem::DeviceMemoryAttributes, sync::IrqSafeSpinlock, Architecture};
|
||||
use kernel_arch_interface::{Architecture, mem::DeviceMemoryAttributes, sync::IrqSafeSpinlock};
|
||||
use kernel_arch_x86::registers::CR3;
|
||||
use libk_mm_interface::{
|
||||
address::PhysicalAddress,
|
||||
device::{DevicePageManager, DevicePageTableLevel},
|
||||
table::{page_index, EntryLevel},
|
||||
table::{EntryLevel, page_index},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ArchitectureImpl, KERNEL_VIRT_OFFSET,
|
||||
mem::{
|
||||
auto_lower_address,
|
||||
table::{PageAttributes, PageEntry, PageTable, L0, L1, L2, L3},
|
||||
table::{L0, L1, L2, L3, PageAttributes, PageEntry, PageTable},
|
||||
},
|
||||
ArchitectureImpl, KERNEL_VIRT_OFFSET,
|
||||
};
|
||||
|
||||
pub const IDENTITY_SIZE_L1: usize = 64;
|
||||
@@ -101,29 +101,33 @@ impl DevicePageTableLevel for L3DeviceMemory {
|
||||
}
|
||||
|
||||
pub(super) unsafe fn setup(have_1gib_pages: bool) {
|
||||
let phys = PhysicalAddress::from_usize(auto_lower_address(&raw const KERNEL_PDPT));
|
||||
KERNEL_PML4[KERNEL_L0I] = PageEntry::table(phys, PageAttributes::WRITABLE);
|
||||
unsafe {
|
||||
let phys = PhysicalAddress::from_usize(auto_lower_address(&raw const KERNEL_PDPT));
|
||||
KERNEL_PML4[KERNEL_L0I] = PageEntry::table(phys, PageAttributes::WRITABLE);
|
||||
|
||||
if have_1gib_pages {
|
||||
for i in 0..IDENTITY_SIZE_L1 {
|
||||
let phys = PhysicalAddress::from_usize(i * L1::SIZE);
|
||||
KERNEL_PDPT[i] = PageEntry::<L1>::block(phys, PageAttributes::WRITABLE);
|
||||
if have_1gib_pages {
|
||||
for i in 0..IDENTITY_SIZE_L1 {
|
||||
let phys = PhysicalAddress::from_usize(i * L1::SIZE);
|
||||
KERNEL_PDPT[i] = PageEntry::<L1>::block(phys, PageAttributes::WRITABLE);
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
ArchitectureImpl::halt();
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
ArchitectureImpl::halt();
|
||||
}
|
||||
|
||||
// DEVICE_L1 -> Device L2 table
|
||||
// 0..DEVICE_MAPPING_L3_COUNT -> Device L3 tables -> Device L3 pages
|
||||
// ..512 -> Device L2 pages
|
||||
for i in 0..DEVICE_MAPPING_L3_COUNT {
|
||||
// DEVICE_L1 -> Device L2 table
|
||||
// 0..DEVICE_MAPPING_L3_COUNT -> Device L3 tables -> Device L3 pages
|
||||
// ..512 -> Device L2 pages
|
||||
for i in 0..DEVICE_MAPPING_L3_COUNT {
|
||||
let phys = PhysicalAddress::from_usize(auto_lower_address(
|
||||
&raw const DEVICE_MEMORY.normal.0[i],
|
||||
));
|
||||
DEVICE_MEMORY.large.0[i] = PageEntry::table(phys, PageAttributes::WRITABLE);
|
||||
}
|
||||
let phys =
|
||||
PhysicalAddress::from_usize(auto_lower_address(&raw const DEVICE_MEMORY.normal.0[i]));
|
||||
DEVICE_MEMORY.large.0[i] = PageEntry::table(phys, PageAttributes::WRITABLE);
|
||||
PhysicalAddress::from_usize(auto_lower_address(&raw const DEVICE_MEMORY.large.0));
|
||||
KERNEL_PDPT[DEVICE_L1] = PageEntry::table(phys, PageAttributes::WRITABLE);
|
||||
}
|
||||
let phys = PhysicalAddress::from_usize(auto_lower_address(&raw const DEVICE_MEMORY.large.0));
|
||||
KERNEL_PDPT[DEVICE_L1] = PageEntry::table(phys, PageAttributes::WRITABLE);
|
||||
}
|
||||
|
||||
pub(super) unsafe fn load() {
|
||||
|
||||
@@ -6,7 +6,7 @@ use yggdrasil_abi::error::Error;
|
||||
|
||||
use crate::KERNEL_VIRT_OFFSET;
|
||||
|
||||
use self::table::{PageTable, L0, L1};
|
||||
use self::table::{L0, L1, PageTable};
|
||||
|
||||
pub mod fixed;
|
||||
pub mod process;
|
||||
@@ -41,13 +41,17 @@ impl KernelTableManager for KernelTableManagerImpl {
|
||||
) -> Result<RawDeviceMemoryMapping<Self>, Error> {
|
||||
let _lock = fixed::LOCK.lock();
|
||||
#[allow(static_mut_refs)]
|
||||
fixed::DEVICE_MEMORY.map_device_pages(PhysicalAddress::from_u64(base), count, attrs)
|
||||
unsafe {
|
||||
fixed::DEVICE_MEMORY.map_device_pages(PhysicalAddress::from_u64(base), count, attrs)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn unmap_device_pages(mapping: &RawDeviceMemoryMapping<Self>) {
|
||||
let _lock = fixed::LOCK.lock();
|
||||
#[allow(static_mut_refs)]
|
||||
fixed::DEVICE_MEMORY.unmap_device_pages(mapping);
|
||||
unsafe {
|
||||
fixed::DEVICE_MEMORY.unmap_device_pages(mapping)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,9 +88,11 @@ pub fn auto_lower_address<T>(pointer: *const T) -> usize {
|
||||
/// Unsafe, must only be called by BSP during its early init, must already be in "higher-half"
|
||||
#[inline(never)]
|
||||
pub unsafe fn init_fixed_tables(have_1gib_pages: bool, bsp: bool) {
|
||||
fixed::setup(have_1gib_pages);
|
||||
if bsp {
|
||||
fixed::load();
|
||||
unsafe {
|
||||
fixed::setup(have_1gib_pages);
|
||||
if bsp {
|
||||
fixed::load();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,5 +101,5 @@ pub unsafe fn init_fixed_tables(have_1gib_pages: bool, bsp: bool) {
|
||||
/// `address` must be page-aligned.
|
||||
#[inline]
|
||||
pub unsafe fn flush_tlb_entry(address: usize) {
|
||||
core::arch::asm!("invlpg ({0})", in(reg) address, options(att_syntax));
|
||||
unsafe { core::arch::asm!("invlpg ({0})", in(reg) address, options(att_syntax)) };
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ use crate::KernelTableManagerImpl;
|
||||
|
||||
use super::{
|
||||
clone_kernel_tables, flush_tlb_entry,
|
||||
table::{PageEntry, PageTable, L0, L1, L2, L3},
|
||||
table::{L0, L1, L2, L3, PageEntry, PageTable},
|
||||
};
|
||||
|
||||
/// Represents a process or kernel address space. Because x86-64 does not have cool stuff like
|
||||
@@ -85,8 +85,10 @@ impl<TA: TableAllocator> ProcessAddressSpaceManager<TA> for ProcessAddressSpaceI
|
||||
}
|
||||
|
||||
unsafe fn clear(&mut self) {
|
||||
self.l0
|
||||
.drop_range::<TA>(0..((Self::UPPER_LIMIT_PFN * L3::SIZE).page_index::<L1>()));
|
||||
unsafe {
|
||||
self.l0
|
||||
.drop_range::<TA>(0..((Self::UPPER_LIMIT_PFN * L3::SIZE).page_index::<L1>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -220,12 +220,12 @@ impl<L: EntryLevel> PageTable<L> {
|
||||
/// Unsafe: the caller must ensure the provided reference is properly aligned and contains sane
|
||||
/// data.
|
||||
pub unsafe fn from_raw_slice_mut(data: &mut [PageEntry<L>; 512]) -> &mut Self {
|
||||
core::mem::transmute(data)
|
||||
unsafe { core::mem::transmute(data) }
|
||||
}
|
||||
|
||||
/// Allocates a new page table, filling it with non-preset entries
|
||||
pub fn new_zeroed<'a, TA: TableAllocator>(
|
||||
) -> Result<PhysicalRefMut<'a, Self, KernelTableManagerImpl>, Error> {
|
||||
pub fn new_zeroed<'a, TA: TableAllocator>()
|
||||
-> Result<PhysicalRefMut<'a, Self, KernelTableManagerImpl>, Error> {
|
||||
let physical = TA::allocate_page_table()?;
|
||||
let mut table =
|
||||
unsafe { PhysicalRefMut::<'a, Self, KernelTableManagerImpl>::map(physical) };
|
||||
@@ -243,8 +243,10 @@ impl<L: EntryLevel> PageTable<L> {
|
||||
///
|
||||
/// The caller must ensure the table is no longer in use and is not referenced anymore.
|
||||
pub unsafe fn free<TA: TableAllocator>(this: PhysicalRefMut<Self, KernelTableManagerImpl>) {
|
||||
let physical = this.as_physical_address();
|
||||
TA::free_page_table(physical);
|
||||
unsafe {
|
||||
let physical = this.as_physical_address();
|
||||
TA::free_page_table(physical);
|
||||
}
|
||||
}
|
||||
|
||||
// /// Returns the physical address of this table
|
||||
@@ -303,25 +305,29 @@ where
|
||||
const FULL_RANGE: Range<usize> = 0..512;
|
||||
|
||||
unsafe fn drop_range<TA: TableAllocator>(&mut self, range: Range<usize>) {
|
||||
for index in range {
|
||||
let entry = self[index];
|
||||
unsafe {
|
||||
for index in range {
|
||||
let entry = self[index];
|
||||
|
||||
if let Some(table) = entry.as_table() {
|
||||
let mut table_ref: PhysicalRefMut<PageTable<L::NextLevel>, KernelTableManagerImpl> =
|
||||
PhysicalRefMut::map(table);
|
||||
if let Some(table) = entry.as_table() {
|
||||
let mut table_ref: PhysicalRefMut<
|
||||
PageTable<L::NextLevel>,
|
||||
KernelTableManagerImpl,
|
||||
> = PhysicalRefMut::map(table);
|
||||
|
||||
table_ref.drop_all::<TA>();
|
||||
table_ref.drop_all::<TA>();
|
||||
|
||||
TA::free_page_table(table);
|
||||
} else if entry.is_present() {
|
||||
// Memory must've been cleared beforehand, so no non-table entries must be present
|
||||
panic!(
|
||||
"Expected a table containing only tables, got table[{}] = {:#x?}",
|
||||
index, entry.0
|
||||
);
|
||||
TA::free_page_table(table);
|
||||
} else if entry.is_present() {
|
||||
// Memory must've been cleared beforehand, so no non-table entries must be present
|
||||
panic!(
|
||||
"Expected a table containing only tables, got table[{}] = {:#x?}",
|
||||
index, entry.0
|
||||
);
|
||||
}
|
||||
|
||||
self[index] = PageEntry::INVALID;
|
||||
}
|
||||
|
||||
self[index] = PageEntry::INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -6,9 +6,9 @@ use std::{
|
||||
};
|
||||
|
||||
use abi_generator::{
|
||||
abi::{ty::TypeWidth, AbiBuilder},
|
||||
syntax::UnwrapFancy,
|
||||
TargetEnv,
|
||||
abi::{AbiBuilder, ty::TypeWidth},
|
||||
syntax::UnwrapFancy,
|
||||
};
|
||||
|
||||
fn build_x86_64() {
|
||||
|
||||
@@ -7,7 +7,7 @@ use device_api::{
|
||||
device::Device,
|
||||
interrupt::{InterruptHandler, Irq, IrqVector},
|
||||
};
|
||||
use kernel_arch_x86::{intrinsics, ISA_IRQ_OFFSET};
|
||||
use kernel_arch_x86::{ISA_IRQ_OFFSET, intrinsics};
|
||||
use libk::device::external_interrupt_controller;
|
||||
use libk_mm::{
|
||||
address::{PhysicalAddress, Virtualize},
|
||||
@@ -15,8 +15,8 @@ use libk_mm::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
mem::{read_memory, write_memory},
|
||||
ACPI_SYSTEM,
|
||||
mem::{read_memory, write_memory},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#![feature(allocator_api)]
|
||||
#![feature(allocator_api, never_type)]
|
||||
#![no_std]
|
||||
|
||||
use acpi::AcpiTables;
|
||||
use acpi_system::{AcpiInterruptMethod, AcpiSystem};
|
||||
use acpi_system::{AcpiInterruptMethod, AcpiSleepState, AcpiSystem};
|
||||
use alloc::boxed::Box;
|
||||
use libk::error::Error;
|
||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||
use libk_util::{OneTimeInit, sync::IrqSafeSpinlock};
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
@@ -45,6 +45,17 @@ pub fn get_pci_route(
|
||||
.ok()
|
||||
}
|
||||
|
||||
pub fn power_off() -> Result<!, Error> {
|
||||
let system = ACPI_SYSTEM.get();
|
||||
unsafe {
|
||||
system.lock().enter_sleep_state(AcpiSleepState::S5).ok();
|
||||
|
||||
loop {
|
||||
core::arch::asm!("cli; hlt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes ACPI management
|
||||
pub fn switch_to_acpi(tables: &'static AcpiTables<AcpiHandlerImpl>) -> Result<(), Error> {
|
||||
// NOTE mostly broken for real HW
|
||||
@@ -67,12 +78,6 @@ pub fn switch_to_acpi(tables: &'static AcpiTables<AcpiHandlerImpl>) -> Result<()
|
||||
// // 6. Do something with the devices
|
||||
// // 7. Actually enter the S5 state
|
||||
|
||||
// unsafe {
|
||||
// PLATFORM
|
||||
// .send_ipi(IpiDeliveryTarget::OtherCpus, IpiMessage::Shutdown)
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// SHUTDOWN_FENCE.signal();
|
||||
// SHUTDOWN_FENCE.wait_all(CPU_COUNT.load(Ordering::Acquire));
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "ygg_driver_ahci"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
authors = ["Mark Poliakov <mark@alnyan.me>"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use core::mem::{size_of, MaybeUninit};
|
||||
use core::mem::{MaybeUninit, size_of};
|
||||
|
||||
use device_api::dma::DmaAllocator;
|
||||
use libk::dma::{BusAddress, DmaBuffer, DmaSliceMut};
|
||||
use tock_registers::register_structs;
|
||||
|
||||
use crate::{data::AtaString, error::AhciError, MAX_PRD_SIZE};
|
||||
use crate::{MAX_PRD_SIZE, data::AtaString, error::AhciError};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[repr(u8)]
|
||||
@@ -115,7 +115,7 @@ impl AtaCommand for AtaIdentify {
|
||||
}
|
||||
|
||||
unsafe fn into_response(self) -> Self::Response {
|
||||
DmaBuffer::assume_init(self.buffer)
|
||||
unsafe { DmaBuffer::assume_init(self.buffer) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ use libk_util::{ConstAssert, IsTrue};
|
||||
use static_assertions::const_assert_eq;
|
||||
|
||||
use crate::{
|
||||
MAX_PRD_SIZE,
|
||||
command::{AtaCommand, AtaIdentify, AtaIdentifyResponse},
|
||||
error::AhciError,
|
||||
MAX_PRD_SIZE,
|
||||
};
|
||||
|
||||
pub const COMMAND_LIST_LENGTH: usize = 32;
|
||||
@@ -20,7 +20,7 @@ const AHCI_FIS_REG_H2D: u8 = 0x27;
|
||||
#[repr(C)]
|
||||
pub struct AtaString<const N: usize>
|
||||
where
|
||||
ConstAssert<{ N % 2 == 0 }>: IsTrue,
|
||||
ConstAssert<{ N.is_multiple_of(2) }>: IsTrue,
|
||||
{
|
||||
data: [u8; N],
|
||||
}
|
||||
@@ -243,7 +243,7 @@ impl AtaIdentifyResponse {
|
||||
|
||||
impl<const N: usize> AtaString<N>
|
||||
where
|
||||
ConstAssert<{ N % 2 == 0 }>: IsTrue,
|
||||
ConstAssert<{ N.is_multiple_of(2) }>: IsTrue,
|
||||
{
|
||||
#[allow(clippy::inherent_to_string)]
|
||||
pub fn to_string(&self) -> String {
|
||||
|
||||
@@ -15,18 +15,18 @@ use device_api::{
|
||||
use error::AhciError;
|
||||
use libk::{device::manager::probe_partitions, dma::DmaBuffer, fs::devfs, task::runtime};
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||
use libk_util::{OneTimeInit, sync::IrqSafeSpinlock};
|
||||
use port::AhciPort;
|
||||
use regs::{PortRegs, Regs};
|
||||
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
||||
use ygg_driver_pci::{
|
||||
PciCommandRegister, PciConfigurationSpace,
|
||||
device::{PciDeviceInfo, PreferredInterruptMode},
|
||||
macros::pci_driver,
|
||||
PciCommandRegister, PciConfigurationSpace,
|
||||
};
|
||||
use yggdrasil_abi::{error::Error, io::FileMode};
|
||||
|
||||
use crate::regs::{Version, CAP, GHC, SSTS};
|
||||
use crate::regs::{CAP, GHC, SSTS, Version};
|
||||
|
||||
mod command;
|
||||
mod data;
|
||||
|
||||
@@ -16,18 +16,18 @@ use libk::{
|
||||
error::Error,
|
||||
};
|
||||
use libk_mm::{
|
||||
address::PhysicalAddress, device::DeviceMemoryIo, table::MapAttributes, OnDemandPage,
|
||||
PageProvider, VirtualPage,
|
||||
OnDemandPage, PageProvider, VirtualPage, address::PhysicalAddress, device::DeviceMemoryIo,
|
||||
table::MapAttributes,
|
||||
};
|
||||
use libk_util::{sync::IrqSafeSpinlock, waker::QueueWaker, OneTimeInit};
|
||||
use libk_util::{OneTimeInit, sync::IrqSafeSpinlock, waker::QueueWaker};
|
||||
use tock_registers::interfaces::{Readable, Writeable};
|
||||
|
||||
use crate::{
|
||||
command::{AtaCommand, AtaIdentify, AtaReadDmaEx},
|
||||
data::{CommandListEntry, CommandTable, ReceivedFis, COMMAND_LIST_LENGTH},
|
||||
error::AhciError,
|
||||
regs::{PortRegs, CMD_PENDING, CMD_READY, IE, TFD},
|
||||
AhciController, MAX_COMMANDS, MAX_PRD_SIZE, SECTOR_SIZE,
|
||||
command::{AtaCommand, AtaIdentify, AtaReadDmaEx},
|
||||
data::{COMMAND_LIST_LENGTH, CommandListEntry, CommandTable, ReceivedFis},
|
||||
error::AhciError,
|
||||
regs::{CMD_PENDING, CMD_READY, IE, PortRegs, TFD},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
@@ -319,11 +319,11 @@ impl BlockDevice for AhciPort {
|
||||
position: u64,
|
||||
buffer: DmaSliceMut<'_, MaybeUninit<u8>>,
|
||||
) -> Result<(), Error> {
|
||||
if buffer.len() % SECTOR_SIZE != 0 {
|
||||
if !buffer.len().is_multiple_of(SECTOR_SIZE) {
|
||||
log::warn!("ahci: misaligned buffer size: {}", buffer.len());
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
if position % SECTOR_SIZE as u64 != 0 {
|
||||
if !position.is_multiple_of(SECTOR_SIZE as u64) {
|
||||
log::warn!("ahci: misaligned read");
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "ygg_driver_nvme"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
authors = ["Mark Poliakov <mark@alnyan.me>"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use core::fmt::{self, Write};
|
||||
|
||||
use libk::dma::BusAddress;
|
||||
use tock_registers::{interfaces::Readable, register_structs, registers::ReadOnly, UIntLike};
|
||||
use tock_registers::{UIntLike, interfaces::Readable, register_structs, registers::ReadOnly};
|
||||
|
||||
use crate::queue::PhysicalRegionPage;
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@ use libk::{
|
||||
error::Error,
|
||||
};
|
||||
use libk_mm::{
|
||||
OnDemandPage, PageProvider, PageSlice, VirtualPage,
|
||||
address::{AsPhysicalAddress, PhysicalAddress},
|
||||
table::MapAttributes,
|
||||
OnDemandPage, PageProvider, PageSlice, VirtualPage,
|
||||
};
|
||||
|
||||
use crate::{command::IdentifyNamespaceRequest, register_nvme_namespace, IoDirection};
|
||||
use crate::{IoDirection, command::IdentifyNamespaceRequest, register_nvme_namespace};
|
||||
|
||||
use super::{error::NvmeError, NvmeController};
|
||||
use super::{NvmeController, error::NvmeError};
|
||||
|
||||
#[allow(unused)]
|
||||
pub struct NvmeNamespace {
|
||||
@@ -92,10 +92,10 @@ impl BlockDevice for NvmeNamespace {
|
||||
position: u64,
|
||||
buffer: DmaSliceMut<'_, MaybeUninit<u8>>,
|
||||
) -> Result<(), Error> {
|
||||
if position % self.block_size() as u64 != 0 {
|
||||
if !position.is_multiple_of(self.block_size() as u64) {
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
if buffer.len() % self.block_size() != 0 || buffer.is_empty() {
|
||||
if !buffer.len().is_multiple_of(self.block_size()) || buffer.is_empty() {
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
let lba = position / self.block_size() as u64;
|
||||
@@ -115,10 +115,10 @@ impl BlockDevice for NvmeNamespace {
|
||||
}
|
||||
|
||||
async fn write_aligned(&self, position: u64, buffer: DmaSlice<'_, u8>) -> Result<(), Error> {
|
||||
if position % self.block_size() as u64 != 0 {
|
||||
if !position.is_multiple_of(self.block_size() as u64) {
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
if buffer.len() % self.block_size() != 0 || buffer.is_empty() {
|
||||
if !buffer.len().is_multiple_of(self.block_size()) || buffer.is_empty() {
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
let lba = position / self.block_size() as u64;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#![feature(const_trait_impl, let_chains, if_let_guard, maybe_uninit_slice)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![allow(missing_docs)]
|
||||
#![no_std]
|
||||
// TODO
|
||||
@@ -7,7 +7,7 @@
|
||||
extern crate alloc;
|
||||
|
||||
use core::{
|
||||
mem::{size_of, MaybeUninit},
|
||||
mem::{MaybeUninit, size_of},
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
time::Duration,
|
||||
};
|
||||
@@ -27,10 +27,10 @@ use libk::{
|
||||
fs::devfs,
|
||||
task::{cpu_count, cpu_index, runtime},
|
||||
};
|
||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo, L3_PAGE_SIZE};
|
||||
use libk_mm::{L3_PAGE_SIZE, address::PhysicalAddress, device::DeviceMemoryIo};
|
||||
use libk_util::{
|
||||
sync::{IrqGuard, IrqSafeSpinlock},
|
||||
OneTimeInit,
|
||||
sync::{IrqGuard, IrqSafeSpinlock},
|
||||
};
|
||||
use queue::PrpList;
|
||||
use regs::{CAP, CC};
|
||||
@@ -40,9 +40,9 @@ use tock_registers::{
|
||||
registers::{ReadOnly, ReadWrite, WriteOnly},
|
||||
};
|
||||
use ygg_driver_pci::{
|
||||
PciCommandRegister, PciConfigurationSpace,
|
||||
device::{PciDeviceInfo, PreferredInterruptMode},
|
||||
macros::pci_driver,
|
||||
PciCommandRegister, PciConfigurationSpace,
|
||||
};
|
||||
use yggdrasil_abi::{error::Error, io::FileMode};
|
||||
|
||||
@@ -284,8 +284,8 @@ impl NvmeController {
|
||||
|
||||
unsafe fn doorbell_pair(&self, idx: usize) -> (*mut u32, *mut u32) {
|
||||
let regs = self.regs.lock();
|
||||
let sq_ptr = regs.doorbell_ptr(self.doorbell_shift, false, idx);
|
||||
let cq_ptr = regs.doorbell_ptr(self.doorbell_shift, true, idx);
|
||||
let sq_ptr = unsafe { regs.doorbell_ptr(self.doorbell_shift, false, idx) };
|
||||
let cq_ptr = unsafe { regs.doorbell_ptr(self.doorbell_shift, true, idx) };
|
||||
(sq_ptr, cq_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ impl PrpList {
|
||||
size: usize,
|
||||
) -> Result<Self, NvmeError> {
|
||||
// TODO hardcoded page size
|
||||
if base.into_u64() % 0x1000 != 0 {
|
||||
if !base.into_u64().is_multiple_of(0x1000) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#![feature(generic_const_exprs, maybe_uninit_slice)]
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
#![no_std]
|
||||
|
||||
@@ -23,11 +23,11 @@ use libk::{
|
||||
task::{runtime, sync::AsyncMutex},
|
||||
};
|
||||
use libk_mm::{
|
||||
address::PhysicalAddress, table::MapAttributes, OnDemandPage, PageProvider, VirtualPage,
|
||||
OnDemandPage, PageProvider, VirtualPage, address::PhysicalAddress, table::MapAttributes,
|
||||
};
|
||||
use libk_util::{
|
||||
sync::{spin_rwlock::IrqSafeRwLock, IrqSafeSpinlock},
|
||||
OneTimeInit,
|
||||
sync::{IrqSafeSpinlock, spin_rwlock::IrqSafeRwLock},
|
||||
};
|
||||
use transport::{ScsiTransport, ScsiTransportWrapper};
|
||||
use yggdrasil_abi::io::FileMode;
|
||||
@@ -40,7 +40,7 @@ pub mod transport;
|
||||
|
||||
pub struct ScsiEnclosure {
|
||||
transport: AsyncMutex<ScsiTransportWrapper>,
|
||||
units: Vec<IrqSafeRwLock<Option<Arc<ScsiUnit>>>>,
|
||||
units: Vec<AsyncMutex<Option<Arc<ScsiUnit>>>>,
|
||||
index: OneTimeInit<u32>,
|
||||
shutdown: AtomicBool,
|
||||
}
|
||||
@@ -60,7 +60,7 @@ impl ScsiEnclosure {
|
||||
lun_count: usize,
|
||||
) -> Result<Arc<Self>, Error> {
|
||||
let transport = AsyncMutex::new(ScsiTransportWrapper::new(transport));
|
||||
let units = (0..lun_count).map(|_| IrqSafeRwLock::new(None)).collect();
|
||||
let units = (0..lun_count).map(|_| AsyncMutex::new(None)).collect();
|
||||
let this = Arc::new(Self {
|
||||
transport,
|
||||
units,
|
||||
@@ -74,7 +74,7 @@ impl ScsiEnclosure {
|
||||
if this.probe_lun(i as u8).await
|
||||
&& let Ok(unit) = ScsiUnit::setup(this.clone(), i as u8).await
|
||||
{
|
||||
*this.units[i].write() = Some(unit);
|
||||
*this.units[i].lock().await = Some(unit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ impl ScsiEnclosure {
|
||||
async fn poll(self: &Arc<Self>) {
|
||||
let index = *self.index.get();
|
||||
for lun in 0..self.units.len() {
|
||||
let mut slot = self.units[lun].write();
|
||||
let mut slot = self.units[lun].lock().await;
|
||||
let present = self.probe_lun(lun as u8).await;
|
||||
|
||||
if let Some(unit) = slot.as_ref() {
|
||||
@@ -143,12 +143,12 @@ impl ScsiEnclosure {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn detach(&self) {
|
||||
pub async fn detach(&self) {
|
||||
self.shutdown.store(true, Ordering::Release);
|
||||
let index = self.index.try_get().copied();
|
||||
|
||||
for unit in self.units.iter() {
|
||||
if let Some(unit) = unit.write().take() {
|
||||
if let Some(unit) = unit.lock().await.take() {
|
||||
unit.detach();
|
||||
}
|
||||
}
|
||||
@@ -214,11 +214,11 @@ impl BlockDevice for ScsiUnit {
|
||||
position: u64,
|
||||
buffer: DmaSliceMut<'_, MaybeUninit<u8>>,
|
||||
) -> Result<(), Error> {
|
||||
if position % self.lba_size as u64 != 0 {
|
||||
if !position.is_multiple_of(self.lba_size as u64) {
|
||||
log::warn!("scsi: misaligned read");
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
if buffer.len() % self.lba_size != 0 {
|
||||
if !buffer.len().is_multiple_of(self.lba_size) {
|
||||
log::warn!("scsi: misaligned buffer size");
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
@@ -368,10 +368,11 @@ fn register_unit(enclosure_index: u32, lun: u8, unit: Arc<ScsiUnit>) {
|
||||
}
|
||||
|
||||
fn remove_enclosure(index: u32) {
|
||||
log::info!("scsi: enclosure {index} detached");
|
||||
|
||||
let mut devices = SCSI_ENCLOSURES.lock();
|
||||
let mut bitmap = SCSI_BITMAP.lock();
|
||||
|
||||
*bitmap &= !(1 << index);
|
||||
devices.remove(&index);
|
||||
log::info!("scsi: enclosure {index} detached");
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@
|
||||
extern crate alloc;
|
||||
|
||||
mod pl011;
|
||||
mod pl031;
|
||||
mod pl061;
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
// TODO baud rate configuration
|
||||
use alloc::sync::Arc;
|
||||
use device_api::{
|
||||
device::{Device, DeviceInitContext},
|
||||
interrupt::{FullIrq, InterruptHandler, IrqVector},
|
||||
interrupt::{InterruptHandler, IrqHandle, IrqVector},
|
||||
};
|
||||
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
|
||||
use device_tree::driver::{Node, ProbeContext, device_tree_driver};
|
||||
use libk::{
|
||||
debug::DebugSink,
|
||||
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
||||
device::manager::DEVICE_REGISTRY,
|
||||
vfs::{Terminal, TerminalInput, TerminalOutput},
|
||||
};
|
||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
|
||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||
use libk_util::{OneTimeInit, sync::IrqSafeSpinlock};
|
||||
use tock_registers::{
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
registers::{ReadOnly, ReadWrite, WriteOnly},
|
||||
};
|
||||
use yggdrasil_abi::{error::Error, io::TerminalOptions};
|
||||
use yggdrasil_abi::{
|
||||
error::Error,
|
||||
io::{TerminalOptions, TerminalOutputOptions},
|
||||
};
|
||||
|
||||
register_bitfields! {
|
||||
u32,
|
||||
@@ -68,7 +72,7 @@ struct Pl011Inner {
|
||||
pub struct Pl011 {
|
||||
inner: OneTimeInit<Arc<Terminal<Pl011Inner>>>,
|
||||
base: PhysicalAddress,
|
||||
irq: FullIrq,
|
||||
irq: IrqHandle,
|
||||
}
|
||||
|
||||
impl Io {
|
||||
@@ -89,14 +93,25 @@ impl Io {
|
||||
}
|
||||
|
||||
impl TerminalOutput for Pl011Inner {
|
||||
fn write(&self, byte: u8) -> Result<(), Error> {
|
||||
self.io.lock().send(byte);
|
||||
fn write(&self, byte: u8, options: &TerminalOutputOptions) -> Result<(), Error> {
|
||||
let mut lock = self.io.lock();
|
||||
if byte == b'\n' && options.contains(TerminalOutputOptions::NL_TO_CRNL) {
|
||||
lock.send(b'\r');
|
||||
}
|
||||
lock.send(b'\n');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_multiple(&self, bytes: &[u8]) -> Result<usize, Error> {
|
||||
fn write_multiple(
|
||||
&self,
|
||||
bytes: &[u8],
|
||||
options: &TerminalOutputOptions,
|
||||
) -> Result<usize, Error> {
|
||||
let mut lock = self.io.lock();
|
||||
for &byte in bytes {
|
||||
if byte == b'\n' && options.contains(TerminalOutputOptions::NL_TO_CRNL) {
|
||||
lock.send(b'\r');
|
||||
}
|
||||
lock.send(byte);
|
||||
}
|
||||
Ok(bytes.len())
|
||||
@@ -117,6 +132,11 @@ impl DebugSink for Pl011 {
|
||||
self.inner.get().putc_to_output(byte)
|
||||
}
|
||||
|
||||
fn puts(&self, s: &str) -> Result<(), Error> {
|
||||
self.inner.get().write_to_output(s.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn supports_control_sequences(&self) -> bool {
|
||||
true
|
||||
}
|
||||
@@ -164,14 +184,12 @@ impl Device for Pl011 {
|
||||
}
|
||||
|
||||
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
|
||||
let intc = external_interrupt_controller()?;
|
||||
|
||||
intc.register_irq(self.irq.irq, self.irq.options, self.clone())?;
|
||||
self.irq.register(self.clone())?;
|
||||
{
|
||||
let io = self.inner.get().output().io.lock();
|
||||
io.regs.IMSC.modify(IMSC::RXIM::SET);
|
||||
}
|
||||
intc.enable_irq(self.irq.irq)?;
|
||||
self.irq.enable()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
use alloc::sync::Arc;
|
||||
use device_api::device::{Device, DeviceInitContext};
|
||||
use device_tree::driver::{Node, ProbeContext, device_tree_driver};
|
||||
use libk::{
|
||||
error::Error,
|
||||
fs::sysfs::{self, nodes::SysfsRtcNode},
|
||||
};
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
use tock_registers::{
|
||||
interfaces::Readable,
|
||||
register_structs,
|
||||
registers::{ReadOnly, ReadWrite, WriteOnly},
|
||||
};
|
||||
|
||||
register_structs! {
|
||||
#[allow(non_snake_case)]
|
||||
Regs {
|
||||
(0x00 => RTCDR: ReadOnly<u32>),
|
||||
(0x04 => RTCMR: ReadWrite<u32>),
|
||||
(0x08 => RTCLR: ReadWrite<u32>),
|
||||
(0x0C => RTCCR: ReadWrite<u32>),
|
||||
(0x10 => RTCIMSC: ReadWrite<u32>),
|
||||
(0x14 => RTCRIS: ReadOnly<u32>),
|
||||
(0x18 => RTCMIS: ReadOnly<u32>),
|
||||
(0x1C => RTCICR: WriteOnly<u32>),
|
||||
(0x20 => @END),
|
||||
}
|
||||
}
|
||||
|
||||
struct Pl031 {
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
}
|
||||
|
||||
impl SysfsRtcNode for Pl031 {
|
||||
fn read(&self) -> Result<u64, Error> {
|
||||
let regs = self.regs.lock();
|
||||
Ok(regs.RTCDR.get() as _)
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Pl031 {
|
||||
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
|
||||
sysfs::nodes::add_rtc_node(self.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
"ARM PL031 RTC"
|
||||
}
|
||||
}
|
||||
|
||||
device_tree_driver! {
|
||||
compatible: ["arm,pl031"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let base = node.map_base(context, 0)?;
|
||||
|
||||
let regs = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?;
|
||||
|
||||
let rtc = Arc::new(Pl031 { regs: IrqSafeSpinlock::new(regs) });
|
||||
|
||||
Some(rtc)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,16 +8,16 @@ use device_api::{
|
||||
GpioController, GpioInterruptEvent, GpioInterruptMode, GpioPinLevel, PinHandle,
|
||||
SinglePinDirection,
|
||||
},
|
||||
interrupt::{FullIrq, InterruptHandler, IrqVector},
|
||||
interrupt::{InterruptHandler, IrqHandle, IrqVector},
|
||||
};
|
||||
use device_tree::{
|
||||
driver::{
|
||||
device_tree_driver, util::generic_gpio_config, DeviceTreeGpioPins, DeviceTreePinController,
|
||||
Node, ProbeContext,
|
||||
},
|
||||
DeviceTreePropertyRead, TProp,
|
||||
driver::{
|
||||
DeviceTreeGpioPins, DeviceTreePinController, Node, ProbeContext, device_tree_driver,
|
||||
util::generic_gpio_config,
|
||||
},
|
||||
};
|
||||
use libk::{device::external_interrupt_controller, event::signal_gpio_event};
|
||||
use libk::event::signal_gpio_event;
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::{bit::BitField, sync::IrqSafeSpinlock};
|
||||
use tock_registers::{
|
||||
@@ -50,7 +50,7 @@ register_structs! {
|
||||
struct Pl061 {
|
||||
#[allow(unused)]
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
irq: FullIrq,
|
||||
irq: IrqHandle,
|
||||
clocks: Vec<ClockHandle>,
|
||||
resets: Vec<ResetHandle>,
|
||||
gpio_events: [AtomicU64; 8],
|
||||
@@ -69,9 +69,8 @@ impl Device for Pl061 {
|
||||
}
|
||||
|
||||
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
|
||||
let intc = external_interrupt_controller()?;
|
||||
intc.register_irq(self.irq.irq, self.irq.options, self.clone())?;
|
||||
intc.enable_irq(self.irq.irq)?;
|
||||
self.irq.register(self.clone())?;
|
||||
self.irq.enable()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -16,3 +16,4 @@ tock-registers.workspace = true
|
||||
log.workspace = true
|
||||
bytemuck.workspace = true
|
||||
futures-util.workspace = true
|
||||
async-trait.workspace = true
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use alloc::sync::Arc;
|
||||
use device_api::{
|
||||
clock::{ClockController, ClockHandle},
|
||||
clock::{ClockController, ClockHandle, Hertz, IntoHertz},
|
||||
device::{Device, DeviceInitContext},
|
||||
};
|
||||
use device_tree::{
|
||||
driver::{device_tree_driver, DeviceTreeClockController, Node, ProbeContext},
|
||||
DeviceTreePropertyRead, TProp,
|
||||
driver::{DeviceTreeClockController, Node, ProbeContext, device_tree_driver},
|
||||
};
|
||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
|
||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||
use libk_util::{OneTimeInit, sync::IrqSafeSpinlock};
|
||||
use tock_registers::{
|
||||
interfaces::ReadWriteable,
|
||||
register_bitfields, register_structs,
|
||||
@@ -54,10 +54,10 @@ impl ClockController for Bcm2835Aux {
|
||||
let regs = regs.lock();
|
||||
match clock {
|
||||
Some(0) => {
|
||||
// TODO CPRMAN driver
|
||||
regs.AUX_ENABLES.modify(AUX_ENABLES::MU_ENABLE::SET);
|
||||
Ok(())
|
||||
}
|
||||
None => todo!(),
|
||||
_ => Err(Error::InvalidArgument),
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,16 @@ impl ClockController for Bcm2835Aux {
|
||||
fn disable_clock(&self, _clock: Option<u32>) -> Result<(), Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
|
||||
fn clock_rate(&self, clock: Option<u32>) -> Result<Hertz, Error> {
|
||||
match clock {
|
||||
Some(0) => {
|
||||
// TODO CPRMAN driver
|
||||
Ok(54u64.mhz())
|
||||
}
|
||||
_ => Err(Error::InvalidArgument),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceTreeClockController for Bcm2835Aux {
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
use alloc::sync::Arc;
|
||||
use device_api::{
|
||||
clock::ClockHandle,
|
||||
device::{Device, DeviceInitContext},
|
||||
interrupt::{FullIrq, InterruptHandler, IrqVector},
|
||||
};
|
||||
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
|
||||
use libk::{
|
||||
debug::DebugSink,
|
||||
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
||||
vfs::{Terminal, TerminalInput, TerminalOutput},
|
||||
};
|
||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
|
||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||
use tock_registers::{
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
registers::{ReadOnly, ReadWrite},
|
||||
};
|
||||
use yggdrasil_abi::{
|
||||
error::Error,
|
||||
io::{TerminalOptions, TerminalOutputOptions},
|
||||
};
|
||||
|
||||
register_bitfields! {
|
||||
u32,
|
||||
AUX_MU_IER_REG [
|
||||
RX_IRQ OFFSET(0) NUMBITS(1) [],
|
||||
TX_IRQ OFFSET(1) NUMBITS(1) [],
|
||||
],
|
||||
AUX_MU_IIR_REG [
|
||||
IID OFFSET(1) NUMBITS(2) [
|
||||
None = 0,
|
||||
TxEmpty = 1,
|
||||
RxNotEmpty = 2,
|
||||
],
|
||||
PENDING OFFSET(0) NUMBITS(1) [],
|
||||
],
|
||||
AUX_MU_LSR_REG [
|
||||
TX_EMPTY OFFSET(5) NUMBITS(1) [],
|
||||
]
|
||||
}
|
||||
|
||||
register_structs! {
|
||||
#[allow(non_snake_case)]
|
||||
Regs {
|
||||
(0x00 => AUX_MU_IO_REG: ReadWrite<u32>),
|
||||
(0x04 => AUX_MU_IER_REG: ReadWrite<u32, AUX_MU_IER_REG::Register>),
|
||||
(0x08 => AUX_MU_IIR_REG: ReadWrite<u32, AUX_MU_IIR_REG::Register>),
|
||||
(0x0C => _0),
|
||||
(0x14 => AUX_MU_LSR_REG: ReadOnly<u32, AUX_MU_LSR_REG::Register>),
|
||||
(0x18 => _1),
|
||||
(0x30 => @END),
|
||||
}
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
}
|
||||
|
||||
/// Broadcom 283x mini-UART driver
|
||||
pub struct Bcm2835AuxUart {
|
||||
base: PhysicalAddress,
|
||||
irq: FullIrq,
|
||||
clock: ClockHandle,
|
||||
inner: OneTimeInit<Arc<Terminal<Inner>>>,
|
||||
}
|
||||
|
||||
impl Regs {
|
||||
fn write_byte(&self, byte: u8) -> Result<(), Error> {
|
||||
if byte == b'\n' {
|
||||
self.write_byte(b'\r').ok();
|
||||
}
|
||||
|
||||
while !self
|
||||
.AUX_MU_LSR_REG
|
||||
.matches_all(AUX_MU_LSR_REG::TX_EMPTY::SET)
|
||||
{
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
self.AUX_MU_IO_REG.set(byte as u32);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_bytes(&self, bytes: &[u8]) -> Result<(), Error> {
|
||||
for &byte in bytes {
|
||||
self.write_byte(byte)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TerminalOutput for Inner {
|
||||
fn write(&self, byte: u8) -> Result<(), Error> {
|
||||
self.regs.lock().write_byte(byte)
|
||||
}
|
||||
|
||||
fn write_multiple(&self, bytes: &[u8]) -> Result<usize, Error> {
|
||||
self.regs.lock().write_bytes(bytes)?;
|
||||
Ok(bytes.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl DebugSink for Bcm2835AuxUart {
|
||||
fn putc(&self, c: u8) -> Result<(), Error> {
|
||||
self.inner.get().putc_to_output(c)
|
||||
}
|
||||
|
||||
fn puts(&self, s: &str) -> Result<(), Error> {
|
||||
self.inner.get().write_to_output(s.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn supports_control_sequences(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptHandler for Bcm2835AuxUart {
|
||||
fn handle_irq(self: Arc<Self>, _vector: IrqVector) -> bool {
|
||||
let inner = self.inner.get();
|
||||
|
||||
let (status, byte) = {
|
||||
let regs = inner.output().regs.lock();
|
||||
|
||||
// Reset IRQ
|
||||
regs.AUX_MU_IIR_REG.modify(AUX_MU_IIR_REG::IID::SET);
|
||||
|
||||
let byte = regs.AUX_MU_IO_REG.get() as u8;
|
||||
let status = regs
|
||||
.AUX_MU_IIR_REG
|
||||
.matches_all(AUX_MU_IIR_REG::PENDING::SET);
|
||||
|
||||
(status, byte)
|
||||
};
|
||||
|
||||
if status {
|
||||
inner.write_to_input(byte);
|
||||
}
|
||||
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Bcm2835AuxUart {
|
||||
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
|
||||
// TODO initialize pinctrl
|
||||
|
||||
self.clock.enable()?;
|
||||
|
||||
let regs = unsafe { DeviceMemoryIo::map(self.base, Default::default()) }?;
|
||||
let config = TerminalOptions {
|
||||
output: TerminalOutputOptions::NL_TO_CRNL,
|
||||
..Default::default()
|
||||
};
|
||||
let output = Inner {
|
||||
regs: IrqSafeSpinlock::new(regs),
|
||||
};
|
||||
let input = TerminalInput::with_capacity(64)?;
|
||||
|
||||
let inner = self
|
||||
.inner
|
||||
.init(Arc::new(Terminal::from_parts(config, input, output)));
|
||||
|
||||
DEVICE_REGISTRY
|
||||
.serial_terminal
|
||||
.register(inner.clone(), Some(self.clone()))
|
||||
.ok();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
|
||||
let intc = external_interrupt_controller()?;
|
||||
intc.register_irq(self.irq.irq, self.irq.options, self.clone())?;
|
||||
intc.enable_irq(self.irq.irq)?;
|
||||
|
||||
let inner = self.inner.get().output();
|
||||
let regs = inner.regs.lock();
|
||||
|
||||
regs.AUX_MU_IER_REG
|
||||
.modify(AUX_MU_IER_REG::RX_IRQ::SET + AUX_MU_IER_REG::TX_IRQ::CLEAR);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
"bcm2835 mini-UART"
|
||||
}
|
||||
}
|
||||
|
||||
// TODO handle pinctrl
|
||||
device_tree_driver! {
|
||||
compatible: ["brcm,bcm2835-aux-uart"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let base = node.map_base(context, 0)?;
|
||||
let irq = node.interrupt(0)?;
|
||||
let clock = node.clock(0)?;
|
||||
|
||||
Some(Arc::new(Bcm2835AuxUart {
|
||||
base,
|
||||
irq,
|
||||
clock,
|
||||
inner: OneTimeInit::new(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
use alloc::sync::Arc;
|
||||
use device_api::{
|
||||
clock::{ClockController, ClockHandle, Hertz},
|
||||
device::{Device, DeviceInitContext},
|
||||
};
|
||||
use device_tree::{
|
||||
DeviceTreePropertyRead, TProp,
|
||||
driver::{DeviceTreeClockController, Node, ProbeContext, device_tree_driver},
|
||||
};
|
||||
use libk::error::Error;
|
||||
|
||||
use crate::mbox::{Bcm2835Mbox, Bcm2835VcClock};
|
||||
|
||||
const CLK_VPU: u32 = 0x14;
|
||||
|
||||
struct Cprman {
|
||||
clk_osc: ClockHandle,
|
||||
mbox: Arc<Bcm2835Mbox>,
|
||||
}
|
||||
|
||||
impl Device for Cprman {
|
||||
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
|
||||
let _ = &self.clk_osc;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
"bcm2711-cprman"
|
||||
}
|
||||
}
|
||||
|
||||
impl ClockController for Cprman {
|
||||
fn clock_rate(&self, clock: Option<u32>) -> Result<Hertz, Error> {
|
||||
let vc_clock = match clock {
|
||||
Some(CLK_VPU) => Bcm2835VcClock::Core,
|
||||
Some(n) => todo!("clock_rate({n:#02x})"),
|
||||
None => return Err(Error::InvalidArgument),
|
||||
};
|
||||
|
||||
let rate = self.mbox.vc_clock_rate(vc_clock)?;
|
||||
|
||||
Ok(rate)
|
||||
}
|
||||
|
||||
fn set_clock_rate(&self, clock: Option<u32>, rate: Hertz) -> Result<Hertz, Error> {
|
||||
let _ = clock;
|
||||
let _ = rate;
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn enable_clock(&self, clock: Option<u32>) -> Result<(), Error> {
|
||||
let _ = clock;
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn disable_clock(&self, clock: Option<u32>) -> Result<(), Error> {
|
||||
let _ = clock;
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceTreeClockController for Cprman {
|
||||
fn map_clock(self: Arc<Self>, property: &TProp, offset: usize) -> Option<(ClockHandle, usize)> {
|
||||
let clock = property.read_cell(offset, 1)? as u32;
|
||||
Some((
|
||||
ClockHandle {
|
||||
parent: self.clone(),
|
||||
clock: Some(clock),
|
||||
},
|
||||
1,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
device_tree_driver! {
|
||||
compatible: ["brcm,bcm2711-cprman"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let _base = node.map_base(context, 0)?;
|
||||
let mbox = Node::by_compatible("brcm,bcm2835-mbox", true).unwrap().device().unwrap();
|
||||
let mbox = Arc::downcast::<Bcm2835Mbox>(mbox.as_any()).unwrap();
|
||||
let clk_osc = node.clock(0)?;
|
||||
|
||||
let cprman = Arc::new(Cprman {
|
||||
clk_osc,
|
||||
mbox,
|
||||
});
|
||||
|
||||
node.make_clock_controller(cprman.clone());
|
||||
Some(cprman)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,15 @@ use alloc::sync::Arc;
|
||||
use device_api::{
|
||||
device::{Device, DeviceInitContext},
|
||||
gpio::{GpioController, GpioInterruptEvent, PinHandle},
|
||||
interrupt::{FullIrq, InterruptHandler, IrqVector},
|
||||
interrupt::{InterruptHandler, IrqHandle, IrqVector},
|
||||
};
|
||||
use device_tree::{
|
||||
driver::{
|
||||
device_tree_driver, util::generic_gpio_config, DeviceTreeGpioPins, DeviceTreePinController,
|
||||
Node, ProbeContext,
|
||||
},
|
||||
DeviceTreePropertyRead, TProp,
|
||||
driver::{
|
||||
DeviceTreeGpioPins, DeviceTreePinController, Node, ProbeContext, device_tree_driver,
|
||||
util::generic_gpio_config,
|
||||
},
|
||||
};
|
||||
use libk::device::external_interrupt_controller;
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
use tock_registers::{
|
||||
@@ -69,7 +68,7 @@ register_structs! {
|
||||
struct Bcm2711Gpio {
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
#[allow(unused)]
|
||||
irqs: [FullIrq; 2],
|
||||
irqs: [IrqHandle; 2],
|
||||
}
|
||||
|
||||
impl Regs {
|
||||
@@ -142,10 +141,9 @@ impl Device for Bcm2711Gpio {
|
||||
regs.configure_pin_interrupts(pin, false, false, false, false);
|
||||
}
|
||||
|
||||
let intc = external_interrupt_controller()?;
|
||||
for irq in self.irqs.iter() {
|
||||
intc.register_irq(irq.irq, irq.options, self.clone())?;
|
||||
intc.enable_irq(irq.irq)?;
|
||||
irq.register(self.clone())?;
|
||||
irq.enable()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
use alloc::{boxed::Box, sync::Arc};
|
||||
use async_trait::async_trait;
|
||||
use device_api::{
|
||||
clock::{ClockHandle, Hertz},
|
||||
device::{Device, DeviceInitContext},
|
||||
i2c::{I2CAddress, I2CController, I2CMessage, I2CTransfer},
|
||||
interrupt::{InterruptHandler, IrqHandle, IrqVector},
|
||||
};
|
||||
use device_tree::driver::{Node, ProbeContext, device_tree_driver};
|
||||
use futures_util::task::AtomicWaker;
|
||||
use libk::{device::manager::DEVICE_REGISTRY, error::Error};
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::{OneTimeInit, event::BitmapEvent, sync::spin_rwlock::IrqSafeRwLock};
|
||||
use tock_registers::{
|
||||
LocalRegisterCopy,
|
||||
fields::FieldValue,
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
registers::ReadWrite,
|
||||
};
|
||||
use yggdrasil_abi::io::device::i2c::I2CMasterInfo;
|
||||
|
||||
register_bitfields! {
|
||||
u32,
|
||||
C [
|
||||
I2CEN OFFSET(15) NUMBITS(1) [],
|
||||
INTR OFFSET(10) NUMBITS(1) [],
|
||||
INTT OFFSET(9) NUMBITS(1) [],
|
||||
INTD OFFSET(8) NUMBITS(1) [],
|
||||
ST OFFSET(7) NUMBITS(1) [],
|
||||
CLEAR OFFSET(4) NUMBITS(2) [],
|
||||
READ OFFSET(0) NUMBITS(1) [],
|
||||
],
|
||||
S [
|
||||
CLKT OFFSET(9) NUMBITS(1) [],
|
||||
ERR OFFSET(8) NUMBITS(1) [],
|
||||
RXF OFFSET(7) NUMBITS(1) [],
|
||||
TXE OFFSET(6) NUMBITS(1) [],
|
||||
RXD OFFSET(5) NUMBITS(1) [],
|
||||
TXD OFFSET(4) NUMBITS(1) [],
|
||||
RXR OFFSET(3) NUMBITS(1) [],
|
||||
TXW OFFSET(2) NUMBITS(1) [],
|
||||
DONE OFFSET(1) NUMBITS(1) [],
|
||||
TA OFFSET(0) NUMBITS(1) [],
|
||||
],
|
||||
}
|
||||
|
||||
register_structs! {
|
||||
#[allow(non_snake_case)]
|
||||
Regs {
|
||||
(0x00 => C: ReadWrite<u32, C::Register>),
|
||||
(0x04 => S: ReadWrite<u32, S::Register>),
|
||||
(0x08 => DLEN: ReadWrite<u32>),
|
||||
(0x0C => A: ReadWrite<u32>),
|
||||
(0x10 => FIFO: ReadWrite<u32>),
|
||||
(0x14 => DIV: ReadWrite<u32>),
|
||||
(0x18 => DEL: ReadWrite<u32>),
|
||||
(0x1C => CLKT: ReadWrite<u32>),
|
||||
(0x20 => @END),
|
||||
}
|
||||
}
|
||||
|
||||
struct I2CState {
|
||||
status: BitmapEvent<AtomicWaker>,
|
||||
}
|
||||
|
||||
struct I2C {
|
||||
name: &'static str,
|
||||
clock_frequency: Option<Hertz>,
|
||||
irq: IrqHandle,
|
||||
clock: Option<ClockHandle>,
|
||||
regs: IrqSafeRwLock<DeviceMemoryIo<'static, Regs>>,
|
||||
index: OneTimeInit<u32>,
|
||||
state: I2CState,
|
||||
}
|
||||
|
||||
impl I2CState {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
status: BitmapEvent::new(AtomicWaker::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All of these are thread-unsafe, but I2C subsystem locks the peripheral by process
|
||||
impl I2C {
|
||||
async fn wait_for_event(&self) -> LocalRegisterCopy<u32, S::Register> {
|
||||
let event = self.state.status.wait().await;
|
||||
LocalRegisterCopy::new(event as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for I2C {
|
||||
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
|
||||
// TODO
|
||||
let _ = &self.clock;
|
||||
|
||||
log::info!("{}: initialize", self.name);
|
||||
let regs = self.regs.write();
|
||||
regs.C.set(0);
|
||||
|
||||
let index = DEVICE_REGISTRY.i2c.register_bus(self.clone())?;
|
||||
self.index.init(index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
|
||||
self.irq.register(self.clone())?;
|
||||
self.irq.enable()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptHandler for I2C {
|
||||
fn handle_irq(self: Arc<Self>, _vector: IrqVector) -> bool {
|
||||
let regs = self.regs.write();
|
||||
let event = regs.S.extract();
|
||||
// log::info!("I2C irq {:#x}", event.get());
|
||||
let mut clear = FieldValue::none();
|
||||
if event.matches_all(S::RXR::SET) {
|
||||
clear += C::INTR::CLEAR;
|
||||
}
|
||||
if event.matches_all(S::TXW::SET) {
|
||||
clear += C::INTT::CLEAR;
|
||||
}
|
||||
if event.matches_all(S::DONE::SET) {
|
||||
clear += C::INTD::CLEAR;
|
||||
}
|
||||
regs.C.modify(clear);
|
||||
self.state.status.signal(event.get() as u64);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl I2CController for I2C {
|
||||
fn bus_number(&self) -> u32 {
|
||||
*self.index.get()
|
||||
}
|
||||
|
||||
fn child_number(&self) -> Option<u32> {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_speed(&self, speed: Hertz) -> Result<Hertz, Error> {
|
||||
if let Some(frequency) = self.clock_frequency {
|
||||
// Fixed frequency
|
||||
if speed == frequency {
|
||||
Ok(speed)
|
||||
} else {
|
||||
Err(Error::InvalidArgument)
|
||||
}
|
||||
} else {
|
||||
todo!("Set i2c speed = {speed}")
|
||||
}
|
||||
}
|
||||
|
||||
fn capabilities(&self) -> I2CMasterInfo {
|
||||
let max_speed_hz = if let Some(frequency) = self.clock_frequency {
|
||||
frequency
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
.0 as u32;
|
||||
I2CMasterInfo {
|
||||
max_speed_hz,
|
||||
supports_10bit_addresses: true,
|
||||
}
|
||||
}
|
||||
|
||||
async fn i2c_transfer(
|
||||
&self,
|
||||
address: I2CAddress,
|
||||
transfer: &mut I2CTransfer,
|
||||
) -> Result<usize, Error> {
|
||||
// TODO validate transfer
|
||||
let address = address.as_8_bit().ok_or(Error::NotImplemented)?;
|
||||
let repeat_start = transfer.repeat_start;
|
||||
let mut nbytes = 0;
|
||||
let mut error = None;
|
||||
for (i, message) in transfer.messages.iter_mut().enumerate() {
|
||||
if i == 0 || repeat_start {
|
||||
let (read, len) = match message {
|
||||
I2CMessage::Read(buffer) => (true, buffer.len()),
|
||||
I2CMessage::Write(buffer) => (false, buffer.len()),
|
||||
};
|
||||
// log::info!("{}: START {:#x} read={}", self.name, address, read);
|
||||
let read = if read { C::READ::SET } else { C::READ::CLEAR };
|
||||
let regs = self.regs.write();
|
||||
regs.S.write(S::ERR::SET + S::DONE::SET);
|
||||
regs.DLEN.set(len as u32);
|
||||
regs.C.modify(C::ST::CLEAR);
|
||||
regs.A.set(address as u32);
|
||||
regs.C.modify(
|
||||
read + C::ST::SET + C::I2CEN::SET + C::INTD::SET + C::INTR::SET + C::INTT::SET,
|
||||
);
|
||||
}
|
||||
|
||||
let mut pos = 0;
|
||||
let status = loop {
|
||||
let s = self.wait_for_event().await;
|
||||
let regs = self.regs.write();
|
||||
if s.matches_all(S::ERR::SET) || s.matches_all(S::DONE::SET) {
|
||||
break s;
|
||||
}
|
||||
match message {
|
||||
I2CMessage::Write(buffer) => {
|
||||
if s.matches_all(S::TXW::SET) {
|
||||
while regs.S.matches_all(S::TXD::SET) && pos < buffer.len() {
|
||||
let byte = buffer[pos];
|
||||
// log::info!("{}: tx {:#x}", self.name, byte);
|
||||
regs.FIFO.set(byte as u32);
|
||||
pos += 1;
|
||||
nbytes += 1;
|
||||
}
|
||||
}
|
||||
regs.C.modify(C::INTT::SET);
|
||||
}
|
||||
I2CMessage::Read(buffer) => {
|
||||
if s.matches_all(S::RXR::SET) {
|
||||
while regs.S.matches_all(S::RXD::SET) && pos < buffer.len() {
|
||||
let byte = regs.FIFO.get() as u8;
|
||||
// log::info!("{}: rx {:#x}", self.name, byte);
|
||||
buffer[pos] = byte;
|
||||
pos += 1;
|
||||
nbytes += 1;
|
||||
}
|
||||
}
|
||||
regs.C.modify(C::INTR::SET);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Finalize message
|
||||
let regs = self.regs.write();
|
||||
if status.matches_all(S::ERR::SET) {
|
||||
regs.S.write(S::DONE::SET + S::ERR::SET);
|
||||
error = Some(Error::HostUnreachable);
|
||||
break;
|
||||
} else if status.matches_all(S::DONE::SET) {
|
||||
regs.S.write(S::DONE::SET);
|
||||
} else {
|
||||
log::error!("{}: transfer finished without DONE or ERR set", self.name);
|
||||
log::error!("{}: S = {:#x}", self.name, status.get());
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
// Finish transfer
|
||||
// log::info!(
|
||||
// "{}: finish xfer, error={:?}, nbytes={}",
|
||||
// self.name,
|
||||
// error,
|
||||
// nbytes
|
||||
// );
|
||||
let regs = self.regs.write();
|
||||
regs.C.set(0);
|
||||
|
||||
match error {
|
||||
Some(error) => Err(error),
|
||||
None => Ok(nbytes),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
device_tree_driver! {
|
||||
compatible: ["brcm,bcm2711-i2c", "brcm,bcm2835-i2c"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let clock_frequency = node.prop_usize("clock-frequency").map(|p| Hertz(p as u64));
|
||||
let base = node.map_base(context, 0)?;
|
||||
let name = node.name().unwrap_or("bcm2835-i2c");
|
||||
let irq = node.interrupt(0)?;
|
||||
let clock = node.clock(0);
|
||||
|
||||
let regs = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?;
|
||||
|
||||
let i2c = Arc::new(I2C {
|
||||
name,
|
||||
clock_frequency,
|
||||
irq,
|
||||
clock,
|
||||
index: OneTimeInit::new(),
|
||||
regs: IrqSafeRwLock::new(regs),
|
||||
state: I2CState::new()
|
||||
});
|
||||
|
||||
node.make_i2c_controller(i2c.clone());
|
||||
|
||||
Some(i2c)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,9 @@
|
||||
extern crate alloc;
|
||||
|
||||
mod aux;
|
||||
mod aux_uart;
|
||||
// mod aux_uart;
|
||||
mod cprman;
|
||||
mod gpio;
|
||||
mod i2c;
|
||||
mod mbox;
|
||||
mod spi;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
use core::{cell::UnsafeCell, mem::MaybeUninit};
|
||||
use core::{any::Any, cell::UnsafeCell, mem::MaybeUninit};
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use device_api::device::{Device, DeviceInitContext};
|
||||
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
|
||||
use device_api::{
|
||||
clock::Hertz,
|
||||
device::{Device, DeviceInitContext},
|
||||
};
|
||||
use device_tree::driver::{Node, ProbeContext, device_tree_driver};
|
||||
use kernel_arch_aarch64::mem::table::L3;
|
||||
use libk::device::{
|
||||
display::{
|
||||
@@ -11,10 +14,10 @@ use libk::device::{
|
||||
manager::DEVICE_REGISTRY,
|
||||
};
|
||||
use libk_mm::{
|
||||
OnDemandPage, PageBox, PageProvider, VirtualPage,
|
||||
address::{AsPhysicalAddress, PhysicalAddress},
|
||||
device::DeviceMemoryIo,
|
||||
table::{EntryLevel, MapAttributes},
|
||||
OnDemandPage, PageBox, PageProvider, VirtualPage,
|
||||
};
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
use tock_registers::{
|
||||
@@ -61,7 +64,13 @@ register_structs! {
|
||||
}
|
||||
}
|
||||
|
||||
struct Bcm2835Mbox {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[repr(u32)]
|
||||
pub(crate) enum Bcm2835VcClock {
|
||||
Core = 4,
|
||||
}
|
||||
|
||||
pub(crate) struct Bcm2835Mbox {
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
}
|
||||
|
||||
@@ -85,13 +94,20 @@ impl Device for Bcm2835Mbox {
|
||||
fn display_name(&self) -> &str {
|
||||
"bcm2835-mbox"
|
||||
}
|
||||
|
||||
fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Bcm2835Mbox {
|
||||
const RAM_TO_GPU_OFFSET: u32 = 0x40000000;
|
||||
|
||||
const CHANNEL_FRAMEBUFFER: u32 = 1;
|
||||
const CHANNEL_ARM2VC: u32 = 8;
|
||||
|
||||
pub unsafe fn call_raw(&self, buffer: PhysicalAddress, channel: u32) -> Result<(), Error> {
|
||||
log::info!("bcm2835-mbox: mbox call buffer={buffer:#x}, channel={channel}");
|
||||
log::debug!("bcm2835-mbox: mbox call buffer={buffer:#x}, channel={channel}");
|
||||
|
||||
let address = buffer
|
||||
.try_into_u32()
|
||||
@@ -125,10 +141,31 @@ impl Bcm2835Mbox {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn configure_framebuffer(
|
||||
&self,
|
||||
mode_info: &DisplayMode,
|
||||
) -> Result<FramebufferResponse, Error> {
|
||||
pub fn vc_clock_rate(&self, clock: Bcm2835VcClock) -> Result<Hertz, Error> {
|
||||
let mut buffer = PageBox::new_slice(0u32, 4096 / 4)?;
|
||||
buffer[0] = 9 * 4; // buffer size
|
||||
buffer[1] = 0; // process request
|
||||
|
||||
// Tag 1 (Response)
|
||||
buffer[2] = 0x00030002; // tag
|
||||
buffer[3] = 0; // value buffer size
|
||||
buffer[4] = 0; // request
|
||||
buffer[5] = clock as u32; // value buffer[0]
|
||||
buffer[6] = 0; // value buffer[1]
|
||||
buffer[7] = 0;
|
||||
|
||||
// End tag
|
||||
buffer[8] = 0;
|
||||
|
||||
unsafe { self.call_raw(buffer.as_physical_address(), Self::CHANNEL_ARM2VC) }?;
|
||||
if buffer[4] == 0 || buffer[1] == 0 {
|
||||
todo!();
|
||||
}
|
||||
let rate = Hertz::from(buffer[6]);
|
||||
Ok(rate)
|
||||
}
|
||||
|
||||
fn configure_framebuffer(&self, mode_info: &DisplayMode) -> Result<FramebufferResponse, Error> {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct FramebufferRequest {
|
||||
@@ -158,7 +195,7 @@ impl Bcm2835Mbox {
|
||||
}))?;
|
||||
|
||||
// TODO flush cache for buffer
|
||||
unsafe { self.call_raw(buffer.as_physical_address(), 0x01) }?;
|
||||
unsafe { self.call_raw(buffer.as_physical_address(), Self::CHANNEL_FRAMEBUFFER) }?;
|
||||
|
||||
let buffer = buffer.get_mut();
|
||||
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
use core::iter;
|
||||
|
||||
use alloc::{boxed::Box, sync::Arc};
|
||||
use async_trait::async_trait;
|
||||
use device_api::{
|
||||
clock::{ClockHandle, Hertz},
|
||||
device::{Device, DeviceInitContext},
|
||||
interrupt::IrqHandle,
|
||||
spi::SpiController,
|
||||
};
|
||||
use device_tree::driver::{Node, ProbeContext, device_tree_driver};
|
||||
use libk::{device::manager::DEVICE_REGISTRY, error::Error};
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
use tock_registers::{
|
||||
interfaces::{Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
registers::ReadWrite,
|
||||
};
|
||||
use yggdrasil_abi::io::device::spi::{SpiClockPhase, SpiClockPolarity, SpiConfig};
|
||||
|
||||
register_bitfields! {
|
||||
u32,
|
||||
CS [
|
||||
LEN_LONG OFFSET(25) NUMBITS(1) [],
|
||||
DMA_LEN OFFSET(24) NUMBITS(1) [],
|
||||
CSPOL2 OFFSET(23) NUMBITS(1) [],
|
||||
CSPOL1 OFFSET(22) NUMBITS(1) [],
|
||||
CSPOL0 OFFSET(21) NUMBITS(1) [],
|
||||
RXF OFFSET(20) NUMBITS(1) [],
|
||||
RXR OFFSET(19) NUMBITS(1) [],
|
||||
TXD OFFSET(18) NUMBITS(1) [],
|
||||
RXD OFFSET(17) NUMBITS(1) [],
|
||||
DONE OFFSET(16) NUMBITS(1) [],
|
||||
LEN OFFSET(13) NUMBITS(1) [],
|
||||
REN OFFSET(12) NUMBITS(1) [],
|
||||
ADCS OFFSET(11) NUMBITS(1) [],
|
||||
INTR OFFSET(10) NUMBITS(1) [],
|
||||
INTD OFFSET(9) NUMBITS(1) [],
|
||||
DMAEN OFFSET(8) NUMBITS(1) [],
|
||||
TA OFFSET(7) NUMBITS(1) [],
|
||||
CSPOL OFFSET(6) NUMBITS(1) [],
|
||||
CLEAR OFFSET(4) NUMBITS(2) [],
|
||||
CPOL OFFSET(3) NUMBITS(1) [
|
||||
IdleLow = 0,
|
||||
IdleHigh = 1
|
||||
],
|
||||
CPHA OFFSET(2) NUMBITS(1) [
|
||||
CaptureOnFirstTransition = 0,
|
||||
CaptureOnSecondTransition = 1
|
||||
],
|
||||
CS OFFSET(0) NUMBITS(2) [],
|
||||
]
|
||||
}
|
||||
|
||||
register_structs! {
|
||||
#[allow(non_snake_case)]
|
||||
Regs {
|
||||
(0x00 => CS: ReadWrite<u32, CS::Register>),
|
||||
(0x04 => FIFO: ReadWrite<u32>),
|
||||
(0x08 => CLK: ReadWrite<u32>),
|
||||
(0x0C => DLEN: ReadWrite<u32>),
|
||||
(0x10 => LTOH: ReadWrite<u32>),
|
||||
(0x14 => DC: ReadWrite<u32>),
|
||||
(0x18 => @END),
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Spi {
|
||||
name: &'static str,
|
||||
clock: ClockHandle,
|
||||
irq: IrqHandle,
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
}
|
||||
|
||||
impl Device for Spi {
|
||||
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
|
||||
let _ = &self.irq;
|
||||
let regs = self.regs.lock();
|
||||
regs.CS.set(0);
|
||||
|
||||
DEVICE_REGISTRY.spi.register_bus(self.clone()).ok();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl Regs {
|
||||
fn start_transfer(&self, core_clock: Hertz, config: &SpiConfig) -> Result<(), Error> {
|
||||
let want_clock = Hertz::from(config.frequency.unwrap_or(100000));
|
||||
let divider = Hertz::divider(core_clock, want_clock).ok_or(Error::InvalidArgument)?;
|
||||
let divider: u16 = divider.try_into().map_err(|_| Error::InvalidArgument)?;
|
||||
let divider = divider.wrapping_add(1) & !1;
|
||||
|
||||
let mut cs = CS::REN::SET + CS::TA::SET;
|
||||
if let Some(cs_index) = config.chip_select_index
|
||||
&& cs_index < 3
|
||||
{
|
||||
cs += CS::CS.val(cs_index);
|
||||
}
|
||||
if let Some(cpol) = config.clock_polarity {
|
||||
match cpol {
|
||||
SpiClockPolarity::IdleLow => cs += CS::CPOL::IdleLow,
|
||||
SpiClockPolarity::IdleHigh => cs += CS::CPOL::IdleHigh,
|
||||
}
|
||||
}
|
||||
if let Some(cpha) = config.clock_phase {
|
||||
match cpha {
|
||||
SpiClockPhase::CaptureOnFirstTransition => cs += CS::CPHA::CaptureOnFirstTransition,
|
||||
SpiClockPhase::CaptureOnSecondTransition => {
|
||||
cs += CS::CPHA::CaptureOnSecondTransition
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.CLK.set(divider as u32);
|
||||
self.CS.write(cs);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn tx_rx_byte(&self, tx: u8) -> Result<Option<u8>, Error> {
|
||||
// Wait for tx
|
||||
loop {
|
||||
let status = self.CS.extract();
|
||||
if status.matches_all(CS::TXD::SET) {
|
||||
break;
|
||||
}
|
||||
if status.matches_all(CS::DONE::SET) {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
self.FIFO.set(tx as u32);
|
||||
// Wait for rx
|
||||
loop {
|
||||
let status = self.CS.extract();
|
||||
if status.matches_all(CS::RXD::SET) {
|
||||
break;
|
||||
}
|
||||
if status.matches_all(CS::DONE::SET) {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
Ok(Some(self.FIFO.get() as u8))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl SpiController for Spi {
|
||||
async fn spi_transfer(
|
||||
&self,
|
||||
tx_buffer: &[u8],
|
||||
rx_buffer: &mut [u8],
|
||||
config: &SpiConfig,
|
||||
) -> Result<usize, Error> {
|
||||
// TODO interrupt/DMA
|
||||
log::debug!("{}: spi_transfer {} bytes", self.name, rx_buffer.len());
|
||||
let core_clock = self.clock.rate()?;
|
||||
let regs = self.regs.lock();
|
||||
regs.start_transfer(core_clock, config)?;
|
||||
|
||||
let mut len = 0;
|
||||
for (&tx, rx) in iter::zip(tx_buffer, rx_buffer) {
|
||||
match regs.tx_rx_byte(tx)? {
|
||||
Some(b) => {
|
||||
*rx = b;
|
||||
len += 1;
|
||||
}
|
||||
None => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
device_tree_driver! {
|
||||
compatible: ["brcm,bcm2835-spi"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let name = node.name().unwrap_or("bcm2835-spi");
|
||||
let base = node.map_base(context, 0)?;
|
||||
let irq = node.interrupt(0)?;
|
||||
let clock = node.clock(0)?;
|
||||
|
||||
let regs = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?;
|
||||
|
||||
let spi = Arc::new(Spi {
|
||||
regs: IrqSafeSpinlock::new(regs),
|
||||
name,
|
||||
clock,
|
||||
irq
|
||||
});
|
||||
|
||||
Some(spi)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,11 @@ use device_api::{
|
||||
device::{Device, DeviceInitContext},
|
||||
};
|
||||
use device_tree::{
|
||||
driver::{
|
||||
device_tree_driver, lookup_phandle, DeviceTreeClockController, DeviceTreeResetController,
|
||||
DeviceTreeSyscon, Node, ProbeContext,
|
||||
},
|
||||
DeviceTreePropertyRead, TProp,
|
||||
driver::{
|
||||
DeviceTreeClockController, DeviceTreeResetController, DeviceTreeSyscon, Node, ProbeContext,
|
||||
device_tree_driver, lookup_phandle,
|
||||
},
|
||||
};
|
||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIoMut};
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
@@ -57,6 +57,16 @@ const SYSCRG_GMAC0_GTXC: usize = 0x1BC / 4;
|
||||
// uart
|
||||
const SYSCRG_UART0_APB: usize = 0x244 / 4;
|
||||
const SYSCRG_UART0_CORE: usize = 0x248 / 4;
|
||||
const SYSCRG_UART1_APB: usize = 0x24C / 4;
|
||||
const SYSCRG_UART1_CORE: usize = 0x250 / 4;
|
||||
const SYSCRG_UART2_APB: usize = 0x254 / 4;
|
||||
const SYSCRG_UART2_CORE: usize = 0x258 / 4;
|
||||
const SYSCRG_UART3_APB: usize = 0x25C / 4;
|
||||
const SYSCRG_UART3_CORE: usize = 0x260 / 4;
|
||||
const SYSCRG_UART4_APB: usize = 0x264 / 4;
|
||||
const SYSCRG_UART4_CORE: usize = 0x268 / 4;
|
||||
const SYSCRG_UART5_APB: usize = 0x26C / 4;
|
||||
const SYSCRG_UART5_CORE: usize = 0x270 / 4;
|
||||
// jtag
|
||||
const SYSCRG_JTAG_CERTIFICATION_TRNG: usize = 0x2F4 / 4;
|
||||
const SYSCRG_CLOCK_COUNT: usize = SYSCRG_JTAG_CERTIFICATION_TRNG + 1;
|
||||
@@ -171,7 +181,7 @@ trait ClockDefinition {
|
||||
const CLOCKS: &'static [Option<(&'static str, ClockDef)>];
|
||||
}
|
||||
|
||||
const SYSCRG_CLOCKS: &'static [Option<(&'static str, ClockDef)>] = &const {
|
||||
const SYSCRG_CLOCKS: &[Option<(&'static str, ClockDef)>] = &const {
|
||||
use ClockDef::*;
|
||||
|
||||
let mut t = [const { None }; SYSCRG_CLOCK_COUNT];
|
||||
@@ -226,11 +236,21 @@ const SYSCRG_CLOCKS: &'static [Option<(&'static str, ClockDef)>] = &const {
|
||||
// uart
|
||||
t[SYSCRG_UART0_APB] = Some(("clk_uart0_apb", Gate(SYSCRG_APB0)));
|
||||
t[SYSCRG_UART0_CORE] = Some(("clk_uart0_core", Gate(SYSCRG_OSC)));
|
||||
t[SYSCRG_UART1_APB] = Some(("clk_uart1_apb", Gate(SYSCRG_APB0)));
|
||||
t[SYSCRG_UART1_CORE] = Some(("clk_uart1_core", Gate(SYSCRG_OSC)));
|
||||
t[SYSCRG_UART2_APB] = Some(("clk_uart2_apb", Gate(SYSCRG_APB0)));
|
||||
t[SYSCRG_UART2_CORE] = Some(("clk_uart2_core", Gate(SYSCRG_OSC)));
|
||||
t[SYSCRG_UART3_APB] = Some(("clk_uart3_apb", Gate(SYSCRG_APB0)));
|
||||
t[SYSCRG_UART3_CORE] = Some(("clk_uart3_core", GateDiv(10, SYSCRG_PERH_ROOT)));
|
||||
t[SYSCRG_UART4_APB] = Some(("clk_uart4_apb", Gate(SYSCRG_APB0)));
|
||||
t[SYSCRG_UART4_CORE] = Some(("clk_uart4_core", GateDiv(10, SYSCRG_PERH_ROOT)));
|
||||
t[SYSCRG_UART5_APB] = Some(("clk_uart5_apb", Gate(SYSCRG_APB0)));
|
||||
t[SYSCRG_UART5_CORE] = Some(("clk_uart5_core", GateDiv(10, SYSCRG_PERH_ROOT)));
|
||||
|
||||
t
|
||||
};
|
||||
|
||||
const AONCRG_CLOCKS: &'static [Option<(&'static str, ClockDef)>] = &const {
|
||||
const AONCRG_CLOCKS: &[Option<(&'static str, ClockDef)>] = &const {
|
||||
use ClockDef::*;
|
||||
|
||||
let mut t = [const { None }; AONCRG_CLOCK_COUNT];
|
||||
@@ -262,7 +282,7 @@ const AONCRG_CLOCKS: &'static [Option<(&'static str, ClockDef)>] = &const {
|
||||
t
|
||||
};
|
||||
|
||||
const STGCRG_CLOCKS: &'static [Option<(&'static str, ClockDef)>] = &const {
|
||||
const STGCRG_CLOCKS: &[Option<(&'static str, ClockDef)>] = &const {
|
||||
use ClockDef::*;
|
||||
|
||||
let mut t = [const { None }; STGCRG_CLOCK_COUNT];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#![allow(unsafe_op_in_unsafe_fn)]
|
||||
#![allow(unsafe_op_in_unsafe_fn, clippy::eq_op, clippy::erasing_op)]
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
@@ -8,15 +8,14 @@ use device_api::{
|
||||
},
|
||||
};
|
||||
use device_tree::{
|
||||
driver::{
|
||||
device_tree_driver,
|
||||
util::{generic_gpio_config, GenericPinctrlBiasConfig, GenericPinctrlConfig},
|
||||
DeviceTreeGpioPins, DeviceTreePinController, Node, ProbeContext,
|
||||
},
|
||||
DeviceTreePropertyRead, TProp,
|
||||
driver::{
|
||||
DeviceTreeGpioPins, DeviceTreePinController, Node, ProbeContext, device_tree_driver,
|
||||
util::{GenericPinctrlBiasConfig, GenericPinctrlConfig, generic_gpio_config},
|
||||
},
|
||||
};
|
||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIoMut};
|
||||
use libk_util::{bit::BitField, sync::IrqSafeSpinlock, OneTimeInit};
|
||||
use libk_util::{OneTimeInit, bit::BitField, sync::IrqSafeSpinlock};
|
||||
use yggdrasil_abi::error::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
use alloc::sync::Arc;
|
||||
use device_api::device::{Device, DeviceInitContext};
|
||||
use device_tree::driver::{Node, ProbeContext, device_tree_driver};
|
||||
use libk::{
|
||||
error::Error,
|
||||
fs::sysfs::{self, nodes::SysfsRtcNode},
|
||||
};
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
use tock_registers::{
|
||||
interfaces::Readable,
|
||||
register_structs,
|
||||
registers::{ReadOnly, ReadWrite},
|
||||
};
|
||||
use yggdrasil_abi::time::NANOSECONDS_IN_SECOND;
|
||||
|
||||
register_structs! {
|
||||
#[allow(non_snake_case)]
|
||||
Regs {
|
||||
(0x00 => TIME_LOW: ReadOnly<u32>),
|
||||
(0x04 => TIME_HIGH: ReadOnly<u32>),
|
||||
(0x08 => ALARM_LOW: ReadWrite<u32>),
|
||||
(0x0C => ALARM_HIGH: ReadWrite<u32>),
|
||||
(0x10 => IRQ_ENABLED: ReadWrite<u32>),
|
||||
(0x14 => CLEAR_ALARM: ReadWrite<u32>),
|
||||
(0x18 => ALARM_STATUS: ReadOnly<u32>),
|
||||
(0x1C => CLEAR_INTERRUPT: ReadWrite<u32>),
|
||||
(0x20 => @END),
|
||||
}
|
||||
}
|
||||
|
||||
struct Rtc {
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
}
|
||||
|
||||
impl SysfsRtcNode for Rtc {
|
||||
fn read(&self) -> Result<u64, Error> {
|
||||
let regs = self.regs.lock();
|
||||
let low = regs.TIME_LOW.get();
|
||||
let high = regs.TIME_HIGH.get();
|
||||
let t = ((high as u64) << 32) | (low as u64);
|
||||
Ok(t / NANOSECONDS_IN_SECOND)
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Rtc {
|
||||
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
|
||||
sysfs::nodes::add_rtc_node(self.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
"Google Goldfish RTC"
|
||||
}
|
||||
}
|
||||
|
||||
device_tree_driver! {
|
||||
compatible: ["google,goldfish-rtc"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let base = node.map_base(context, 0)?;
|
||||
|
||||
let regs = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?;
|
||||
|
||||
let rtc = Arc::new(Rtc { regs: IrqSafeSpinlock::new(regs) });
|
||||
|
||||
Some(rtc)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#![allow(unsafe_op_in_unsafe_fn)]
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
mod goldfish_rtc;
|
||||
mod plic;
|
||||
|
||||
@@ -2,20 +2,23 @@ use alloc::{sync::Arc, vec::Vec};
|
||||
use device_api::{
|
||||
device::{Device, DeviceInitContext},
|
||||
interrupt::{
|
||||
ExternalInterruptController, FixedInterruptTable, FullIrq, InterruptHandler,
|
||||
InterruptTable, Irq, IrqOptions, IrqVector,
|
||||
ExternalInterruptController, InterruptHandler, Irq, IrqHandle, IrqOptions, IrqPriority,
|
||||
IrqVector,
|
||||
},
|
||||
};
|
||||
use device_tree::{
|
||||
driver::{
|
||||
device_tree_driver, lookup_phandle, DeviceTreeInterruptController, Node, ProbeContext,
|
||||
},
|
||||
DeviceTreePropertyRead, TProp,
|
||||
driver::{
|
||||
DeviceTreeInterruptController, Node, ProbeContext, device_tree_driver, lookup_phandle,
|
||||
},
|
||||
};
|
||||
use kernel_arch_riscv64::boot_hart_id;
|
||||
use libk::{arch::Cpu, device::register_external_interrupt_controller};
|
||||
use libk::{
|
||||
arch::Cpu,
|
||||
device::{interrupt::FixedInterruptTable, register_external_interrupt_controller},
|
||||
};
|
||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
|
||||
use libk_util::{sync::spin_rwlock::IrqSafeRwLock, OneTimeInit};
|
||||
use libk_util::{OneTimeInit, sync::spin_rwlock::IrqSafeRwLock};
|
||||
use tock_registers::{
|
||||
interfaces::{Readable, Writeable},
|
||||
register_structs,
|
||||
@@ -77,8 +80,7 @@ register_structs! {
|
||||
struct Context {
|
||||
enable: IrqSafeRwLock<DeviceMemoryIo<'static, ContextEnableRegs>>,
|
||||
control: IrqSafeRwLock<DeviceMemoryIo<'static, ContextControlRegs>>,
|
||||
// TODO scale the table depending on effective MAX_IRQS value
|
||||
table: IrqSafeRwLock<FixedInterruptTable<128>>,
|
||||
table: FixedInterruptTable,
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
@@ -95,13 +97,71 @@ struct HartContext {
|
||||
/// RISC-V Platform-Level Interrupt Controller (PLIC) device
|
||||
pub struct Plic {
|
||||
base: PhysicalAddress,
|
||||
max_irqs: usize,
|
||||
max_irq: usize,
|
||||
// hart id -> context map
|
||||
context_map: Vec<HartContext>,
|
||||
inner: OneTimeInit<Inner>,
|
||||
}
|
||||
|
||||
impl Plic {
|
||||
fn ensure_init(&self) -> Result<(), Error> {
|
||||
self.inner.or_try_init_with(|| {
|
||||
log::info!("Initialize RISC-V PLIC");
|
||||
|
||||
let common =
|
||||
unsafe { DeviceMemoryIo::<CommonRegs>::map(self.base, Default::default())? };
|
||||
|
||||
for i in 0..self.max_irq {
|
||||
common.PRIORITY[i].set(0);
|
||||
}
|
||||
|
||||
for context in self.context_map.iter() {
|
||||
let enable_offset = ENABLE_BASE + context.index * ENABLE_STRIDE;
|
||||
let control_offset = CONTROL_BASE + context.index * CONTROL_STRIDE;
|
||||
|
||||
log::info!(
|
||||
"* HART {}: context {}, enable={:#x}, control={:#x}",
|
||||
context.hart,
|
||||
context.index,
|
||||
enable_offset,
|
||||
control_offset
|
||||
);
|
||||
let enable = unsafe {
|
||||
DeviceMemoryIo::<ContextEnableRegs>::map(
|
||||
self.base.add(enable_offset),
|
||||
Default::default(),
|
||||
)?
|
||||
};
|
||||
let control = unsafe {
|
||||
DeviceMemoryIo::<ContextControlRegs>::map(
|
||||
self.base.add(control_offset),
|
||||
Default::default(),
|
||||
)?
|
||||
};
|
||||
|
||||
for i in 0..self.max_irq.div_ceil(32) {
|
||||
enable.ENABLE[i].set(0);
|
||||
}
|
||||
control.THRESHOLD.set(0);
|
||||
|
||||
context.context.init(Context {
|
||||
enable: IrqSafeRwLock::new(enable),
|
||||
control: IrqSafeRwLock::new(control),
|
||||
table: FixedInterruptTable::new(MAX_IRQS), // table: IrqSafeRwLock::new(FixedInterruptTable::new()),
|
||||
});
|
||||
}
|
||||
|
||||
// self.inner.init(Inner {
|
||||
// common: IrqSafeRwLock::new(common),
|
||||
// });
|
||||
|
||||
Ok(Inner {
|
||||
common: IrqSafeRwLock::new(common),
|
||||
})
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn hart_context(&self, hart: u32) -> Option<&HartContext> {
|
||||
self.context_map.iter().find(|c| c.hart == hart)
|
||||
}
|
||||
@@ -115,8 +175,8 @@ impl Plic {
|
||||
log::error!("plic: irq cannot be zero");
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
if irq as usize >= self.max_irqs {
|
||||
log::error!("plic: irq ({}) >= max_irqs ({})", irq, self.max_irqs);
|
||||
if irq as usize > self.max_irq {
|
||||
log::error!("plic: irq ({}) > max_irq ({})", irq, self.max_irq);
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
Ok(irq)
|
||||
@@ -152,24 +212,33 @@ impl ExternalInterruptController for Plic {
|
||||
fn register_irq(
|
||||
&self,
|
||||
irq: Irq,
|
||||
_options: IrqOptions,
|
||||
options: IrqOptions,
|
||||
handler: Arc<dyn InterruptHandler>,
|
||||
) -> Result<(), Error> {
|
||||
self.ensure_init()?;
|
||||
let bsp_hart_id = boot_hart_id() as u32;
|
||||
let irq = self.validate_irq(irq)?;
|
||||
let prioval = match options.priority {
|
||||
IrqPriority::Low => 3,
|
||||
IrqPriority::Normal => 5,
|
||||
IrqPriority::High => 7,
|
||||
};
|
||||
let inner = self.inner.get();
|
||||
let common = inner.common.write();
|
||||
common.PRIORITY[irq as usize - 1].set(prioval);
|
||||
let context = self
|
||||
.hart_context(bsp_hart_id)
|
||||
.ok_or(Error::InvalidArgument)
|
||||
.inspect_err(|_| log::error!("plic: no context for hart {bsp_hart_id}"))?
|
||||
.context
|
||||
.get();
|
||||
let mut table = context.table.write();
|
||||
// let mut table = context.table.write();
|
||||
|
||||
log::info!(
|
||||
"Bind irq #{irq} -> hart {bsp_hart_id}, {:?}",
|
||||
handler.display_name()
|
||||
);
|
||||
|
||||
table.insert(irq as usize, handler)?;
|
||||
context.table.insert(irq as usize, handler);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -183,72 +252,26 @@ impl ExternalInterruptController for Plic {
|
||||
let context = context.context.get();
|
||||
|
||||
let control = context.control.write();
|
||||
let table = context.table.read();
|
||||
// let table = context.table.read();
|
||||
|
||||
loop {
|
||||
let irq = control.CLAIM.get();
|
||||
if irq == 0 {
|
||||
break;
|
||||
}
|
||||
let vector = IrqVector::Irq(Irq::External(irq));
|
||||
|
||||
if let Some(handler) = table.handler(irq as usize) {
|
||||
handler.clone().handle_irq(vector);
|
||||
} else {
|
||||
log::warn!("plic: no handler for IRQ #{irq}");
|
||||
}
|
||||
|
||||
// Done servicing
|
||||
control.CLAIM.set(irq);
|
||||
let irq = control.CLAIM.get();
|
||||
if irq == 0 {
|
||||
return;
|
||||
}
|
||||
let vector = IrqVector::Irq(Irq::External(irq));
|
||||
|
||||
if !context.table.handle_irq_line(irq as usize, vector) {
|
||||
log::warn!("plic: no handler for IRQ #{irq}");
|
||||
}
|
||||
|
||||
// Done servicing
|
||||
control.CLAIM.set(irq);
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Plic {
|
||||
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
|
||||
log::info!("Initialize RISC-V PLIC");
|
||||
|
||||
let common = DeviceMemoryIo::<CommonRegs>::map(self.base, Default::default())?;
|
||||
|
||||
for i in 0..self.max_irqs - 1 {
|
||||
common.PRIORITY[i].set(3);
|
||||
}
|
||||
|
||||
for context in self.context_map.iter() {
|
||||
let enable_offset = ENABLE_BASE + context.index * ENABLE_STRIDE;
|
||||
let control_offset = CONTROL_BASE + context.index * CONTROL_STRIDE;
|
||||
|
||||
log::info!(
|
||||
"* HART {}: context {}, enable={:#x}, control={:#x}",
|
||||
context.hart,
|
||||
context.index,
|
||||
enable_offset,
|
||||
control_offset
|
||||
);
|
||||
let enable = DeviceMemoryIo::<ContextEnableRegs>::map(
|
||||
self.base.add(enable_offset),
|
||||
Default::default(),
|
||||
)?;
|
||||
let control = DeviceMemoryIo::<ContextControlRegs>::map(
|
||||
self.base.add(control_offset),
|
||||
Default::default(),
|
||||
)?;
|
||||
|
||||
for i in 0..self.max_irqs.div_ceil(32) {
|
||||
enable.ENABLE[i].set(0);
|
||||
}
|
||||
control.THRESHOLD.set(0);
|
||||
|
||||
context.context.init(Context {
|
||||
enable: IrqSafeRwLock::new(enable),
|
||||
control: IrqSafeRwLock::new(control),
|
||||
table: IrqSafeRwLock::new(FixedInterruptTable::new()),
|
||||
});
|
||||
}
|
||||
|
||||
self.inner.init(Inner {
|
||||
common: IrqSafeRwLock::new(common),
|
||||
});
|
||||
self.ensure_init()?;
|
||||
|
||||
register_external_interrupt_controller(self);
|
||||
|
||||
@@ -261,11 +284,12 @@ impl Device for Plic {
|
||||
}
|
||||
|
||||
impl DeviceTreeInterruptController for Plic {
|
||||
fn map_interrupt(&self, property: &TProp, offset: usize) -> Option<FullIrq> {
|
||||
fn map_interrupt(self: Arc<Self>, property: &TProp, offset: usize) -> Option<IrqHandle> {
|
||||
let num = property.read_cell(offset, 1)?;
|
||||
Some(FullIrq {
|
||||
Some(IrqHandle {
|
||||
irq: Irq::External(num as _),
|
||||
options: IrqOptions::default(),
|
||||
intc: self.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -289,7 +313,7 @@ device_tree_driver! {
|
||||
let ndev = node.prop_usize("riscv,ndev")?;
|
||||
let iext = node.property("interrupts-extended")?;
|
||||
|
||||
let max_irqs = MAX_IRQS.min(ndev);
|
||||
let max_irq = MAX_IRQS.min(ndev);
|
||||
|
||||
// Parse the context -> hart mapping, only select S-mode external interrupts
|
||||
let mut context_map = Vec::new();
|
||||
@@ -301,6 +325,7 @@ device_tree_driver! {
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
log::info!("Context #{context}: mode={mode:?}, hart={hart_id}");
|
||||
if mode != ContextMode::ExternalS {
|
||||
continue;
|
||||
}
|
||||
@@ -322,7 +347,7 @@ device_tree_driver! {
|
||||
|
||||
let intc = Arc::new(Plic {
|
||||
base,
|
||||
max_irqs,
|
||||
max_irq,
|
||||
context_map,
|
||||
inner: OneTimeInit::new(),
|
||||
});
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "ygg_driver_bsp_sifive"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
device-tree.workspace = true
|
||||
device-api.workspace = true
|
||||
yggdrasil-abi.workspace = true
|
||||
libk-mm.workspace = true
|
||||
libk-util.workspace = true
|
||||
libk.workspace = true
|
||||
ygg_driver_net_core.path = "../../net/core"
|
||||
|
||||
static_assertions.workspace = true
|
||||
tock-registers.workspace = true
|
||||
log.workspace = true
|
||||
bytemuck.workspace = true
|
||||
futures-util.workspace = true
|
||||
async-trait.workspace = true
|
||||
@@ -0,0 +1,190 @@
|
||||
use alloc::sync::Arc;
|
||||
use device_api::{
|
||||
clock::{ClockController, ClockHandle, Hertz},
|
||||
device::{Device, DeviceInitContext},
|
||||
};
|
||||
use device_tree::{
|
||||
DeviceTreePropertyRead, TProp,
|
||||
driver::{DeviceTreeClockController, Node, ProbeContext, device_tree_driver},
|
||||
};
|
||||
use libk::error::Error;
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::{OneTimeInit, sync::IrqSafeSpinlock};
|
||||
use tock_registers::{
|
||||
interfaces::{Readable, Writeable},
|
||||
register_structs,
|
||||
registers::ReadWrite,
|
||||
};
|
||||
|
||||
use crate::pll::{PllCfg, WrpllData};
|
||||
|
||||
const CLK_COREPLL: u32 = 0;
|
||||
const CLK_DDRPLL: u32 = 1;
|
||||
const CLK_GEMGXLPLL: u32 = 2;
|
||||
const CLK_TLCLK: u32 = 3;
|
||||
|
||||
register_structs! {
|
||||
Regs {
|
||||
(0x000 => hfxosccfg: ReadWrite<u32>),
|
||||
(0x004 => corepllcfg0: ReadWrite<u32, PllCfg::Register>),
|
||||
(0x008 => _0),
|
||||
(0x00C => ddrpllcfg0: ReadWrite<u32>),
|
||||
(0x010 => ddrpllcfg1: ReadWrite<u32>),
|
||||
(0x014 => _1),
|
||||
(0x01C => gemgxlpllcfg0: ReadWrite<u32>),
|
||||
(0x020 => gemgxlpllcfg1: ReadWrite<u32>),
|
||||
(0x024 => coreclksel: ReadWrite<u32>),
|
||||
(0x028 => deviceresetreg: ReadWrite<u32>),
|
||||
(0x02C => _2),
|
||||
(0x100 => @END),
|
||||
}
|
||||
}
|
||||
|
||||
struct Prci {
|
||||
clk_osc: ClockHandle,
|
||||
clk_rtc: ClockHandle,
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
init: OneTimeInit<()>,
|
||||
}
|
||||
|
||||
impl Regs {
|
||||
fn read_core_pll(&self) -> WrpllData {
|
||||
let pll = self.corepllcfg0.extract();
|
||||
let divr = pll.read(PllCfg::PLLR);
|
||||
let divf = pll.read(PllCfg::PLLF);
|
||||
let divq = pll.read(PllCfg::PLLQ);
|
||||
WrpllData {
|
||||
divq,
|
||||
divr,
|
||||
divf,
|
||||
int_feedback: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Prci {
|
||||
fn ensure_init(&self) {
|
||||
// U-Boot should configure coreclk to 1GHz, but when booting
|
||||
// in QEMU, there is not U-Boot stage, and some peripherals
|
||||
// like PWM expect the clock to be configured this way. So
|
||||
// this needs to be done manually here
|
||||
self.init.or_init_with(|| {
|
||||
let regs = self.regs.lock();
|
||||
if regs.coreclksel.get() != 0 {
|
||||
// coreclk configured to hfclk
|
||||
// configure corepll to output 1GHz and switch to it
|
||||
// divf = 150
|
||||
// divr = 4
|
||||
// divq = 1
|
||||
regs.corepllcfg0.write(
|
||||
PllCfg::PLLF.val(150)
|
||||
+ PllCfg::PLLR.val(4)
|
||||
+ PllCfg::PLLQ.val(1)
|
||||
+ PllCfg::PLLFSEBYPASS::SET,
|
||||
);
|
||||
while !regs.corepllcfg0.matches_all(PllCfg::PLLLOCK::SET) {
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
regs.coreclksel.set(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Prci {
|
||||
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
|
||||
self.ensure_init();
|
||||
if let Ok(coreclk) = self.clock_rate(Some(CLK_COREPLL)) {
|
||||
log::info!("coreclk = {coreclk}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
"sifive,fu540-c000-prci"
|
||||
}
|
||||
}
|
||||
|
||||
impl ClockController for Prci {
|
||||
fn clock_rate(&self, clock: Option<u32>) -> Result<Hertz, Error> {
|
||||
self.ensure_init();
|
||||
let _ = &self.clk_rtc;
|
||||
match clock {
|
||||
Some(CLK_COREPLL) => {
|
||||
let regs = self.regs.lock();
|
||||
let hfclk = self.clk_osc.rate()?;
|
||||
// == 0 -> use corepll
|
||||
// == 1 -> use hfclk
|
||||
let coreclksel = regs.coreclksel.get() != 0;
|
||||
let coreclk = match coreclksel {
|
||||
true => hfclk,
|
||||
false => {
|
||||
let pll = regs.read_core_pll();
|
||||
pll.output_rate(hfclk)
|
||||
}
|
||||
};
|
||||
Ok(coreclk)
|
||||
}
|
||||
Some(CLK_TLCLK) => {
|
||||
let coreclk = self.clock_rate(Some(CLK_COREPLL))?;
|
||||
Ok(coreclk / 2)
|
||||
}
|
||||
Some(_) => todo!(),
|
||||
None => Err(Error::InvalidArgument),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_clock_rate(&self, _clock: Option<u32>, _rate: Hertz) -> Result<Hertz, Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
|
||||
fn enable_clock(&self, clock: Option<u32>) -> Result<(), Error> {
|
||||
self.ensure_init();
|
||||
match clock {
|
||||
Some(CLK_GEMGXLPLL) | Some(CLK_DDRPLL) | Some(CLK_COREPLL) => todo!(),
|
||||
Some(CLK_TLCLK) => Ok(()),
|
||||
_ => Err(Error::InvalidArgument),
|
||||
}
|
||||
}
|
||||
|
||||
fn disable_clock(&self, _clock: Option<u32>) -> Result<(), Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceTreeClockController for Prci {
|
||||
fn map_clock(self: Arc<Self>, property: &TProp, offset: usize) -> Option<(ClockHandle, usize)> {
|
||||
let clock = property.read_cell(offset, 1)? as u32;
|
||||
Some((
|
||||
ClockHandle {
|
||||
parent: self.clone(),
|
||||
clock: Some(clock),
|
||||
},
|
||||
1,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
device_tree_driver! {
|
||||
compatible: ["sifive,fu540-c000-prci"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let base = node.map_base(context, 0)?;
|
||||
let clk_osc = node.clock(0)?;
|
||||
let clk_rtc = node.clock(1)?;
|
||||
|
||||
let regs = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?;
|
||||
|
||||
let prci = Arc::new(Prci {
|
||||
regs: IrqSafeSpinlock::new(regs),
|
||||
clk_osc,
|
||||
clk_rtc,
|
||||
init: OneTimeInit::new()
|
||||
});
|
||||
|
||||
node.make_clock_controller(prci.clone());
|
||||
|
||||
Some(prci)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
use alloc::sync::Arc;
|
||||
use device_api::{
|
||||
clock::{ClockController, ClockHandle, Hertz},
|
||||
device::Device,
|
||||
};
|
||||
use device_tree::{
|
||||
DeviceTreePropertyRead, TProp,
|
||||
driver::{DeviceTreeClockController, Node, ProbeContext, device_tree_driver},
|
||||
};
|
||||
use libk::error::Error;
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
use tock_registers::{
|
||||
interfaces::Readable,
|
||||
register_structs,
|
||||
registers::{ReadOnly, ReadWrite},
|
||||
};
|
||||
|
||||
use crate::pll::{PllCfg, WrpllData};
|
||||
|
||||
// const CLK_COREPLL: u32 = 0;
|
||||
// const CLK_DDRPLL: u32 = 1;
|
||||
// const CLK_GEMGXLPLL: u32 = 2;
|
||||
// const CLK_DVFSCOREPLL: u32 = 3;
|
||||
// const CLK_HFPCLKPLL: u32 = 4;
|
||||
// const CLK_CLTXPLL: u32 = 5;
|
||||
// const CLK_TLCLK: u32 = 6;
|
||||
const CLK_PCLK: u32 = 7;
|
||||
// const CLK_PCIE_AUX: u32 = 8;
|
||||
|
||||
register_structs! {
|
||||
Regs {
|
||||
(0x00 => hfxosccfg: ReadWrite<u32>),
|
||||
(0x04 => core_pllcfg: ReadWrite<u32>),
|
||||
(0x08 => core_plloutdiv: ReadWrite<u32>),
|
||||
(0x0C => ddr_pllcfg: ReadWrite<u32>),
|
||||
(0x10 => ddr_plloutdiv: ReadWrite<u32>),
|
||||
(0x14 => _0),
|
||||
(0x1C => gemgxl_pllcfg: ReadWrite<u32, PllCfg::Register>),
|
||||
(0x20 => gemgxl_plloutdiv: ReadWrite<u32>),
|
||||
(0x24 => core_clk_sel_reg: ReadWrite<u32>),
|
||||
(0x28 => devices_reset_n: ReadWrite<u32>),
|
||||
(0x2C => clk_mux_status: ReadOnly<u32>),
|
||||
(0x30 => _1),
|
||||
(0x38 => dvfs_core_pllcfg: ReadWrite<u32>),
|
||||
(0x3C => dvfs_core_plloutdiv: ReadWrite<u32>),
|
||||
(0x40 => corepllsel: ReadWrite<u32>),
|
||||
(0x44 => _2),
|
||||
(0x50 => hfpclk_pllcfg: ReadWrite<u32, PllCfg::Register>),
|
||||
(0x54 => hfpclk_plloutdiv: ReadWrite<u32>),
|
||||
(0x58 => hfpclkpllsel: ReadWrite<u32>),
|
||||
(0x5C => hfpclk_div_reg: ReadWrite<u32>),
|
||||
(0x60 => _3),
|
||||
(0xE0 => prci_plls: ReadOnly<u32>),
|
||||
(0xE4 => _4),
|
||||
(0x100 => @END),
|
||||
}
|
||||
}
|
||||
|
||||
struct Prci {
|
||||
clk_hfclk: ClockHandle,
|
||||
clk_rtcclk: ClockHandle,
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
}
|
||||
|
||||
impl Regs {
|
||||
fn read_hfpclk_pll(&self) -> WrpllData {
|
||||
let reg = self.hfpclk_pllcfg.extract();
|
||||
let divr = reg.read(PllCfg::PLLR);
|
||||
let divq = reg.read(PllCfg::PLLQ);
|
||||
let divf = reg.read(PllCfg::PLLF);
|
||||
WrpllData {
|
||||
divq,
|
||||
divr,
|
||||
divf,
|
||||
int_feedback: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Prci {
|
||||
fn display_name(&self) -> &str {
|
||||
"sifive,fu740-c000-prci"
|
||||
}
|
||||
}
|
||||
|
||||
impl ClockController for Prci {
|
||||
fn clock_rate(&self, clock: Option<u32>) -> Result<Hertz, Error> {
|
||||
// hart frequency: coreclk, supplied either by corepll or dvfscorepll, selected by
|
||||
// corepllsel
|
||||
// hfpclkpll: clock for SPI, UART, GPIO, I2C, PWM
|
||||
//
|
||||
let _ = &self.clk_rtcclk;
|
||||
let regs = self.regs.lock();
|
||||
match clock {
|
||||
Some(CLK_PCLK) => {
|
||||
// PCLK calculation:
|
||||
// pclk <- X / hfpclkdiv
|
||||
// case [hfpclkpllsel]:
|
||||
// 1: X <- (hfclk)
|
||||
// 0: X <- hfpclkpllcfg/out & hfpclkpll
|
||||
// hfpclkdiv <- [hfpclk_div_reg] + 2
|
||||
|
||||
let hfpclkpllsel = regs.hfpclkpllsel.get() & 1 != 0;
|
||||
let hfpclk_div_reg = regs.hfpclk_div_reg.get() + 2;
|
||||
let x = match hfpclkpllsel {
|
||||
true => self.clk_hfclk.rate()?,
|
||||
false => {
|
||||
let pclk_pll = regs.read_hfpclk_pll();
|
||||
pclk_pll.output_rate(self.clk_hfclk.rate()?)
|
||||
}
|
||||
};
|
||||
Ok(x / hfpclk_div_reg)
|
||||
}
|
||||
Some(_) => {
|
||||
todo!();
|
||||
}
|
||||
None => {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_clock_rate(&self, _clock: Option<u32>, _rate: Hertz) -> Result<Hertz, Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
|
||||
fn enable_clock(&self, _clock: Option<u32>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn disable_clock(&self, _clock: Option<u32>) -> Result<(), Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceTreeClockController for Prci {
|
||||
fn map_clock(self: Arc<Self>, property: &TProp, offset: usize) -> Option<(ClockHandle, usize)> {
|
||||
let clock = property.read_cell(offset, 1)? as u32;
|
||||
Some((
|
||||
ClockHandle {
|
||||
parent: self.clone(),
|
||||
clock: Some(clock),
|
||||
},
|
||||
1,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
device_tree_driver! {
|
||||
compatible: ["sifive,fu740-c000-prci"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let base = node.map_base(context, 0)?;
|
||||
let clk_hfclk = node.clock(0)?;
|
||||
let clk_rtcclk = node.clock(1)?;
|
||||
|
||||
let regs = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?;
|
||||
|
||||
let prci = Arc::new(Prci {
|
||||
regs: IrqSafeSpinlock::new(regs),
|
||||
clk_hfclk,
|
||||
clk_rtcclk
|
||||
});
|
||||
|
||||
node.make_clock_controller(prci.clone());
|
||||
|
||||
Some(prci)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
use core::{mem::MaybeUninit, time::Duration};
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use device_api::{
|
||||
clock::ClockHandle,
|
||||
device::{Device, DeviceInitContext},
|
||||
dma::DmaAllocator,
|
||||
interrupt::{InterruptHandler, IrqHandle, IrqVector},
|
||||
};
|
||||
use device_tree::driver::{
|
||||
InitSequence, Node, ProbeContext, device_tree_driver, util::read_mac_address,
|
||||
};
|
||||
use futures_util::task::AtomicWaker;
|
||||
use libk::{
|
||||
dma::DmaBuffer,
|
||||
error::Error,
|
||||
task::runtime::{self, with_timeout},
|
||||
};
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::{OneTimeInit, event::BitmapEvent, sync::IrqSafeSpinlock};
|
||||
use tock_registers::{
|
||||
LocalRegisterCopy,
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
};
|
||||
use ygg_driver_net_core::{
|
||||
RxPacket,
|
||||
ephy::PhyAccess,
|
||||
interface::{NetworkDevice, NetworkInterfaceType},
|
||||
util::GenericQueue,
|
||||
};
|
||||
use yggdrasil_abi::net::{MacAddress, link::LinkState};
|
||||
|
||||
use crate::ethernet::{
|
||||
queue::Descriptor,
|
||||
regs::{ControlRegs, Regs},
|
||||
};
|
||||
|
||||
const RX_BUF_SIZE_MUL: usize = 64;
|
||||
|
||||
mod queue;
|
||||
mod regs;
|
||||
|
||||
// TODO multiqueue
|
||||
struct Ethernet {
|
||||
// Device tree info
|
||||
name: &'static str,
|
||||
irq: IrqHandle,
|
||||
clk_pclk: ClockHandle,
|
||||
clk_hclk: ClockHandle,
|
||||
local_mac_address: Option<MacAddress>,
|
||||
|
||||
// Memory/HW
|
||||
// caps: Capabilities,
|
||||
dma: OneTimeInit<Arc<dyn DmaAllocator>>,
|
||||
control_regs: IrqSafeSpinlock<DeviceMemoryIo<'static, ControlRegs>>,
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
|
||||
// Operation
|
||||
queue: OneTimeInit<GenericQueue<Descriptor, Descriptor>>,
|
||||
softirq: BitmapEvent<AtomicWaker>,
|
||||
iface_id: OneTimeInit<u32>,
|
||||
}
|
||||
|
||||
// bitflags! {
|
||||
// pub struct CapFlags: u32 {
|
||||
// const MACB_IS_GEM: bit 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// struct Capabilities {
|
||||
// flags: CapFlags,
|
||||
// queue_mask: u32,
|
||||
// queue_count: usize,
|
||||
// }
|
||||
|
||||
impl Ethernet {
|
||||
fn probe(node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let name = node.name().unwrap_or("gemgxl");
|
||||
let irq = node.interrupt(0)?;
|
||||
let clk_pclk = node.named_clock("pclk")?;
|
||||
let clk_hclk = node.named_clock("hclk")?;
|
||||
let base = node.map_base(context, 0)?;
|
||||
let base_control = node.map_base(context, 1)?;
|
||||
let local_mac_address = read_mac_address(node);
|
||||
|
||||
let regs = unsafe { DeviceMemoryIo::<Regs>::map(base, Default::default()) }.ok()?;
|
||||
let control_regs = unsafe { DeviceMemoryIo::map(base_control, Default::default()) }.ok()?;
|
||||
|
||||
// let caps = regs.probe_capabilities();
|
||||
|
||||
let gem = Arc::new(Ethernet {
|
||||
name,
|
||||
clk_pclk,
|
||||
clk_hclk,
|
||||
irq,
|
||||
local_mac_address,
|
||||
|
||||
// caps,
|
||||
dma: OneTimeInit::new(),
|
||||
regs: IrqSafeSpinlock::new(regs),
|
||||
control_regs: IrqSafeSpinlock::new(control_regs),
|
||||
|
||||
queue: OneTimeInit::new(),
|
||||
softirq: BitmapEvent::new(AtomicWaker::new()),
|
||||
iface_id: OneTimeInit::new(),
|
||||
});
|
||||
|
||||
context.sequence = Some(InitSequence::Late);
|
||||
|
||||
Some(gem)
|
||||
}
|
||||
|
||||
async fn softirq(self: Arc<Self>) {
|
||||
let iface = *self.iface_id.get();
|
||||
let queue = self.queue.get();
|
||||
|
||||
loop {
|
||||
let event_fut = self.softirq.wait();
|
||||
let bits = match with_timeout(event_fut, Duration::from_millis(100)).await {
|
||||
Ok(bits) => bits as u32,
|
||||
Err(_) => {
|
||||
queue.consume_tx().ok();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let status = LocalRegisterCopy::<_, regs::Interrupt::Register>::new(bits);
|
||||
|
||||
if status.matches_all(regs::Interrupt::RCOMP::SET) {
|
||||
queue
|
||||
.consume_rx(&**self.dma.get(), None, |packet, _len| {
|
||||
let packet = RxPacket::new(packet, 0, iface);
|
||||
ygg_driver_net_core::receive_packet(packet).ok();
|
||||
})
|
||||
.ok();
|
||||
|
||||
let regs = self.regs.lock();
|
||||
regs.interrupt_enable.write(regs::Interrupt::RCOMP::SET);
|
||||
}
|
||||
if status.matches_all(regs::Interrupt::TCOMP::SET) {
|
||||
queue.consume_tx().ok();
|
||||
|
||||
let regs = self.regs.lock();
|
||||
regs.interrupt_enable.write(regs::Interrupt::RCOMP::SET);
|
||||
}
|
||||
if status.matches_all(regs::Interrupt::LINK::SET) {
|
||||
log::info!("Link status changed");
|
||||
let regs = self.regs.lock();
|
||||
regs.interrupt_enable.write(regs::Interrupt::LINK::SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn start_xmit(&self, frame: DmaBuffer<[u8]>) -> Result<(), Error> {
|
||||
let queue = self.queue.get();
|
||||
|
||||
queue.try_push_xmit(frame)?;
|
||||
|
||||
let regs = self.regs.lock();
|
||||
regs.network_control
|
||||
.modify(regs::NetworkControl::TSTART::SET);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Ethernet {
|
||||
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
|
||||
let _ = (&self.clk_pclk, &self.clk_hclk, &self.control_regs);
|
||||
log::info!("{}: hw address {:?}", self.name, self.local_mac_address);
|
||||
// TODO enable clocks
|
||||
let dma = self.dma.init(cx.dma_allocator);
|
||||
let regs = self.regs.lock();
|
||||
|
||||
let queue = self.queue.init(GenericQueue::with_capacity(
|
||||
&**dma,
|
||||
256,
|
||||
256,
|
||||
queue::RX_BUFFER_SIZE,
|
||||
)?);
|
||||
|
||||
let rx_queue_base = queue.rx_buffer_base().try_into_u32().unwrap();
|
||||
let tx_queue_base = queue.tx_buffer_base().try_into_u32().unwrap();
|
||||
|
||||
regs.interrupt_disable.set(0xFFFFFFFF);
|
||||
|
||||
regs.rx_buffer_queue_base.set(rx_queue_base);
|
||||
regs.tx_buffer_queue_base.set(tx_queue_base);
|
||||
regs.dma_config.write(
|
||||
regs::DmaConfig::RX_BUF_SIZE.val((queue::RX_BUFFER_SIZE / RX_BUF_SIZE_MUL) as _),
|
||||
);
|
||||
|
||||
regs.network_control.modify(regs::NetworkControl::MPE::SET);
|
||||
|
||||
{
|
||||
let phy = PhyAccess::new(&**regs, 0);
|
||||
let phy_id = phy.id()?;
|
||||
log::info!("{}: PHY {:04x}:{:04x}", self.name, phy_id.0, phy_id.1);
|
||||
phy.setup_link(false, None)?;
|
||||
}
|
||||
|
||||
regs.network_config.write(regs::NetworkConfig::PROMISC::SET);
|
||||
regs.network_control
|
||||
.modify(regs::NetworkControl::TE::SET + regs::NetworkControl::RE::SET);
|
||||
|
||||
// if (GEM_BFEXT(DAW64, gem_readl(...)))
|
||||
// hw_dma_cap |= HW_DMA_CAP_64B
|
||||
|
||||
regs.interrupt_enable.write(
|
||||
regs::Interrupt::LINK::SET + regs::Interrupt::RCOMP::SET + regs::Interrupt::TCOMP::SET,
|
||||
);
|
||||
|
||||
let iface =
|
||||
ygg_driver_net_core::register_interface(NetworkInterfaceType::Ethernet, self.clone());
|
||||
self.iface_id.init(iface.id());
|
||||
|
||||
runtime::spawn(self.clone().softirq())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
|
||||
self.irq.register(self.clone())?;
|
||||
self.irq.enable()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkDevice for Ethernet {
|
||||
fn allocate_transmit_buffer(&self, len: usize) -> Result<DmaBuffer<[MaybeUninit<u8>]>, Error> {
|
||||
DmaBuffer::new_uninit_slice(&**self.dma.get(), len)
|
||||
}
|
||||
|
||||
fn transmit_buffer(&self, buffer: DmaBuffer<[u8]>) -> Result<(), Error> {
|
||||
self.start_xmit(buffer)
|
||||
}
|
||||
|
||||
fn packet_prefix_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
fn read_hardware_address(&self) -> MacAddress {
|
||||
// TODO from registers
|
||||
self.local_mac_address.unwrap()
|
||||
}
|
||||
|
||||
fn link_state(&self) -> LinkState {
|
||||
self.regs.lock().link_state()
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptHandler for Ethernet {
|
||||
fn handle_irq(self: Arc<Self>, _vector: IrqVector) -> bool {
|
||||
const MASK: u32 = regs::Interrupt::RCOMP::SET.value
|
||||
| regs::Interrupt::TCOMP::SET.value
|
||||
| regs::Interrupt::LINK::SET.value;
|
||||
|
||||
let regs = self.regs.lock();
|
||||
let status = regs.interrupt_status.get();
|
||||
// Mask the IRQ and send it to softirq handler
|
||||
regs.interrupt_disable.set(MASK & status);
|
||||
self.softirq.signal(status as u64);
|
||||
|
||||
status != 0
|
||||
}
|
||||
}
|
||||
|
||||
device_tree_driver! {
|
||||
compatible: ["sifive,fu540-c000-gem"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
Ethernet::probe(node, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
use libk::{dma::BusAddress, error::Error};
|
||||
use ygg_driver_net_core::util::{GenericRxDescriptor, GenericTxDescriptor};
|
||||
|
||||
pub const RX_BUFFER_SIZE: usize = 4096;
|
||||
|
||||
static_assertions::const_assert_eq!(RX_BUFFER_SIZE % super::RX_BUF_SIZE_MUL, 0);
|
||||
static_assertions::const_assert_ne!(RX_BUFFER_SIZE / super::RX_BUF_SIZE_MUL, 0);
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct Descriptor {
|
||||
address: u32,
|
||||
control: u32,
|
||||
}
|
||||
|
||||
impl GenericTxDescriptor for Descriptor {
|
||||
// USED = 0: owned by hardware
|
||||
// USED = 1: owned by software
|
||||
const EMPTY: Self = Self {
|
||||
address: 0,
|
||||
control: Self::DESC_1_USED,
|
||||
};
|
||||
const EMPTY_LAST: Self = Self {
|
||||
address: 0,
|
||||
control: Self::DESC_1_USED | Self::DESC_1_TX_WRAP,
|
||||
};
|
||||
|
||||
fn consume(&mut self) -> Option<Result<(), Error>> {
|
||||
if self.control & Self::DESC_1_USED != 0 && self.address != 0 {
|
||||
Some(Ok(()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_tx(
|
||||
&mut self,
|
||||
buffer_address: BusAddress,
|
||||
size: usize,
|
||||
index: usize,
|
||||
capacity: usize,
|
||||
) -> Result<(), Error> {
|
||||
let buffer_address = buffer_address.try_into_u32()?;
|
||||
if !(8..8192).contains(&size) {
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
let mut control = size as u32 | Self::DESC_1_TX_LAST;
|
||||
if index == capacity - 1 {
|
||||
control |= Self::DESC_1_TX_WRAP;
|
||||
}
|
||||
self.address = buffer_address;
|
||||
self.control = control;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericRxDescriptor for Descriptor {
|
||||
fn consume(&mut self) -> Option<Result<usize, Error>> {
|
||||
if self.address & Self::DESC_0_RX_OWNERSHIP != 0 {
|
||||
Some(Ok((self.control & Self::LENGTH) as usize))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_rx(buffer_address: BusAddress, _size: usize, last: bool) -> Result<Self, Error> {
|
||||
let mut address = buffer_address.try_into_u32()?;
|
||||
if last {
|
||||
address |= Self::DESC_0_RX_WRAP;
|
||||
}
|
||||
Ok(Self {
|
||||
control: 0,
|
||||
address,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Descriptor {
|
||||
const DESC_1_USED: u32 = 1 << 31;
|
||||
const LENGTH: u32 = 0x1FFF;
|
||||
|
||||
const DESC_1_TX_WRAP: u32 = 1 << 30;
|
||||
const DESC_1_TX_LAST: u32 = 1 << 15;
|
||||
|
||||
const DESC_0_RX_OWNERSHIP: u32 = 1 << 0;
|
||||
const DESC_0_RX_WRAP: u32 = 1 << 1;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user