use crate::{ecall1, SbiError};
pub const EXTENSION_ID: usize = 0x43505043;
#[doc(hidden)]
pub trait CastRegisterValue: Sized + Copy {
fn cast(from: usize) -> Self;
fn reverse_cast(self) -> usize;
fn hi_lo(self) -> (usize, usize);
}
impl CastRegisterValue for u64 {
fn cast(from: usize) -> Self {
from as u64
}
fn reverse_cast(self) -> usize {
self as usize
}
fn hi_lo(self) -> (usize, usize) {
((self >> 32) as usize, (self & 0xFFFF_FFFF) as usize)
}
}
impl CastRegisterValue for u32 {
fn cast(from: usize) -> Self {
from as u32
}
fn reverse_cast(self) -> usize {
self as usize
}
fn hi_lo(self) -> (usize, usize) {
(0, self as usize)
}
}
pub trait Register {
const ID: u32;
type Width: CastRegisterValue;
}
pub trait Readable: Register {}
pub trait Writable: Register {}
pub mod registers {
use super::{Readable, Register, Writable};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct HighestPerformance;
impl Readable for HighestPerformance {}
impl Register for HighestPerformance {
const ID: u32 = 0x00000000;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NominalPerformance;
impl Readable for NominalPerformance {}
impl Register for NominalPerformance {
const ID: u32 = 0x00000001;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LowestNonlinearPerformance;
impl Readable for LowestNonlinearPerformance {}
impl Register for LowestNonlinearPerformance {
const ID: u32 = 0x00000002;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LowestPerformance;
impl Readable for LowestPerformance {}
impl Register for LowestPerformance {
const ID: u32 = 0x00000003;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct GuaranteedPerformance;
impl Readable for GuaranteedPerformance {}
impl Register for GuaranteedPerformance {
const ID: u32 = 0x00000004;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DesiredPerformance;
impl Readable for DesiredPerformance {}
impl Writable for DesiredPerformance {}
impl Register for DesiredPerformance {
const ID: u32 = 0x00000005;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MinimumPerformance;
impl Readable for MinimumPerformance {}
impl Writable for MinimumPerformance {}
impl Register for MinimumPerformance {
const ID: u32 = 0x00000006;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MaximumPerformance;
impl Readable for MaximumPerformance {}
impl Writable for MaximumPerformance {}
impl Register for MaximumPerformance {
const ID: u32 = 0x00000007;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PerformanceReductionTolerance;
impl Readable for PerformanceReductionTolerance {}
impl Writable for PerformanceReductionTolerance {}
impl Register for PerformanceReductionTolerance {
const ID: u32 = 0x00000008;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TimeWindow;
impl Readable for TimeWindow {}
impl Writable for TimeWindow {}
impl Register for TimeWindow {
const ID: u32 = 0x00000009;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CounterWraparoundTime;
impl Readable for CounterWraparoundTime {}
impl Register for CounterWraparoundTime {
const ID: u32 = 0x0000000A;
type Width = u64;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ReferencePerformanceCounter;
impl Readable for ReferencePerformanceCounter {}
impl Register for ReferencePerformanceCounter {
const ID: u32 = 0x0000000B;
type Width = u64;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DeliveredPerformanceCounter;
impl Readable for DeliveredPerformanceCounter {}
impl Register for DeliveredPerformanceCounter {
const ID: u32 = 0x0000000C;
type Width = u64;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PerformanceLimited;
impl Readable for PerformanceLimited {}
impl Writable for PerformanceLimited {}
impl Register for PerformanceLimited {
const ID: u32 = 0x0000000D;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CppcEnable;
impl Readable for CppcEnable {}
impl Writable for CppcEnable {}
impl Register for CppcEnable {
const ID: u32 = 0x0000000E;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AutonomousSelectionEnable;
impl Readable for AutonomousSelectionEnable {}
impl Writable for AutonomousSelectionEnable {}
impl Register for AutonomousSelectionEnable {
const ID: u32 = 0x0000000F;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AutonomousAcivityWindow;
impl Readable for AutonomousAcivityWindow {}
impl Writable for AutonomousAcivityWindow {}
impl Register for AutonomousAcivityWindow {
const ID: u32 = 0x00000010;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EnergyPerformancePreference;
impl Readable for EnergyPerformancePreference {}
impl Writable for EnergyPerformancePreference {}
impl Register for EnergyPerformancePreference {
const ID: u32 = 0x00000011;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ReferencePerformance;
impl Readable for ReferencePerformance {}
impl Register for ReferencePerformance {
const ID: u32 = 0x00000012;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LowestFrequency;
impl Readable for LowestFrequency {}
impl Register for LowestFrequency {
const ID: u32 = 0x00000013;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NominalFrequency;
impl Readable for NominalFrequency {}
impl Register for NominalFrequency {
const ID: u32 = 0x00000014;
type Width = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TransitionLatency;
impl Readable for TransitionLatency {}
impl Register for TransitionLatency {
const ID: u32 = 0x80000000;
type Width = u32;
}
}
#[doc(alias = "sbi_cppc_probe")]
pub fn probe_register<R: Register>(
#[allow(unused_variables)] register: R,
) -> Result<Option<usize>, SbiError> {
let ret = unsafe { ecall1(R::ID as usize, EXTENSION_ID, 0) }?;
match ret {
0 => Ok(None),
_ => Ok(Some(ret)),
}
}
#[doc(alias = "sbi_cppc_read")]
pub fn read_register<R: Readable>(
#[allow(unused_variables)] register: R,
) -> Result<R::Width, SbiError> {
unsafe { ecall1(R::ID as usize, EXTENSION_ID, 1) }.map(<R::Width as CastRegisterValue>::cast)
}
#[doc(alias = "sbi_cppc_read_hi")]
pub fn read_register_hi<R: Readable>(
#[allow(unused_variables)] register: R,
) -> Result<R::Width, SbiError> {
unsafe { ecall1(R::ID as usize, EXTENSION_ID, 2) }.map(<R::Width as CastRegisterValue>::cast)
}
#[doc(alias = "sbi_cppc_write")]
pub fn write_register<R: Readable>(
#[allow(unused_variables)] register: R,
value: R::Width,
) -> Result<(), SbiError> {
#[cfg(target_arch = "riscv64")]
unsafe {
crate::ecall2(
R::ID as usize,
<R::Width as CastRegisterValue>::reverse_cast(value),
EXTENSION_ID,
3,
)?;
};
#[cfg(target_arch = "riscv32")]
unsafe {
let (high, low) = <R::Width as CastRegisterValue>::hi_lo(value);
crate::ecall3(R::ID as usize, low, high, EXTENSION_ID, 3)?;
};
Ok(())
}