forked from M-Labs/zynq-rs
Compare commits
46 Commits
feature/zc
...
master
Author | SHA1 | Date | |
---|---|---|---|
af42d9b819 | |||
19efdafce7 | |||
213529cf7a | |||
4cfcc75d5c | |||
578431cbc6 | |||
6188fe7d69 | |||
2713b459ed | |||
0ea7e2c760 | |||
fa660a7433 | |||
d2ec041107 | |||
48ab85bf2e | |||
d477272c5c | |||
80180ba8f6 | |||
12975de2e1 | |||
8c404829ef | |||
8f041b017c | |||
5815baf88b | |||
cc20478d91 | |||
5ef3016554 | |||
6a45a0dfd0 | |||
b2b3e5c933 | |||
0efbbe39fe | |||
51b8111e79 | |||
46dc25b89e | |||
731684abb4 | |||
195a21fe78 | |||
96cefe6f06 | |||
7c58c0cf43 | |||
9005b73316 | |||
b1994dbe16 | |||
5bd336c961 | |||
298f64a2f9 | |||
4168eb63a7 | |||
a43b8bf64e | |||
91bae572f9 | |||
301f9236e5 | |||
55b36ee37e | |||
24c804e6f0 | |||
be672ab662 | |||
0106430805 | |||
|
c15b54f92b | ||
de42a5d1b2 | |||
ff03bf92a3 | |||
f20c008264 | |||
67dbb5932f | |||
dab5c6f070 |
54
Cargo.lock
generated
54
Cargo.lock
generated
@ -1,5 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.1"
|
||||
@ -14,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
checksum = "60f0b0d4c0a382d2734228fd12b5a6b5dac185c60e938026fd31b265b94f9bd2"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
@ -32,18 +34,14 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.39"
|
||||
version = "0.1.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b"
|
||||
checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"
|
||||
|
||||
[[package]]
|
||||
name = "core_io"
|
||||
version = "0.1.20210325"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97f8932064288cc79feb4d343a399d353a6f6f001e586ece47fe518a9e8507df"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/rs-core_io.git?rev=e9d3edf027#e9d3edf0272502b0dd6c26e8a4869c2912657615"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
@ -70,9 +68,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "fatfs"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e18f80a87439240dac45d927fd8f8081b6f1e34c03e97271189fa8a8c2e96c8f"
|
||||
version = "0.3.6"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/rust-fatfs.git?rev=4b5e420084#4b5e420084fd1c4a9c105680b687523909b6469c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
@ -107,22 +104,6 @@ dependencies = [
|
||||
"volatile-register",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libboard_zynq_us"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"embedded-hal",
|
||||
"libasync",
|
||||
"libboard_zynq",
|
||||
"libregister",
|
||||
"log",
|
||||
"nb 0.1.3",
|
||||
"smoltcp",
|
||||
"void",
|
||||
"volatile-register",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libconfig"
|
||||
version = "0.1.0"
|
||||
@ -212,21 +193,6 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
|
||||
|
||||
[[package]]
|
||||
name = "smoltcp"
|
||||
version = "0.7.5"
|
||||
|
@ -8,7 +8,6 @@ members = [
|
||||
"libconfig",
|
||||
"experiments",
|
||||
"szl",
|
||||
"libboard_zynq_us",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
@ -1,12 +1,4 @@
|
||||
{
|
||||
"abi-blacklist": [
|
||||
"stdcall",
|
||||
"fastcall",
|
||||
"vectorcall",
|
||||
"thiscall",
|
||||
"win64",
|
||||
"sysv64"
|
||||
],
|
||||
"arch": "arm",
|
||||
"data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
|
||||
"emit-debug-gdb-scripts": false,
|
||||
|
@ -8,6 +8,7 @@ edition = "2018"
|
||||
[features]
|
||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706"]
|
||||
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7"]
|
||||
target_ebaz4205 = ["libboard_zynq/target_ebaz4205", "libsupport_zynq/target_ebaz4205"]
|
||||
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya"]
|
||||
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc"]
|
||||
default = ["target_zc706"]
|
||||
@ -18,5 +19,5 @@ embedded-hal = "0.2"
|
||||
libregister = { path = "../libregister" }
|
||||
libcortex_a9 = { path = "../libcortex_a9" }
|
||||
libboard_zynq = { path = "../libboard_zynq" }
|
||||
libsupport_zynq = { path = "../libsupport_zynq", default-features = false, features = ["panic_handler"]}
|
||||
libsupport_zynq = { path = "../libsupport_zynq", default-features = false, features = ["panic_handler", "dummy_fiq_handler"]}
|
||||
libasync = { path = "../libasync" }
|
||||
|
@ -1,12 +1,14 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(const_in_array_repeat_expressions)]
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(asm)]
|
||||
#![feature(inline_const)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::collections::BTreeMap;
|
||||
use core::arch::asm;
|
||||
use libasync::{
|
||||
delay,
|
||||
smoltcp::{Sockets, TcpStream},
|
||||
@ -39,7 +41,7 @@ use libcortex_a9::{
|
||||
};
|
||||
use libregister::{RegisterR, RegisterW};
|
||||
use libsupport_zynq::{
|
||||
boot, ram,
|
||||
boot, exception_vectors, ram,
|
||||
};
|
||||
use log::{info, warn};
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
@ -56,19 +58,29 @@ extern "C" {
|
||||
static CORE1_RESTART: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
||||
if MPIDR.read().cpu_id() == 1{
|
||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||
let mut gic = gic::InterruptController::gic(mpcore);
|
||||
let id = gic.get_interrupt_id();
|
||||
if id.0 == 0 {
|
||||
gic.end_interrupt(id);
|
||||
asm::exit_irq();
|
||||
SP.write(&mut __stack1_start as *mut _ as u32);
|
||||
asm::enable_irq();
|
||||
CORE1_RESTART.store(false, Ordering::Relaxed);
|
||||
notify_spin_lock();
|
||||
main_core1();
|
||||
}
|
||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||
let mut gic = gic::InterruptController::gic(mpcore);
|
||||
let id = gic.get_interrupt_id();
|
||||
match MPIDR.read().cpu_id(){
|
||||
0 => {
|
||||
if id.0 == 0 {
|
||||
println!("Interrupting core0...");
|
||||
gic.end_interrupt(id);
|
||||
return;
|
||||
}
|
||||
},
|
||||
1 => {
|
||||
if id.0 == 0 {
|
||||
gic.end_interrupt(id);
|
||||
asm::exit_irq();
|
||||
SP.write(&mut __stack1_start as *mut _ as u32);
|
||||
asm::enable_irq();
|
||||
CORE1_RESTART.store(false, Ordering::Relaxed);
|
||||
notify_spin_lock();
|
||||
main_core1();
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
stdio::drop_uart();
|
||||
println!("IRQ");
|
||||
@ -86,6 +98,7 @@ pub fn restart_core1() {
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main_core0() {
|
||||
exception_vectors::set_vector_table(0x0);
|
||||
// zynq::clocks::CpuClocks::enable_io(1_250_000_000);
|
||||
enable_l2_cache(0x8);
|
||||
println!("\nZynq experiments");
|
||||
@ -105,6 +118,7 @@ pub fn main_core0() {
|
||||
|
||||
#[cfg(any(
|
||||
feature = "target_zc706",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
@ -134,6 +148,10 @@ pub fn main_core0() {
|
||||
ddr.memtest();
|
||||
ram::init_alloc_ddr(&mut ddr);
|
||||
|
||||
info!("Send software interrupt to core0");
|
||||
interrupt_controller.send_sgi(gic::InterruptId(0), gic::CPUCore::Core0.into());
|
||||
info!("Core0 returned from interrupt");
|
||||
|
||||
boot::Core1::start(false);
|
||||
|
||||
let core1_req = unsafe { &mut CORE1_REQ.0 };
|
||||
|
49
flake.lock
generated
49
flake.lock
generated
@ -1,41 +1,46 @@
|
||||
{
|
||||
"nodes": {
|
||||
"mozilla-overlay": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1650459918,
|
||||
"narHash": "sha256-sroCK+QJTmoXtcRkwZyKOP9iAYOPID2Bwdxn4GkG16w=",
|
||||
"owner": "mozilla",
|
||||
"repo": "nixpkgs-mozilla",
|
||||
"rev": "e1f7540fc0a8b989fb8cf701dc4fd7fc76bcf168",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "mozilla",
|
||||
"repo": "nixpkgs-mozilla",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1653920503,
|
||||
"narHash": "sha256-BBeCZwZImtjP3oYy4WogkQYy5OxNyfNciVSc1AfZgLQ=",
|
||||
"lastModified": 1736867362,
|
||||
"narHash": "sha256-i/UJ5I7HoqmFMwZEH6vAvBxOrjjOJNU739lnZnhUln8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a634c8f6c1fbf9b9730e01764999666f3436f10a",
|
||||
"rev": "9c6b49aeac36e2ed73a8c472f1546f6d9cf1addc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-22.05",
|
||||
"ref": "nixos-24.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"mozilla-overlay": "mozilla-overlay",
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-overlay": "rust-overlay"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1719454714,
|
||||
"narHash": "sha256-MojqG0lyUINkEk0b3kM2drsU5vyaF8DFZe/FAlZVOGs=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "d1c527659cf076ecc4b96a91c702d080b213801e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"ref": "snapshot/2024-08-01",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
246
flake.nix
246
flake.nix
@ -1,173 +1,53 @@
|
||||
{
|
||||
description = "Bare-metal Rust on Zynq-7000";
|
||||
|
||||
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-22.05;
|
||||
inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; };
|
||||
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-24.11;
|
||||
inputs.rust-overlay = {
|
||||
url = "github:oxalica/rust-overlay?ref=snapshot/2024-08-01";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, mozilla-overlay }:
|
||||
outputs = { self, nixpkgs, rust-overlay }:
|
||||
let
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) ]; };
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import rust-overlay) crosspkgs-overlay ]; };
|
||||
|
||||
rustManifest = pkgs.fetchurl {
|
||||
url = "https://static.rust-lang.org/dist/2021-01-29/channel-rust-nightly.toml";
|
||||
sha256 = "sha256-EZKgw89AH4vxaJpUHmIMzMW/80wAFQlfcxRoBD9nz0c=";
|
||||
rust = pkgs.rust-bin.nightly."2021-09-01".default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
targets = [ ];
|
||||
};
|
||||
rustTargets = [];
|
||||
rustChannelOfTargets = _channel: _date: targets:
|
||||
(pkgs.lib.rustLib.fromManifestFile rustManifest {
|
||||
inherit (pkgs) stdenv lib fetchurl patchelf;
|
||||
}).rust.override {
|
||||
inherit targets;
|
||||
extensions = ["rust-src"];
|
||||
rustPlatform = pkgs.makeRustPlatform {
|
||||
rustc = rust // {
|
||||
# https://github.com/oxalica/rust-overlay/commit/c48c2d76b68dd9ede0815fec53479375c61af857
|
||||
targetPlatforms = pkgs.lib.platforms.all;
|
||||
tier1TargetPlatforms = pkgs.lib.platforms.all;
|
||||
badTargetPlatforms = [ ];
|
||||
};
|
||||
rust = rustChannelOfTargets "nightly" null rustTargets;
|
||||
rustPlatform = pkgs.recurseIntoAttrs (pkgs.makeRustPlatform {
|
||||
rustc = rust;
|
||||
cargo = rust;
|
||||
};
|
||||
|
||||
crosspkgs-overlay = (self: super: {
|
||||
pkgsCross = super.pkgsCross // {
|
||||
zynq-baremetal = import super.path {
|
||||
system = "x86_64-linux";
|
||||
crossSystem = {
|
||||
config = "arm-none-eabihf";
|
||||
libc = "newlib";
|
||||
gcc.cpu = "cortex-a9";
|
||||
gcc.fpu = "vfpv3";
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
gnu-platform = "arm-none-eabi";
|
||||
|
||||
binutils-pkg = { zlib, extraConfigureFlags ? [] }: pkgs.stdenv.mkDerivation rec {
|
||||
basename = "binutils";
|
||||
version = "2.30";
|
||||
name = "${basename}-${gnu-platform}-${version}";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://ftp.gnu.org/gnu/binutils/binutils-${version}.tar.bz2";
|
||||
sha256 = "028cklfqaab24glva1ks2aqa1zxa6w6xmc8q34zs1sb7h22dxspg";
|
||||
};
|
||||
configureFlags = [
|
||||
"--enable-deterministic-archives"
|
||||
"--target=${gnu-platform}"
|
||||
"--with-cpu=cortex-a9"
|
||||
"--with-fpu=vfpv3"
|
||||
"--with-float=hard"
|
||||
"--with-mode=thumb"
|
||||
] ++ extraConfigureFlags;
|
||||
outputs = [ "out" "info" "man" ];
|
||||
depsBuildBuild = [ pkgs.buildPackages.stdenv.cc ];
|
||||
buildInputs = [ zlib ];
|
||||
enableParallelBuilding = true;
|
||||
meta = {
|
||||
description = "Tools for manipulating binaries (linker, assembler, etc.)";
|
||||
longDescription = ''
|
||||
The GNU Binutils are a collection of binary tools. The main
|
||||
ones are `ld' (the GNU linker) and `as' (the GNU assembler).
|
||||
They also include the BFD (Binary File Descriptor) library,
|
||||
`gprof', `nm', `strip', etc.
|
||||
'';
|
||||
homepage = http://www.gnu.org/software/binutils/;
|
||||
license = pkgs.lib.licenses.gpl3Plus;
|
||||
/* Give binutils a lower priority than gcc-wrapper to prevent a
|
||||
collision due to the ld/as wrappers/symlinks in the latter. */
|
||||
priority = "10";
|
||||
};
|
||||
};
|
||||
|
||||
gcc-pkg = { gmp, mpfr, libmpc, platform-binutils, extraConfigureFlags ? [] }: pkgs.stdenv.mkDerivation rec {
|
||||
basename = "gcc";
|
||||
version = "9.1.0";
|
||||
name = "${basename}-${gnu-platform}-${version}";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://ftp.gnu.org/gnu/gcc/gcc-${version}/gcc-${version}.tar.xz";
|
||||
sha256 = "1817nc2bqdc251k0lpc51cimna7v68xjrnvqzvc50q3ax4s6i9kr";
|
||||
};
|
||||
preConfigure = ''
|
||||
mkdir build
|
||||
cd build
|
||||
'';
|
||||
configureScript = "../configure";
|
||||
configureFlags = [
|
||||
"--target=${gnu-platform}"
|
||||
"--with-arch=armv7-a"
|
||||
"--with-tune=cortex-a9"
|
||||
"--with-fpu=vfpv3"
|
||||
"--with-float=hard"
|
||||
"--disable-libssp"
|
||||
"--enable-languages=c"
|
||||
"--with-as=${platform-binutils}/bin/${gnu-platform}-as"
|
||||
"--with-ld=${platform-binutils}/bin/${gnu-platform}-ld" ] ++ extraConfigureFlags;
|
||||
outputs = [ "out" "info" "man" ];
|
||||
hardeningDisable = [ "format" "pie" ];
|
||||
propagatedBuildInputs = [ gmp mpfr libmpc platform-binutils ];
|
||||
enableParallelBuilding = true;
|
||||
dontFixup = true;
|
||||
};
|
||||
|
||||
newlib-pkg = { platform-binutils, platform-gcc }: pkgs.stdenv.mkDerivation rec {
|
||||
pname = "newlib";
|
||||
version = "3.1.0";
|
||||
src = pkgs.fetchurl {
|
||||
url = "ftp://sourceware.org/pub/newlib/newlib-${version}.tar.gz";
|
||||
sha256 = "0ahh3n079zjp7d9wynggwrnrs27440aac04340chf1p9476a2kzv";
|
||||
};
|
||||
nativeBuildInputs = [ platform-binutils platform-gcc ];
|
||||
configureFlags = [
|
||||
"--target=${gnu-platform}"
|
||||
|
||||
"--with-cpu=cortex-a9"
|
||||
"--with-fpu=vfpv3"
|
||||
"--with-float=hard"
|
||||
"--with-mode=thumb"
|
||||
"--enable-interwork"
|
||||
"--disable-multilib"
|
||||
|
||||
"--disable-newlib-supplied-syscalls"
|
||||
"--with-gnu-ld"
|
||||
"--with-gnu-as"
|
||||
"--disable-newlib-io-float"
|
||||
"--disable-werror"
|
||||
];
|
||||
dontFixup = true;
|
||||
};
|
||||
gnutoolchain = rec {
|
||||
binutils-bootstrap = pkgs.callPackage binutils-pkg { };
|
||||
gcc-bootstrap = pkgs.callPackage gcc-pkg {
|
||||
platform-binutils = binutils-bootstrap;
|
||||
extraConfigureFlags = [ "--disable-libgcc" ];
|
||||
};
|
||||
newlib = pkgs.callPackage newlib-pkg {
|
||||
platform-binutils = binutils-bootstrap;
|
||||
platform-gcc = gcc-bootstrap;
|
||||
};
|
||||
binutils = pkgs.callPackage binutils-pkg {
|
||||
extraConfigureFlags = [ "--with-lib-path=${newlib}/arm-none-eabi/lib" ];
|
||||
};
|
||||
gcc = pkgs.callPackage gcc-pkg {
|
||||
platform-binutils = binutils;
|
||||
extraConfigureFlags = [ "--enable-newlib" "--with-headers=${newlib}/arm-none-eabi/include" ];
|
||||
};
|
||||
};
|
||||
|
||||
cargo-xbuild = rustPlatform.buildRustPackage rec {
|
||||
pname = "cargo-xbuild";
|
||||
version = "0.6.5";
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "rust-osdev";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "18djvygq9v8rmfchvi2hfj0i6fhn36m716vqndqnj56fiqviwxvf";
|
||||
};
|
||||
cargoSha256 = "13sj9j9kl6js75h9xq0yidxy63vixxm9q3f8jil6ymarml5wkhx8";
|
||||
|
||||
meta = with pkgs.lib; {
|
||||
description = "Automatically cross-compiles the sysroot crates core, compiler_builtins, and alloc";
|
||||
homepage = "https://github.com/rust-osdev/cargo-xbuild";
|
||||
license = with licenses; [ mit asl20 ];
|
||||
maintainers = with maintainers; [ johntitor xrelkd ];
|
||||
};
|
||||
};
|
||||
|
||||
mkbootimage = pkgs.stdenv.mkDerivation {
|
||||
pname = "mkbootimage";
|
||||
version = "2.2";
|
||||
version = "2.3dev";
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "antmicro";
|
||||
repo = "zynq-mkbootimage";
|
||||
rev = "4ee42d782a9ba65725ed165a4916853224a8edf7";
|
||||
sha256 = "1k1mbsngqadqihzjgvwvsrkvryxy5ladpxd9yh9iqn2s7fxqwqa9";
|
||||
rev = "872363ce32c249f8278cf107bc6d3bdeb38d849f";
|
||||
sha256 = "sha256-5FPyAhUWZDwHbqmp9J2ZXTmjaXPz+dzrJMolaNwADHs=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ pkgs.libelf pkgs.pcre ];
|
||||
@ -180,6 +60,7 @@
|
||||
mkdir -p $out/bin
|
||||
cp mkbootimage $out/bin
|
||||
'';
|
||||
hardeningDisable = [ "fortify" ];
|
||||
};
|
||||
|
||||
fsbl = { board ? "zc706" }: pkgs.stdenv.mkDerivation {
|
||||
@ -187,19 +68,20 @@
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "Xilinx";
|
||||
repo = "embeddedsw";
|
||||
rev = "65c849ed46c88c67457e1fc742744f96db968ff1";
|
||||
sha256 = "1rvl06ha40dzd6s9aa4sylmksh4xb9dqaxq462lffv1fdk342pda";
|
||||
rev = "xilinx_v2022.2";
|
||||
sha256 = "sha256-UDz9KK/Hw3qM1BAeKif30rE8Bi6C2uvuZlvyvtJCMfw=";
|
||||
};
|
||||
patches = [ ./fsbl.patch ];
|
||||
nativeBuildInputs = [
|
||||
pkgs.gnumake
|
||||
gnutoolchain.binutils
|
||||
gnutoolchain.gcc
|
||||
pkgs.pkgsCross.zynq-baremetal.buildPackages.binutils
|
||||
pkgs.pkgsCross.zynq-baremetal.buildPackages.gcc
|
||||
];
|
||||
patchPhase = ''
|
||||
patch -p1 -i ${./fsbl.patch}
|
||||
patchShebangs lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh
|
||||
echo 'SEARCH_DIR("${gnutoolchain.newlib}/arm-none-eabi/lib");' >> lib/sw_apps/zynq_fsbl/src/lscript.ld
|
||||
|
||||
for x in lib/sw_apps/zynq_fsbl/src/Makefile lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh lib/bsp/standalone/src/arm/cortexa9/gcc/Makefile; do
|
||||
substituteInPlace $x \
|
||||
--replace "arm-none-eabi-" "arm-none-eabihf-"
|
||||
done
|
||||
'';
|
||||
buildPhase = ''
|
||||
cd lib/sw_apps/zynq_fsbl/src
|
||||
@ -213,17 +95,27 @@
|
||||
dontFixup = true;
|
||||
};
|
||||
|
||||
cargo-xbuild = pkgs.cargo-xbuild.overrideAttrs(oa: {
|
||||
postPatch = "substituteInPlace src/sysroot.rs --replace 2021 2018";
|
||||
});
|
||||
|
||||
build-crate = name: crate: features: rustPlatform.buildRustPackage rec {
|
||||
name = "${crate}";
|
||||
|
||||
src = builtins.filterSource (path: type:
|
||||
baseNameOf path != "target"
|
||||
) ./.;
|
||||
cargoLock = { lockFile = ./Cargo.lock; };
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"core_io-0.1.0" = "sha256-0HINFWRiJx8pjMgUOL/CS336ih7SENSRh3Kah9LPRrw=";
|
||||
"fatfs-0.3.6" = "sha256-Nz9hCq/1YgSXF8ltJ5ZawV0Hc8WV44KNK0tJdVnNb4U=";
|
||||
};
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_9.clang-unwrapped ];
|
||||
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_13.clang-unwrapped ];
|
||||
buildPhase = ''
|
||||
export XARGO_RUST_SRC="${rustPlatform.rust.rustc}/lib/rustlib/src/rust/library"
|
||||
export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library"
|
||||
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
||||
pushd ${crate}
|
||||
cargo xbuild --release --frozen \
|
||||
@ -240,13 +132,14 @@
|
||||
|
||||
doCheck = false;
|
||||
dontFixup = true;
|
||||
auditable = false;
|
||||
};
|
||||
|
||||
targetCrates = target: {
|
||||
"${target}-experiments" = build-crate "${target}-experiments" "experiments" "target_${target}";
|
||||
"${target}-szl" = build-crate "${target}-szl" "szl" "target_${target}";
|
||||
};
|
||||
targets = ["zc706" "coraz7" "redpitaya" "kasli_soc"];
|
||||
targets = ["zc706" "coraz7" "redpitaya" "kasli_soc" "ebaz4205"];
|
||||
allTargetCrates = (builtins.foldl' (results: target:
|
||||
results // targetCrates target
|
||||
) {} targets);
|
||||
@ -265,21 +158,20 @@
|
||||
|
||||
hydraJobs = packages.x86_64-linux;
|
||||
|
||||
inherit rustPlatform;
|
||||
inherit rust rustPlatform;
|
||||
|
||||
devShell.x86_64-linux = pkgs.mkShell {
|
||||
name = "zynq-rs-dev-shell";
|
||||
buildInputs = with pkgs; [
|
||||
rustPlatform.rust.rustc
|
||||
rustPlatform.rust.cargo
|
||||
cacert
|
||||
buildInputs = [
|
||||
rust
|
||||
cargo-xbuild
|
||||
mkbootimage
|
||||
|
||||
openocd gdb
|
||||
openssh rsync
|
||||
llvmPackages_9.clang-unwrapped
|
||||
(python3.withPackages(ps: [ ps.pyftdi ]))
|
||||
mkbootimage ];
|
||||
};
|
||||
pkgs.openocd pkgs.gdb
|
||||
pkgs.openssh pkgs.rsync
|
||||
pkgs.llvmPackages_13.clang-unwrapped
|
||||
(pkgs.python3.withPackages(ps: [ ps.pyftdi ]))
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
31
fsbl.patch
31
fsbl.patch
@ -1,31 +0,0 @@
|
||||
diff --git a/lib/sw_apps/zynq_fsbl/src/Makefile b/lib/sw_apps/zynq_fsbl/src/Makefile
|
||||
index 0e3ccdf1c5..a5b02f386e 100644
|
||||
--- a/lib/sw_apps/zynq_fsbl/src/Makefile
|
||||
+++ b/lib/sw_apps/zynq_fsbl/src/Makefile
|
||||
@@ -71,11 +71,14 @@ endif
|
||||
all: $(EXEC)
|
||||
|
||||
$(EXEC): $(LIBS) $(OBJS) $(INCLUDES)
|
||||
- cp $(BSP_DIR)/$(BOARD)/ps7_init.* .
|
||||
$(LINKER) $(LD1FLAGS) -o $@ $(OBJS) $(LDFLAGS)
|
||||
rm -rf $(OBJS)
|
||||
-
|
||||
-
|
||||
+
|
||||
+.PHONY: ps7_init
|
||||
+
|
||||
+ps7_init:
|
||||
+ cp $(BSP_DIR)/$(BOARD)/ps7_init.* .
|
||||
+
|
||||
$(LIBS):
|
||||
echo "Copying BSP files"
|
||||
$(BSP_DIR)/copy_bsp.sh $(BOARD) $(CC)
|
||||
@@ -86,7 +89,7 @@ $(LIBS):
|
||||
make -C $(BSP_DIR) -k all "CC=armcc" "AR=armar" "C_FLAGS= -O2 -c" "EC_FLAGS=--debug --wchar32"; \
|
||||
fi;
|
||||
|
||||
-%.o:%.c
|
||||
+%.o:%.c ps7_init
|
||||
$(CC) $(CC_FLAGS) $(CFLAGS) $(ECFLAGS) -c $< -o $@ $(INCLUDEPATH)
|
||||
|
||||
%.o:%.S
|
@ -8,6 +8,7 @@ edition = "2018"
|
||||
[features]
|
||||
target_zc706 = []
|
||||
target_coraz7 = []
|
||||
target_ebaz4205 = []
|
||||
target_redpitaya = []
|
||||
target_kasli_soc = []
|
||||
ipv6 = [ "smoltcp/proto-ipv6" ]
|
||||
|
@ -1,3 +1,5 @@
|
||||
use core::unimplemented;
|
||||
|
||||
use libregister::{RegisterR, RegisterRW};
|
||||
use super::slcr;
|
||||
pub use slcr::ArmPllSource;
|
||||
@ -101,6 +103,8 @@ impl Clocks {
|
||||
self.ddr,
|
||||
slcr::PllSource::IoPll =>
|
||||
self.io,
|
||||
slcr::PllSource::Emio =>
|
||||
unimplemented!(),
|
||||
};
|
||||
pll / u32::from(uart_clk_ctrl.divisor())
|
||||
}
|
||||
@ -115,6 +119,8 @@ impl Clocks {
|
||||
self.ddr,
|
||||
slcr::PllSource::IoPll =>
|
||||
self.io,
|
||||
slcr::PllSource::Emio =>
|
||||
unimplemented!(),
|
||||
};
|
||||
pll / u32::from(sdio_clk_ctrl.divisor())
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ use super::slcr;
|
||||
pub const PS_CLK: u32 = 33_333_333;
|
||||
#[cfg(feature = "target_coraz7")]
|
||||
pub const PS_CLK: u32 = 50_000_000;
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
pub const PS_CLK: u32 = 33_333_333;
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
pub const PS_CLK: u32 = 33_333_333;
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
|
@ -16,6 +16,10 @@ const DDR_FREQ: u32 = 666_666_666;
|
||||
/// Micron MT41K256M16HA-125: 800 MHz DDR3L, max supported 533 MHz
|
||||
const DDR_FREQ: u32 = 525_000_000;
|
||||
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
/// EtronTech Memory EM6GD16EWKG-12H: 800 MHz DDR3 at 533 MHz
|
||||
const DDR_FREQ: u32 = 533_333_333;
|
||||
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
/// Alliance Memory AS4C256M16D3B: 800 MHz DDR3 at 533 MHz
|
||||
const DDR_FREQ: u32 = 533_333_333;
|
||||
@ -147,22 +151,23 @@ impl DdrRam {
|
||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||
#[cfg(feature = "target_zc706")]
|
||||
let data1_config = data0_config.clone();
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
let data0_config = slcr::DdriobConfig::zeroed()
|
||||
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
||||
.term_en(true)
|
||||
.dci_type(slcr::DdriobDciType::Termination)
|
||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||
let data1_config = slcr::DdriobConfig::zeroed()
|
||||
.pullup_en(true);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
let data0_config = slcr::DdriobConfig::zeroed()
|
||||
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
||||
.term_en(true)
|
||||
.dci_type(slcr::DdriobDciType::Termination)
|
||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
let data1_config = slcr::DdriobConfig::zeroed()
|
||||
.pullup_en(true);
|
||||
slcr.ddriob_data0.write(data0_config);
|
||||
@ -176,22 +181,23 @@ impl DdrRam {
|
||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||
#[cfg(feature = "target_zc706")]
|
||||
let diff1_config = diff0_config.clone();
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
let diff0_config = slcr::DdriobConfig::zeroed()
|
||||
.inp_type(slcr::DdriobInputType::Differential)
|
||||
.term_en(true)
|
||||
.dci_type(slcr::DdriobDciType::Termination)
|
||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||
let diff1_config = slcr::DdriobConfig::zeroed()
|
||||
.pullup_en(true);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
let diff0_config = slcr::DdriobConfig::zeroed()
|
||||
.inp_type(slcr::DdriobInputType::Differential)
|
||||
.term_en(true)
|
||||
.dci_type(slcr::DdriobDciType::Termination)
|
||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
let diff1_config = slcr::DdriobConfig::zeroed()
|
||||
.pullup_en(true);
|
||||
slcr.ddriob_diff0.write(diff0_config);
|
||||
@ -210,7 +216,12 @@ impl DdrRam {
|
||||
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
||||
.vref_int_en(false)
|
||||
.vref_ext_en_lower(true)
|
||||
@ -224,13 +235,6 @@ impl DdrRam {
|
||||
.vref_ext_en_lower(false)
|
||||
.vref_ext_en_upper(false)
|
||||
);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
||||
.vref_int_en(false)
|
||||
.vref_ext_en_lower(true)
|
||||
.vref_ext_en_upper(false)
|
||||
.refio_en(true)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -242,6 +246,13 @@ impl DdrRam {
|
||||
.t_rfc_min(0x9e)
|
||||
.post_selfref_gap_x32(0x10)
|
||||
);
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
self.regs.dram_param0.write(
|
||||
regs::DramParam0::zeroed()
|
||||
.t_rc(0x1a)
|
||||
.t_rfc_min(0x56)
|
||||
.post_selfref_gap_x32(0x10)
|
||||
);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
self.regs.dram_param0.write(
|
||||
regs::DramParam0::zeroed()
|
||||
@ -256,6 +267,12 @@ impl DdrRam {
|
||||
.t_rfc_min(0x56)
|
||||
.post_selfref_gap_x32(0x10)
|
||||
);
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
self.regs.dram_param1.modify(
|
||||
|_, w| w
|
||||
.t_faw(0x16)
|
||||
.t_ras_min(0x13)
|
||||
);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
self.regs.dram_param1.modify(
|
||||
|_, w| w
|
||||
@ -277,6 +294,11 @@ impl DdrRam {
|
||||
.rd2pre(0x4)
|
||||
.t_rcd(0x7)
|
||||
);
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
self.regs.dram_param3.modify(
|
||||
|_, w| w
|
||||
.t_rp(7)
|
||||
);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
self.regs.dram_param3.modify(
|
||||
|_, w| w
|
||||
@ -298,19 +320,21 @@ impl DdrRam {
|
||||
.emr(0x4)
|
||||
);
|
||||
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
self.regs.phy_configs[2].modify(
|
||||
|_, w| w.data_slice_in_use(false)
|
||||
);
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||
self.regs.phy_configs[3].modify(
|
||||
|_, w| w.data_slice_in_use(false)
|
||||
);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
self.regs.phy_configs[2].modify(
|
||||
|_, w| w.data_slice_in_use(false)
|
||||
);
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
self.regs.phy_configs[3].modify(
|
||||
|_, w| w.data_slice_in_use(false)
|
||||
);
|
||||
@ -354,7 +378,11 @@ impl DdrRam {
|
||||
.gatelvl_init_ratio(0xee)
|
||||
);
|
||||
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_kasli_soc"),
|
||||
)]
|
||||
self.regs.reg_64.modify(
|
||||
|_, w| w
|
||||
.phy_ctrl_slave_ratio(0x100)
|
||||
@ -390,9 +418,12 @@ impl DdrRam {
|
||||
fn reset_ddrc<F: FnMut(&mut Self)>(&mut self, mut f: F) {
|
||||
#[cfg(feature = "target_zc706")]
|
||||
let width = regs::DataBusWidth::Width32bit;
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||
let width = regs::DataBusWidth::Width16bit;
|
||||
#[cfg(feature = "target_redpitaya")]
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
let width = regs::DataBusWidth::Width16bit;
|
||||
self.regs.ddrc_ctrl.modify(|_, w| w
|
||||
.soft_rstb(false)
|
||||
@ -410,6 +441,7 @@ impl DdrRam {
|
||||
}
|
||||
#[cfg(any(
|
||||
feature = "target_coraz7",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_redpitaya",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
@ -450,6 +482,8 @@ impl DdrRam {
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
let megabytes = 512;
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
let megabytes = 256;
|
||||
|
||||
megabytes * 1024 * 1024
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ impl ErrorLED {
|
||||
.pullup(true)
|
||||
.disable_rcvr(true)
|
||||
);
|
||||
// reset
|
||||
slcr.gpio_rst_ctrl.reset_gpio();
|
||||
});
|
||||
|
||||
Self::error_led_common(0xFFFF - 0x0080)
|
||||
|
@ -13,6 +13,9 @@ mod regs;
|
||||
pub mod rx;
|
||||
pub mod tx;
|
||||
|
||||
use super::time::Milliseconds;
|
||||
use embedded_hal::timer::CountDown;
|
||||
|
||||
/// Size of all the buffers
|
||||
pub const MTU: usize = 1536;
|
||||
/// Maximum MDC clock
|
||||
@ -62,17 +65,31 @@ impl Gem for Gem0 {
|
||||
slcr.gem0_clk_ctrl.write(
|
||||
// 0x0050_0801: 8, 5: 100 Mb/s
|
||||
// ...: 8, 1: 1000 Mb/s
|
||||
#[cfg(not(feature = "target_ebaz4205"))]
|
||||
slcr::GemClkCtrl::zeroed()
|
||||
.clkact(true)
|
||||
.srcsel(slcr::PllSource::IoPll)
|
||||
.divisor(divisor0 as u8)
|
||||
.divisor1(divisor1 as u8),
|
||||
// ebaz4205 -- EMIO
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
slcr::GemClkCtrl::zeroed()
|
||||
.clkact(true)
|
||||
.srcsel(slcr::PllSource::Emio)
|
||||
.divisor(divisor0 as u8)
|
||||
.divisor1(divisor1 as u8)
|
||||
);
|
||||
// Enable gem0 recv clock
|
||||
slcr.gem0_rclk_ctrl.write(
|
||||
// 0x0000_0801
|
||||
#[cfg(not(feature = "target_ebaz4205"))]
|
||||
slcr::RclkCtrl::zeroed()
|
||||
.clkact(true),
|
||||
// ebaz4205 -- EMIO
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
slcr::RclkCtrl::zeroed()
|
||||
.clkact(true)
|
||||
.srcsel(true)
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -151,6 +168,7 @@ pub struct Eth<GEM: Gem, RX, TX> {
|
||||
|
||||
impl Eth<Gem0, (), ()> {
|
||||
pub fn eth0(macaddr: [u8; 6]) -> Self {
|
||||
#[cfg(not(feature = "target_ebaz4205"))]
|
||||
slcr::RegisterBlock::unlocked(|slcr| {
|
||||
// Manual example: 0x0000_1280
|
||||
// MDIO
|
||||
@ -300,11 +318,18 @@ impl<GEM: Gem> Eth<GEM, (), ()> {
|
||||
fn gem_common(macaddr: [u8; 6]) -> Self {
|
||||
GEM::setup_clock(TX_1000);
|
||||
|
||||
#[cfg(feature="target_kasli_soc")]
|
||||
{
|
||||
let mut eth_reset_pin = PhyRst::rst_pin();
|
||||
eth_reset_pin.reset();
|
||||
}
|
||||
|
||||
let mut inner = EthInner {
|
||||
gem: PhantomData,
|
||||
link: None,
|
||||
};
|
||||
inner.init();
|
||||
|
||||
inner.configure(macaddr);
|
||||
|
||||
let phy = Phy::find(&mut inner).expect("phy");
|
||||
@ -482,6 +507,69 @@ impl<'a, GEM: Gem> smoltcp::phy::Device<'a> for &mut Eth<GEM, rx::DescList, tx::
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PhyRst {
|
||||
regs: regs::GpioRegisterBlock,
|
||||
count_down: super::timer::global::CountDown<Milliseconds>,
|
||||
}
|
||||
|
||||
impl PhyRst {
|
||||
pub fn rst_pin() -> Self {
|
||||
slcr::RegisterBlock::unlocked(|slcr| {
|
||||
// Hardware Reset for PHY
|
||||
slcr.mio_pin_47.write(
|
||||
slcr::MioPin47::zeroed()
|
||||
.l3_sel(0b000)
|
||||
.io_type(slcr::IoBufferType::Lvcmos18)
|
||||
.pullup(true)
|
||||
.disable_rcvr(true)
|
||||
);
|
||||
});
|
||||
Self::eth_reset_common(0xFFFF - 0x8000)
|
||||
}
|
||||
|
||||
fn delay_ms(&mut self, ms: u64) {
|
||||
self.count_down.start(Milliseconds(ms));
|
||||
nb::block!(self.count_down.wait()).unwrap();
|
||||
}
|
||||
|
||||
fn eth_reset_common(gpio_output_mask: u16) -> Self {
|
||||
let self_ = Self {
|
||||
regs: regs::GpioRegisterBlock::regs(),
|
||||
count_down: unsafe { super::timer::GlobalTimer::get() }.countdown(),
|
||||
};
|
||||
|
||||
// Setup GPIO output mask
|
||||
self_.regs.gpio_output_mask.modify(|_, w| {
|
||||
w.mask(gpio_output_mask)
|
||||
});
|
||||
|
||||
self_.regs.gpio_direction.modify(|_, w| {
|
||||
w.phy_rst(true)
|
||||
});
|
||||
|
||||
self_
|
||||
}
|
||||
|
||||
fn oe(&mut self, oe: bool) {
|
||||
self.regs.gpio_output_enable.modify(|_, w| {
|
||||
w.phy_rst(oe)
|
||||
})
|
||||
}
|
||||
|
||||
fn toggle(&mut self, o: bool) {
|
||||
self.regs.gpio_output_mask.modify(|_, w| {
|
||||
w.phy_rst(o)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.toggle(false); // drive phy_rst (active LOW) pin low
|
||||
self.oe(true); // enable pin's output
|
||||
self.delay_ms(10);
|
||||
self.toggle(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct EthInner<GEM: Gem> {
|
||||
gem: PhantomData<GEM>,
|
||||
|
@ -83,6 +83,7 @@ pub struct Phy {
|
||||
const OUI_MARVELL: u32 = 0x005043;
|
||||
const OUI_REALTEK: u32 = 0x000732;
|
||||
const OUI_LANTIQ : u32 = 0x355969;
|
||||
const OUI_ICPLUS : u32 = 0x0090c3;
|
||||
|
||||
//only change pages on Kasli-SoC's Marvel 88E11xx
|
||||
#[cfg(feature="target_kasli_soc")]
|
||||
@ -117,6 +118,12 @@ impl Phy {
|
||||
model: 0,
|
||||
..
|
||||
}) => true,
|
||||
Some(PhyIdentifier {
|
||||
oui: OUI_ICPLUS,
|
||||
// IP101G-DS-R01
|
||||
model: 5,
|
||||
rev: 4,
|
||||
}) => true,
|
||||
_ => false,
|
||||
}
|
||||
}).map(|addr| Phy { addr })
|
||||
|
@ -55,12 +55,22 @@ impl Status {
|
||||
pub fn get_link(&self) -> Option<Link> {
|
||||
if ! self.link_status() {
|
||||
None
|
||||
} else if self.cap_10base_t_half() {
|
||||
} else if self.cap_100base_tx_full() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S10,
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Full,
|
||||
})
|
||||
} else if self.cap_100base_tx_half() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_10base_t_full() {
|
||||
} else if self.cap_100base_t4() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_10base_t2_full() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S10,
|
||||
duplex: LinkDuplex::Full,
|
||||
@ -70,26 +80,16 @@ impl Status {
|
||||
speed: LinkSpeed::S10,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_10base_t2_full() {
|
||||
} else if self.cap_10base_t_full() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S10,
|
||||
duplex: LinkDuplex::Full,
|
||||
})
|
||||
} else if self.cap_100base_t4() {
|
||||
} else if self.cap_10base_t_half() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
speed: LinkSpeed::S10,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_100base_tx_half() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_100base_tx_full() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Full,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -110,6 +110,49 @@ pub struct RegisterBlock {
|
||||
pub design_cfg5: RO<u32>,
|
||||
}
|
||||
|
||||
pub struct GpioRegisterBlock {
|
||||
pub gpio_output_mask: &'static mut OutputMask,
|
||||
pub gpio_direction: &'static mut Direction,
|
||||
pub gpio_output_enable: &'static mut OutputEnable,
|
||||
}
|
||||
|
||||
impl GpioRegisterBlock {
|
||||
pub fn regs() -> Self {
|
||||
Self {
|
||||
gpio_output_mask: OutputMask::new(),
|
||||
gpio_direction: Direction::new(),
|
||||
gpio_output_enable: OutputEnable::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register!(gpio_output_mask,
|
||||
/// MASK_DATA_1_SW:
|
||||
/// Maskable output data for MIO[47:32]
|
||||
OutputMask, RW, u32);
|
||||
register_at!(OutputMask, 0xE000A008, new);
|
||||
register_bit!(gpio_output_mask,
|
||||
/// Output for PHY_RST (MIO[47])
|
||||
phy_rst, 15);
|
||||
register_bits!(gpio_output_mask,
|
||||
mask, u16, 16, 31);
|
||||
register!(gpio_direction,
|
||||
/// DIRM_1:
|
||||
/// Direction mode for MIO[53:32]; 0/1 = in/out
|
||||
Direction, RW, u32);
|
||||
register_at!(Direction, 0xE000A244, new);
|
||||
register_bit!(gpio_direction,
|
||||
/// Direction for PHY_RST
|
||||
phy_rst, 15);
|
||||
register!(gpio_output_enable,
|
||||
/// OEN_1:
|
||||
/// Output enable for MIO[53:32]
|
||||
OutputEnable, RW, u32);
|
||||
register_at!(OutputEnable, 0xE000A248, new);
|
||||
register_bit!(gpio_output_enable,
|
||||
/// Output enable for PHY_RST
|
||||
phy_rst, 15);
|
||||
|
||||
register_at!(RegisterBlock, 0xE000B000, gem0);
|
||||
register_at!(RegisterBlock, 0xE000C000, gem1);
|
||||
|
||||
|
@ -115,7 +115,7 @@ impl InterruptController {
|
||||
let m = (id.0 >> 2) as usize;
|
||||
let n = (8 * (id.0 & 3)) as usize;
|
||||
unsafe {
|
||||
self.mpcore.icdiptr[m].modify(|mut icdiptr| *icdiptr.set_bits(n..=n+1, target_cpu as u32 + 1));
|
||||
self.mpcore.icdiptr[m].modify(|mut icdiptr| *icdiptr.set_bits(n..=n+1, target_cpu as u32));
|
||||
}
|
||||
|
||||
// sensitivity
|
||||
|
@ -4,6 +4,7 @@ use embedded_hal::timer::CountDown;
|
||||
|
||||
pub struct EEPROM<'a> {
|
||||
i2c: &'a mut I2c,
|
||||
#[cfg(not(feature = "target_ebaz4205"))]
|
||||
port: u8,
|
||||
address: u8,
|
||||
page_size: u8,
|
||||
@ -46,6 +47,11 @@ impl<'a> EEPROM<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
fn select(&mut self) -> Result<(), &'static str> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Random read
|
||||
pub fn read<'r>(&mut self, addr: u8, buf: &'r mut [u8]) -> Result<(), &'static str> {
|
||||
self.select()?;
|
||||
|
@ -2,10 +2,13 @@
|
||||
|
||||
mod regs;
|
||||
pub mod eeprom;
|
||||
#[cfg(not(feature = "target_ebaz4205"))]
|
||||
use super::slcr;
|
||||
use super::time::Microseconds;
|
||||
use embedded_hal::timer::CountDown;
|
||||
use libregister::{RegisterR, RegisterRW, RegisterW};
|
||||
use libregister::{RegisterR, RegisterRW};
|
||||
#[cfg(not(feature = "target_ebaz4205"))]
|
||||
use libregister::RegisterW;
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
use log::info;
|
||||
|
||||
@ -22,9 +25,10 @@ pub struct I2c {
|
||||
}
|
||||
|
||||
impl I2c {
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
pub fn i2c0() -> Self {
|
||||
// Route I2C 0 SCL / SDA Signals to MIO Pins 50 / 51
|
||||
#[cfg(not(feature = "target_ebaz4205"))]
|
||||
slcr::RegisterBlock::unlocked(|slcr| {
|
||||
// SCL
|
||||
slcr.mio_pin_50.write(
|
||||
@ -53,8 +57,6 @@ impl I2c {
|
||||
.pullup(false)
|
||||
.disable_rcvr(true)
|
||||
);
|
||||
// Reset
|
||||
slcr.gpio_rst_ctrl.reset_gpio();
|
||||
});
|
||||
|
||||
Self::i2c_common(0xFFFF - 0x000C, 0xFFFF - 0x0002)
|
||||
|
@ -21,6 +21,7 @@ use libregister::{
|
||||
// Current compatibility:
|
||||
// zc706: GPIO 50, 51 == SCL, SDA
|
||||
// kasli_soc: GPIO 50, 51 == SCL, SDA; GPIO 33 == I2C_SW_RESET
|
||||
// ebaz4205: GPIO (EMIO)
|
||||
|
||||
pub struct RegisterBlock {
|
||||
pub gpio_output_mask: &'static mut GPIOOutputMask,
|
||||
@ -48,17 +49,17 @@ register!(gpio_output_mask,
|
||||
/// MASK_DATA_1_MSW:
|
||||
/// Maskable output data for MIO[53:48]
|
||||
GPIOOutputMask, RW, u32);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_at!(GPIOOutputMask, 0xE000A00C, new);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_bit!(gpio_output_mask,
|
||||
/// Output for SCL
|
||||
scl_o, 2);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_bit!(gpio_output_mask,
|
||||
/// Output for SDA
|
||||
sda_o, 3);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_bits!(gpio_output_mask,
|
||||
/// Mask for keeping bits except SCL and SDA unchanged
|
||||
mask, u16, 16, 31);
|
||||
@ -82,13 +83,13 @@ register!(gpio_input,
|
||||
/// DATA_1_RO:
|
||||
/// Input data for MIO[53:32]
|
||||
GPIOInput, RO, u32);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_at!(GPIOInput, 0xE000A064, new);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_bit!(gpio_input,
|
||||
/// Input for SCL
|
||||
scl, 18);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_bit!(gpio_input,
|
||||
/// Input for SDA
|
||||
sda, 19);
|
||||
@ -98,13 +99,13 @@ register!(gpio_direction,
|
||||
/// DIRM_1:
|
||||
/// Direction mode for MIO[53:32]; 0/1 = in/out
|
||||
GPIODirection, RW, u32);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_at!(GPIODirection, 0xE000A244, new);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_bit!(gpio_direction,
|
||||
/// Direction for SCL
|
||||
scl, 18);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_bit!(gpio_direction,
|
||||
/// Direction for SDA
|
||||
sda, 19);
|
||||
@ -117,13 +118,13 @@ register!(gpio_output_enable,
|
||||
/// OEN_1:
|
||||
/// Output enable for MIO[53:32]
|
||||
GPIOOutputEnable, RW, u32);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_at!(GPIOOutputEnable, 0xE000A248, new);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_bit!(gpio_output_enable,
|
||||
/// Output enable for SCL
|
||||
scl, 18);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
register_bit!(gpio_output_enable,
|
||||
/// Output enable for SDA
|
||||
sda, 19);
|
||||
|
@ -19,7 +19,7 @@ pub mod gic;
|
||||
pub mod time;
|
||||
pub mod timer;
|
||||
pub mod sdio;
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||
pub mod i2c;
|
||||
pub mod logger;
|
||||
pub mod ps7_init;
|
||||
|
@ -116,8 +116,8 @@ impl Sdio {
|
||||
.speed(true),
|
||||
);
|
||||
}
|
||||
// redpitaya card detect pin
|
||||
#[cfg(any(feature = "target_redpitaya", feature = "target_kasli_soc"))]
|
||||
// kasli_soc and redpitaya card detect pin
|
||||
#[cfg(any(feature = "target_kasli_soc", feature = "target_redpitaya"))]
|
||||
{
|
||||
unsafe {
|
||||
slcr.sd0_wp_cd_sel.write(46 << 16);
|
||||
@ -128,6 +128,20 @@ impl Sdio {
|
||||
.speed(true),
|
||||
);
|
||||
}
|
||||
// ebaz4205 card detect pin
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
{
|
||||
unsafe {
|
||||
slcr.sd0_wp_cd_sel.write(34 << 16);
|
||||
}
|
||||
slcr.mio_pin_34.write(
|
||||
slcr::MioPin34::zeroed()
|
||||
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||
.pullup(true)
|
||||
.speed(true),
|
||||
);
|
||||
}
|
||||
|
||||
slcr.sdio_rst_ctrl.reset_sdio0();
|
||||
slcr.aper_clk_ctrl.enable_sdio0();
|
||||
slcr.sdio_clk_ctrl.enable_sdio0();
|
||||
|
@ -9,9 +9,11 @@ use libregister::{
|
||||
|
||||
#[repr(u8)]
|
||||
pub enum PllSource {
|
||||
IoPll = 0b00,
|
||||
ArmPll = 0b10,
|
||||
DdrPll = 0b11,
|
||||
IoPll = 0b000,
|
||||
ArmPll = 0b010,
|
||||
DdrPll = 0b011,
|
||||
// Ethernet controller 0 EMIO clock
|
||||
Emio = 0b100,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
|
@ -47,7 +47,11 @@ impl DerefMut for LazyUart {
|
||||
LazyUart::Uninitialized => {
|
||||
#[cfg(any(feature = "target_coraz7", feature = "target_redpitaya"))]
|
||||
let uart = Uart::uart0(UART_RATE);
|
||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||
#[cfg(any(
|
||||
feature = "target_zc706",
|
||||
feature = "target_ebaz4205",
|
||||
feature = "target_kasli_soc",
|
||||
))]
|
||||
let uart = Uart::uart1(UART_RATE);
|
||||
*self = LazyUart::Initialized(uart);
|
||||
self
|
||||
|
@ -5,8 +5,8 @@ use libregister::*;
|
||||
use super::slcr;
|
||||
use super::clocks::Clocks;
|
||||
|
||||
pub mod regs;
|
||||
pub mod baud_rate_gen;
|
||||
mod regs;
|
||||
mod baud_rate_gen;
|
||||
|
||||
pub struct Uart {
|
||||
regs: &'static mut regs::RegisterBlock,
|
||||
@ -79,6 +79,39 @@ impl Uart {
|
||||
self_
|
||||
}
|
||||
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
pub fn uart1(baudrate: u32) -> Self {
|
||||
slcr::RegisterBlock::unlocked(|slcr| {
|
||||
// Route UART 1 RxD/TxD Signals to MIO Pins
|
||||
// TX pin
|
||||
slcr.mio_pin_24.write(
|
||||
slcr::MioPin24::zeroed()
|
||||
.l3_sel(0b111)
|
||||
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||
.pullup(true)
|
||||
);
|
||||
// RX pin
|
||||
slcr.mio_pin_25.write(
|
||||
slcr::MioPin25::zeroed()
|
||||
.tri_enable(true)
|
||||
.l3_sel(0b111)
|
||||
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||
.pullup(true)
|
||||
);
|
||||
});
|
||||
|
||||
slcr::RegisterBlock::unlocked(|slcr| {
|
||||
slcr.uart_rst_ctrl.reset_uart1();
|
||||
slcr.aper_clk_ctrl.enable_uart1();
|
||||
slcr.uart_clk_ctrl.enable_uart1();
|
||||
});
|
||||
let mut self_ = Uart {
|
||||
regs: regs::RegisterBlock::uart1(),
|
||||
};
|
||||
self_.configure(baudrate);
|
||||
self_
|
||||
}
|
||||
|
||||
pub fn write_byte(&mut self, value: u8) {
|
||||
while self.tx_fifo_full() {}
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
[package]
|
||||
name = "libboard_zynq_us"
|
||||
description = "Drivers for peripherals in the Zynq UltraScale+ PS"
|
||||
version = "0.0.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
target_zcu111 = []
|
||||
ipv6 = [ "smoltcp/proto-ipv6" ]
|
||||
default = [ "target_zcu111" ]
|
||||
|
||||
[dependencies]
|
||||
volatile-register = "0.2"
|
||||
bit_field = "0.10"
|
||||
embedded-hal = "0.2"
|
||||
nb = "0.1"
|
||||
void = { version = "1", default-features = false }
|
||||
log = "0.4"
|
||||
libregister = { path = "../libregister" }
|
||||
# libcortex_a9 = { path = "../libcortex_a9" }
|
||||
libasync = { path = "../libasync" }
|
||||
libboard_zynq = { path = "../libboard_zynq" }
|
||||
|
||||
[dependencies.smoltcp]
|
||||
version = "0.7"
|
||||
features = ["ethernet", "proto-ipv4", "socket-tcp"]
|
||||
default-features = false
|
@ -1,89 +0,0 @@
|
||||
use libregister::{RegisterR, RegisterRW};
|
||||
use super::slcr::{crf_apb, crl_apb, common::SlcrRegisterBlock};
|
||||
pub use super::slcr::crf_apb::ApuClkSource;
|
||||
|
||||
pub mod source;
|
||||
use source::*;
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Clocks {
|
||||
/// ARM PLL: Recommended clock source for the APUs and the FPD interconnect
|
||||
pub apu: u32,
|
||||
/// DDR PLL: Recommended clock for the DDR DRAM controller and AXI_HP interfaces
|
||||
pub ddr: u32,
|
||||
/// Video PLL: Recommended clock for display port
|
||||
pub video: u32,
|
||||
/// I/O PLL: Recommended clock for I/O peripherals
|
||||
pub io: u32,
|
||||
/// RPU PLL: Recommended clock for RPUs and LPD interconnect
|
||||
pub rpu: u32,
|
||||
}
|
||||
|
||||
impl Clocks {
|
||||
pub fn get() -> Self {
|
||||
let fpd_regs = crf_apb::RegisterBlock::slcr();
|
||||
let lpd_regs = crl_apb::RegisterBlock::slcr();
|
||||
Clocks {
|
||||
apu: ApuPll::freq(&mut fpd_regs.apu_pll_ctrl),
|
||||
ddr: DdrPll::freq(&mut fpd_regs.ddr_pll_ctrl),
|
||||
video: VideoPll::freq(&mut fpd_regs.video_pll_ctrl),
|
||||
io: IoPll::freq(&mut lpd_regs.io_pll_ctrl),
|
||||
rpu: RpuPll::freq(&mut lpd_regs.rpu_pll_ctrl),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_cpu_freq(target_freq: u32) {
|
||||
let fpd_regs = crf_apb::RegisterBlock::slcr();
|
||||
let apu_pll = ApuPll::freq(&mut fpd_regs.apu_pll_ctrl);
|
||||
let mut div = 1u8;
|
||||
while div < 63 && apu_pll / u32::from(div) > target_freq {
|
||||
div += 1;
|
||||
}
|
||||
|
||||
crf_apb::RegisterBlock::unlocked(|slcr| {
|
||||
slcr.apu_clk_ctrl.modify(|_, w| w
|
||||
.srcsel(ApuClkSource::ApuPll)
|
||||
.divisor0(div)
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn uart0_ref_clk(&self) -> u32 {
|
||||
let lpd_regs = crl_apb::RegisterBlock::slcr();
|
||||
self.uart_ref_clk(&mut lpd_regs.uart0_clk_ctrl)
|
||||
}
|
||||
|
||||
pub fn uart1_ref_clk(&self) -> u32 {
|
||||
let lpd_regs = crl_apb::RegisterBlock::slcr();
|
||||
self.uart_ref_clk(&mut lpd_regs.uart1_clk_ctrl)
|
||||
}
|
||||
|
||||
fn uart_ref_clk(&self, uart_regs: &mut crl_apb::UartClkCtrl) -> u32 {
|
||||
let uart_clk_ctrl = uart_regs.read();
|
||||
let pll = match uart_clk_ctrl.srcsel() {
|
||||
crl_apb::IoClkSource::IoPll => self.io,
|
||||
crl_apb::IoClkSource::RpuPll => self.rpu,
|
||||
crl_apb::IoClkSource::DdrPllToLpd => {
|
||||
let fpd_regs = crf_apb::RegisterBlock::slcr();
|
||||
let divisor = u32::from(fpd_regs.ddr_pll_to_lpd_ctrl.read().divisor0());
|
||||
self.ddr / divisor
|
||||
}
|
||||
};
|
||||
pll / (u32::from(uart_clk_ctrl.divisor0()) * u32::from(uart_clk_ctrl.divisor1()))
|
||||
}
|
||||
|
||||
// pub fn sdio_ref_clk(&self) -> u32 {
|
||||
// let regs = slcr::RegisterBlock::slcr();
|
||||
// let sdio_clk_ctrl = regs.sdio_clk_ctrl.read();
|
||||
// let pll = match sdio_clk_ctrl.srcsel() {
|
||||
// slcr::PllSource::ArmPll =>
|
||||
// self.arm,
|
||||
// slcr::PllSource::DdrPll =>
|
||||
// self.ddr,
|
||||
// slcr::PllSource::IoPll =>
|
||||
// self.io,
|
||||
// };
|
||||
// pll / u32::from(sdio_clk_ctrl.divisor())
|
||||
// }
|
||||
}
|
@ -1,255 +0,0 @@
|
||||
use crate::slcr::common::{PllCfg, PllCtrl, PllFracCfg, SlcrRegisterBlock};
|
||||
use crate::slcr::{crf_apb, crl_apb};
|
||||
use libregister::{RegisterR, RegisterRW};
|
||||
use log::debug;
|
||||
|
||||
pub const PS_CLK: u32 = 33_333_000;
|
||||
|
||||
// DS926 Table: PS PLL Switching Characteristics (same for both speed grades)
|
||||
// const PS_PLL_MAX_LOCK_TIME: f32 = 100e-6; // 100 us
|
||||
const PS_PLL_MAX_OUT_FREQ: u32 = 1_600_000_000;
|
||||
const PS_PLL_MIN_OUT_FREQ: u32 = 750_000_000;
|
||||
// const PS_PLL_MAX_VCO_FREQ: u32 = 3_000_000_000;
|
||||
const PS_PLL_MIN_VCO_FREQ: u32 = 1_500_000_000;
|
||||
|
||||
/// UG1085 table 37-1
|
||||
/// (pll_fdiv_max, (pll_cp, pll_res, lfhf, lock_dly, lock_cnt))
|
||||
const PLL_FDIV_LOCK_PARAM: &[(u8, (u8, u8, u8, u8, u16))] = &[
|
||||
(25, (3, 10, 3, 63, 1000)),
|
||||
(26, (3, 10, 3, 63, 1000)),
|
||||
(27, (4, 6, 3, 63, 1000)),
|
||||
(28, (4, 6, 3, 63, 1000)),
|
||||
(29, (4, 6, 3, 63, 1000)),
|
||||
(30, (4, 6, 3, 63, 1000)),
|
||||
(31, (6, 1, 3, 63, 1000)),
|
||||
(32, (6, 1, 3, 63, 1000)),
|
||||
(33, (4, 10, 3, 63, 1000)),
|
||||
(34, (5, 6, 3, 63, 1000)),
|
||||
(35, (5, 6, 3, 63, 1000)),
|
||||
(36, (5, 6, 3, 63, 1000)),
|
||||
(37, (5, 6, 3, 63, 1000)),
|
||||
(38, (5, 6, 3, 63, 975)),
|
||||
(39, (3, 12, 3, 63, 950)),
|
||||
(40, (3, 12, 3, 63, 925)),
|
||||
(41, (3, 12, 3, 63, 900)),
|
||||
(42, (3, 12, 3, 63, 875)),
|
||||
(43, (3, 12, 3, 63, 850)),
|
||||
(44, (3, 12, 3, 63, 850)),
|
||||
(45, (3, 12, 3, 63, 825)),
|
||||
(46, (3, 12, 3, 63, 800)),
|
||||
(47, (3, 12, 3, 63, 775)),
|
||||
(48, (3, 12, 3, 63, 775)),
|
||||
(49, (3, 12, 3, 63, 750)),
|
||||
(50, (3, 12, 3, 63, 750)),
|
||||
(51, (3, 2, 3, 63, 725)),
|
||||
(52, (3, 2, 3, 63, 700)),
|
||||
(53, (3, 2, 3, 63, 700)),
|
||||
(54, (3, 2, 3, 63, 675)),
|
||||
(55, (3, 2, 3, 63, 675)),
|
||||
(56, (3, 2, 3, 63, 650)),
|
||||
(57, (3, 2, 3, 63, 650)),
|
||||
(58, (3, 2, 3, 63, 625)),
|
||||
(59, (3, 2, 3, 63, 625)),
|
||||
(60, (3, 2, 3, 63, 625)),
|
||||
(82, (3, 2, 3, 63, 600)), // 61-82
|
||||
(102, (4, 2, 3, 63, 600)), // 83-102
|
||||
(103, (5, 2, 3, 63, 600)),
|
||||
(104, (5, 2, 3, 63, 600)),
|
||||
(105, (5, 2, 3, 63, 600)),
|
||||
(106, (5, 2, 3, 63, 600)),
|
||||
(125, (3, 4, 3, 63, 600)), // 107-125
|
||||
];
|
||||
|
||||
pub trait ClockSource<T: SlcrRegisterBlock> {
|
||||
/// picks this ClockSource's registers from the SLCR block
|
||||
fn pll_ctrl_regs(slcr: &mut T) -> (&mut PllCtrl, &mut PllCfg, &mut PllFracCfg);
|
||||
|
||||
/// query PLL lock status
|
||||
fn pll_locked() -> bool;
|
||||
|
||||
// todo: is there any situation in which we'll actually want to use fractional mode?
|
||||
/// query fraction mode enable bit
|
||||
fn frac_enabled(pll_frac_cfg: &mut PllFracCfg) -> bool {
|
||||
bool::from(pll_frac_cfg.read().enabled())
|
||||
}
|
||||
|
||||
/// get configured frequency
|
||||
fn freq(pll_ctrl: &mut PllCtrl) -> u32 {
|
||||
// todo: take into account fractional part (if enabled)
|
||||
u32::from(pll_ctrl.read().pll_fdiv()) * PS_CLK
|
||||
}
|
||||
|
||||
fn name() -> &'static str;
|
||||
|
||||
// UG1085 Chapter 37: PS Clock Subsystem
|
||||
fn setup(target_freq: u32) {
|
||||
assert!(target_freq >= PS_PLL_MIN_OUT_FREQ && target_freq <= PS_PLL_MAX_OUT_FREQ);
|
||||
let div2 = target_freq < PS_PLL_MIN_VCO_FREQ;
|
||||
let divisor = u32::from(div2) + 1;
|
||||
let fdiv = (target_freq * divisor / PS_CLK).min(125) as u8;
|
||||
let (pll_cp, pll_res, lfhf, lock_dly, lock_cnt) = PLL_FDIV_LOCK_PARAM
|
||||
.iter()
|
||||
.filter(|(fdiv_max, _)| fdiv <= *fdiv_max)
|
||||
.nth(0)
|
||||
.expect("PLL_FDIV_LOCK_PARAM")
|
||||
.1
|
||||
.clone();
|
||||
|
||||
debug!("Set {} to {} Hz", Self::name(), target_freq);
|
||||
T::unlocked(|slcr| {
|
||||
let (pll_ctrl, pll_cfg, _) = Self::pll_ctrl_regs(slcr);
|
||||
|
||||
// Write fdiv, div2
|
||||
pll_ctrl.modify(|_, w| w.pll_fdiv(fdiv).pll_div2(div2));
|
||||
// Configure
|
||||
// no need to zero as we're writing every field
|
||||
pll_cfg.modify(|_, w| {
|
||||
w.lock_dly(lock_dly)
|
||||
.lock_cnt(lock_cnt)
|
||||
.lfhf(lfhf)
|
||||
.pll_cp(pll_cp)
|
||||
.pll_res(pll_res)
|
||||
});
|
||||
// Bypass
|
||||
pll_ctrl.modify(|_, w| w.pll_bypass_force(true));
|
||||
// Reset
|
||||
pll_ctrl.modify(|_, w| w.pll_reset(true));
|
||||
pll_ctrl.modify(|_, w| w.pll_reset(false));
|
||||
// Wait for PLL lock
|
||||
// todo: add timeout here according to the 100 us spec?
|
||||
while !Self::pll_locked() {}
|
||||
// Remove bypass
|
||||
pll_ctrl.modify(|_, w| w.pll_bypass_force(false));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// APU PLL: Recommended clock source for the APUs and the FPD interconnect
|
||||
pub struct ApuPll;
|
||||
|
||||
impl ClockSource<crf_apb::RegisterBlock> for ApuPll {
|
||||
#[inline]
|
||||
fn pll_ctrl_regs(
|
||||
slcr: &mut crf_apb::RegisterBlock,
|
||||
) -> (&mut PllCtrl, &mut PllCfg, &mut PllFracCfg) {
|
||||
(
|
||||
&mut slcr.apu_pll_ctrl,
|
||||
&mut slcr.apu_pll_cfg,
|
||||
&mut slcr.apu_pll_frac_cfg,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pll_locked() -> bool {
|
||||
let slcr = crf_apb::RegisterBlock::slcr();
|
||||
slcr.pll_status.read().apu_pll_lock()
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
&"APU_PLL"
|
||||
}
|
||||
}
|
||||
|
||||
/// DDR PLL: Recommended clock for the DDR DRAM controller and AXI_HP interfaces
|
||||
pub struct DdrPll;
|
||||
|
||||
impl ClockSource<crf_apb::RegisterBlock> for DdrPll {
|
||||
#[inline]
|
||||
fn pll_ctrl_regs(
|
||||
slcr: &mut crf_apb::RegisterBlock,
|
||||
) -> (&mut PllCtrl, &mut PllCfg, &mut PllFracCfg) {
|
||||
(
|
||||
&mut slcr.ddr_pll_ctrl,
|
||||
&mut slcr.ddr_pll_cfg,
|
||||
&mut slcr.ddr_pll_frac_cfg,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pll_locked() -> bool {
|
||||
let slcr = crf_apb::RegisterBlock::slcr();
|
||||
slcr.pll_status.read().ddr_pll_lock()
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
&"DDR_PLL"
|
||||
}
|
||||
}
|
||||
|
||||
/// Video PLL: Recommended clock for DisplayPort
|
||||
pub struct VideoPll;
|
||||
|
||||
impl ClockSource<crf_apb::RegisterBlock> for VideoPll {
|
||||
#[inline]
|
||||
fn pll_ctrl_regs(
|
||||
slcr: &mut crf_apb::RegisterBlock,
|
||||
) -> (&mut PllCtrl, &mut PllCfg, &mut PllFracCfg) {
|
||||
(
|
||||
&mut slcr.video_pll_ctrl,
|
||||
&mut slcr.video_pll_cfg,
|
||||
&mut slcr.video_pll_frac_cfg,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pll_locked() -> bool {
|
||||
let slcr = crf_apb::RegisterBlock::slcr();
|
||||
slcr.pll_status.read().video_pll_lock()
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
&"VIDEO_PLL"
|
||||
}
|
||||
}
|
||||
|
||||
/// I/O PLL: Recommended clock for I/O peripherals
|
||||
pub struct IoPll;
|
||||
|
||||
impl ClockSource<crl_apb::RegisterBlock> for IoPll {
|
||||
#[inline]
|
||||
fn pll_ctrl_regs(
|
||||
slcr: &mut crl_apb::RegisterBlock,
|
||||
) -> (&mut PllCtrl, &mut PllCfg, &mut PllFracCfg) {
|
||||
(
|
||||
&mut slcr.io_pll_ctrl,
|
||||
&mut slcr.io_pll_cfg,
|
||||
&mut slcr.io_pll_frac_cfg,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pll_locked() -> bool {
|
||||
let slcr = crl_apb::RegisterBlock::slcr();
|
||||
slcr.pll_status.read().io_pll_lock()
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
&"IO_PLL"
|
||||
}
|
||||
}
|
||||
|
||||
/// RPU PLL: Recommended clock for RPUs and LPD interconnect
|
||||
pub struct RpuPll;
|
||||
|
||||
impl ClockSource<crl_apb::RegisterBlock> for RpuPll {
|
||||
#[inline]
|
||||
fn pll_ctrl_regs(
|
||||
slcr: &mut crl_apb::RegisterBlock,
|
||||
) -> (&mut PllCtrl, &mut PllCfg, &mut PllFracCfg) {
|
||||
(
|
||||
&mut slcr.io_pll_ctrl,
|
||||
&mut slcr.io_pll_cfg,
|
||||
&mut slcr.io_pll_frac_cfg,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pll_locked() -> bool {
|
||||
let slcr = crl_apb::RegisterBlock::slcr();
|
||||
slcr.pll_status.read().rpu_pll_lock()
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
&"RPU_PLL"
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
/// Re-export so that dependents can always use the same version
|
||||
pub use libboard_zynq::smoltcp;
|
||||
|
||||
pub mod slcr;
|
||||
pub mod clocks;
|
@ -1,29 +0,0 @@
|
||||
///! Type definitions for re-use across SLCR blocks
|
||||
|
||||
use libregister::{register, register_bit, register_bits};
|
||||
|
||||
pub trait SlcrRegisterBlock {
|
||||
fn unlocked<F: FnMut(&mut Self) -> R, R>(f: F) -> R;
|
||||
}
|
||||
|
||||
register!(wprot, WProt, RW, u32);
|
||||
register_bit!(wprot, active, 0);
|
||||
|
||||
register!(pll_ctrl, PllCtrl, RW, u32);
|
||||
register_bits!(pll_ctrl, pll_post_src, u8, 24, 26);
|
||||
register_bits!(pll_ctrl, pll_pre_src, u8, 20, 22);
|
||||
register_bit!(pll_ctrl, pll_div2, 16);
|
||||
register_bits!(pll_ctrl, pll_fdiv, u8, 8, 14);
|
||||
register_bit!(pll_ctrl, pll_bypass_force, 3);
|
||||
register_bit!(pll_ctrl, pll_reset, 0);
|
||||
|
||||
register!(pll_cfg, PllCfg, RW, u32);
|
||||
register_bits!(pll_cfg, lock_dly, u8, 25, 31);
|
||||
register_bits!(pll_cfg, lock_cnt, u16, 13, 22);
|
||||
register_bits!(pll_cfg, lfhf, u8, 10, 11);
|
||||
register_bits!(pll_cfg, pll_cp, u8, 5, 8);
|
||||
register_bits!(pll_cfg, pll_res, u8, 0, 3);
|
||||
|
||||
register!(pll_frac_cfg, PllFracCfg, RW, u32);
|
||||
register_bit!(pll_frac_cfg, enabled, 31);
|
||||
register_bits!(pll_frac_cfg, data, u16, 0, 15);
|
@ -1,100 +0,0 @@
|
||||
///! FPD clock and reset control
|
||||
|
||||
use volatile_register::{RO, RW, WO};
|
||||
use libregister::{
|
||||
register, register_at,
|
||||
register_bit, register_bits, register_bits_typed,
|
||||
RegisterW,
|
||||
};
|
||||
|
||||
use super::common::{SlcrRegisterBlock, WProt, PllCfg, PllCtrl, PllFracCfg};
|
||||
|
||||
#[repr(u8)]
|
||||
pub enum ApuClkSource {
|
||||
ApuPll = 0b00,
|
||||
DdrPll = 0b10,
|
||||
VideoPll = 0b11,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct RegisterBlock {
|
||||
// CRF_APB
|
||||
pub err_ctrl: RW<u32>,
|
||||
pub ir_status: RW<u32>, // todo: WTC LSB
|
||||
pub ir_mask: RO<u32>,
|
||||
pub ir_enable: WO<u32>,
|
||||
pub ir_disable: WO<u32>,
|
||||
pub crf_wprot: WProt,
|
||||
pub apu_pll_ctrl: PllCtrl,
|
||||
pub apu_pll_cfg: PllCfg,
|
||||
pub apu_pll_frac_cfg: PllFracCfg,
|
||||
pub ddr_pll_ctrl: PllCtrl,
|
||||
pub ddr_pll_cfg: PllCfg,
|
||||
pub ddr_pll_frac_cfg: PllFracCfg,
|
||||
pub video_pll_ctrl: PllCtrl,
|
||||
pub video_pll_cfg: PllCfg,
|
||||
pub video_pll_frac_cfg: PllFracCfg,
|
||||
pub pll_status: PllStatus,
|
||||
pub apu_pll_to_lpd_ctrl: PllToLpdCtrl,
|
||||
pub ddr_pll_to_lpd_ctrl: PllToLpdCtrl,
|
||||
pub video_pll_to_lpd_ctrl: PllToLpdCtrl,
|
||||
reserved1: [u32; 3],
|
||||
pub apu_clk_ctrl: ApuClkCtrl,
|
||||
pub dbg_trace_clk_ctrl: RW<u32>,
|
||||
pub dbg_fpd_clk_ctrl: RW<u32>,
|
||||
reserved2: [u32; 1],
|
||||
pub dp_video_clk_ctrl: RW<u32>,
|
||||
pub dp_audio_clk_ctrl: RW<u32>,
|
||||
reserved3: [u32; 1],
|
||||
pub dp_sys_clk_ctrl: RW<u32>,
|
||||
pub ddr_clk_ctrl: DdrClkCtrl,
|
||||
pub gpu_clk_ctrl: RW<u32>,
|
||||
reserved4: [u32; 6],
|
||||
pub sata_clk_ctrl: RW<u32>,
|
||||
reserved5: [u32; 4],
|
||||
pub pcie_clk_ctrl: RW<u32>,
|
||||
pub fpd_dma_clk_ctrl: RW<u32>,
|
||||
pub dp_dma_clk_ctrl: RW<u32>,
|
||||
pub topsw_main_clk_ctrl: RW<u32>,
|
||||
pub topsw_lsbus_clk_ctrl: RW<u32>,
|
||||
reserved6: [u32; 8],
|
||||
pub dbg_tstmp_clk_ctrl: RW<u32>,
|
||||
reserved7: [u32; 1],
|
||||
pub rst_fpd_top: RW<u32>,
|
||||
pub rst_fpd_apu: RW<u32>,
|
||||
pub rst_ddr_ss: RW<u32>,
|
||||
}
|
||||
register_at!(RegisterBlock, 0xFD1A_0000, slcr);
|
||||
|
||||
impl SlcrRegisterBlock for RegisterBlock {
|
||||
fn unlocked<F: FnMut(&mut Self) -> R, R>(mut f: F) -> R {
|
||||
let mut self_ = Self::slcr();
|
||||
self_.crf_wprot.write(WProt::zeroed().active(false));
|
||||
let r = f(&mut self_);
|
||||
self_.crf_wprot.write(WProt::zeroed().active(true));
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
register!(pll_status, PllStatus, RO, u32);
|
||||
register_bit!(pll_status, video_pll_stable, 5);
|
||||
register_bit!(pll_status, ddr_pll_stable, 4);
|
||||
register_bit!(pll_status, apu_pll_stable, 3);
|
||||
register_bit!(pll_status, video_pll_lock, 2);
|
||||
register_bit!(pll_status, ddr_pll_lock, 1);
|
||||
register_bit!(pll_status, apu_pll_lock, 0);
|
||||
|
||||
register!(pll_to_lpd_ctrl, PllToLpdCtrl, RW, u32);
|
||||
register_bits!(pll_to_lpd_ctrl, divisor0, u8, 8, 13);
|
||||
|
||||
register!(apu_clk_ctrl, ApuClkCtrl, RW, u32);
|
||||
register_bit!(apu_clk_ctrl, clkact_half, 25);
|
||||
register_bit!(apu_clk_ctrl, clkact_full, 24);
|
||||
register_bits!(apu_clk_ctrl, divisor0, u8, 8, 13);
|
||||
register_bits_typed!(apu_clk_ctrl, srcsel, u8, ApuClkSource, 0, 2);
|
||||
|
||||
register!(ddr_clk_ctrl, DdrClkCtrl, RW, u32);
|
||||
register_bits!(ddr_clk_ctrl, divisor0, u8, 8, 13);
|
||||
// 000: DDR PLL
|
||||
// 001: Video PLL
|
||||
register_bits!(ddr_clk_ctrl, srcsel, u8, 0, 2);
|
@ -1,315 +0,0 @@
|
||||
///! FPD clock and reset control
|
||||
|
||||
use volatile_register::{RO, RW, WO};
|
||||
use libregister::{
|
||||
register, register_at,
|
||||
register_bit, register_bits, register_bits_typed,
|
||||
};
|
||||
|
||||
use super::common::{SlcrRegisterBlock, WProt, PllCfg, PllCtrl, PllFracCfg};
|
||||
|
||||
/// Clock source selection for IO-type devices
|
||||
#[repr(u8)]
|
||||
pub enum IoClkSource {
|
||||
IoPll = 0b00,
|
||||
RpuPll = 0b10,
|
||||
DdrPllToLpd = 0b11,
|
||||
}
|
||||
|
||||
/// Clock source selection for RPU and related (e.g. LPD interconnect) devices
|
||||
#[repr(u8)]
|
||||
pub enum RpuClkSource {
|
||||
RpuPll = 0b00,
|
||||
IoPll = 0b10,
|
||||
DdrPllToLpd = 0b11,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RegisterBlock {
|
||||
pub err_ctrl: RW<u32>,
|
||||
pub ir_status: RW<u32>, // todo: WTC LSB
|
||||
pub ir_mask: RO<u32>,
|
||||
pub ir_enable: WO<u32>,
|
||||
pub ir_disable: WO<u32>,
|
||||
reserved1: [u32; 2],
|
||||
pub crl_wprot: WProt,
|
||||
pub io_pll_ctrl: PllCtrl,
|
||||
pub io_pll_cfg: PllCfg,
|
||||
pub io_pll_frac_cfg: PllFracCfg,
|
||||
reserved2: [u32; 1],
|
||||
pub rpu_pll_ctrl: PllCtrl,
|
||||
pub rpu_pll_cfg: PllCfg,
|
||||
pub rpu_pll_frac_cfg: PllFracCfg,
|
||||
reserved3: [u32; 1],
|
||||
pub pll_status: PllStatus,
|
||||
pub io_pll_to_fpd_ctrl: PllToFpdCtrl,
|
||||
pub rpu_pll_to_fpd_ctrl: PllToFpdCtrl,
|
||||
pub usb3_clk_ctrl: UsbClkCtrl,
|
||||
pub gem0_clk_ctrl: GemClkCtrl,
|
||||
pub gem1_clk_ctrl: GemClkCtrl,
|
||||
pub gem2_clk_ctrl: GemClkCtrl,
|
||||
pub gem3_clk_ctrl: GemClkCtrl,
|
||||
pub usb0_bus_clk_ctrl: UsbClkCtrl,
|
||||
pub usb1_bus_clk_ctrl: UsbClkCtrl,
|
||||
pub qspi_clk_ctrl: QSpiClkCtrl,
|
||||
pub sdio0_clk_ctrl: SdioClkCtrl,
|
||||
pub sdio1_clk_ctrl: SdioClkCtrl,
|
||||
pub uart0_clk_ctrl: UartClkCtrl,
|
||||
pub uart1_clk_ctrl: UartClkCtrl,
|
||||
pub spi0_clk_ctrl: SpiClkCtrl,
|
||||
pub spi1_clk_ctrl: SpiClkCtrl,
|
||||
pub can0_clk_ctrl: CanClkCtrl,
|
||||
pub can1_clk_ctrl: CanClkCtrl,
|
||||
reserved4: [u32; 1],
|
||||
pub rpu_clk_ctrl: RpuClkCtrl,
|
||||
reserved5: [u32; 2],
|
||||
pub iou_switch_clk_ctrl: IouSwitchClkCtrl,
|
||||
pub csu_clk_ctrl: CsuPllCtrl,
|
||||
pub pcap_clk_ctrl: PcapClkCtrl,
|
||||
pub lpd_switch_clk_ctrl: LpdSwitchClkCtrl,
|
||||
pub lpd_lsbus_clk_ctrl: LpdLsbusClkCtrl,
|
||||
pub dbg_lpd_clk_ctrl: DbgLpdClkCtrl,
|
||||
pub nand_clk_ctrl: NandClkCtrl,
|
||||
pub lpd_dma_clk_ctrl: LpdDmaClkCtrl,
|
||||
reserved6: [u32; 1],
|
||||
pub pl0_clk_ctrl: PlClkCtrl,
|
||||
pub pl1_clk_ctrl: PlClkCtrl,
|
||||
pub pl2_clk_ctrl: PlClkCtrl,
|
||||
pub pl3_clk_ctrl: PlClkCtrl,
|
||||
pub pl0_thr_ctrl: PlThrCtrl,
|
||||
pub pl0_thr_cnt: PlThrCnt,
|
||||
pub pl1_thr_ctrl: PlThrCtrl,
|
||||
pub pl1_thr_cnt: PlThrCnt,
|
||||
pub pl2_thr_ctrl: PlThrCtrl,
|
||||
pub pl2_thr_cnt: PlThrCnt,
|
||||
pub pl3_thr_ctrl: PlThrCtrl,
|
||||
reserved7: [u32; 4],
|
||||
pub pl3_thr_cnt: PlThrCnt,
|
||||
pub gem_tsu_clk_ctrl: GemTsuClkCtrl,
|
||||
pub dll_clk_ctrl: DllClkCtrl,
|
||||
pub ps_sysmon_clk_ctrl: PsSysmonClkCtrl,
|
||||
reserved8: [u32; 5],
|
||||
pub i2c0_clk_ctrl: I2cClkCtrl,
|
||||
pub i2c1_clk_ctrl: I2cClkCtrl,
|
||||
pub timestamp_clk_ctrl: TimestampClkCtrl,
|
||||
reserved9: [u32; 1],
|
||||
pub safety_chk: RW<u32>,
|
||||
reserved10: [u32; 3],
|
||||
pub clkmon_status: RW<u32>,
|
||||
pub clkmon_mask: RO<u32>,
|
||||
pub clkmon_enable: WO<u32>,
|
||||
pub clkmon_disable: WO<u32>,
|
||||
pub clkmon_trigger: WO<u32>,
|
||||
reserved11: [u32; 3],
|
||||
pub chkr0_clka_upper: RW<u32>,
|
||||
pub chkr0_clka_lower: RW<u32>,
|
||||
pub chkr0_clkb_cnt: RW<u32>,
|
||||
pub chkr0_ctrl: RW<u32>,
|
||||
pub chkr1_clka_upper: RW<u32>,
|
||||
pub chkr1_clka_lower: RW<u32>,
|
||||
pub chkr1_clkb_cnt: RW<u32>,
|
||||
pub chkr1_ctrl: RW<u32>,
|
||||
pub chkr2_clka_upper: RW<u32>,
|
||||
pub chkr2_clka_lower: RW<u32>,
|
||||
pub chkr2_clkb_cnt: RW<u32>,
|
||||
pub chkr2_ctrl: RW<u32>,
|
||||
pub chkr3_clka_upper: RW<u32>,
|
||||
pub chkr3_clka_lower: RW<u32>,
|
||||
pub chkr3_clkb_cnt: RW<u32>,
|
||||
pub chkr3_ctrl: RW<u32>,
|
||||
pub chkr4_clka_upper: RW<u32>,
|
||||
pub chkr4_clka_lower: RW<u32>,
|
||||
pub chkr4_clkb_cnt: RW<u32>,
|
||||
pub chkr4_ctrl: RW<u32>,
|
||||
pub chkr5_clka_upper: RW<u32>,
|
||||
pub chkr5_clka_lower: RW<u32>,
|
||||
pub chkr5_clkb_cnt: RW<u32>,
|
||||
pub chkr5_ctrl: RW<u32>,
|
||||
pub chkr6_clka_upper: RW<u32>,
|
||||
pub chkr6_clka_lower: RW<u32>,
|
||||
pub chkr6_clkb_cnt: RW<u32>,
|
||||
pub chkr6_ctrl: RW<u32>,
|
||||
pub chkr7_clka_upper: RW<u32>,
|
||||
pub chkr7_clka_lower: RW<u32>,
|
||||
pub chkr7_clkb_cnt: RW<u32>,
|
||||
pub chkr7_ctrl: RW<u32>,
|
||||
reserved12: [u32; 8],
|
||||
pub boot_mode_user: RW<u32>,
|
||||
pub boot_mode: BootMode,
|
||||
reserved13: [u32; 4],
|
||||
pub reset_ctrl: RW<u32>,
|
||||
pub blockonly_rst: RW<u32>, // todo: WTC LSB
|
||||
pub reset_reason: RW<u32>, // todo: WTC 0:6
|
||||
reserved14: [u32; 3],
|
||||
pub gem_rst_ctrl: GemRstCtrl,
|
||||
reserved15: [u32; 1],
|
||||
pub peri_rst_ctrl: PeriRstCtrl,
|
||||
pub rst_lpd_top: RstLpdTop,
|
||||
pub rst_lpd_dbg: RW<u32>,
|
||||
reserved16: [u32; 3],
|
||||
pub boot_pin_ctrl: RW<u32>, // todo: RO 4:7
|
||||
reserved17: [u32; 7],
|
||||
pub bank3_drive0: RW<u32>,
|
||||
pub bank3_drive1: RW<u32>,
|
||||
pub bank3_input_ctrl: RW<u32>,
|
||||
pub bank3_pull_ctrl: RW<u32>,
|
||||
pub bank3_pull_enable: RW<u32>,
|
||||
pub bank3_slew_ctrl: RW<u32>,
|
||||
pub bank3_status: RO<u32>,
|
||||
}
|
||||
register_at!(RegisterBlock, 0xFF5E_0000, slcr);
|
||||
|
||||
impl SlcrRegisterBlock for RegisterBlock {
|
||||
// Dummy definition (CRL_APB has no WProt) for consistency with CRF_APB
|
||||
fn unlocked<F: FnMut(&mut Self) -> R, R>(mut f: F) -> R {
|
||||
let mut self_ = Self::slcr();
|
||||
f(&mut self_)
|
||||
}
|
||||
}
|
||||
|
||||
register!(pll_status, PllStatus, RO, u32);
|
||||
register_bit!(pll_status, rpu_pll_stable, 4);
|
||||
register_bit!(pll_status, io_pll_stable, 3);
|
||||
register_bit!(pll_status, rpu_pll_lock, 1);
|
||||
register_bit!(pll_status, io_pll_lock, 0);
|
||||
|
||||
|
||||
register!(pll_to_fpd_ctrl, PllToFpdCtrl, RW, u32);
|
||||
register_bits!(pll_to_fpd_ctrl, divisor0, u8, 8, 13);
|
||||
|
||||
register!(gem_clk_ctrl, GemClkCtrl, RW, u32);
|
||||
register_bit!(gem_clk_ctrl, rx_clkact, 26);
|
||||
register_bit!(gem_clk_ctrl, clkact, 25);
|
||||
register_bits!(gem_clk_ctrl, divisor1, u8, 16, 21);
|
||||
register_bits!(gem_clk_ctrl, divisor0, u8, 8, 13);
|
||||
register_bits_typed!(gem_clk_ctrl, srcsel, u8, IoClkSource, 0, 2);
|
||||
|
||||
|
||||
register!(usb_clk_ctrl, UsbClkCtrl, RW, u32);
|
||||
register_bit!(usb_clk_ctrl, clkact, 25);
|
||||
register_bits!(usb_clk_ctrl, divisor1, u8, 16, 21);
|
||||
register_bits!(usb_clk_ctrl, divisor0, u8, 8, 13);
|
||||
register_bits_typed!(usb_clk_ctrl, srcsel, u8, IoClkSource, 0, 2);
|
||||
|
||||
|
||||
macro_rules! dual_div_clk_reg {
|
||||
($mod_name: ident, $struct_name: ident, $srcsel_type: ident) => {
|
||||
register!($mod_name, $struct_name, RW, u32);
|
||||
register_bit!($mod_name, clkact, 24);
|
||||
register_bits!($mod_name, divisor1, u8, 16, 21);
|
||||
register_bits!($mod_name, divisor0, u8, 8, 13);
|
||||
register_bits_typed!($mod_name, srcsel, u8, $srcsel_type, 0, 2);
|
||||
};
|
||||
}
|
||||
|
||||
dual_div_clk_reg!(qspi_clk_ctrl, QSpiClkCtrl, IoClkSource);
|
||||
dual_div_clk_reg!(sdio_clk_ctrl, SdioClkCtrl, IoClkSource);
|
||||
dual_div_clk_reg!(uart_clk_ctrl, UartClkCtrl, IoClkSource);
|
||||
dual_div_clk_reg!(spi_clk_ctrl, SpiClkCtrl, IoClkSource);
|
||||
dual_div_clk_reg!(can_clk_ctrl, CanClkCtrl, IoClkSource);
|
||||
dual_div_clk_reg!(nand_clk_ctrl, NandClkCtrl, IoClkSource);
|
||||
dual_div_clk_reg!(pl_clk_ctrl, PlClkCtrl, IoClkSource);
|
||||
dual_div_clk_reg!(gem_tsu_clk_ctrl, GemTsuClkCtrl, IoClkSource);
|
||||
dual_div_clk_reg!(ps_sysmon_clk_ctrl, PsSysmonClkCtrl, RpuClkSource);
|
||||
dual_div_clk_reg!(i2c_clk_ctrl, I2cClkCtrl, IoClkSource);
|
||||
|
||||
|
||||
register!(rpu_clk_ctrl, RpuClkCtrl, RW, u32);
|
||||
register_bit!(rpu_clk_ctrl, clkact_core, 25);
|
||||
register_bit!(rpu_clk_ctrl, clkact, 24);
|
||||
register_bits!(rpu_clk_ctrl, divisor0, u8, 8, 13);
|
||||
register_bits_typed!(rpu_clk_ctrl, srcsel, u8, RpuClkSource, 0, 2);
|
||||
|
||||
|
||||
macro_rules! single_div_clk_reg {
|
||||
// default to RpuClkSource
|
||||
($mod_name: ident, $struct_name: ident, $srcsel_type: ident) => {
|
||||
register!($mod_name, $struct_name, RW, u32);
|
||||
register_bit!($mod_name, clkact, 24);
|
||||
register_bits!($mod_name, divisor1, u8, 16, 21);
|
||||
register_bits!($mod_name, divisor0, u8, 8, 13);
|
||||
register_bits_typed!($mod_name, srcsel, u8, $srcsel_type, 0, 2);
|
||||
};
|
||||
}
|
||||
|
||||
single_div_clk_reg!(iou_switch_clk_ctrl, IouSwitchClkCtrl, RpuClkSource);
|
||||
single_div_clk_reg!(csu_clk_ctrl, CsuPllCtrl, IoClkSource);
|
||||
single_div_clk_reg!(pcap_clk_ctrl, PcapClkCtrl, IoClkSource);
|
||||
single_div_clk_reg!(lpd_switch_clk_ctrl, LpdSwitchClkCtrl, RpuClkSource);
|
||||
single_div_clk_reg!(lpd_lsbus_clk_ctrl, LpdLsbusClkCtrl, RpuClkSource);
|
||||
single_div_clk_reg!(dbg_lpd_clk_ctrl, DbgLpdClkCtrl, RpuClkSource);
|
||||
single_div_clk_reg!(lpd_dma_clk_ctrl, LpdDmaClkCtrl, RpuClkSource);
|
||||
// todo: timestamp clk can also run directly from PS_REF_CLK (0b1xx)
|
||||
single_div_clk_reg!(timestamp_clk_ctrl, TimestampClkCtrl, IoClkSource);
|
||||
|
||||
|
||||
register!(pl_thr_ctrl, PlThrCtrl, RW, u32);
|
||||
register_bits!(pl_thr_ctrl, curr_val, u16, 16, 31, RO);
|
||||
register_bit!(pl_thr_ctrl, running, 15, RO);
|
||||
register_bit!(pl_thr_ctrl, cpu_start, 1);
|
||||
register_bit!(pl_thr_ctrl, cnt_rst, 0);
|
||||
|
||||
|
||||
register!(pl_thr_cnt, PlThrCnt, RW, u32);
|
||||
register_bits!(pl_thr_cnt, last_cnt, u16, 0, 15);
|
||||
|
||||
|
||||
register!(dll_clk_ctrl, DllClkCtrl, RW, u32);
|
||||
register_bits!(dll_clk_ctrl, srcsel, u8, 0, 2);
|
||||
|
||||
// boot mode pin values read after POR and "triplicated for security"
|
||||
register!(boot_mode, BootMode, RO, u32);
|
||||
register_bits!(boot_mode, boot_mode2, u8, 8, 11);
|
||||
register_bits!(boot_mode, boot_mode1, u8, 4, 7);
|
||||
register_bits!(boot_mode, boot_mode0, u8, 0, 3);
|
||||
|
||||
register!(gem_rst_ctrl, GemRstCtrl, RW, u32);
|
||||
register_bit!(gem_rst_ctrl, gem3_rst, 3);
|
||||
register_bit!(gem_rst_ctrl, gem2_rst, 2);
|
||||
register_bit!(gem_rst_ctrl, gem1_rst, 1);
|
||||
register_bit!(gem_rst_ctrl, gem0_rst, 0);
|
||||
|
||||
|
||||
register!(peri_rst_ctrl, PeriRstCtrl, RW, u32);
|
||||
register_bit!(peri_rst_ctrl, timestamp_rst, 20);
|
||||
register_bit!(peri_rst_ctrl, iou_cc_rst, 19);
|
||||
register_bit!(peri_rst_ctrl, gpio_rst, 18);
|
||||
register_bit!(peri_rst_ctrl, lpd_dma_rst, 17);
|
||||
register_bit!(peri_rst_ctrl, nand_rst, 16);
|
||||
register_bit!(peri_rst_ctrl, swdt_rst, 15);
|
||||
register_bit!(peri_rst_ctrl, ttc3_rst, 14);
|
||||
register_bit!(peri_rst_ctrl, ttc2_rst, 13);
|
||||
register_bit!(peri_rst_ctrl, ttc1_rst, 12);
|
||||
register_bit!(peri_rst_ctrl, ttc0_rst, 11);
|
||||
register_bit!(peri_rst_ctrl, i2c1_rst, 10);
|
||||
register_bit!(peri_rst_ctrl, i2c0_rst, 9);
|
||||
register_bit!(peri_rst_ctrl, can1_rst, 8);
|
||||
register_bit!(peri_rst_ctrl, can0_rst, 7);
|
||||
register_bit!(peri_rst_ctrl, sdio1_rst, 6);
|
||||
register_bit!(peri_rst_ctrl, sdio0_rst, 5);
|
||||
register_bit!(peri_rst_ctrl, spi1_rst, 4);
|
||||
register_bit!(peri_rst_ctrl, spi0_rst, 3);
|
||||
register_bit!(peri_rst_ctrl, uart1_rst, 2);
|
||||
register_bit!(peri_rst_ctrl, uart0_rst, 1);
|
||||
register_bit!(peri_rst_ctrl, qspi_rst, 0);
|
||||
|
||||
|
||||
register!(rst_lpd_top, RstLpdTop, RW, u32);
|
||||
register_bit!(rst_lpd_top, fpd_rst, 23);
|
||||
register_bit!(rst_lpd_top, lpd_swdt_rst, 20);
|
||||
register_bit!(rst_lpd_top, s_axi_lpd_rst, 19);
|
||||
register_bit!(rst_lpd_top, sysmon_rst, 17);
|
||||
register_bit!(rst_lpd_top, rtc_rst, 16);
|
||||
register_bit!(rst_lpd_top, apm_rst, 15);
|
||||
register_bit!(rst_lpd_top, ipi_rst, 14);
|
||||
register_bit!(rst_lpd_top, usb1_apb_rst, 11);
|
||||
register_bit!(rst_lpd_top, usb0_apb_rst, 10);
|
||||
register_bit!(rst_lpd_top, usb1_hiber_rst, 9);
|
||||
register_bit!(rst_lpd_top, usb0_hiber_rst, 8);
|
||||
register_bit!(rst_lpd_top, usb1_core_rst, 7);
|
||||
register_bit!(rst_lpd_top, usb0_core_rst, 6);
|
||||
register_bit!(rst_lpd_top, rpu_pge_rst, 4);
|
||||
register_bit!(rst_lpd_top, ocm_rst, 3);
|
||||
register_bit!(rst_lpd_top, rpu_amba_rst, 2);
|
||||
register_bit!(rst_lpd_top, rpu_core1_rst, 1);
|
||||
register_bit!(rst_lpd_top, rpu_core0_rst, 0);
|
@ -1,124 +0,0 @@
|
||||
///! IOU SLCR for MIO pin configuration
|
||||
|
||||
use volatile_register::{RO, RW, WO};
|
||||
use libregister::{
|
||||
register, register_at,
|
||||
register_bit, register_bits,
|
||||
};
|
||||
|
||||
use super::common::SlcrRegisterBlock;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RegisterBlock {
|
||||
pub mio_pin: [MioPin; 78],
|
||||
pub bank0_drive0: BankDriveCtrl,
|
||||
pub bank0_drive1: BankDriveCtrl,
|
||||
pub bank0_input_ctrl: BankInputCtrl,
|
||||
pub bank0_pull_ctrl: BankPullCtrl,
|
||||
pub bank0_pull_enable: BankPullEnable,
|
||||
pub bank0_slew_ctrl: BankSlewCtrl,
|
||||
pub bank0_status: BankStatus,
|
||||
pub bank1_drive0: BankDriveCtrl,
|
||||
pub bank1_drive1: BankDriveCtrl,
|
||||
pub bank1_input_ctrl: BankInputCtrl,
|
||||
pub bank1_pull_ctrl: BankPullCtrl,
|
||||
pub bank1_pull_enable: BankPullEnable,
|
||||
pub bank1_slew_ctrl: BankSlewCtrl,
|
||||
pub bank1_status: BankStatus,
|
||||
pub bank2_drive0: BankDriveCtrl,
|
||||
pub bank2_drive1: BankDriveCtrl,
|
||||
pub bank2_input_ctrl: BankInputCtrl,
|
||||
pub bank2_pull_ctrl: BankPullCtrl,
|
||||
pub bank2_pull_enable: BankPullEnable,
|
||||
pub bank2_slew_ctrl: BankSlewCtrl,
|
||||
pub bank2_status: BankStatus,
|
||||
reserved1: [u32; 5],
|
||||
pub mio_loopback: RW<u32>,
|
||||
pub mio_mst_tri0: RW<u32>,
|
||||
pub mio_mst_tri1: RW<u32>,
|
||||
pub mio_mst_tri2: RW<u32>,
|
||||
pub wdt_clk_sel: RW<u32>, // 0 = internal APB clock, 1 = external
|
||||
pub can_mio_ctrl: RW<u32>,
|
||||
pub gem_clk_ctrl: RW<u32>,
|
||||
pub sdio_clk_ctrl: RW<u32>,
|
||||
pub ctrl_reg_sd: RW<u32>,
|
||||
pub sd_itap_dly: RW<u32>,
|
||||
pub sd_otap_dly_sel: RW<u32>,
|
||||
pub sd_cfg1: RW<u32>,
|
||||
pub sd_cfg2: RW<u32>,
|
||||
pub sd_cfg3: RW<u32>,
|
||||
pub sd_init_preset: RW<u32>,
|
||||
pub sd_speed_preset: RW<u32>,
|
||||
pub sd_hspeed_preset: RW<u32>,
|
||||
pub sd_sdr12_preset: RW<u32>,
|
||||
pub sd_sdr25_preset: RW<u32>,
|
||||
pub sd_sdr50_preset: RW<u32>,
|
||||
reserved2: [u32; 1],
|
||||
pub sd_sdr104_preset: RW<u32>,
|
||||
pub sd_ddr50_preset: RW<u32>,
|
||||
pub sd_max_cur_18: RW<u32>,
|
||||
pub sd_max_cur_30: RW<u32>,
|
||||
pub sd_max_cur_33: RW<u32>,
|
||||
pub sd_dll_ctrl: RW<u32>,
|
||||
pub sd_cdn_ctrl: RW<u32>,
|
||||
pub gem_ctrl: RW<u32>,
|
||||
reserved3: [u32; 7],
|
||||
pub iou_ttc_apb_clk: RW<u32>,
|
||||
reserved4: [u32; 3],
|
||||
pub iou_tapdly_bypass: RW<u32>,
|
||||
reserved5: [u32; 3],
|
||||
pub iou_coherent_ctrl: RW<u32>,
|
||||
pub video_pss_clk_sel: RW<u32>,
|
||||
pub iou_interconnect_route: RW<u32>,
|
||||
reserved6: [u32; 125],
|
||||
pub ctrl: RW<u32>,
|
||||
reserved7: [u32; 63],
|
||||
pub isr: RW<u32>, // todo: WTC LSB
|
||||
pub imr: RO<u32>,
|
||||
pub ier: WO<u32>,
|
||||
pub idr: WO<u32>,
|
||||
pub itr: WO<u32>,
|
||||
}
|
||||
register_at!(RegisterBlock, 0xFF18_0000, slcr);
|
||||
|
||||
impl SlcrRegisterBlock for RegisterBlock {
|
||||
// Dummy definition for consistency
|
||||
fn unlocked<F: FnMut(&mut Self) -> R, R>(mut f: F) -> R {
|
||||
let mut self_ = Self::slcr();
|
||||
f(&mut self_)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
register!(mio_pin, MioPin, RW, u32);
|
||||
register_bits!(mio_pin, l3_sel, u8, 5, 7);
|
||||
register_bits!(mio_pin, l2_sel, u8, 3, 4);
|
||||
register_bit!(mio_pin, l1_sel, 2);
|
||||
register_bit!(mio_pin, l0_sel, 1);
|
||||
|
||||
register!(bank_drive_ctrl, BankDriveCtrl, RW, u32);
|
||||
register_bits!(bank_drive_ctrl, drive, u32, 0, 25);
|
||||
|
||||
// 0 = CMOS, 1 = Schmitt
|
||||
register!(bank_input_ctrl, BankInputCtrl, RW, u32);
|
||||
register_bits!(bank_input_ctrl, schmitt, u32, 0, 25);
|
||||
|
||||
// 0 = down, 1 = up
|
||||
register!(bank_pull_ctrl, BankPullCtrl, RW, u32);
|
||||
register_bits!(bank_pull_ctrl, pull_up, u32, 0, 25);
|
||||
|
||||
register!(bank_pull_enable, BankPullEnable, RW, u32);
|
||||
register_bits!(bank_pull_enable, pull_enable, u32, 0, 25);
|
||||
|
||||
// 0 = fast, 1 = slow
|
||||
register!(bank_slew_ctrl, BankSlewCtrl, RW, u32);
|
||||
register_bits!(bank_slew_ctrl, slow_slew, u32, 0, 25);
|
||||
|
||||
// 0 = 2.5 or 3.3V, 1 = 1.8V
|
||||
register!(bank_status, BankStatus, RO, u32);
|
||||
register_bit!(bank_status, voltage_mode, 0);
|
||||
|
||||
|
||||
// todo: impl for MioPin (or RegisterBlock?) to make drive ctrl less obnoxious
|
||||
// might as well toss in convenience functions for pull up/down, etc.
|
@ -1,15 +0,0 @@
|
||||
///! Register definitions for UltraScale+ System Level Control
|
||||
pub mod common;
|
||||
pub mod crf_apb;
|
||||
// APU
|
||||
// FPD_SLCR
|
||||
// FPD_SLCR_SECURE
|
||||
pub mod iou_slcr;
|
||||
// IOU_SECURE_SLCR
|
||||
// IOU_SCNTRS
|
||||
// LPD_SLCR
|
||||
// LPD_SLCR_SECURE
|
||||
pub mod crl_apb;
|
||||
// RPU
|
||||
// CCI_GPV
|
||||
// FPD_GPV
|
@ -1,7 +0,0 @@
|
||||
use libregister::register_at;
|
||||
|
||||
use libboard_zynq::uart::baud_rate_gen;
|
||||
use libboard_zync::uart::regs::RegisterBlock;
|
||||
|
||||
register_at!(RegisterBlock, 0xFF000000, uart0);
|
||||
register_at!(RegisterBlock, 0xFF010000, uart1); // note: PS_UART1 is not connected on ZCU111
|
@ -6,14 +6,24 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
libboard_zynq = { path = "../libboard_zynq" }
|
||||
core_io = { version = "0.1", features = ["collections"] }
|
||||
fatfs = { version = "0.3", features = ["core_io"], default-features = false }
|
||||
log = "0.4"
|
||||
|
||||
[dependencies.core_io]
|
||||
git = "https://git.m-labs.hk/M-Labs/rs-core_io.git"
|
||||
rev = "e9d3edf027"
|
||||
features = ["collections"]
|
||||
|
||||
[dependencies.fatfs]
|
||||
git = "https://git.m-labs.hk/M-Labs/rust-fatfs.git"
|
||||
rev = "4b5e420084"
|
||||
default-features = false
|
||||
features = ["core_io"]
|
||||
|
||||
[features]
|
||||
target_zc706 = []
|
||||
target_coraz7 = []
|
||||
target_ebaz4205 = []
|
||||
target_redpitaya = []
|
||||
target_kasli_soc = []
|
||||
ipv6 = []
|
||||
fat_lfn = [ "fatfs/alloc" ]
|
||||
fat_lfn = [ "fatfs/alloc" ]
|
||||
|
@ -59,6 +59,10 @@ pub fn get_addresses(cfg: &Config) -> NetAddresses {
|
||||
let mut hardware_addr = get_address_from_eeprom();
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 56);
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
let mut hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x57]);
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 57);
|
||||
|
||||
if let Ok(Ok(addr)) = cfg.read_str("mac").map(|s| s.parse()) {
|
||||
hardware_addr = addr;
|
||||
|
@ -1,53 +1,60 @@
|
||||
use core::arch::asm;
|
||||
|
||||
/// The classic no-op
|
||||
#[inline]
|
||||
pub fn nop() {
|
||||
unsafe { llvm_asm!("nop" :::: "volatile") }
|
||||
unsafe { asm!("nop") }
|
||||
}
|
||||
|
||||
/// Wait For Event
|
||||
#[inline]
|
||||
pub fn wfe() {
|
||||
unsafe { llvm_asm!("wfe" :::: "volatile") }
|
||||
unsafe { asm!("wfe") }
|
||||
}
|
||||
|
||||
/// Send Event
|
||||
#[inline]
|
||||
pub fn sev() {
|
||||
unsafe { llvm_asm!("sev" :::: "volatile") }
|
||||
unsafe { asm!("sev") }
|
||||
}
|
||||
|
||||
/// Data Memory Barrier
|
||||
#[inline]
|
||||
pub fn dmb() {
|
||||
unsafe { llvm_asm!("dmb" :::: "volatile") }
|
||||
unsafe { asm!("dmb") }
|
||||
}
|
||||
|
||||
/// Data Synchronization Barrier
|
||||
#[inline]
|
||||
pub fn dsb() {
|
||||
unsafe { llvm_asm!("dsb" :::: "volatile") }
|
||||
unsafe { asm!("dsb") }
|
||||
}
|
||||
|
||||
/// Instruction Synchronization Barrier
|
||||
#[inline]
|
||||
pub fn isb() {
|
||||
unsafe { llvm_asm!("isb" :::: "volatile") }
|
||||
unsafe { asm!("isb") }
|
||||
}
|
||||
|
||||
/// Enable FIQ
|
||||
#[inline]
|
||||
pub unsafe fn enable_fiq() {
|
||||
asm!("cpsie f");
|
||||
}
|
||||
|
||||
/// Enable IRQ
|
||||
#[inline]
|
||||
pub unsafe fn enable_irq() {
|
||||
llvm_asm!("cpsie i":::: "volatile");
|
||||
asm!("cpsie i");
|
||||
}
|
||||
|
||||
/// Disable IRQ, return if IRQ was originally enabled.
|
||||
#[inline]
|
||||
pub unsafe fn enter_critical() -> bool {
|
||||
let mut cpsr: u32;
|
||||
llvm_asm!(
|
||||
"mrs $0, cpsr
|
||||
cpsid i"
|
||||
: "=r"(cpsr) ::: "volatile");
|
||||
asm!(
|
||||
"mrs {}, cpsr
|
||||
cpsid i", lateout(reg) cpsr);
|
||||
(cpsr & (1 << 7)) == 0
|
||||
}
|
||||
|
||||
@ -59,18 +66,18 @@ pub unsafe fn exit_critical(enable: bool) {
|
||||
} else {
|
||||
0
|
||||
};
|
||||
llvm_asm!(
|
||||
asm!(
|
||||
"mrs r1, cpsr
|
||||
bic r1, r1, $0
|
||||
bic r1, r1, {}
|
||||
msr cpsr_c, r1"
|
||||
:: "r"(mask) : "r1");
|
||||
, in(reg) mask, out("r1") _);
|
||||
}
|
||||
|
||||
/// Exiting IRQ
|
||||
#[inline]
|
||||
pub unsafe fn exit_irq() {
|
||||
llvm_asm!("
|
||||
asm!("
|
||||
mrs r0, SPSR
|
||||
msr CPSR, r0
|
||||
" ::: "r0");
|
||||
", out("r0") _);
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
use super::asm::{dmb, dsb};
|
||||
use super::l2c::*;
|
||||
use core::arch::asm;
|
||||
|
||||
/// Invalidate TLBs
|
||||
#[inline(always)]
|
||||
pub fn tlbiall() {
|
||||
unsafe {
|
||||
llvm_asm!("mcr p15, 0, $0, c8, c7, 0" :: "r" (0) :: "volatile");
|
||||
asm!("mcr p15, 0, {}, c8, c7, 0", in(reg) 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +14,7 @@ pub fn tlbiall() {
|
||||
#[inline(always)]
|
||||
pub fn iciallu() {
|
||||
unsafe {
|
||||
llvm_asm!("mcr p15, 0, $0, c7, c5, 0" :: "r" (0) :: "volatile");
|
||||
asm!("mcr p15, 0, {}, c7, c5, 0", in(reg) 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +22,7 @@ pub fn iciallu() {
|
||||
#[inline(always)]
|
||||
pub fn bpiall() {
|
||||
unsafe {
|
||||
llvm_asm!("mcr p15, 0, $0, c7, c5, 6" :: "r" (0) :: "volatile");
|
||||
asm!("mcr p15, 0, {}, c7, c5, 6", in(reg) 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +30,7 @@ pub fn bpiall() {
|
||||
#[inline(always)]
|
||||
pub fn dccsw(setway: u32) {
|
||||
unsafe {
|
||||
llvm_asm!("mcr p15, 0, $0, c7, c10, 2" :: "r" (setway) :: "volatile");
|
||||
asm!("mcr p15, 0, {}, c7, c10, 2", in(reg) setway);
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +42,7 @@ pub fn dcisw(setway: u32) {
|
||||
// also see example code (for DCCISW, but DCISW will be
|
||||
// analogous) "Example code for cache maintenance operations"
|
||||
// on pages B2-1286 and B2-1287.
|
||||
llvm_asm!("mcr p15, 0, $0, c7, c6, 2" :: "r" (setway) :: "volatile");
|
||||
asm!("mcr p15, 0, {}, c7, c6, 2", in(reg) setway);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +50,7 @@ pub fn dcisw(setway: u32) {
|
||||
#[inline(always)]
|
||||
pub fn dccisw(setway: u32) {
|
||||
unsafe {
|
||||
llvm_asm!("mcr p15, 0, $0, c7, c14, 2" :: "r" (setway) :: "volatile");
|
||||
asm!("mcr p15, 0, {}, c7, c14, 2", in(reg) setway);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +70,7 @@ pub fn dciall_l1() {
|
||||
|
||||
// select L1 data cache
|
||||
unsafe {
|
||||
llvm_asm!("mcr p15, 2, $0, c0, c0, 0" :: "r" (0) :: "volatile");
|
||||
asm!("mcr p15, 2, {}, c0, c0, 0", in(reg) 0);
|
||||
}
|
||||
|
||||
// Invalidate entire D-Cache by iterating every set and every way
|
||||
@ -104,7 +105,7 @@ pub fn dcciall_l1() {
|
||||
|
||||
// select L1 data cache
|
||||
unsafe {
|
||||
llvm_asm!("mcr p15, 2, $0, c0, c0, 0" :: "r" (0) :: "volatile");
|
||||
asm!("mcr p15, 2, {}, c0, c0, 0", in(reg) 0);
|
||||
}
|
||||
|
||||
// Invalidate entire D-Cache by iterating every set and every way
|
||||
@ -156,7 +157,7 @@ fn slice_cache_line_addrs<T>(slice: &[T]) -> impl Iterator<Item = usize> {
|
||||
#[inline(always)]
|
||||
pub fn dccimvac(addr: usize) {
|
||||
unsafe {
|
||||
llvm_asm!("mcr p15, 0, $0, c7, c14, 1" :: "r" (addr) :: "volatile");
|
||||
asm!("mcr p15, 0, {}, c7, c14, 1", in(reg) addr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,10 +199,9 @@ pub fn dcci_slice<T>(slice: &[T]) {
|
||||
#[inline(always)]
|
||||
pub fn dccmvac(addr: usize) {
|
||||
unsafe {
|
||||
llvm_asm!("mcr p15, 0, $0, c7, c10, 1" :: "r" (addr) :: "volatile");
|
||||
asm!("mcr p15, 0, {}, c7, c10, 1", in(reg) addr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Data cache clean for an object.
|
||||
pub fn dcc<T>(object: &T) {
|
||||
dmb();
|
||||
@ -239,7 +239,7 @@ pub fn dcc_slice<T>(slice: &[T]) {
|
||||
/// affecting more data than intended.
|
||||
#[inline(always)]
|
||||
pub unsafe fn dcimvac(addr: usize) {
|
||||
llvm_asm!("mcr p15, 0, $0, c7, c6, 1" :: "r" (addr) :: "volatile");
|
||||
asm!("mcr p15, 0, {}, c7, c6, 1", in(reg) addr);
|
||||
}
|
||||
|
||||
/// Data cache clean and invalidate for an object.
|
||||
|
@ -1,7 +1,8 @@
|
||||
use core::arch::asm;
|
||||
/// Enable FPU in the current core.
|
||||
pub fn enable_fpu() {
|
||||
unsafe {
|
||||
llvm_asm!("
|
||||
asm!("
|
||||
mrc p15, 0, r1, c1, c0, 2
|
||||
orr r1, r1, (0b1111<<20)
|
||||
mcr p15, 0, r1, c1, c0, 2
|
||||
@ -9,6 +10,6 @@ pub fn enable_fpu() {
|
||||
vmrs r1, fpexc
|
||||
orr r1, r1, (1<<30)
|
||||
vmsr fpexc, r1
|
||||
":::"r1");
|
||||
", out("r1") _);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
#![no_std]
|
||||
#![feature(llvm_asm, global_asm)]
|
||||
#![feature(never_type)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(global_asm)]
|
||||
#![feature(asm)]
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(inline_const)]
|
||||
#![feature(const_fn_trait_bound)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
@ -17,6 +20,7 @@ pub mod sync_channel;
|
||||
mod uncached;
|
||||
pub use fpu::enable_fpu;
|
||||
pub use uncached::UncachedSlice;
|
||||
use core::arch::global_asm;
|
||||
|
||||
global_asm!(include_str!("exceptions.s"));
|
||||
|
||||
@ -36,7 +40,9 @@ pub fn notify_spin_lock() {
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
/// Interrupt handler, which setup the stack and jump to actual interrupt handler.
|
||||
/// Interrupt handler, which setup the stack and preserve registers before jumping to actual interrupt handler.
|
||||
/// Registers r0-r12, PC, SP and CPSR are restored after the actual handler.
|
||||
///
|
||||
/// - `name` is the name of the interrupt, should be the same as the one defined in vector table.
|
||||
/// - `name2` is the name for the actual handler, should be different from name.
|
||||
/// - `stack0` is the stack for the interrupt handler when called from core0.
|
||||
@ -44,8 +50,7 @@ pub fn notify_spin_lock() {
|
||||
/// - `body` is the body of the actual interrupt handler, should be a normal unsafe rust function
|
||||
/// body.
|
||||
///
|
||||
/// Note that the interrupt handler would use the same stack as normal programs by default, so
|
||||
/// interrupt handlers should not return to normal program or it may corrupt the stack.
|
||||
/// Note that the interrupt handler would use the same stack as normal programs by default.
|
||||
macro_rules! interrupt_handler {
|
||||
($name:ident, $name2:ident, $stack0:ident, $stack1:ident, $body:block) => {
|
||||
#[link_section = ".text.boot"]
|
||||
@ -54,19 +59,27 @@ macro_rules! interrupt_handler {
|
||||
pub unsafe extern "C" fn $name() -> ! {
|
||||
asm!(
|
||||
// setup SP, depending on CPU 0 or 1
|
||||
// and preserve registers
|
||||
"sub lr, lr, #4",
|
||||
"stmfd sp!, {{r0-r12, lr}}",
|
||||
"mrc p15, #0, r0, c0, c0, #5",
|
||||
concat!("movw r1, :lower16:", stringify!($stack0)),
|
||||
concat!("movt r1, :upper16:", stringify!($stack0)),
|
||||
"tst r0, #3",
|
||||
concat!("movwne r1, :lower16:", stringify!($stack1)),
|
||||
concat!("movtne r1, :upper16:", stringify!($stack1)),
|
||||
"mov r0, sp",
|
||||
"mov sp, r1",
|
||||
"push {{r0, r1}}", // 2 registers are pushed to maintain 8 byte stack alignment
|
||||
concat!("bl ", stringify!($name2)),
|
||||
"pop {{r0, r1}}",
|
||||
"mov sp, r0",
|
||||
"ldmfd sp!, {{r0-r12, pc}}^", // caret ^ : copy SPSR to the CPSR
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn $name2() -> ! $body
|
||||
pub unsafe extern "C" fn $name2() $body
|
||||
};
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use libregister::{
|
||||
register_bit, register_bits,
|
||||
RegisterR, RegisterW, RegisterRW,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
macro_rules! def_reg_r {
|
||||
($name:tt, $type: ty, $asm_instr:tt) => {
|
||||
@ -11,7 +12,7 @@ macro_rules! def_reg_r {
|
||||
#[inline]
|
||||
fn read(&self) -> Self::R {
|
||||
let mut value: u32;
|
||||
unsafe { llvm_asm!($asm_instr : "=r" (value) ::: "volatile") }
|
||||
unsafe { asm!($asm_instr, lateout(reg) value) }
|
||||
value.into()
|
||||
}
|
||||
}
|
||||
@ -26,7 +27,7 @@ macro_rules! def_reg_w {
|
||||
#[inline]
|
||||
fn write(&mut self, value: Self::W) {
|
||||
let value: u32 = value.into();
|
||||
unsafe { llvm_asm!($asm_instr :: "r" (value) :: "volatile") }
|
||||
unsafe { asm!($asm_instr, in(reg) value) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -71,29 +72,29 @@ macro_rules! wrap_reg {
|
||||
|
||||
/// Stack Pointer
|
||||
pub struct SP;
|
||||
def_reg_r!(SP, u32, "mov $0, sp");
|
||||
def_reg_w!(SP, u32, "mov sp, $0");
|
||||
def_reg_r!(SP, u32, "mov {}, sp");
|
||||
def_reg_w!(SP, u32, "mov sp, {}");
|
||||
|
||||
/// Link register (function call return address)
|
||||
pub struct LR;
|
||||
def_reg_r!(LR, u32, "mov $0, lr");
|
||||
def_reg_w!(LR, u32, "mov lr, $0");
|
||||
def_reg_r!(LR, u32, "mov {}, lr");
|
||||
def_reg_w!(LR, u32, "mov lr, {}");
|
||||
|
||||
pub struct VBAR;
|
||||
def_reg_r!(VBAR, u32, "mrc p15, 0, $0, c12, c0, 0");
|
||||
def_reg_w!(VBAR, u32, "mcr p15, 0, $0, c12, c0, 0");
|
||||
def_reg_r!(VBAR, u32, "mrc p15, 0, {}, c12, c0, 0");
|
||||
def_reg_w!(VBAR, u32, "mcr p15, 0, {}, c12, c0, 0");
|
||||
|
||||
pub struct MVBAR;
|
||||
def_reg_r!(MVBAR, u32, "mrc p15, 0, $0, c12, c0, 1");
|
||||
def_reg_w!(MVBAR, u32, "mcr p15, 0, $0, c12, c0, 1");
|
||||
def_reg_r!(MVBAR, u32, "mrc p15, 0, {}, c12, c0, 1");
|
||||
def_reg_w!(MVBAR, u32, "mcr p15, 0, {}, c12, c0, 1");
|
||||
|
||||
pub struct HVBAR;
|
||||
def_reg_r!(HVBAR, u32, "mrc p15, 4, $0, c12, c0, 0");
|
||||
def_reg_w!(HVBAR, u32, "mcr p15, 4, $0, c12, c0, 0");
|
||||
def_reg_r!(HVBAR, u32, "mrc p15, 4, {}, c12, c0, 0");
|
||||
def_reg_w!(HVBAR, u32, "mcr p15, 4, {}, c12, c0, 0");
|
||||
|
||||
/// Multiprocess Affinity Register
|
||||
pub struct MPIDR;
|
||||
def_reg_r!(MPIDR, mpidr::Read, "mrc p15, 0, $0, c0, c0, 5");
|
||||
def_reg_r!(MPIDR, mpidr::Read, "mrc p15, 0, {}, c0, c0, 5");
|
||||
wrap_reg!(mpidr);
|
||||
register_bits!(mpidr,
|
||||
/// CPU core index
|
||||
@ -106,15 +107,15 @@ register_bit!(mpidr,
|
||||
u, 30);
|
||||
|
||||
pub struct DFAR;
|
||||
def_reg_r!(DFAR, u32, "mrc p15, 0, $0, c6, c0, 0");
|
||||
def_reg_r!(DFAR, u32, "mrc p15, 0, {}, c6, c0, 0");
|
||||
|
||||
pub struct DFSR;
|
||||
def_reg_r!(DFSR, u32, "mrc p15, 0, $0, c5, c0, 0");
|
||||
def_reg_r!(DFSR, u32, "mrc p15, 0, {}, c5, c0, 0");
|
||||
|
||||
pub struct SCTLR;
|
||||
wrap_reg!(sctlr);
|
||||
def_reg_r!(SCTLR, sctlr::Read, "mrc p15, 0, $0, c1, c0, 0");
|
||||
def_reg_w!(SCTLR, sctlr::Write, "mcr p15, 0, $0, c1, c0, 0");
|
||||
def_reg_r!(SCTLR, sctlr::Read, "mrc p15, 0, {}, c1, c0, 0");
|
||||
def_reg_w!(SCTLR, sctlr::Write, "mcr p15, 0, {}, c1, c0, 0");
|
||||
register_bit!(sctlr,
|
||||
/// Enables MMU
|
||||
m, 0);
|
||||
@ -147,8 +148,8 @@ register_bit!(sctlr,
|
||||
/// Auxiliary Control Register
|
||||
pub struct ACTLR;
|
||||
wrap_reg!(actlr);
|
||||
def_reg_r!(ACTLR, actlr::Read, "mrc p15, 0, $0, c1, c0, 1");
|
||||
def_reg_w!(ACTLR, actlr::Write, "mcr p15, 0, $0, c1, c0, 1");
|
||||
def_reg_r!(ACTLR, actlr::Read, "mrc p15, 0, {}, c1, c0, 1");
|
||||
def_reg_w!(ACTLR, actlr::Write, "mcr p15, 0, {}, c1, c0, 1");
|
||||
// SMP bit
|
||||
register_bit!(actlr, parity_on, 9);
|
||||
register_bit!(actlr, alloc_one_way, 8);
|
||||
@ -183,17 +184,17 @@ impl ACTLR {
|
||||
|
||||
/// Domain Access Control Register
|
||||
pub struct DACR;
|
||||
def_reg_r!(DACR, u32, "mrc p15, 0, $0, c3, c0, 0");
|
||||
def_reg_w!(DACR, u32, "mcr p15, 0, $0, c3, c0, 0");
|
||||
def_reg_r!(DACR, u32, "mrc p15, 0, {}, c3, c0, 0");
|
||||
def_reg_w!(DACR, u32, "mcr p15, 0, {}, c3, c0, 0");
|
||||
|
||||
/// Translation Table Base Register 0
|
||||
pub struct TTBR0;
|
||||
/// Translation Table Base Register 1
|
||||
pub struct TTBR1;
|
||||
def_reg_r!(TTBR0, ttbr::Read, "mrc p15, 0, $0, c2, c0, 0");
|
||||
def_reg_w!(TTBR0, ttbr::Write, "mcr p15, 0, $0, c2, c0, 0");
|
||||
def_reg_r!(TTBR1, ttbr::Read, "mrc p15, 0, $0, c2, c0, 1");
|
||||
def_reg_w!(TTBR1, ttbr::Write, "mcr p15, 0, $0, c2, c0, 1");
|
||||
def_reg_r!(TTBR0, ttbr::Read, "mrc p15, 0, {}, c2, c0, 0");
|
||||
def_reg_w!(TTBR0, ttbr::Write, "mcr p15, 0, {}, c2, c0, 0");
|
||||
def_reg_r!(TTBR1, ttbr::Read, "mrc p15, 0, {}, c2, c0, 1");
|
||||
def_reg_w!(TTBR1, ttbr::Write, "mcr p15, 0, {}, c2, c0, 1");
|
||||
wrap_reg!(ttbr);
|
||||
register_bits!(ttbr, table_base, u32, 14, 31);
|
||||
register_bit!(ttbr, irgn0, 6);
|
||||
|
@ -172,13 +172,15 @@ impl<'a, T> Iterator for Receiver<'a, T> where T: Clone {
|
||||
|
||||
#[macro_export]
|
||||
/// Macro for initializing the sync_channel with static buffer and indexes.
|
||||
/// Note that this requires `#![feature(const_in_array_repeat_expressions)]`
|
||||
macro_rules! sync_channel {
|
||||
($t: ty, $cap: expr) => {
|
||||
{
|
||||
use core::sync::atomic::{AtomicUsize, AtomicPtr};
|
||||
use $crate::sync_channel::{Sender, Receiver};
|
||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [AtomicPtr::new(core::ptr::null_mut()); $cap + 1];
|
||||
const fn new_atomic() -> AtomicPtr<$t> {
|
||||
AtomicPtr::new(core::ptr::null_mut())
|
||||
}
|
||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [const { new_atomic() }; $cap + 1];
|
||||
static WRITE: AtomicUsize = AtomicUsize::new(0);
|
||||
static READ: AtomicUsize = AtomicUsize::new(0);
|
||||
(Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ))
|
||||
|
@ -19,8 +19,8 @@ impl<T> UncachedSlice<T> {
|
||||
.max(L1_PAGE_SIZE);
|
||||
let layout = Layout::from_size_align(size, align)?;
|
||||
let ptr = unsafe { alloc::alloc::alloc(layout).cast::<T>() };
|
||||
assert!(!ptr.is_null());
|
||||
let start = ptr as usize;
|
||||
assert_eq!(start & (L1_PAGE_SIZE - 1), 0);
|
||||
|
||||
for page_start in (start..(start + size)).step_by(L1_PAGE_SIZE) {
|
||||
// non-shareable device
|
||||
@ -33,9 +33,6 @@ impl<T> UncachedSlice<T> {
|
||||
}
|
||||
|
||||
let slice = unsafe { core::slice::from_raw_parts_mut(ptr, len) };
|
||||
// verify size
|
||||
assert!(unsafe { slice.get_unchecked(len) } as *const _ as usize <= start + size);
|
||||
// initialize
|
||||
for e in slice.iter_mut() {
|
||||
*e = default();
|
||||
}
|
||||
|
@ -290,19 +290,6 @@ macro_rules! register_bits {
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
($mod_name: ident, $(#[$outer:meta])* $name: ident, $type: ty, $bit_begin: expr, $bit_end: expr, RO) => (
|
||||
impl $mod_name::Read {
|
||||
#[allow(unused)]
|
||||
#[inline]
|
||||
$(#[$outer])*
|
||||
pub fn $name(&self) -> $type {
|
||||
use bit_field::BitField;
|
||||
|
||||
self.inner.get_bits($bit_begin..=$bit_end) as $type
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// Define a multi-bit field of a register, coerced to a certain type
|
||||
|
@ -8,17 +8,19 @@ edition = "2018"
|
||||
[features]
|
||||
target_zc706 = ["libboard_zynq/target_zc706"]
|
||||
target_coraz7 = ["libboard_zynq/target_coraz7"]
|
||||
target_ebaz4205 = ["libboard_zynq/target_ebaz4205"]
|
||||
target_redpitaya = ["libboard_zynq/target_redpitaya"]
|
||||
target_kasli_soc = ["libboard_zynq/target_kasli_soc"]
|
||||
panic_handler = []
|
||||
dummy_irq_handler = []
|
||||
dummy_fiq_handler = []
|
||||
alloc_core = []
|
||||
|
||||
default = ["panic_handler", "dummy_irq_handler"]
|
||||
default = ["panic_handler", "dummy_irq_handler", "dummy_fiq_handler"]
|
||||
|
||||
[dependencies]
|
||||
r0 = "1"
|
||||
compiler_builtins = "=0.1.39"
|
||||
compiler_builtins = "=0.1.49"
|
||||
linked_list_allocator = { version = "0.8", default-features = false, features = ["const_mut_refs"] }
|
||||
libregister = { path = "../libregister" }
|
||||
libcortex_a9 = { path = "../libcortex_a9" }
|
||||
|
@ -1,5 +1,6 @@
|
||||
use r0::zero_bss;
|
||||
use core::ptr::write_volatile;
|
||||
use core::arch::asm;
|
||||
use libregister::{
|
||||
VolatileCell,
|
||||
RegisterR, RegisterRW,
|
||||
@ -54,6 +55,7 @@ unsafe extern "C" fn boot_core0() -> ! {
|
||||
asm::dmb();
|
||||
asm::dsb();
|
||||
|
||||
asm::enable_fiq();
|
||||
asm::enable_irq();
|
||||
main_core0();
|
||||
panic!("return from main");
|
||||
@ -75,6 +77,7 @@ unsafe extern "C" fn boot_core1() -> ! {
|
||||
asm::dmb();
|
||||
asm::dsb();
|
||||
|
||||
asm::enable_fiq();
|
||||
asm::enable_irq();
|
||||
main_core1();
|
||||
panic!("return from main_core1");
|
||||
|
@ -1,6 +1,11 @@
|
||||
use libregister::RegisterR;
|
||||
use libcortex_a9::{regs::{DFSR, MPIDR}, interrupt_handler};
|
||||
use libboard_zynq::{println, stdio};
|
||||
use libregister::{RegisterR, RegisterW};
|
||||
use libcortex_a9::{regs::{DFSR, MPIDR, VBAR}, interrupt_handler};
|
||||
use libboard_zynq::{println, stdio};
|
||||
use core::arch::asm;
|
||||
|
||||
pub fn set_vector_table(base_addr: u32){
|
||||
VBAR.write(base_addr);
|
||||
}
|
||||
|
||||
interrupt_handler!(UndefinedInstruction, undefined_instruction, __irq_stack0_start, __irq_stack1_start, {
|
||||
stdio::drop_uart();
|
||||
@ -42,6 +47,7 @@ interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
||||
loop {}
|
||||
});
|
||||
|
||||
#[cfg(feature = "dummy_fiq_handler")]
|
||||
interrupt_handler!(FIQ, fiq, __irq_stack0_start, __irq_stack1_start, {
|
||||
stdio::drop_uart();
|
||||
println!("FIQ");
|
@ -3,13 +3,14 @@
|
||||
#![feature(alloc_error_handler)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(global_asm)]
|
||||
#![feature(asm)]
|
||||
|
||||
pub extern crate alloc;
|
||||
pub extern crate compiler_builtins;
|
||||
|
||||
pub mod boot;
|
||||
mod abort;
|
||||
pub mod exception_vectors;
|
||||
#[cfg(feature = "panic_handler")]
|
||||
mod panic;
|
||||
pub mod ram;
|
||||
|
33
openocd/ebaz4205.cfg
Normal file
33
openocd/ebaz4205.cfg
Normal file
@ -0,0 +1,33 @@
|
||||
# The contents of this file are partially dependend on
|
||||
# the adapter that you have. Please modify accordingly.
|
||||
adapter driver ftdi
|
||||
ftdi vid_pid 0x0403 0x6010
|
||||
ftdi channel 0
|
||||
# Every pin set as high impedance except TCK, TDI, TDO and TMS
|
||||
ftdi layout_init 0x0088 0x008b
|
||||
|
||||
# nSRST defined on pin CN2-13 of the MiniModule (pin ADBUS5 [AD5] on the FT2232H chip)
|
||||
# This choice is arbitrary. Use other GPIO pin if desired.
|
||||
ftdi layout_signal nSRST -data 0x0020 -oe 0x0020
|
||||
|
||||
transport select jtag
|
||||
adapter speed 10000
|
||||
|
||||
set PL_TAPID 0x13722093
|
||||
set SMP 1
|
||||
|
||||
source ./zynq-7000.cfg
|
||||
|
||||
reset_config srst_only srst_open_drain
|
||||
adapter srst pulse_width 250
|
||||
adapter srst delay 400
|
||||
|
||||
source ./common.cfg
|
||||
|
||||
reset halt
|
||||
|
||||
# Disable MMU
|
||||
targets $_TARGETNAME_1
|
||||
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
||||
targets $_TARGETNAME_0
|
||||
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
@ -8,6 +8,7 @@ edition = "2018"
|
||||
[features]
|
||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
|
||||
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7", "libconfig/target_coraz7"]
|
||||
target_ebaz4205 = ["libboard_zynq/target_ebaz4205", "libsupport_zynq/target_ebaz4205", "libconfig/target_ebaz4205"]
|
||||
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya", "libconfig/target_redpitaya"]
|
||||
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc", "libconfig/target_kasli_soc"]
|
||||
default = ["target_zc706"]
|
||||
@ -15,10 +16,14 @@ default = ["target_zc706"]
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
byteorder = { version = "1.3", default-features = false }
|
||||
core_io = { version = "0.1", features = ["collections"] }
|
||||
|
||||
libboard_zynq = { path = "../libboard_zynq" }
|
||||
libsupport_zynq = { path = "../libsupport_zynq" }
|
||||
libcortex_a9 = { path = "../libcortex_a9" }
|
||||
libregister = { path = "../libregister" }
|
||||
libconfig = { path = "../libconfig" }
|
||||
|
||||
[dependencies.core_io]
|
||||
git = "https://git.m-labs.hk/M-Labs/rs-core_io.git"
|
||||
rev = "e9d3edf027"
|
||||
features = ["collections"]
|
||||
|
||||
|
@ -80,12 +80,15 @@ pub fn main_core0() {
|
||||
);
|
||||
info!("Simple Zynq Loader starting...");
|
||||
|
||||
#[cfg(not(feature = "target_kasli_soc"))]
|
||||
#[cfg(not(any(feature = "target_kasli_soc", feature = "target_ebaz4205")))]
|
||||
const CPU_FREQ: u32 = 800_000_000;
|
||||
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
const CPU_FREQ: u32 = 1_000_000_000;
|
||||
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
const CPU_FREQ: u32 = 666_666_666;
|
||||
|
||||
ArmPll::setup(2 * CPU_FREQ);
|
||||
Clocks::set_cpu_freq(CPU_FREQ);
|
||||
IoPll::setup(1_000_000_000);
|
||||
|
Loading…
Reference in New Issue
Block a user