blob: 255f73556852125cb541d98badb550d701343cdb [file]
// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0
//! AST10x0 SCU low-level register access.
use ast1060_pac as device;
use core::cell::UnsafeCell;
use core::marker::PhantomData;
const SCU_UNLOCK_KEY: u32 = 0x1688_A8A8;
/// Safe wrapper around the AST10x0 SCU register block.
pub struct ScuRegisters {
base: *const device::scu::RegisterBlock,
_not_sync: PhantomData<UnsafeCell<()>>, // Prevent Sync, allow Send.
}
impl ScuRegisters {
/// Create a register accessor from a raw SCU register block pointer.
///
/// # Safety
/// Caller must ensure:
/// - `base` points to a valid SCU register block.
/// - access to the SCU instance is serialized appropriately.
const unsafe fn new(base: *const device::scu::RegisterBlock) -> Self {
Self {
base,
_not_sync: PhantomData,
}
}
/// Create a register accessor for the global SCU instance.
///
/// # Safety
/// Caller must ensure access to the singleton SCU is coordinated.
const unsafe fn new_global() -> Self {
// SAFETY: Caller upholds the singleton access contract.
unsafe { Self::new(device::Scu::ptr()) }
}
/// Create a register accessor for the global SCU instance, with write
/// protection immediately unlocked.
///
/// Follows the aspeed-rust pattern: unlock once, then perform all
/// register writes in sequence without re-locking between operations.
///
/// # Safety
/// Caller must ensure access to the singleton SCU is coordinated.
pub unsafe fn new_global_unlocked() -> Self {
// SAFETY: Caller upholds the singleton access contract.
let scu = unsafe { Self::new_global() };
scu.unlock_write_protection();
scu
}
#[inline]
pub fn regs(&self) -> &device::scu::RegisterBlock {
// SAFETY: Constructor guarantees a valid SCU register block pointer.
unsafe { &*self.base }
}
/// Unlock SCU write-protected registers for subsequent write operations.
///
/// Call this once before a sequence of SCU writes, following the aspeed-rust
/// pattern of a single unlock per batch of register operations.
#[inline]
fn unlock_write_protection(&self) {
self.regs()
.scu000()
.write(|w| unsafe { w.bits(SCU_UNLOCK_KEY) });
}
}