# Rockchip Power Management Driver (rockchip-pm)
A Rust library for Rockchip SoC power management, based on the Linux kernel driver `pm_domains.c`.
## Features
- 🔋 **Complete Power Domain Control**: Support for RK3568 and RK3588 power domains
- 🚀 **Full-featured Implementation**: Memory power control, bus idle management, and complete power sequencing
- 🛡️ **Memory Safe**: Leveraging Rust's type system for memory safety and thread safety
- 📋 **No Standard Library**: `#![no_std]` design suitable for embedded environments
- 🎯 **Hardware Accurate**: Direct translation from Linux kernel implementation
- 🔌 **Multi-Chip Support**: Extensible architecture supporting multiple Rockchip SoC families
## Supported Power Domains
## Usage Example
```rust
use rockchip_pm::{RockchipPM, RkBoard, PowerDomain, RK3568, RK3588};
use core::ptr::NonNull;
// Initialize PMU for RK3588 (base address should be obtained from device tree)
let pmu_base = unsafe { NonNull::new_unchecked(0xfd8d8000 as *mut u8) };
let mut pm_rk3588 = RockchipPM::new(pmu_base, RkBoard::Rk3588);
// Method 1: Use chip-specific constants (Recommended)
pm_rk3588.power_domain_on(RK3588::NPU1)?; // NPU core 1
// Method 2: Create PowerDomain directly with ID
let NPU1 = PowerDomain::new(10);
pm_rk3588.power_domain_on(NPU1)?; // NPU1 (ID: 10)
```
### Choosing the Right Method
**Method 1 (Named Constants)** - Recommended for most use cases:
- ✅ Clear and self-documenting code
- ✅ Compile-time verification
- ✅ IDE autocomplete support
- ✅ Prevents using wrong IDs
**Method 2 (Direct ID)** - Use when:
- Dynamic power domain selection is needed
- Working with power domain IDs from configuration files
- Interfacing with external systems that use raw IDs
- Need to query power domain ID: `domain.id()`
```
## Architecture
The library implements a complete power management sequence:
### Power-On Sequence
1. **Memory Power**: Power on domain memory (if available)
2. **Bus Idle Cancel**: Cancel bus idle requests
3. **Main Power**: Power on the main domain
4. **Repair Wait**: Wait for repair operations to complete
5. **State Verification**: Verify power state is stable
### Power-Off Sequence
1. **Bus Idle Request**: Request bus to enter idle state
2. **Main Power**: Power off the main domain
3. **State Verification**: Verify power state is stable
4. **Memory Power**: Power off domain memory (if available)
### Module Structure
```
rockchip-pm/
├── src/
│ ├── lib.rs # Main API and RockchipPM struct
│ ├── power_sequencer.rs # Complete power control sequencing
│ ├── memory_control.rs # Memory power management
│ ├── idle_control.rs # Bus idle control
│ ├── qos_control.rs # QoS register save/restore
│ ├── registers/ # Register definitions and access
│ └── variants/ # Chip-specific implementations
│ ├── mod.rs # Common structures
│ ├── _macros.rs # Domain definition macros
│ ├── rk3568.rs # RK3568-specific domains
│ └── rk3588.rs # RK3588-specific domains
└── tests/
└── test.rs # Integration tests
```
## Advanced Features
### Dependency Management
Power domains may have parent-child relationships that must be respected during power transitions:
- **Parent Dependencies**: Child domains require their parent domain to be powered on first
- **Child Dependencies**: Parent domains require all child domains to be powered off first
- **Safe Sequencing**: Use `_with_deps` methods to enforce dependency checking
#### Usage Example
```rust
use rockchip_pm::{RockchipPM, RkBoard, RK3588};
let mut pm = RockchipPM::new(pmu_base, RkBoard::Rk3588);
// Power on with dependency checking
// Example: NPU1 requires NPUTOP to be powered on first
pm.power_domain_on_with_deps(RK3588::NPUTOP)?; // Power on parent first
pm.power_domain_on_with_deps(RK3588::NPU1)?; // Then power on child
// Power off with dependency checking
// Child domains must be powered off before parent
pm.power_domain_off_with_deps(RK3588::NPU1)?; // Power off child first
pm.power_domain_off_with_deps(RK3588::NPUTOP)?; // Then power off parent
// Query currently active domains
let active = pm.get_active_domains();
for domain in active {
println!("Domain {} is active", domain.id());
}
```
#### Dependency Error Handling
If dependencies are not met, operations will fail with `PowerError::DependencyNotMet`:
```rust
// This will fail if NPUTOP is not powered on
match pm.power_domain_on_with_deps(RK3588::NPU1) {
Ok(()) => println!("NPU1 powered on successfully"),
Err(PowerError::DependencyNotMet) => {
println!("Parent domain NPUTOP must be powered on first");
// Power on parent first
pm.power_domain_on_with_deps(RK3588::NPUTOP)?;
pm.power_domain_on_with_deps(RK3588::NPU1)?;
}
Err(e) => return Err(e),
}
```
### QoS (Quality of Service) Management
The library includes comprehensive QoS infrastructure for managing hardware QoS settings:
- **Automatic QoS Preservation**: QoS settings (priority, mode, bandwidth, saturation, extcontrol) are saved before power domain shutdown
- **Seamless Restoration**: QoS configuration is automatically restored when the domain powers back on
- **Multi-port Support**: Each power domain can have multiple QoS ports (up to 8)
- **Five Register Types**:
- Priority (`0x08`): Bus access priority
- Mode (`0x0c`): QoS mode control
- Bandwidth (`0x10`): Bandwidth limitation
- Saturation (`0x14`): Saturation threshold
- ExtControl (`0x18`): Extended control
#### Configured QoS Domains (RK3588)
The following domains have QoS configuration:
- **GPU**: 2 QoS ports @ 0xFDF35000
- **NPU**: 4 QoS ports @ 0xFDF40000
- **VCODEC**: 3 QoS ports @ 0xFDF78000
- **VENC0**: 2 QoS ports @ 0xFDF50000
- **RKVDEC0**: 2 QoS ports @ 0xFDF48000
- **VOP**: 4 QoS ports @ 0xFDF60000
- **VI**: 2 QoS ports @ 0xFDF70000
#### QoS State Persistence
QoS states are maintained across power cycles:
```rust
// Check if domain has saved QoS state
if pm.has_qos_state(RK3588::GPU) {
println!("GPU has saved QoS configuration");
}
// Clear QoS state for a specific domain
pm.clear_qos_state(RK3588::GPU);
// Clear all QoS states
pm.clear_all_qos_states();
```
#### QoS Integration
QoS save/restore is automatically integrated into the power sequencing:
```rust
// Power off sequence includes QoS save
pm.power_domain_off(RK3588::GPU)?; // QoS automatically saved
// Power on sequence includes QoS restore
pm.power_domain_on(RK3588::GPU)?; // QoS automatically restored
```
**Note**: QoS operations are performed transparently during power transitions. No explicit QoS management is required from the user code. The integration ensures that performance-critical QoS settings are preserved across power cycles.
### RK3588 Domain Dependencies
The following parent-child relationships are configured:
| **NPUTOP** | NPU1, NPU2 | Neural Processing Unit hierarchy |
| **VCODEC** | VENC0, VENC1, RKVDEC0, RKVDEC1 | Video codec hierarchy |
| **VOP** | VO0, VO1 | Video Output Processor hierarchy |
| **VI** | ISP1 | Video Input and Image Signal Processor |
**Power-On Rule**: Parent must be powered on before any children
**Power-Off Rule**: All children must be powered off before parent
## Memory Mapping Requirements
To use this library, ensure:
1. **Correct PMU Base Address**:
- RK3588: Usually `0xfd8d8000` (verify from device tree)
- RK3568: Usually `0xfdd90000` (verify from device tree)
2. **Memory Mapping Permissions**: Read/write access to PMU register region
3. **Clock Configuration**: Ensure PMU clocks are properly configured
## Important Notes
⚠️ **CRITICAL**: This library directly manipulates hardware registers. Before use:
- System PMU hardware must be properly initialized
- No other drivers should control the same power domains concurrently
- Perform thorough validation before testing on real hardware
## Build and Test
### Environment Setup
```bash
# Install required tools
cargo install ostool
# Add target architecture support
rustup target add aarch64-unknown-none-softfloat
```
### Building
```bash
# Build library
cargo build
# Build release version
cargo build --release
# Check for errors
cargo check
```
### Running Tests
The test suite includes comprehensive unit and integration tests:
**Test Categories:**
- **Unit Tests**: DependencyManager functionality (4 tests)
- **QoS State Tests**: QoS state management (1 test)
- **Dependency Enforcement**: Parent-child power sequencing (4 tests)
- **Complex Hierarchies**: Multi-level dependencies (2 tests)
- **Edge Cases**: Error handling and invalid inputs (3 tests)
- **Integration Tests**: Real hardware testing (3 tests)
**Total: 17 comprehensive test cases**
```bash
# Run on development board (requires U-Boot environment)
cargo uboot
```
**Test Coverage:**
- ✅ DependencyManager state tracking
- ✅ Parent-child power sequencing enforcement
- ✅ Multi-level dependency hierarchies (VCODEC with 4 children)
- ✅ QoS state persistence
- ✅ Independent domain operations
- ✅ Error handling for invalid domains
- ✅ Active domain tracking
- ✅ Real NPU hardware verification
## Technical Features
### 🔒 Safety
- **Memory Safety**: Compile-time guarantees prevent dangling pointers
- **Type Safety**: Strong typing for power domains and states
- **Thread Safety**: Built-in synchronization mechanisms
- **Boundary Checks**: Automatic prevention of buffer overflows
### 🚀 Extensibility
- **Modular Design**: Trait-based register access abstraction
- **Easy Extension**: Simple addition of new power domains
- **Plugin Support**: Custom power policies and optimization algorithms
- **Platform Adaptation**: Easy porting to other Rockchip series chips
### 📱 Embedded Friendly
- **no-std Support**: Suitable for bare-metal environments
- **Small Memory Footprint**: Optimized memory usage
- **Efficient Access**: Direct memory-mapped I/O with minimal overhead
- **Real-time Response**: Low-latency power control
## Dependencies
### Core Dependencies
- **rdif-base**: Device driver framework
- **tock-registers**: Type-safe register access and bitfield operations
- **mbarrier**: Memory barrier primitives for register access ordering
### Development Dependencies
- **bare-test**: Bare-metal testing framework
### System Requirements
- **Rust Version**: 1.75.0 or higher
- **Target Architecture**: aarch64-unknown-none-softfloat
- **Development Environment**: Linux/macOS/Windows + Rust toolchain
- **Deployment Environment**: RK3588/RK3588S development board
## Hardware Compatibility
### Supported Chips
- **RK3568**: Quad-core ARM Cortex-A55 SoC with integrated NPU and GPU
- **RK3588**: Octa-core ARM Cortex-A55/A76 flagship SoC
- **RK3588S**: Cost-optimized variant of RK3588
### Development Boards
- **RK3568 Boards**:
- NanoPi R5S/R5C
- ROCK 3A/3B/3C
- Radxa E25
- Other RK3568-based boards
- **RK3588 Boards**:
- Orange Pi 5/5 Plus/5B
- Rock 5A/5B/5C
- NanoPC-T6
- Other RK3588/RK3588S-based boards
### Hardware Features
- **CPU Architecture**: ARM Cortex-A55/A76 heterogeneous cores
- **GPU**: Mali-G52 (RK3568) / Mali-G610 MP4 (RK3588)
- **NPU**: 1 TOPS (RK3568) / 6 TOPS (RK3588) AI accelerator
## License
This project is based on the same GPL-2.0 license as the Linux kernel.
## Contributing
Contributions are welcome! Please submit Issues and Pull Requests.
### Development Setup
```bash
# Clone the project
git clone <repository-url>
cd rockchip-pm
# Install dependencies
rustup component add rustfmt clippy
# Format code
cargo fmt
# Run linter
cargo clippy
```
## References
- Linux Kernel `drivers/soc/rockchip/pm_domains.c`
- RK3588 Technical Reference Manual
- Device Tree Bindings for Rockchip Power Domains
---
**Note**: This driver is low-level system software. Ensure that hardware register operations comply with chip specifications. Perform thorough testing before use in production environments.