rockchip-pm 0.3.1

Driver for Rockchip Power Management Unit (PMU) supporting RK3588 and similar SoCs.
Documentation

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

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:

// 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:

// 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:

// 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:

Parent Domain Child Domains Description
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

# Install required tools
cargo install ostool

# Add target architecture support
rustup target add aarch64-unknown-none-softfloat

Building

# 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

# 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

# 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.