Skip to content

Commit

Permalink
尝试补全 probe
Browse files Browse the repository at this point in the history
  • Loading branch information
creatoy committed Aug 7, 2024
1 parent b1f9142 commit cf2291a
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 25 deletions.
65 changes: 52 additions & 13 deletions drivers/i2c/busses/i2c_bcm2835_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ use kernel::{
prelude::*,
str::CString,
sync::Arc,
{c_str, container_of, define_of_id_table, module_platform_driver},
{c_str, container_of, define_of_id_table, module_platform_driver, new_completion},
};

/// I2C 地址预留空间
const I2C_SIZE: usize = 0x100;
const I2C_SIZE: usize = 0x200;

/// I2C 控制寄存器地址偏移
pub const BCM2835_I2C_C: usize = 0x0;
Expand Down Expand Up @@ -97,7 +97,7 @@ struct Bcm2835Debug {
// Use Vec<T> as a ptr buf
struct Bcm2835I2cDev {
dev: Device,
regs: IoMem<I2C_SIZE>,
reg_base: *mut u8,
irq: i32,
adapter: I2cAdapter,
completion: Completion,
Expand Down Expand Up @@ -221,13 +221,13 @@ impl ClkOps for ClkBcm2835I2cOps {

impl Bcm2835I2cDev {
pub(crate) fn bcm2835_i2c_writel(&mut self, reg: usize, val: u32) {
let i2c_reg = self.regs.get();
let i2c_reg = self.reg_base;
let addr = i2c_reg.wrapping_add(reg);
unsafe { bindings::writel(val as _, addr as _) }
}

pub(crate) fn bcm2835_i2c_readl(&mut self, reg: usize) -> u32 {
let i2c_reg = self.regs.get();
let i2c_reg = self.reg_base;
let addr = i2c_reg.wrapping_add(reg);
unsafe { bindings::readl(addr as _) }
}
Expand Down Expand Up @@ -402,6 +402,10 @@ fn bcm2835_i2c_isr(this_irq: i32, data: *mut core::ffi::c_void) -> irq::Return {
irq::Return::None
}

unsafe extern "C" fn bcm2835_i2c_isr_cb(this_irq: i32, data: *mut core::ffi::c_void) -> u32 {
bcm2835_i2c_isr(this_irq, data) as u32
}

fn goto_complete(i2c_dev: &mut Bcm2835I2cDev) -> irq::Return {
i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
i2c_dev.bcm2835_i2c_writel(
Expand Down Expand Up @@ -538,14 +542,49 @@ impl platform::Driver for Bcm2835I2cDriver {
pdev: &mut platform::Device,
id_info: core::prelude::v1::Option<&Self::IdInfo>,
) -> Result<Self::Data> {
pr_info!("BCM2835 i2c bus device ({}) driver probe.\n", pdev.name());

// TODO: initialize and probe i2c driver
/*let i2c_dev = unsafe {
let dev = &mut *(pdev.raw_device().dev) as &mut Device;
dev.kzall
};*/
// TODO: initialize i2c_dev
dev_info!(
pdev,
"BCM2835 i2c bus device ({}) driver probe.\n",
pdev.name()
);

let dev = unsafe { Device::new(pdev.raw_device()) };
let i2c_dev_ptr: *mut Bcm2835I2cDev = dev.kzalloc::<Bcm2835I2cDev>()?;

let i2c_dev = unsafe { &mut (*i2c_dev_ptr) };
i2c_dev.dev = dev;
i2c_dev.completion.reinit();
i2c_dev.reg_base = pdev.ioremap_resource(0)?;
dev_info!(pdev, "I2c bus device reg_base: {:?}\n", i2c_dev.reg_base);

let mclk = i2c_dev.dev.clk_get()?;

// TODO: initialise i2c bus clock
// let bus_clk =

let mut bus_clk_rate = 0;
let ret = i2c_dev
.dev
.of_property_read_u32(c_str!("clock-frequency"), &mut bus_clk_rate);
dev_info!(pdev, "I2c bus device clock-frequency: {}\n", bus_clk_rate);

let irq = pdev.irq_resource(0)?;
i2c_dev.irq = irq;

let ret = unsafe {
bindings::request_threaded_irq(
irq as u32,
Some(bcm2835_i2c_isr_cb),
None,
bindings::IRQF_SHARED as u64,
c_str!("i2c_bcm2835_rust").as_char_ptr(),
i2c_dev_ptr as *mut core::ffi::c_void,
)
};
if ret == 0 {
dev_err!(pdev, "Could not request IRQ: {}\n", irq);
// TODO: disable bus clock
}

let dev_data =
kernel::new_device_data!((), (), Bcm2835I2cData {}, "BCM2835_I2C device data")?;
Expand Down
6 changes: 6 additions & 0 deletions rust/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ void *rust_helper_dev_get_drvdata(struct device *dev)
}
EXPORT_SYMBOL_GPL(rust_helper_dev_get_drvdata);

void rust_helper_dev_set_drvdata(struct device *dev, void *data)
{
dev_set_drvdata(dev, data);
}
EXPORT_SYMBOL_GPL(rust_helper_dev_set_drvdata);

const char *rust_helper_dev_name(const struct device *dev)
{
return dev_name(dev);
Expand Down
12 changes: 6 additions & 6 deletions rust/kernel/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,9 @@ impl Device {
}

/// Allocate(kmalloc) and return the corresponding mutable pointer.
pub fn kmalloc<T>(&self) -> Result<*mut T> {
pub fn kmalloc<T>(&self, gfp: bindings::gfp_t) -> Result<*mut T> {
let size = core::mem::size_of::<T>();
let ptr = unsafe {
bindings::devm_kmalloc(self.ptr, size, bindings::GFP_KERNEL | bindings::__GFP_ZERO)
};
let ptr = unsafe { bindings::devm_kmalloc(self.ptr, size, gfp) };
if ptr.is_null() {
return Err(ENOMEM);
}
Expand All @@ -253,13 +251,15 @@ impl Device {
}

// Find and read an array of 32 bit from a property.
pub unsafe fn of_property_read_u32(&self, propname: &'static CStr, out_values: *mut u32) -> Result {
pub fn of_property_read_u32(&self, propname: &'static CStr, out_values: &mut u32) -> Result {
// SAFETY: The safety requirements are satisfied by the existence of `RawDevice` and its
// safety requirements.
let ret = unsafe {
let np = (*self.raw_device()).of_node;
bindings::of_property_read_variable_u32_array(
np,
propname.as_char_ptr(),
out_values,
out_values as *mut u32,
1,
0,
)
Expand Down
4 changes: 1 addition & 3 deletions rust/kernel/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,7 @@ impl I2cAdapter {
}

pub unsafe fn i2c_set_adapdata<T>(&mut self, data: *mut T) {
unsafe {
self.0.dev.driver_data = data as *mut c_void;
}
unsafe { bindings::dev_set_drvdata(&self.0.dev as *const _ as *mut _, data as *mut c_void) }
}

pub fn i2c_add_adapter(&self) -> Result {
Expand Down
12 changes: 9 additions & 3 deletions rust/kernel/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
bindings,
device::{self, RawDevice},
driver,
error::{from_err_ptr, from_result, to_result, Result},
error::{from_err_ptr, from_result, to_result, Error, Result},
io_mem::Resource,
of,
str::CStr,
Expand Down Expand Up @@ -188,9 +188,15 @@ impl Device {
}

/// Returns irq of the platform device.
pub fn irq_resource(&self, index: u32) -> Result {
pub fn irq_resource(&self, index: u32) -> Result<i32> {
// SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
to_result(unsafe { bindings::platform_get_irq(self.ptr, index) })
let res = unsafe { bindings::platform_get_irq(self.ptr, index) };

if res < 0 {
Err(Error::from_errno(res))
} else {
Ok(res)
}
}

/// Return ioremap ptr
Expand Down

0 comments on commit cf2291a

Please sign in to comment.