#[cfg(target_arch = "aarch64")]
mod arch {
use core::arch::asm;
pub const CORE0_AFF: u64 = 0x200;
pub const CORE1_AFF: u64 = 0x201;
pub const CORE2_AFF: u64 = 0x00;
pub const CORE3_AFF: u64 = 0x100;
pub const FCORE_NUM: u64 = 4;
pub(crate) fn mpidr2cpuid(mpidr: u64) -> usize {
match (mpidr & 0xfff) {
CORE0_AFF => 0,
CORE1_AFF => 1,
CORE2_AFF => 2,
CORE3_AFF => 3,
_ => {
error!("Failed to get PhytiumPi CPU Id from mpidr={:#x}", mpidr);
0
}
}
}
#[inline]
fn read_mpidr() -> u64 {
let mut reg_r = 0;
unsafe {
core::arch::asm!("mrs {}, MPIDR_EL1", out(reg) reg_r);
}
reg_r
}
pub(crate) fn get_cpu_id() -> usize {
let mpidr = read_mpidr();
mpidr2cpuid(mpidr)
}
pub(crate) fn DSB() {
unsafe {
core::arch::asm!("dsb sy");
}
}
#[inline]
fn MFCPSR() -> u32 {
let mut rval: u32 = 0;
unsafe {
asm!("mrs {0:x}, DAIF", out(reg) rval);
}
rval
}
#[inline]
fn MTCPSR(val: u32) {
unsafe {
asm!("msr DAIF, {0:x}", in(reg) val);
}
}
#[inline]
fn MTCPDC_CIVAC(adr: u64) {
unsafe {
asm!("dc CIVAC, {}", in(reg) adr);
}
}
#[inline]
fn MTCPDC_CVAC(adr: u64) {
unsafe {
asm!("dc CVAC, {}", in(reg) adr);
}
}
pub const CACHE_LINE_ADDR_MASK: u64 = 0x3F;
pub const CACHE_LINE: u64 = 64;
pub const IRQ_FIQ_MASK: u32 = 0xC0;
pub(crate) fn FCacheDCacheInvalidateRange(mut adr: u64, len: u64) {
let end: u64 = adr + len;
adr &= !CACHE_LINE_ADDR_MASK;
let currmask: u32 = MFCPSR();
MTCPSR(currmask | IRQ_FIQ_MASK);
if (len != 0) {
while adr < end {
MTCPDC_CIVAC(adr);
adr += CACHE_LINE;
}
}
DSB();
MTCPSR(currmask);
}
pub(crate) fn FCacheDCacheFlushRange(mut adr: u64, len: u64) {
let end: u64 = adr + len;
adr &= !CACHE_LINE_ADDR_MASK;
let currmask: u32 = MFCPSR();
MTCPSR(currmask | IRQ_FIQ_MASK);
if len != 0 {
while (adr < end) {
MTCPDC_CVAC(adr);
adr += CACHE_LINE;
}
}
DSB();
MTCPSR(currmask);
}
use aarch64_cpu::registers::{CNTFRQ_EL0, CNTVCT_EL0, Readable};
#[inline]
pub fn now_tsc() -> u64 {
CNTVCT_EL0.get()
}
#[inline]
pub fn timer_freq() -> u64 {
CNTFRQ_EL0.get()
}
}
#[cfg(not(target_arch = "aarch64"))]
mod arch {
pub fn timer_freq() -> u64 {
unimplemented!()
}
pub fn now_tsc() -> u64 {
unimplemented!()
}
pub(crate) fn get_cpu_id() -> usize {
unimplemented!()
}
pub(crate) fn DSB() {
unimplemented!()
}
pub(crate) fn FCacheDCacheFlushRange(mut adr: u64, len: u64) {
unimplemented!()
}
pub(crate) fn FCacheDCacheInvalidateRange(mut adr: u64, len: u64) {
unimplemented!()
}
}
use alloc::boxed::Box;
pub use arch::*;
#[inline]
pub(crate) fn now_ns() -> u64 {
let freq = timer_freq();
now_tsc() * (1_000_000_000 / freq)
}
pub(crate) fn ticks_to_nanos(ticks: u64) -> u64 {
let freq = timer_freq();
ticks * (1_000_000_000 / freq)
}
pub(crate) fn usdelay(us: u64) {
let mut current_ticks: u64 = now_tsc();
let delay2 = current_ticks + us * (timer_freq() / 1000000);
while delay2 >= current_ticks {
core::hint::spin_loop();
current_ticks = now_tsc();
}
trace!("usdelay current_ticks: {}", current_ticks);
}
pub(crate) fn msdelay(ms: u64) {
usdelay(ms * 1000);
}
#[linkage = "weak"]
#[unsafe(export_name = "virt_to_phys_fxmac")]
pub(crate) fn virt_to_phys(addr: usize) -> usize {
debug!("fxmac: virt_to_phys_fxmac {:#x}", addr);
addr
}
#[linkage = "weak"]
#[unsafe(export_name = "phys_to_virt_fxmac")]
pub(crate) fn phys_to_virt(addr: usize) -> usize {
debug!("fxmac: phys_to_virt_fxmac {:#x}", addr);
addr
}
#[linkage = "weak"]
#[unsafe(export_name = "dma_alloc_coherent_fxmac")]
pub(crate) fn dma_alloc_coherent(pages: usize) -> (usize, usize) {
let paddr: Box<[u32]> = if pages == 1 {
Box::new([0; 1024]) } else if pages == 8 {
Box::new([0; 1024 * 8]) } else {
warn!("Alloc {} pages failed", pages);
Box::new([0; 1024])
};
let len = paddr.len();
let paddr = Box::into_raw(paddr) as *const u32 as usize;
let vaddr = paddr;
debug!("fxmac: dma alloc paddr: {:#x}, len={}", paddr, len);
(vaddr, paddr)
}
#[linkage = "weak"]
#[unsafe(export_name = "dma_free_coherent_fxmac")]
pub(crate) fn dma_free_coherent(vaddr: usize, pages: usize) {
debug!("fxmac: dma free vaddr: {:#x}, pages={}", vaddr, pages);
let palloc = vaddr as *mut [u32; 1024];
unsafe {
drop(Box::from_raw(palloc));
}
}
#[linkage = "weak"]
#[unsafe(export_name = "dma_request_irq_fxmac")]
pub(crate) fn dma_request_irq(irq: usize, handler: fn()) {
warn!("dma_request_irq_fxmac unimplemented");
}