Skip to content

Commit

Permalink
Merge pull request #1 from creatoy/nostalgia
Browse files Browse the repository at this point in the history
Modification on clk_provider, clk, i2c-bcm
  • Loading branch information
lvyuemeng authored Jul 29, 2024
2 parents 01a2940 + 9829db2 commit 88a540d
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 27 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,6 @@ sphinx_*/

# Rust analyzer configuration
/rust-project.json

# lsp config
code_init.sh
4 changes: 4 additions & 0 deletions drivers/i2c/busses/i2c_bcm2835_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ fn clk_bcm2835_i2c_recalc_rate(hw: &mut ClkHw, parent_rate: u32) -> u32 {
parent_rate.div_ceil(divider)
}

struct ClkBcm2835I2cOps;

impl ClkOps for ClkBcm2835I2cOps {}

impl kernel::Module for Bcm2835I2cDevice {
fn init(_module: &'static ThisModule) -> Result<Self> {
pr_info!("BCM2835 i2c bus device driver (init)\n");
Expand Down
7 changes: 4 additions & 3 deletions rust/kernel/clk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use crate::{
bindings,
clk_provider::ClkHw,
error::{to_result, Result},
str::CStr,
types::Opaque,
Expand Down Expand Up @@ -54,8 +53,10 @@ impl Clk {
}

pub fn name(&self) -> &CStr {
// SAFETY: call ffi and ptr is valid
unsafe { CStr::from_char_ptr(bindings::__clk_get_name(self.0.get())) }
// SAFETY: if clk is valid, name is valid. name must be a UTF-8 string.
unsafe {
CStr::from_char_ptr(bindings::__clk_get_name(self.0.get()))
}
}
}

Expand Down
135 changes: 111 additions & 24 deletions rust/kernel/clk_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@
use crate::{
bindings,
error::{to_result, Result},
error::{from_result, to_result, Result},
str::CStr,
types::{ForeignOwnable, Opaque},
};

use core::marker::PhantomData;

use alloc::vec::Vec;
use core::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit};
use macros::vtable;

/// Represents `struct clk_core`
///
/// # Invariants
Expand All @@ -35,7 +33,7 @@ pub struct ClkHw(Opaque<bindings::clk_hw>);

impl ClkHw {
/// Create ClkHw from raw ptr
pub fn from_raw<'a>(ptr: *mut bindings::clk_hw) -> &'a Self {
pub unsafe fn from_raw<'a>(ptr: *mut bindings::clk_hw) -> &'a Self {
let ptr = ptr.cast::<Self>();
unsafe { &*ptr }
}
Expand All @@ -46,6 +44,10 @@ impl ClkHw {
self.0.get()
}

pub fn name(&self) -> &CStr {
// SAFETY: if clk_hw is valid, name is valid. name must be UTF-8 string.
unsafe { CStr::from_char_ptr(bindings::clk_hw_get_name(self.0.get())) }
}
// Register one clock lookup for a struct clk_hw
pub fn register_clkdev(&mut self, con_id: &'static CStr, dev_id: &'static CStr) -> Result {
let ret = unsafe {
Expand All @@ -57,6 +59,22 @@ impl ClkHw {
};
to_result(ret)
}

// How to implement clk_hw api?
/*
pub fn prepare_enable(&mut self) -> Result {
// SAFETY: call ffi and ptr is valid
unsafe {
to_result(bindings::clk_ops::prepare(self.as_ptr()))?;
let ret = to_result(bindings::clk_ops::enable(self.as_ptr()));
if ret.is_err() {
bindings::clk_ops::unprepare(self.as_ptr());
return ret;
}
}
Ok(())
}
*/
}

/*
Expand All @@ -70,6 +88,55 @@ impl Drop for ClkHw {
}
*/

pub struct ClkInitData(bindings::clk_init_data);

impl ClkInitData {
/// Create a new ClkInitData
pub fn new() -> Self {
let up = unsafe { MaybeUninit::<bindings::clk_init_data>::zeroed().assume_init() };
Self(up)
}

/// Set the name config of the clk_init_data
///
/// It will automatically set the num_parents to the length of parent_names.
pub fn name_config(mut self, name: &CStr, parent_names: Vec<&'static CStr>) -> Self {
self.0.name = name.as_char_ptr();
self.0.num_parents = parent_names.len() as u8;
self.0.parent_names = {
let mut vec: Vec<*const i8> = Vec::new();
for s in parent_names {
vec.try_push(s.as_char_ptr());
}
vec.as_ptr()
};
self
}

pub fn ops<T>(mut self, _ops: T) -> Self
where
T: ClkOps,
{
let ops = Adapter::<T>::build();
self.0.ops = ops as *const bindings::clk_ops;
self
}

pub fn flags(mut self, flags: u64) -> Self {
self.0.flags = flags;
self
}
/// Create ClkInitData from raw ptr
///
/// # Safety
///
/// The pointer must be valid.
pub unsafe fn from_raw<'a>(ptr: *const bindings::clk_init_data) -> &'a Self {
let ptr = ptr.cast::<Self>();
unsafe { &*ptr }
}
}

/// Trait about a clock device's operations
#[vtable]
pub trait ClkOps {
Expand Down Expand Up @@ -104,28 +171,36 @@ pub trait ClkOps {
/// parent clock that should be used to provide the clock rate.
fn determine_rate(hw: &ClkHw, req: *mut bindings::clk_rate_request) -> i32;
/// Change the input source of this clock
fn set_parent(hw: &ClkHw, index: u8) -> i32;
/// Returns 0 on success, -EERROR otherwise.
fn set_parent(hw: &ClkHw, index: u8) -> Result;
/// Queries the hardware to determine the parent of a clock
fn get_parent(hw: &ClkHw) -> u8;
/// Change the rate of this clock
fn set_rate(hw: &ClkHw, rate: u64, parent_rate: u64) -> i32;
/// Returns 0 on success, -EERROR otherwise.
fn set_rate(hw: &ClkHw, rate: u64, parent_rate: u64) -> Result;
/// Change the rate and the parent of this clock
fn set_rate_and_parent(hw: &ClkHw, rate: u64, parent_rate: u64, index: u8) -> i32;
/// Returns 0 on success, -EERROR otherwise.
fn set_rate_and_parent(hw: &ClkHw, rate: u64, parent_rate: u64, index: u8) -> Result;
/// Recalculate the accuracy of this clock
fn recalc_accuracy(hw: &ClkHw, parent_accuracy: u64) -> u64;
/// Queries the hardware to get the current phase of a clock
/// error codes on failure.
fn get_phase(hw: &ClkHw) -> i32;
/// Shift the phase this clock signal in degrees specified by the second argument
fn set_phase(hw: &ClkHw, degrees: i32) -> i32;
/// Returns 0 on success, -EERROR otherwise.
fn set_phase(hw: &ClkHw, degrees: i32) -> Result;
/// Queries the hardware to get the current duty cycle ratio of a clock
fn get_duty_cycle(hw: &ClkHw, duty: *mut bindings::clk_duty) -> i32;
/// Apply the duty cycle ratio to this clock signal specified by the numerator (2nd argurment) and denominator (3rd argument)
fn set_duty_cycle(hw: &ClkHw, duty: *mut bindings::clk_duty) -> i32;
/// Returns 0 on success, -EERROR otherwise.
fn set_duty_cycle(hw: &ClkHw, duty: *mut bindings::clk_duty) -> Result;
/// Perform platform-specific initialization magic
fn init(hw: &ClkHw) -> i32;
/// Returns 0 on success, -EERROR otherwise.
fn init(hw: &ClkHw) -> Result;
/// Free any resource allocated by init
fn terminate(hw: &ClkHw);
/// Set up type-specific debugfs entries for this clock
/// Returns 0 on success, -EERROR otherwise.
fn debug_init(hw: &ClkHw, dentry: *mut bindings::dentry);
}

Expand Down Expand Up @@ -211,8 +286,10 @@ impl<T: ClkOps> Adapter<T> {
clk_hw: *mut bindings::clk_hw,
index: u8,
) -> core::ffi::c_int {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_parent(&hw, index)
from_result(|| {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_parent(&hw, index).and(Ok(0))
})
}

unsafe extern "C" fn get_parent_callback(clk_hw: *mut bindings::clk_hw) -> bindings::u8_ {
Expand All @@ -225,8 +302,10 @@ impl<T: ClkOps> Adapter<T> {
rate: u64,
parent_rate: u64,
) -> core::ffi::c_int {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_rate(&hw, rate, parent_rate)
from_result(|| {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_rate(&hw, rate, parent_rate).and(Ok(0))
})
}

unsafe extern "C" fn set_rate_and_parent_callback(
Expand All @@ -235,8 +314,10 @@ impl<T: ClkOps> Adapter<T> {
parent_rate: u64,
index: u8,
) -> core::ffi::c_int {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_rate_and_parent(&hw, rate, parent_rate, index)
from_result(|| {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_rate_and_parent(&hw, rate, parent_rate, index).and(Ok(0))
})
}

unsafe extern "C" fn recalc_accuracy_callback(
Expand All @@ -256,8 +337,10 @@ impl<T: ClkOps> Adapter<T> {
clk_hw: *mut bindings::clk_hw,
degrees: i32,
) -> core::ffi::c_int {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_phase(&hw, degrees)
from_result(|| {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_phase(&hw, degrees).and(Ok(0))
})
}

unsafe extern "C" fn get_duty_cycle_callback(
Expand All @@ -272,13 +355,17 @@ impl<T: ClkOps> Adapter<T> {
clk_hw: *mut bindings::clk_hw,
duty: *mut bindings::clk_duty,
) -> core::ffi::c_int {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_duty_cycle(&hw, duty)
from_result(|| {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::set_duty_cycle(&hw, duty).and(Ok(0))
})
}

unsafe extern "C" fn init_callback(clk_hw: *mut bindings::clk_hw) -> core::ffi::c_int {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::init(&hw)
from_result(|| {
let hw = unsafe { ClkHw::from_raw(clk_hw) };
T::init(&hw).and(Ok(0))
})
}

unsafe extern "C" fn terminate_callback(clk_hw: *mut bindings::clk_hw) {
Expand Down

0 comments on commit 88a540d

Please sign in to comment.