From 898ae1972903dccdec931ebb0ee42123db4548d2 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Tue, 13 Aug 2024 17:16:39 +0800 Subject: [PATCH 01/16] =?UTF-8?q?=E8=A1=A5=E5=85=A8I2c=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4bcm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I2c: 补全algorithm bcm: 调整代码布局,填充部分批注,函数 Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 102 +++++++------- rust/kernel/i2c.rs | 184 ++++++++++++++++++++++--- rust/kernel/platform.rs | 9 -- 3 files changed, 217 insertions(+), 78 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index b9cbc59e0740ba..f34ecc12977754 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -84,7 +84,7 @@ struct Bcm2835Debug { status: u32, } -// May Wrong! Vec for *mut T +// Vec for *mut T // C use u8* as a ptr msg_buf,i2c_msg* as a ptr i2c_msg // C use NULL, Rust use None. // Use Vec as a ptr buf @@ -115,15 +115,15 @@ impl Bcm2835I2cDev { } } -fn to_clk_bcm2835_i2c(hw_ptr: &ClkHw) -> &mut ClkBcm2835I2c<'_> { - unsafe { &mut *(container_of!(hw_ptr, ClkBcm2835I2c<'_>, hw) as *mut ClkBcm2835I2c<'_>) } -} - struct ClkBcm2835I2c<'c> { hw: ClkHw, i2c_dev: &'c Bcm2835I2cDev, } +fn to_clk_bcm2835_i2c(hw_ptr: &ClkHw) -> &mut ClkBcm2835I2c<'_> { + unsafe { &mut *(container_of!(hw_ptr, ClkBcm2835I2c<'_>, hw) as *mut ClkBcm2835I2c<'_>) } +} + impl<'c> ClkBcm2835I2c<'c> { fn from_raw<'a>(ptr: *mut Self) -> &'a mut Self { let ptr = ptr.cast::(); @@ -333,6 +333,7 @@ impl Bcm2835I2cDev { } } +// TODO: impl interrupt irq_handler fn bcm2835_i2c_isr(this_irq: i32, data: &mut Bcm2835I2cDev) -> irq::Return { let i2c_dev = unsafe { &mut *(data as *mut Bcm2835I2cDev) }; @@ -395,10 +396,6 @@ fn bcm2835_i2c_isr(this_irq: i32, data: &mut Bcm2835I2cDev) -> 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, unsafe { &mut *data.cast() }) 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( @@ -410,7 +407,11 @@ fn goto_complete(i2c_dev: &mut Bcm2835I2cDev) -> irq::Return { irq::Return::Handled } -fn bcm2835_i2c_xfer(adap: I2cAdapter, msgs: Vec, num: i32) -> Result<()> { +unsafe extern "C" fn bcm2835_i2c_isr_cb(this_irq: i32, data: *mut core::ffi::c_void) -> u32 { + bcm2835_i2c_isr(this_irq, unsafe { &mut *data.cast() }) as u32 +} + +fn bcm2835_i2c_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result<()> { let i2c_dev = unsafe { &mut (*adap.i2c_get_adapdata::()) }; let mut ignore_nak = false; @@ -482,53 +483,20 @@ fn bcm2835_i2c_xfer(adap: I2cAdapter, msgs: Vec, num: i32) -> Result<()> Err(EIO) } +#[inline] fn bcm2835_i2c_func(adap: I2cAdapter) -> u32 { i2c::I2C_FUNC_I2C | i2c::I2C_FUNC_10BIT_ADDR | i2c::I2C_FUNC_PROTOCOL_MANGLING } -// I2C_AQ .. -// const BCM2835_I2C_QUIRKS: I2cAdapterQuirks = -// I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); - struct Bcm2835I2cAlgo; -struct Bcm2835I2cData {} +static BCM2835_I2C_QUIRKS: I2cAdapterQuirks = + I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); -unsafe impl Sync for Bcm2835I2cData {} -unsafe impl Send for Bcm2835I2cData {} +unsafe impl Sync for Bcm2835I2cDev {} +unsafe impl Send for Bcm2835I2cDev {} -struct Bcm2835I2cDriver; - -module_platform_driver! { - type: Bcm2835I2cDriver, - name:"i2c_bcm2835_rust", - author:" <>", - description:"BCM2835 I2C bus driver (written in rust)", - license:"GPL", - initcall: "arch", - alias: ["platform:i2c-bcm2835"], - params: { - debug: u32 { - default: 0, - permissions: 0o644, - description: "1=err, 2=isr, 3=xfer", - }, - clk_out_ms: u32 { - default: 35, - permissions: 0o644, - description: "clock-stretch timeout (mS)", - }, - }, -} - -kernel::module_of_id_table!(BCM2835_I2C_MOD_TABLE, BCM2835_I2C_ID_TABLE); - -kernel::define_of_id_table! {BCM2835_I2C_ID_TABLE, (), [ - (DeviceId::Compatible(b"brcm,bcm2711-i2c"), None), - (DeviceId::Compatible(b"brcm,bcm2835-i2c"), None), -]} - -type DeviceData = device::Data<(), (), Bcm2835I2cData>; +type DeviceData = device::Data<(), (), Bcm2835I2cDev>; impl platform::Driver for Bcm2835I2cDriver { kernel::driver_of_id_table!(BCM2835_I2C_ID_TABLE); @@ -643,7 +611,41 @@ impl platform::Driver for Bcm2835I2cDriver { fn remove(_data: &Self::Data) -> Result { pr_info!("BCM2835 i2c bus device driver remove.\n"); - // TODO: remove i2c driver + // impl drop for: + // clk: clk_rate_exclusive_put, disable_unprepare + // irq: free_irq + // i2c_adapter: i2c_del_adapter Ok(()) } } + +kernel::define_of_id_table! {BCM2835_I2C_ID_TABLE, (), [ + (DeviceId::Compatible(b"brcm,bcm2711-i2c"), None), + (DeviceId::Compatible(b"brcm,bcm2835-i2c"), Some(BCM2835_I2C_QUIRKS)), +]} + +kernel::module_of_id_table!(BCM2835_I2C_MOD_TABLE, BCM2835_I2C_ID_TABLE); + +struct Bcm2835I2cDriver; + +module_platform_driver! { + type: Bcm2835I2cDriver, + name:"i2c_bcm2835_rust", + author:" <>", + description:"BCM2835 I2C bus adapter (rust)", + license:"GPL v2", + initcall: "arch", + alias: ["platform:i2c-bcm2835"], + params: { + debug: u32 { + default: 0, + permissions: 0o644, + description: "1=err, 2=isr, 3=xfer", + }, + clk_out_ms: u32 { + default: 35, + permissions: 0o644, + description: "clock-stretch timeout (mS)", + }, + }, +} diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 76cfbea485345f..6263b290e8cc22 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -1,12 +1,13 @@ use crate::{ device::{Device, RawDevice}, - error::{to_result, Result}, + error::{from_result, to_result, Result}, + prelude::ENOTSUPP, str::CStr, types::{ForeignOwnable, Opaque}, }; use alloc::vec::Vec; -use core::mem::MaybeUninit; use core::{ffi::c_void, marker::PhantomData}; +use core::{mem::MaybeUninit, slice}; use macros::vtable; pub const I2C_M_RD: u32 = bindings::I2C_M_RD; @@ -70,11 +71,18 @@ impl I2cAdapterQuirks { /// Represents i2c_msg /// -/// Note: buf is a raw pointer /// Note: all primitive fields are __u16 type in C, represented as u16 in Rust. +/// Note: buf is a raw pointer +/// Note: struct i2c_msg *msg is a i2c_msg ptr buf. pub struct I2cMsg(bindings::i2c_msg); impl I2cMsg { + // Create I2CMsg buf from raw pointer + pub fn from_raw<'a>(ptr: *mut bindings::i2c_msg, len: usize) -> &'a Vec { + let buf_ptr = unsafe { Vec::from_raw_parts(ptr.cast::(), len, len) }; + unsafe { &*ptr } + } + /// return flags of i2c_msg pub fn flags(&self) -> u16 { self.0.flags as u16 @@ -103,17 +111,16 @@ impl I2cMsg { } } -/* -impl Default for I2cMsg { - fn default() -> Self { - Self(bindings::i2c_msg::default()) - } -}*/ - /// Represents i2c_adapter /// pub struct I2cAdapter(bindings::i2c_adapter); impl I2cAdapter { + // Create I2CMsg from raw pointer + pub fn from_raw<'a>(ptr: *mut bindings::i2c_adapter) -> &'a Self { + let ptr = ptr.cast::(); + unsafe { &*ptr } + } + pub fn as_ptr(&self) -> *mut bindings::i2c_adapter { &self.0 as *const _ as *mut _ } @@ -178,8 +185,25 @@ impl Drop for I2cAdapter { } /// Represents i2c_smbus_data /// -pub struct I2cSmbusData(Opaque); +pub struct I2cSmbusData(bindings::i2c_smbus_data); + +impl I2cSmbusData { + pub fn from_raw<'a>(ptr: *mut bindings::i2c_smbus_data) -> &'a Self { + let ptr = ptr.cast::(); + unsafe { &*ptr } + } +} + +/// Represents i2c_client +/// +pub struct I2cClient(bindings::i2c_client); +impl I2cClient { + pub fn from_raw<'a>(ptr: *mut bindings::i2c_client) -> &'a Self { + let ptr = ptr.cast::(); + unsafe { &*ptr } + } +} /// Represents i2c_algorithm /// #[vtable] @@ -189,34 +213,156 @@ pub trait I2cAlgorithm { // Caution: May ! - fn master_xfer(adap: &mut I2cAdapter, msgs: &mut I2cMsg, num: i32) -> i32; + fn master_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result<()> { + Err(ENOTSUPP) + } - fn master_xfer_atomic(adap: &mut I2cAdapter, msgs: &mut I2cMsg, num: i32) -> i32; + fn master_xfer_atomic(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result<()> { + Err(ENOTSUPP) + } // Caution: read_write is c_char, flags is c_ushort! fn smbus_xfer( - adap: &mut I2cAdapter, + adap: &I2cAdapter, addr: u16, flags: u16, read_write: u8, command: u8, size: i32, - data: &mut I2cSmbusData, - ) -> i32; + data: &I2cSmbusData, + ) -> Result<()> { + Err(ENOTSUPP) + } fn smbus_xfer_atomic( - adap: &mut I2cAdapter, + adap: &I2cAdapter, addr: u16, flags: u16, read_write: u8, command: u8, size: i32, - data: &mut I2cSmbusData, - ) -> i32; + data: &I2cSmbusData, + ) -> Result<()> { + Err(ENOTSUPP) + } + + fn functionality(adap: &I2cAdapter) -> u32 { + 0 + } + + // IS_ENABLED(CONFIG_I2C_SLAVE) + fn reg_slave(i2c_client: &I2cClient) -> Result<()> { + Err(ENOTSUPP) + } + + fn unreg_slave(i2c_client: &I2cClient) -> Result<()> { + Err(ENOTSUPP) + } } pub(crate) struct Adapter(PhantomData); impl Adapter { // TODO! + unsafe extern "C" fn master_xfer_callback( + _adap: *mut bindings::i2c_adapter, + _msgs: *mut bindings::i2c_msg, + _num: core::ffi::c_int, + ) -> core::ffi::c_int { + from_result(|| { + let adap = unsafe { I2cAdapter::from_raw(_adap) }; + let msgs = unsafe { I2cMsg::from_raw(_msgs, num as usize) }; + T::master_xfer(adap, msgs, _num).and(0) + }) + } + unsafe extern "C" fn master_xfer_atomic_callback( + adap: *mut i2c_adapter, + msgs: *mut i2c_msg, + num: core::ffi::c_int, + ) -> core::ffi::c_int { + from_result(|| { + let adap = unsafe { I2cAdapter::from_raw(adap) }; + let msgs = unsafe { I2cMsg::from_raw(msgs, num as usize) }; + T::master_xfer_atomic(adap, msgs, num) + }) + } + + unsafe extern "C" fn smbus_xfer_callback( + adap: *mut i2c_adapter, + addr: u16_, + flags: core::ffi::c_ushort, + read_write: core::ffi::c_char, + command: u8_, + size: core::ffi::c_int, + data: *mut i2c_smbus_data, + ) -> core::ffi::c_int { + from_result(|| { + let adap = unsafe { I2cAdapter::from_raw(adap) }; + let data = unsafe { I2cSmbusData::from_raw(data) }; + T::smbus_xfer(adap, addr, flags, read_write, command, size, data).and(Ok(0)) + }) + } + + unsafe extern "C" fn smbus_xfer_atomic_callback( + adap: *mut i2c_adapter, + addr: u16_, + flags: core::ffi::c_ushort, + read_write: core::ffi::c_char, + command: u8_, + size: core::ffi::c_int, + data: *mut i2c_smbus_data, + ) -> core::ffi::c_int { + from_result(|| { + let adap = unsafe { I2cAdapter::from_raw(adap) }; + let data = unsafe { I2cSmbusData::from_raw(data) }; + T::smbus_xfer_atomic(adap, addr, flags, read_write, command, size, data).and(Ok(0)) + }) + } + + unsafe extern "C" fn functionality_callback(adap: *mut i2c_adapter) -> u32 { + let adap = unsafe { I2cAdapter::from_raw(adap) }; + T::functionality(adap) + } + + const VTABLE: bindings::i2c_algorithm = bindings::i2c_algorithm { + master_xfer: if T::HAS_MASTER_XFER { + Some(Adapter::::master_xfer_callback) + } else { + None + }, + master_xfer_atomic: if T::HAS_MASTER_XFER_ATOMIC { + Some(Adapter::::master_xfer_atomic_callback) + } else { + None + }, + smbus_xfer: if T::HAS_SMBUS_XFER { + Some(Adapter::::smbus_xfer_callback) + } else { + None + }, + smbus_xfer_atomic: if T::HAS_SMBUS_XFER_ATOMIC { + Some(Adapter::::smbus_xfer_atomic_callback) + } else { + None + }, + functionality: if T::HAS_FUNCTIONALITY { + Some(Adapter::::functionality_callback) + } else { + None + }, + reg_slave: if T::HAS_REG_SLAVE { + Some(Adapter::::reg_slave_callback) + } else { + None + }, + unreg_slave: if T::HAS_UNREG_SLAVE { + Some(Adapter::::unreg_slave_callback) + } else { + None + }, + }; + + const fn build() -> &'static bindings::i2c_algorithm { + &Adapter::::VTABLE + } } diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 6d1a1118602da6..44248ea515a5b6 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -207,15 +207,6 @@ impl Device { Ok(ptr as *mut u8) } } - - pub unsafe fn platform_set_drvdata(&self, data: *mut T) { - unsafe { bindings::platform_set_drvdata(self.ptr, data as *mut c_void) }; - } - - pub unsafe fn platform_get_drvdata(&self) -> *mut T { - unsafe { bindings::platform_get_drvdata(self.ptr) as *mut T } - } - // TODO! /* pub fn get_and_ioremap_resource(&self, index: u32) -> Result { From 331fe0c2c8db7c39032638a347f60dea5b58aa27 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Tue, 13 Aug 2024 17:16:39 +0800 Subject: [PATCH 02/16] =?UTF-8?q?=E8=A1=A5=E5=85=A8I2c=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4bcm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I2c: 补全algorithm bcm: 调整代码布局,填充部分批注,函数 Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index f34ecc12977754..7bf01ffea20f10 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -484,7 +484,7 @@ fn bcm2835_i2c_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result<() } #[inline] -fn bcm2835_i2c_func(adap: I2cAdapter) -> u32 { +fn bcm2835_i2c_func(adap: &I2cAdapter) -> u32 { i2c::I2C_FUNC_I2C | i2c::I2C_FUNC_10BIT_ADDR | i2c::I2C_FUNC_PROTOCOL_MANGLING } From b5973ff3492c0cbf390938715b6170f4f0b8a8cb Mon Sep 17 00:00:00 2001 From: creatoy Date: Fri, 9 Aug 2024 01:05:05 +0800 Subject: [PATCH 03/16] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E8=A1=A5=E5=85=A8=20pr?= =?UTF-8?q?obe=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index f9d8fa683a6083..5bc75fdcf9a2a2 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -603,6 +603,33 @@ impl platform::Driver for Bcm2835I2cDriver { } let _ = to_result(ret)?; + // TODO: setup i2c_adapter + let quirks = I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); + let mut adap = i2c_dev.adapter; + unsafe { + adap.i2c_set_adapdata(i2c_dev); + // adap.set_owner(); + adap.set_class(bindings::I2C_CLASS_DEPRECATED); + } + i2c_dev.adapter = adap; + + /* + * Disable the hardware clock stretching timeout. SMBUS + * specifies a limit for how long the device can stretch the + * clock, but core I2C doesn't. + */ + i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_CLKT, 0); + i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, 0); + + let ret = unsafe { bindings::i2c_add_adapter(adap.as_ptr()) }; + if ret < 0 { + dev_info!(pdev, "Could not add I2C adapter: {:?}\n", to_result(ret)); + unsafe { + bindings::free_irq(irq as u32, i2c_dev_ptr as *mut core::ffi::c_void); + } + } + let _ = to_result(ret)?; + let dev_data = kernel::new_device_data!((), (), Bcm2835I2cData {}, "BCM2835_I2C device data")?; /* From 2f002ab0907e3baa112ba516f27eaafbf4ebe451 Mon Sep 17 00:00:00 2001 From: creatoy Date: Sun, 11 Aug 2024 17:55:29 +0800 Subject: [PATCH 04/16] =?UTF-8?q?=E5=A4=84=E7=90=86=20prboe=20=E4=B8=AD?= =?UTF-8?q?=E7=94=9F=E5=91=BD=E5=91=A8=E6=9C=9F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 5bc75fdcf9a2a2..7eb91f73fccaad 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -605,13 +605,18 @@ impl platform::Driver for Bcm2835I2cDriver { // TODO: setup i2c_adapter let quirks = I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); - let mut adap = i2c_dev.adapter; + // let mut adap = i2c_dev.adapter; unsafe { - adap.i2c_set_adapdata(i2c_dev); - // adap.set_owner(); - adap.set_class(bindings::I2C_CLASS_DEPRECATED); + i2c_dev.adapter.i2c_set_adapdata(i2c_dev.as_ptr()); + // TODO: set owner + // i2c_dev.adapter.set_owner((&bindings::__this_module) as *const _ as *mut _); + i2c_dev.adapter.set_class(bindings::I2C_CLASS_DEPRECATED); + let full_name = bindings::of_node_full_name((*pdev.raw_device()).of_node); + let adap_name = + CString::try_from_fmt(fmt!("bcm2835 ({})", CStr::from_char_ptr(full_name)))?; + i2c_dev.adapter.set_name(&adap_name); } - i2c_dev.adapter = adap; + // i2c_dev.adapter = adap; /* * Disable the hardware clock stretching timeout. SMBUS @@ -621,7 +626,7 @@ impl platform::Driver for Bcm2835I2cDriver { i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_CLKT, 0); i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, 0); - let ret = unsafe { bindings::i2c_add_adapter(adap.as_ptr()) }; + let ret = unsafe { bindings::i2c_add_adapter(i2c_dev.adapter.as_ptr()) }; if ret < 0 { dev_info!(pdev, "Could not add I2C adapter: {:?}\n", to_result(ret)); unsafe { From 8c1108bd1955d75e0fee910ea2991c3c1a5c0a88 Mon Sep 17 00:00:00 2001 From: creatoy Date: Mon, 12 Aug 2024 21:00:01 +0800 Subject: [PATCH 05/16] =?UTF-8?q?=E8=A1=A5=E5=85=A8=20I2cAlgorithm=20Adapt?= =?UTF-8?q?er=20=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rust/kernel/i2c.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 65a41d65cca90f..7bd75493e9da19 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -263,7 +263,6 @@ pub trait I2cAlgorithm { pub(crate) struct Adapter(PhantomData); impl Adapter { - // TODO! unsafe extern "C" fn master_xfer_callback( _adap: *mut bindings::i2c_adapter, _msgs: *mut bindings::i2c_msg, From 0b90e04485f3975b4253ce2bbfa4a94552aea754 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Tue, 13 Aug 2024 17:16:39 +0800 Subject: [PATCH 06/16] =?UTF-8?q?=E8=A1=A5=E5=85=A8I2c=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4bcm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I2c: 补全algorithm bcm: 调整代码布局,填充部分批注,函数 Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 24 +++++++--- rust/kernel/i2c.rs | 62 +++++++++++++++----------- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 7eb91f73fccaad..7843f93b3c7200 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -416,7 +416,7 @@ unsafe extern "C" fn bcm2835_i2c_isr_cb(this_irq: i32, data: *mut core::ffi::c_v bcm2835_i2c_isr(this_irq, unsafe { &mut *data.cast() }) as u32 } -fn bcm2835_i2c_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result<()> { +fn bcm2835_i2c_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result { let i2c_dev = unsafe { &mut (*adap.i2c_get_adapdata::()) }; let mut ignore_nak = false; @@ -495,13 +495,27 @@ fn bcm2835_i2c_func(adap: &I2cAdapter) -> u32 { struct Bcm2835I2cAlgo; -static BCM2835_I2C_QUIRKS: I2cAdapterQuirks = - I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); +#[vtable] +impl I2cAlgorithm for Bcm2835I2cAlgo { + fn master_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result { + bcm2835_i2c_xfer(adap, msgs, num) + } + + fn functionality(adap: &I2cAdapter) -> u32 { + bcm2835_i2c_func(adap) + } +} + +//static BCM2835_I2C_QUIRKS: I2cAdapterQuirks = + //I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); +struct Bcm2835I2cData {} unsafe impl Sync for Bcm2835I2cDev {} unsafe impl Send for Bcm2835I2cDev {} +unsafe impl Sync for Bcm2835I2cData {} +unsafe impl Send for Bcm2835I2cData {} -type DeviceData = device::Data<(), (), Bcm2835I2cDev>; +type DeviceData = device::Data<(), (), Bcm2835I2cData>; impl platform::Driver for Bcm2835I2cDriver { kernel::driver_of_id_table!(BCM2835_I2C_ID_TABLE); @@ -659,7 +673,7 @@ impl platform::Driver for Bcm2835I2cDriver { kernel::define_of_id_table! {BCM2835_I2C_ID_TABLE, (), [ (DeviceId::Compatible(b"brcm,bcm2711-i2c"), None), - (DeviceId::Compatible(b"brcm,bcm2835-i2c"), Some(BCM2835_I2C_QUIRKS)), + (DeviceId::Compatible(b"brcm,bcm2835-i2c"), None), ]} kernel::module_of_id_table!(BCM2835_I2C_MOD_TABLE, BCM2835_I2C_ID_TABLE); diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 7bd75493e9da19..64366a7ffbfe97 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -49,6 +49,7 @@ pub const I2C_FUNC_SMBUS_EMUL_ALL: u32 = bindings::I2C_FUNC_SMBUS_EMUL_ALL; // No BIT macros. pub const I2C_AQ_NO_CLK_STRETCH: u32 = 1 << 4; + /// Represents i2c_adapter_quirks /// pub struct I2cAdapterQuirks(bindings::i2c_adapter_quirks); @@ -78,9 +79,9 @@ pub struct I2cMsg(bindings::i2c_msg); impl I2cMsg { // Create I2CMsg buf from raw pointer - pub fn from_raw<'a>(ptr: *mut bindings::i2c_msg, len: usize) -> &'a Vec { + pub fn from_raw<'a>(ptr: *mut bindings::i2c_msg, len: usize) -> Vec { let buf_ptr = unsafe { Vec::from_raw_parts(ptr.cast::(), len, len) }; - unsafe { &*ptr } + unsafe { buf_ptr } } /// return flags of i2c_msg @@ -213,11 +214,11 @@ pub trait I2cAlgorithm { // Caution: May ! - fn master_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result<()> { + fn master_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result { Err(ENOTSUPP) } - fn master_xfer_atomic(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result<()> { + fn master_xfer_atomic(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result { Err(ENOTSUPP) } @@ -230,7 +231,7 @@ pub trait I2cAlgorithm { command: u8, size: i32, data: &I2cSmbusData, - ) -> Result<()> { + ) -> Result { Err(ENOTSUPP) } @@ -242,7 +243,7 @@ pub trait I2cAlgorithm { command: u8, size: i32, data: &I2cSmbusData, - ) -> Result<()> { + ) -> Result { Err(ENOTSUPP) } @@ -263,20 +264,21 @@ pub trait I2cAlgorithm { pub(crate) struct Adapter(PhantomData); impl Adapter { + // TODO! unsafe extern "C" fn master_xfer_callback( - _adap: *mut bindings::i2c_adapter, - _msgs: *mut bindings::i2c_msg, - _num: core::ffi::c_int, + adap: *mut bindings::i2c_adapter, + msgs: *mut bindings::i2c_msg, + num: core::ffi::c_int, ) -> core::ffi::c_int { from_result(|| { - let adap = unsafe { I2cAdapter::from_raw(_adap) }; - let msgs = unsafe { I2cMsg::from_raw(_msgs, num as usize) }; - T::master_xfer(adap, msgs, _num).and(0) + let adap = unsafe { I2cAdapter::from_raw(adap) }; + let msgs = unsafe { I2cMsg::from_raw(msgs, num as usize) }; + T::master_xfer(adap, msgs, num) }) } unsafe extern "C" fn master_xfer_atomic_callback( - adap: *mut i2c_adapter, - msgs: *mut i2c_msg, + adap: *mut bindings::i2c_adapter, + msgs: *mut bindings::i2c_msg, num: core::ffi::c_int, ) -> core::ffi::c_int { from_result(|| { @@ -287,42 +289,52 @@ impl Adapter { } unsafe extern "C" fn smbus_xfer_callback( - adap: *mut i2c_adapter, - addr: u16_, + adap: *mut bindings::i2c_adapter, + addr: u16, flags: core::ffi::c_ushort, read_write: core::ffi::c_char, - command: u8_, + command: u8, size: core::ffi::c_int, - data: *mut i2c_smbus_data, + data: *mut bindings::i2c_smbus_data, ) -> core::ffi::c_int { from_result(|| { let adap = unsafe { I2cAdapter::from_raw(adap) }; let data = unsafe { I2cSmbusData::from_raw(data) }; - T::smbus_xfer(adap, addr, flags, read_write, command, size, data).and(Ok(0)) + T::smbus_xfer(adap, addr, flags, read_write, command, size, data) }) } unsafe extern "C" fn smbus_xfer_atomic_callback( - adap: *mut i2c_adapter, - addr: u16_, + adap: *mut bindings::i2c_adapter, + addr: u16, flags: core::ffi::c_ushort, read_write: core::ffi::c_char, - command: u8_, + command: u8, size: core::ffi::c_int, - data: *mut i2c_smbus_data, + data: *mut bindings::i2c_smbus_data, ) -> core::ffi::c_int { from_result(|| { let adap = unsafe { I2cAdapter::from_raw(adap) }; let data = unsafe { I2cSmbusData::from_raw(data) }; - T::smbus_xfer_atomic(adap, addr, flags, read_write, command, size, data).and(Ok(0)) + T::smbus_xfer_atomic(adap, addr, flags, read_write, command, size, data) }) } - unsafe extern "C" fn functionality_callback(adap: *mut i2c_adapter) -> u32 { + unsafe extern "C" fn functionality_callback(adap: *mut bindings::i2c_adapter) -> u32 { let adap = unsafe { I2cAdapter::from_raw(adap) }; T::functionality(adap) } + unsafe extern "C" fn reg_slave_callback(client: *mut bindings::i2c_client) -> core::ffi::c_int { + 0 + } + + unsafe extern "C" fn unreg_slave_callback( + client: *mut bindings::i2c_client, + ) -> core::ffi::c_int { + 0 + } + const VTABLE: bindings::i2c_algorithm = bindings::i2c_algorithm { master_xfer: if T::HAS_MASTER_XFER { Some(Adapter::::master_xfer_callback) From 0b583e56d58cff58792db4a22534ed8293266a6e Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Tue, 13 Aug 2024 17:16:39 +0800 Subject: [PATCH 07/16] =?UTF-8?q?=E8=A1=A5=E5=85=A8I2c=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4bcm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I2c: 补全algorithm bcm: 调整代码布局,填充部分批注,函数 Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 32 ++++++++++++++++++++------ rust/kernel/interrupt.rs | 2 +- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 7843f93b3c7200..37920534d5ba77 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -2,22 +2,23 @@ //! BCM2835 master mode driver use kernel::{ - bindings, + bindings, c_str, clk::Clk, clk_provider::{ClkHw, ClkInitData, ClkOps}, completion::Completion, + container_of, define_of_id_table, device::{self, Device, RawDevice}, driver::DeviceRemoval, error::to_result, i2c::{self, I2cAdapter, I2cAdapterQuirks, I2cAlgorithm, I2cMsg, I2C_M_NOSTART, I2C_M_RD}, + interrupt::{request_irq, IrqHandler, IRQF_SHARED}, io_mem::IoMem, - irq, + irq, module_platform_driver, new_completion, of::DeviceId, platform, prelude::*, str::CString, sync::Arc, - {c_str, container_of, define_of_id_table, module_platform_driver, new_completion}, }; /// I2C 地址预留空间 @@ -338,7 +339,6 @@ impl Bcm2835I2cDev { } } -// TODO: impl interrupt irq_handler fn bcm2835_i2c_isr(this_irq: i32, data: &mut Bcm2835I2cDev) -> irq::Return { let i2c_dev = unsafe { &mut *(data as *mut Bcm2835I2cDev) }; @@ -412,6 +412,16 @@ fn goto_complete(i2c_dev: &mut Bcm2835I2cDev) -> irq::Return { irq::Return::Handled } +struct Bcm2835I2cIrqHandler; + +impl IrqHandler for Bcm2835I2cIrqHandler { + type Context = Bcm2835I2cDev; + + fn handler(irq: i32, ctx: &mut Self::Context) -> irq::Return { + bcm2835_i2c_isr(irq, ctx) + } +} + unsafe extern "C" fn bcm2835_i2c_isr_cb(this_irq: i32, data: *mut core::ffi::c_void) -> u32 { bcm2835_i2c_isr(this_irq, unsafe { &mut *data.cast() }) as u32 } @@ -507,7 +517,7 @@ impl I2cAlgorithm for Bcm2835I2cAlgo { } //static BCM2835_I2C_QUIRKS: I2cAdapterQuirks = - //I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); +//I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); struct Bcm2835I2cData {} unsafe impl Sync for Bcm2835I2cDev {} @@ -568,7 +578,7 @@ impl platform::Driver for Bcm2835I2cDriver { let irq = pdev.irq_resource(0)?; - let ret = unsafe { + /*let ret = unsafe { bindings::request_threaded_irq( irq as u32, Some(bcm2835_i2c_isr_cb), @@ -581,7 +591,15 @@ impl platform::Driver for Bcm2835I2cDriver { if ret < 0 { dev_err!(pdev, "Could not request IRQ: {}\n", irq); to_result(ret)?; - } + }*/ + + request_irq( + irq as u32, + Bcm2835I2cIrqHandler, + IRQF_SHARED as u64, + c_str!("i2c_bcm2835_rust"), + &i2c_dev, + )?; i2c_dev.irq = irq; // TODO: setup i2c_adapter diff --git a/rust/kernel/interrupt.rs b/rust/kernel/interrupt.rs index 3a7f0271af8113..986d6ccfa83b79 100644 --- a/rust/kernel/interrupt.rs +++ b/rust/kernel/interrupt.rs @@ -10,7 +10,7 @@ use crate::{ irq, str::CStr, }; -use core::{marker::PhantomData, task::Context}; +use core::marker::PhantomData; pub const IRQF_TRIGGER_NONE: u32 = bindings::IRQF_TRIGGER_NONE; pub const IRQF_TRIGGER_RISING: u32 = bindings::IRQF_TRIGGER_RISING; From 0a526fdcc5119bf476c7f8e4b76c10105e387e46 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Tue, 13 Aug 2024 21:53:10 +0800 Subject: [PATCH 08/16] =?UTF-8?q?=E4=BF=AE=E6=94=B9bcm=5Frust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 尝试裸指针传递i2c_dev as Data Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 37920534d5ba77..7567aedb77dbbe 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 //! BCM2835 master mode driver +use core::ops::Deref; + use kernel::{ bindings, c_str, clk::Clk, @@ -525,7 +527,7 @@ unsafe impl Send for Bcm2835I2cDev {} unsafe impl Sync for Bcm2835I2cData {} unsafe impl Send for Bcm2835I2cData {} -type DeviceData = device::Data<(), (), Bcm2835I2cData>; +type DeviceData = device::Data<(), (), Bcm2835I2cDev>; impl platform::Driver for Bcm2835I2cDriver { kernel::driver_of_id_table!(BCM2835_I2C_ID_TABLE); @@ -667,8 +669,8 @@ impl platform::Driver for Bcm2835I2cDriver { } let _ = to_result(ret)?; - let dev_data = - kernel::new_device_data!((), (), Bcm2835I2cData {}, "BCM2835_I2C device data")?; + let item = unsafe { Box::from_raw(i2c_dev_ptr) }; + let dev_data = kernel::new_device_data!((), (), *item, "BCM2835_I2C device data")?; /* * Disable the hardware clock stretching timeout. SMBUS * specifies a limit for how long the device can stretch the From cf03d19e2ce08a3a841c1f44593e363fe905211e Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Wed, 14 Aug 2024 20:01:09 +0800 Subject: [PATCH 09/16] =?UTF-8?q?=E4=BF=AE=E6=94=B9bcm=5Frust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 尝试修改 probe 中的 unsafe 代码 改进 of_property_read_u32 Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 34 ++++++++++++++++---------- rust/kernel/device.rs | 17 ------------- rust/kernel/i2c.rs | 22 +++++++++++------ rust/kernel/of.rs | 25 ++++++++++++++++++- 4 files changed, 59 insertions(+), 39 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 7567aedb77dbbe..1ec0c492a05495 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -560,11 +560,20 @@ impl platform::Driver for Bcm2835I2cDriver { let bus_clk = i2c_dev.bcm2835_i2c_register_div(mclk)?; let mut bus_clk_rate = 0; - if let Err(_) = dev.of_property_read_u32(c_str!("clock-frequency"), &mut bus_clk_rate) { + if let Err(_) = dev + .of_node() + .read_u32(c_str!("clock-frequency"), &mut bus_clk_rate) + { + dev_warn!(pdev, "Could not read clock-frequency property\n"); bus_clk_rate = bindings::I2C_MAX_STANDARD_MODE_FREQ; }; dev_info!(pdev, "I2c bus device clock-frequency: {}\n", bus_clk_rate); + if let Err(_) = i2c_dev.bus_clk.set_rate_exclusive(bus_clk_rate as u64) { + dev_err!(pdev, "Could not set clock frequency\n"); + } + + /* let ret = unsafe { bindings::clk_set_rate_exclusive(bus_clk.as_ptr(), bus_clk_rate as u64) }; if ret < 0 { @@ -574,7 +583,7 @@ impl platform::Driver for Bcm2835I2cDriver { to_result(ret) ); to_result(ret)?; - } + }*/ i2c_dev.bus_clk.prepare_enable()?; @@ -595,22 +604,20 @@ impl platform::Driver for Bcm2835I2cDriver { to_result(ret)?; }*/ - request_irq( + if let Err(_) = request_irq( irq as u32, Bcm2835I2cIrqHandler, IRQF_SHARED as u64, c_str!("i2c_bcm2835_rust"), &i2c_dev, - )?; + ) { + dev_err!(pdev, "Could not request IRQ\n"); + } i2c_dev.irq = irq; - // TODO: setup i2c_adapter let quirks = I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); - // let mut adap = i2c_dev.adapter; unsafe { i2c_dev.adapter.i2c_set_adapdata(i2c_dev.as_ptr()); - // TODO: set owner - // i2c_dev.adapter.set_owner((&bindings::__this_module) as *const _ as *mut _); i2c_dev.adapter.set_class(bindings::I2C_CLASS_DEPRECATED); let full_name = bindings::of_node_full_name((*pdev.raw_device()).of_node); let adap_name = @@ -618,7 +625,6 @@ impl platform::Driver for Bcm2835I2cDriver { i2c_dev.adapter.set_name(&adap_name); i2c_dev.adapter.set_algorithm::(); } - // i2c_dev.adapter = adap; /* * Disable the hardware clock stretching timeout. SMBUS @@ -642,8 +648,7 @@ impl platform::Driver for Bcm2835I2cDriver { // let mut adap = i2c_dev.adapter; unsafe { i2c_dev.adapter.i2c_set_adapdata(i2c_dev.as_ptr()); - // TODO: set owner - // i2c_dev.adapter.set_owner((&bindings::__this_module) as *const _ as *mut _); + i2c_dev.adapter.set_owner(&THIS_MODULE); i2c_dev.adapter.set_class(bindings::I2C_CLASS_DEPRECATED); let full_name = bindings::of_node_full_name((*pdev.raw_device()).of_node); let adap_name = @@ -660,14 +665,17 @@ impl platform::Driver for Bcm2835I2cDriver { i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_CLKT, 0); i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, 0); - let ret = unsafe { bindings::i2c_add_adapter(i2c_dev.adapter.as_ptr()) }; + dbg!("Try to add I2C adapter..."); + i2c_dev.adapter.i2c_add_adapter()?; + dbg!("I2C adapter added!"); + /*let ret = unsafe { bindings::i2c_add_adapter(i2c_dev.adapter.as_ptr()) }; if ret < 0 { dev_info!(pdev, "Could not add I2C adapter: {:?}\n", to_result(ret)); unsafe { bindings::free_irq(irq as u32, i2c_dev_ptr as *mut core::ffi::c_void); } } - let _ = to_result(ret)?; + let _ = to_result(ret)?;*/ let item = unsafe { Box::from_raw(i2c_dev_ptr) }; let dev_data = kernel::new_device_data!((), (), *item, "BCM2835_I2C device data")?; diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index 6d1cf7e7ad025c..75dffb6a66efa7 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -257,23 +257,6 @@ impl Device { // return ptr must be null. Ok(ptr as *mut T) } - - // Find and read an array of 32 bit from a property. - 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 as *mut u32, - 1, - 0, - ) - }; - to_result(ret) - } } // SAFETY: The device returned by `raw_device` is the one for which we hold a reference. diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 64366a7ffbfe97..e09fe5f72456a9 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -4,6 +4,7 @@ use crate::{ prelude::ENOTSUPP, str::CStr, types::{ForeignOwnable, Opaque}, + ThisModule, }; use alloc::vec::Vec; use core::{ffi::c_void, marker::PhantomData}; @@ -148,28 +149,33 @@ impl I2cAdapter { self.0.name[len] = 0; } - pub unsafe fn set_owner(&mut self, owner: *mut bindings::module) { - self.0.owner = owner + pub unsafe fn set_owner(mut self, owner: &'static ThisModule) -> Self { + self.0.owner = owner.as_ptr(); + self } - pub fn set_class(&mut self, class: u32) { - self.0.class = class + pub fn set_class(mut self, class: u32) -> Self { + self.0.class = class; + self } - pub unsafe fn set_algorithm(&mut self) { - self.0.algo = Adapter::::build() + pub unsafe fn set_algorithm(mut self) -> Self { + self.0.algo = Adapter::::build(); + self } - pub unsafe fn setup_device(&mut self, device: &Device) { + pub unsafe fn setup_device(mut self, device: &Device) -> Self { let dev_ptr = device.raw_device(); self.0.dev.parent = dev_ptr; unsafe { self.0.dev.of_node = (*dev_ptr).of_node; } + self } - pub unsafe fn set_quirks(&mut self, quirks: &I2cAdapterQuirks) { + pub unsafe fn set_quirks(mut self, quirks: &I2cAdapterQuirks) -> Self { self.0.quirks = &quirks.0 as *const _; + self } pub fn timeout(&self) -> usize { diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs index c77f3da713ec20..f1e8167031d81a 100644 --- a/rust/kernel/of.rs +++ b/rust/kernel/of.rs @@ -4,7 +4,12 @@ //! //! C header: [`include/linux/of_*.h`](../../../../include/linux/of_*.h) -use crate::{bindings, driver::RawDeviceId, str::BStr}; +use crate::{ + bindings, + driver::RawDeviceId, + error::{to_result, Result}, + str::{BStr, CStr}, +}; /// An open firmware device id. #[derive(Clone, Copy)] @@ -114,4 +119,22 @@ impl DeviceNode { pub fn flags(&self) -> u64 { self.0._flags } + + // Note: Try to implement in a award way. Wait for imporvement. + fn read_u32_array(&self, propname: &'static CStr, out_value: &mut u32, sz: usize) -> Result { + let ret = unsafe { + bindings::of_property_read_variable_u32_array( + self.as_ptr(), + propname.as_char_ptr(), + out_value, + sz, + 0, + ) + }; + to_result(ret) + } + + pub fn read_u32(&self, propname: &'static CStr, out_value: &mut u32) -> Result { + self.read_u32_array(propname, out_value, 1) + } } From fe73b3551d28f8289cd66a12fd0b98cc534674d5 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Thu, 15 Aug 2024 16:46:55 +0800 Subject: [PATCH 10/16] =?UTF-8?q?=E4=BF=AE=E6=94=B9bcm=5Frust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bcm_rust: 修改probe 尝试rust构建结构 i2c: 加入更多常数,修改adapter of: full_name Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 130 ++++++------------------- rust/kernel/device.rs | 5 +- rust/kernel/i2c.rs | 122 +++++++++++++++-------- rust/kernel/of.rs | 7 ++ 4 files changed, 124 insertions(+), 140 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 1ec0c492a05495..f4b3c03233e3b1 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 //! BCM2835 master mode driver -use core::ops::Deref; +use core::{mem::MaybeUninit, ops::Deref}; use kernel::{ bindings, c_str, @@ -110,6 +110,12 @@ struct Bcm2835I2cDev { } impl Bcm2835I2cDev { + pub(crate) fn new() -> Self { + let up = unsafe { MaybeUninit::::uninit().assume_init() }; + + up + } + unsafe fn from_ptr<'a>(ptr: *mut Self) -> &'a mut Self { unsafe { &mut *ptr.cast() } } @@ -239,7 +245,7 @@ impl Bcm2835I2cDev { unsafe { bindings::readl(addr as _) } } - pub(crate) fn bcm2835_i2c_register_div(&mut self, mclk: &Clk) -> Result<&mut Clk> { + pub(crate) fn bcm2835_i2c_register_div(&mut self, mclk: &Clk) -> Result { let name = CString::try_from_fmt(fmt!("{}_div", self.dev.name()))?; let mclk_name = mclk.name(); let parent_names = [mclk_name.as_char_ptr()]; @@ -258,10 +264,6 @@ impl Bcm2835I2cDev { clk_i2c }; - // Ensure these objects live long enough - // TODO: Try to achieve this in a more elegant way - // let _ = (name, parent_names, init_data); - self.dev.clk_register(&mut clk_i2c.hw) } @@ -544,10 +546,8 @@ impl platform::Driver for Bcm2835I2cDriver { pdev.name() ); - let dev = unsafe { Device::from_dev(pdev) }; - let i2c_dev_ptr: *mut Bcm2835I2cDev = dev.kzalloc::()?; - - let i2c_dev = unsafe { Bcm2835I2cDev::from_ptr(i2c_dev_ptr) }; + let dev = Device::from_dev(pdev); + let mut i2c_dev = Bcm2835I2cDev::new(); i2c_dev.dev = dev.clone(); i2c_dev.completion = Arc::pin_init(new_completion!())?; @@ -556,8 +556,7 @@ impl platform::Driver for Bcm2835I2cDriver { dev_info!(pdev, "I2c bus device reg_base: {:?}\n", reg_base); let mclk = dev.clk_get()?; - - let bus_clk = i2c_dev.bcm2835_i2c_register_div(mclk)?; + i2c_dev.bus_clk = i2c_dev.bcm2835_i2c_register_div(mclk)?; let mut bus_clk_rate = 0; if let Err(_) = dev @@ -565,45 +564,22 @@ impl platform::Driver for Bcm2835I2cDriver { .read_u32(c_str!("clock-frequency"), &mut bus_clk_rate) { dev_warn!(pdev, "Could not read clock-frequency property\n"); - bus_clk_rate = bindings::I2C_MAX_STANDARD_MODE_FREQ; + bus_clk_rate = i2c::I2C_MAX_STANDARD_MODE_FREQ; }; dev_info!(pdev, "I2c bus device clock-frequency: {}\n", bus_clk_rate); - if let Err(_) = i2c_dev.bus_clk.set_rate_exclusive(bus_clk_rate as u64) { + if let Err(e) = i2c_dev.bus_clk.set_rate_exclusive(bus_clk_rate as u64) { dev_err!(pdev, "Could not set clock frequency\n"); + return Err(e); } - /* - let ret = - unsafe { bindings::clk_set_rate_exclusive(bus_clk.as_ptr(), bus_clk_rate as u64) }; - if ret < 0 { - dev_err!( - pdev, - "Could not set clock frequency: {:?}\n", - to_result(ret) - ); - to_result(ret)?; - }*/ - - i2c_dev.bus_clk.prepare_enable()?; + if let Err(e) = i2c_dev.bus_clk.prepare_enable() { + dev_err!(pdev, "Could not prepare clock\n"); + return Err(e); + } let irq = pdev.irq_resource(0)?; - /*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); - to_result(ret)?; - }*/ - if let Err(_) = request_irq( irq as u32, Bcm2835I2cIrqHandler, @@ -616,14 +592,17 @@ impl platform::Driver for Bcm2835I2cDriver { i2c_dev.irq = irq; let quirks = I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); + let name = CString::try_from_fmt(fmt!("bcm2835 ({})", dev.of_node().full_name()))?; + let adap = i2c::I2cAdapter::new().set_up::( + &name, + &THIS_MODULE, + i2c::I2C_CLASS_DEPRECATED, + &dev, + quirks, + ); + i2c_dev.adapter = adap; unsafe { i2c_dev.adapter.i2c_set_adapdata(i2c_dev.as_ptr()); - i2c_dev.adapter.set_class(bindings::I2C_CLASS_DEPRECATED); - let full_name = bindings::of_node_full_name((*pdev.raw_device()).of_node); - let adap_name = - CString::try_from_fmt(fmt!("bcm2835 ({})", CStr::from_char_ptr(full_name)))?; - i2c_dev.adapter.set_name(&adap_name); - i2c_dev.adapter.set_algorithm::(); } /* @@ -634,58 +613,13 @@ impl platform::Driver for Bcm2835I2cDriver { i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_CLKT, 0); i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, 0); - let ret = unsafe { bindings::i2c_add_adapter(i2c_dev.adapter.as_ptr()) }; - if ret < 0 { - dev_info!(pdev, "Could not add I2C adapter: {:?}\n", to_result(ret)); - unsafe { - bindings::free_irq(irq as u32, i2c_dev_ptr as *mut core::ffi::c_void); - } - } - let _ = to_result(ret)?; - - // TODO: setup i2c_adapter - let quirks = I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); - // let mut adap = i2c_dev.adapter; - unsafe { - i2c_dev.adapter.i2c_set_adapdata(i2c_dev.as_ptr()); - i2c_dev.adapter.set_owner(&THIS_MODULE); - i2c_dev.adapter.set_class(bindings::I2C_CLASS_DEPRECATED); - let full_name = bindings::of_node_full_name((*pdev.raw_device()).of_node); - let adap_name = - CString::try_from_fmt(fmt!("bcm2835 ({})", CStr::from_char_ptr(full_name)))?; - i2c_dev.adapter.set_name(&adap_name); - } - // i2c_dev.adapter = adap; - - /* - * Disable the hardware clock stretching timeout. SMBUS - * specifies a limit for how long the device can stretch the - * clock, but core I2C doesn't. - */ - i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_CLKT, 0); - i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, 0); + if let Err(e) = i2c_dev.adapter.i2c_add_adapter() { + dev_err!(pdev, "Could not add I2C adapter\n"); + return Err(e); + }; - dbg!("Try to add I2C adapter..."); - i2c_dev.adapter.i2c_add_adapter()?; - dbg!("I2C adapter added!"); - /*let ret = unsafe { bindings::i2c_add_adapter(i2c_dev.adapter.as_ptr()) }; - if ret < 0 { - dev_info!(pdev, "Could not add I2C adapter: {:?}\n", to_result(ret)); - unsafe { - bindings::free_irq(irq as u32, i2c_dev_ptr as *mut core::ffi::c_void); - } - } - let _ = to_result(ret)?;*/ + let dev_data = kernel::new_device_data!((), (), i2c_dev, "BCM2835_I2C device data")?; - let item = unsafe { Box::from_raw(i2c_dev_ptr) }; - let dev_data = kernel::new_device_data!((), (), *item, "BCM2835_I2C device data")?; - /* - * Disable the hardware clock stretching timeout. SMBUS - * specifies a limit for how long the device can stretch the - * clock, but core I2C doesn't. - */ - i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_CLKT, 0); - i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, 0); Ok(dev_data.into()) } diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index 75dffb6a66efa7..b1fe751a45fee8 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -3,6 +3,7 @@ //! Generic devices that are part of the kernel's driver model. //! //! C header: [`include/linux/device.h`](../../../../include/linux/device.h) +use alloc::boxed::Box; use crate::{ bindings, @@ -222,11 +223,11 @@ impl Device { } /// Allocate a new clock, register it and return an opaque cookie - pub fn clk_register(&self, clk_hw: &mut ClkHw) -> Result<&mut Clk> { + pub fn clk_register(&self, clk_hw: &mut ClkHw) -> Result { // SAFETY: call ffi and ptr is valid let raw = unsafe { from_err_ptr(bindings::devm_clk_register(self.ptr, clk_hw.as_mut_ptr()))? }; - Ok(Clk::from_raw(raw)) + Ok(unsafe { *Box::from_raw(Clk::from_raw(raw) as *mut Clk) }) } /// Allocate(kmalloc) and return the corresponding mutable pointer. diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index e09fe5f72456a9..264e390d34976e 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -7,7 +7,7 @@ use crate::{ ThisModule, }; use alloc::vec::Vec; -use core::{ffi::c_void, marker::PhantomData}; +use core::{ffi::c_void, marker::PhantomData, mem}; use core::{mem::MaybeUninit, slice}; use macros::vtable; @@ -47,12 +47,59 @@ pub const I2C_FUNC_SMBUS_BLOCK_DATA: u32 = bindings::I2C_FUNC_SMBUS_BLOCK_DATA; pub const I2C_FUNC_SMBUS_I2C_BLOCK: u32 = bindings::I2C_FUNC_SMBUS_I2C_BLOCK; pub const I2C_FUNC_SMBUS_EMUL: u32 = bindings::I2C_FUNC_SMBUS_EMUL; pub const I2C_FUNC_SMBUS_EMUL_ALL: u32 = bindings::I2C_FUNC_SMBUS_EMUL_ALL; - +pub const I2C_SMBUS_BLOCK_MAX: u32 = 32; +pub const I2C_SMBUS_READ: u32 = 1; +pub const I2C_SMBUS_WRITE: u32 = 0; +pub const I2C_SMBUS_QUICK: u32 = 0; +pub const I2C_SMBUS_BYTE: u32 = 1; +pub const I2C_SMBUS_BYTE_DATA: u32 = 2; +pub const I2C_SMBUS_WORD_DATA: u32 = 3; +pub const I2C_SMBUS_PROC_CALL: u32 = 4; +pub const I2C_SMBUS_BLOCK_DATA: u32 = 5; +pub const I2C_SMBUS_I2C_BLOCK_BROKEN: u32 = 6; +pub const I2C_SMBUS_BLOCK_PROC_CALL: u32 = 7; +pub const I2C_SMBUS_I2C_BLOCK_DATA: u32 = 8; +pub const I2C_MAX_STANDARD_MODE_FREQ: u32 = 100000; +pub const I2C_MAX_FAST_MODE_FREQ: u32 = 400000; +pub const I2C_MAX_FAST_MODE_PLUS_FREQ: u32 = 1000000; +pub const I2C_MAX_TURBO_MODE_FREQ: u32 = 1400000; +pub const I2C_MAX_HIGH_SPEED_MODE_FREQ: u32 = 3400000; +pub const I2C_MAX_ULTRA_FAST_MODE_FREQ: u32 = 5000000; +pub const I2C_DEVICE_ID_NXP_SEMICONDUCTORS: u32 = 0; +pub const I2C_DEVICE_ID_NXP_SEMICONDUCTORS_1: u32 = 1; +pub const I2C_DEVICE_ID_NXP_SEMICONDUCTORS_2: u32 = 2; +pub const I2C_DEVICE_ID_NXP_SEMICONDUCTORS_3: u32 = 3; +pub const I2C_DEVICE_ID_RAMTRON_INTERNATIONAL: u32 = 4; +pub const I2C_DEVICE_ID_ANALOG_DEVICES: u32 = 5; +pub const I2C_DEVICE_ID_STMICROELECTRONICS: u32 = 6; +pub const I2C_DEVICE_ID_ON_SEMICONDUCTOR: u32 = 7; +pub const I2C_DEVICE_ID_SPRINTEK_CORPORATION: u32 = 8; +pub const I2C_DEVICE_ID_ESPROS_PHOTONICS_AG: u32 = 9; +pub const I2C_DEVICE_ID_FUJITSU_SEMICONDUCTOR: u32 = 10; +pub const I2C_DEVICE_ID_FLIR: u32 = 11; +pub const I2C_DEVICE_ID_O2MICRO: u32 = 12; +pub const I2C_DEVICE_ID_ATMEL: u32 = 13; +pub const I2C_DEVICE_ID_NONE: u32 = 65535; +pub const I2C_CLIENT_PEC: u32 = 4; +pub const I2C_CLIENT_TEN: u32 = 16; +pub const I2C_CLIENT_SLAVE: u32 = 32; +pub const I2C_CLIENT_HOST_NOTIFY: u32 = 64; +pub const I2C_CLIENT_WAKE: u32 = 128; +pub const I2C_CLIENT_SCCB: u32 = 36864; +pub const I2C_ALF_IS_SUSPENDED: u32 = 0; +pub const I2C_ALF_SUSPEND_REPORTED: u32 = 1; +pub const I2C_CLASS_HWMON: u32 = 1; +pub const I2C_CLASS_DDC: u32 = 8; +pub const I2C_CLASS_SPD: u32 = 128; +pub const I2C_CLASS_DEPRECATED: u32 = 256; +pub const I2C_CLIENT_END: u32 = 65534; // No BIT macros. pub const I2C_AQ_NO_CLK_STRETCH: u32 = 1 << 4; /// Represents i2c_adapter_quirks /// +#[derive(Clone)] +#[repr(transparent)] pub struct I2cAdapterQuirks(bindings::i2c_adapter_quirks); impl I2cAdapterQuirks { @@ -117,12 +164,19 @@ impl I2cMsg { /// pub struct I2cAdapter(bindings::i2c_adapter); impl I2cAdapter { - // Create I2CMsg from raw pointer + /// Create a new instance of the I2cAdapter + pub const fn new() -> Self { + let up = unsafe { MaybeUninit::::zeroed().assume_init() }; + Self(up) + } + + /// Create I2CMsg from raw pointer pub fn from_raw<'a>(ptr: *mut bindings::i2c_adapter) -> &'a Self { let ptr = ptr.cast::(); unsafe { &*ptr } } + #[inline] pub fn as_ptr(&self) -> *mut bindings::i2c_adapter { &self.0 as *const _ as *mut _ } @@ -135,54 +189,42 @@ impl I2cAdapter { unsafe { bindings::dev_set_drvdata(&self.0.dev as *const _ as *mut _, data as *mut c_void) } } - pub fn i2c_add_adapter(&self) -> Result { + pub fn i2c_add_adapter(&mut self) -> Result { let ret = unsafe { bindings::i2c_add_adapter(self.as_ptr()) }; to_result(ret) } - pub fn set_name(&mut self, name: &CStr) { - let len = name.len().min(self.0.name.len() - 1); - let s = name.as_bytes(); - for b in &s[0..len] { - self.0.name[0] = *b as i8; - } - self.0.name[len] = 0; - } - - pub unsafe fn set_owner(mut self, owner: &'static ThisModule) -> Self { - self.0.owner = owner.as_ptr(); - self - } - - pub fn set_class(mut self, class: u32) -> Self { - self.0.class = class; - self - } - - pub unsafe fn set_algorithm(mut self) -> Self { - self.0.algo = Adapter::::build(); - self + pub fn timeout(&self) -> usize { + unsafe { self.0.timeout as usize } } - pub unsafe fn setup_device(mut self, device: &Device) -> Self { - let dev_ptr = device.raw_device(); - self.0.dev.parent = dev_ptr; + pub fn set_up( + mut self, + name: &CStr, + owner: &'static ThisModule, + class: u32, + device: &Device, + quirks: I2cAdapterQuirks, + ) -> Self { unsafe { + // set_name + bindings::snprintf( + self.0.name.as_mut_ptr(), + mem::size_of_val(&self.0.name) as u64, + name.as_char_ptr(), + ); + self.0.owner = owner.as_ptr(); + self.0.class = class; + self.0.algo = Adapter::::build(); + + let dev_ptr = device.raw_device(); + self.0.dev.parent = dev_ptr; self.0.dev.of_node = (*dev_ptr).of_node; - } - self - } - pub unsafe fn set_quirks(mut self, quirks: &I2cAdapterQuirks) -> Self { - self.0.quirks = &quirks.0 as *const _; + self.0.quirks = &quirks.0 as *const _; + }; self } - - pub fn timeout(&self) -> usize { - unsafe { self.0.timeout as usize } - } - - //pub fn set_up(self) } impl Drop for I2cAdapter { diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs index f1e8167031d81a..00dceadb791c8b 100644 --- a/rust/kernel/of.rs +++ b/rust/kernel/of.rs @@ -120,6 +120,13 @@ impl DeviceNode { self.0._flags } + pub fn full_name<'a>(&self) -> &'a CStr { + unsafe { + let name_ptr = bindings::of_node_full_name(self.as_ptr()); + CStr::from_char_ptr(name_ptr) + } + } + // Note: Try to implement in a award way. Wait for imporvement. fn read_u32_array(&self, propname: &'static CStr, out_value: &mut u32, sz: usize) -> Result { let ret = unsafe { From 6e3ea66241bb7dcdb816583f0275d3919c86a295 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Thu, 15 Aug 2024 16:46:55 +0800 Subject: [PATCH 11/16] =?UTF-8?q?=E4=BF=AE=E6=94=B9bcm=5Frust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bcm_rust: 修改probe 尝试rust构建结构 i2c: 加入更多常数,修改adapter of: full_name Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 10 ++++---- rust/helpers.c | 35 ++++++++++++++------------ rust/kernel/device.rs | 6 ++--- rust/kernel/i2c.rs | 1 - 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index f4b3c03233e3b1..0f61b6a2a760ca 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 //! BCM2835 master mode driver -use core::{mem::MaybeUninit, ops::Deref}; +use core::{clone::Clone, mem::MaybeUninit, ops::Deref}; use kernel::{ bindings, c_str, @@ -97,9 +97,9 @@ struct Bcm2835I2cDev { reg_base: *mut u8, irq: i32, adapter: I2cAdapter, - completion: Arc, + completion: Completion, curr_msg: Option>, - bus_clk: Clk, + bus_clk: Box, num_msgs: i32, msg_err: u32, msg_buf: Option>, @@ -245,7 +245,7 @@ impl Bcm2835I2cDev { unsafe { bindings::readl(addr as _) } } - pub(crate) fn bcm2835_i2c_register_div(&mut self, mclk: &Clk) -> Result { + pub(crate) fn bcm2835_i2c_register_div(&mut self, mclk: &Clk) -> Result> { let name = CString::try_from_fmt(fmt!("{}_div", self.dev.name()))?; let mclk_name = mclk.name(); let parent_names = [mclk_name.as_char_ptr()]; @@ -549,7 +549,7 @@ impl platform::Driver for Bcm2835I2cDriver { let dev = Device::from_dev(pdev); let mut i2c_dev = Bcm2835I2cDev::new(); i2c_dev.dev = dev.clone(); - i2c_dev.completion = Arc::pin_init(new_completion!())?; + i2c_dev.completion.init_completion(); let reg_base = pdev.ioremap_resource(0)?; i2c_dev.reg_base = reg_base; diff --git a/rust/helpers.c b/rust/helpers.c index 8c14deda181649..97fba8be730f94 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -170,9 +170,9 @@ void rust_helper_lockdep_unregister_key(struct lock_class_key *key) EXPORT_SYMBOL_GPL(rust_helper_lockdep_unregister_key); int rust_helper_fs_parse(struct fs_context *fc, - const struct fs_parameter_spec *desc, - struct fs_parameter *param, - struct fs_parse_result *result) + const struct fs_parameter_spec *desc, + struct fs_parameter *param, + struct fs_parse_result *result) { return fs_parse(fc, desc, param, result); } @@ -184,7 +184,8 @@ const struct cred *rust_helper_get_cred(const struct cred *cred) } EXPORT_SYMBOL_GPL(rust_helper_get_cred); -void rust_helper_put_cred(const struct cred *cred) { +void rust_helper_put_cred(const struct cred *cred) +{ put_cred(cred); } EXPORT_SYMBOL_GPL(rust_helper_put_cred); @@ -219,19 +220,21 @@ struct page *rust_helper_alloc_pages(gfp_t gfp_mask, unsigned int order) EXPORT_SYMBOL_GPL(rust_helper_alloc_pages); void *rust_helper_alloc_inode_sb(struct super_block *sb, - struct kmem_cache *cache, gfp_t gfp) + struct kmem_cache *cache, gfp_t gfp) { return alloc_inode_sb(sb, cache, gfp); } EXPORT_SYMBOL_GPL(rust_helper_alloc_inode_sb); -unsigned long rust_helper_copy_from_user(void *to, const void __user *from, unsigned long n) +unsigned long rust_helper_copy_from_user(void *to, const void __user *from, + unsigned long n) { return copy_from_user(to, from, n); } EXPORT_SYMBOL_GPL(rust_helper_copy_from_user); -unsigned long rust_helper_copy_to_user(void __user *to, const void *from, unsigned long n) +unsigned long rust_helper_copy_to_user(void __user *to, const void *from, + unsigned long n) { return copy_to_user(to, from, n); } @@ -255,8 +258,9 @@ const char *rust_helper_dev_name(const struct device *dev) } EXPORT_SYMBOL_GPL(rust_helper_dev_name); -const struct of_device_id *rust_helper_of_match_device( - const struct of_device_id *matches, const struct device *dev) +const struct of_device_id * +rust_helper_of_match_device(const struct of_device_id *matches, + const struct device *dev) { return of_match_device(matches, dev); } @@ -264,7 +268,7 @@ EXPORT_SYMBOL_GPL(rust_helper_of_match_device); const char *rust_helper_of_node_full_name(const struct device_node *np) { - return rust_helper_of_node_full_name(np); + return of_node_full_name(np); } EXPORT_SYMBOL_GPL(rust_helper_of_node_full_name); @@ -402,7 +406,8 @@ void rust_helper_writeq_relaxed(u64 value, volatile void __iomem *addr) EXPORT_SYMBOL_GPL(rust_helper_writeq_relaxed); #endif -void rust_helper_memcpy_fromio(void *to, const volatile void __iomem *from, long count) +void rust_helper_memcpy_fromio(void *to, const volatile void __iomem *from, + long count) { memcpy_fromio(to, from, count); } @@ -430,8 +435,6 @@ EXPORT_SYMBOL_GPL(rust_helper_clk_disable_unprepare); * your platform such that `size_t` matches `uintptr_t` (i.e., to increase * `size_t`, because `uintptr_t` has to be at least as big as `size_t`). */ -static_assert( - sizeof(size_t) == sizeof(uintptr_t) && - __alignof__(size_t) == __alignof__(uintptr_t), - "Rust code expects C `size_t` to match Rust `usize`" -); +static_assert(sizeof(size_t) == sizeof(uintptr_t) && + __alignof__(size_t) == __alignof__(uintptr_t), + "Rust code expects C `size_t` to match Rust `usize`"); diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index b1fe751a45fee8..72f94b592b2497 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -222,12 +222,12 @@ impl Device { DeviceNode::from_raw(ptr) } - /// Allocate a new clock, register it and return an opaque cookie - pub fn clk_register(&self, clk_hw: &mut ClkHw) -> Result { + /// Allocate a new clk which cannot be dereferenced by driver code. + pub fn clk_register(&self, clk_hw: &mut ClkHw) -> Result> { // SAFETY: call ffi and ptr is valid let raw = unsafe { from_err_ptr(bindings::devm_clk_register(self.ptr, clk_hw.as_mut_ptr()))? }; - Ok(unsafe { *Box::from_raw(Clk::from_raw(raw) as *mut Clk) }) + Ok(unsafe { Box::from_raw(Clk::from_raw(raw) as *mut Clk) }) } /// Allocate(kmalloc) and return the corresponding mutable pointer. diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 264e390d34976e..52354a772343a3 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -312,7 +312,6 @@ pub trait I2cAlgorithm { pub(crate) struct Adapter(PhantomData); impl Adapter { - // TODO! unsafe extern "C" fn master_xfer_callback( adap: *mut bindings::i2c_adapter, msgs: *mut bindings::i2c_msg, From e0b517da256387a92a19990d7218290aad9e6456 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Sun, 18 Aug 2024 20:27:05 +0800 Subject: [PATCH 12/16] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E4=BF=AE=E6=94=B9bcm?= =?UTF-8?q?=5Frust=20=E6=88=90=E5=8A=9Fprobe=20=E5=8A=9F=E8=83=BD=E6=9C=AA?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 仍使用BcmData封装 Signed-off-by: Nostalgia --- .../arm/boot/dts/broadcom/bcm2710-rpi-3-b.dts | 1 + arch/arm64/configs/bcm2711_rust_defconfig | 2 +- drivers/i2c/busses/i2c_bcm2835_rust.rs | 23 +++++++++++-------- rust/kernel/i2c.rs | 2 ++ 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/broadcom/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/broadcom/bcm2710-rpi-3-b.dts index b893affe69974c..d07d27496cc231 100644 --- a/arch/arm/boot/dts/broadcom/bcm2710-rpi-3-b.dts +++ b/arch/arm/boot/dts/broadcom/bcm2710-rpi-3-b.dts @@ -237,6 +237,7 @@ pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins>; clock-frequency = <100000>; + status = "okay"; }; &i2c2 { diff --git a/arch/arm64/configs/bcm2711_rust_defconfig b/arch/arm64/configs/bcm2711_rust_defconfig index 4e8cd2be0e7068..94003573817cac 100644 --- a/arch/arm64/configs/bcm2711_rust_defconfig +++ b/arch/arm64/configs/bcm2711_rust_defconfig @@ -1677,4 +1677,4 @@ CONFIG_SAMPLES_RUST=y CONFIG_SAMPLE_RUST_MINIMAL=m CONFIG_SAMPLE_RUST_PRINT=m CONFIG_SAMPLE_RUST_HOSTPROGS=y -# CONFIG_STRICT_DEVMEM is not set +# CONFIG_STRICT_DEVMEM is not set \ No newline at end of file diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 0f61b6a2a760ca..bfa72cf53e0782 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -523,13 +523,16 @@ impl I2cAlgorithm for Bcm2835I2cAlgo { //static BCM2835_I2C_QUIRKS: I2cAdapterQuirks = //I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); -struct Bcm2835I2cData {} +struct Bcm2835I2cData { + pub(crate) dev: Device, + pub(crate) i2c_dev_ptr: *mut Bcm2835I2cDev, +} unsafe impl Sync for Bcm2835I2cDev {} unsafe impl Send for Bcm2835I2cDev {} unsafe impl Sync for Bcm2835I2cData {} unsafe impl Send for Bcm2835I2cData {} -type DeviceData = device::Data<(), (), Bcm2835I2cDev>; +type DeviceData = device::Data<(), (), Bcm2835I2cData>; impl platform::Driver for Bcm2835I2cDriver { kernel::driver_of_id_table!(BCM2835_I2C_ID_TABLE); @@ -540,14 +543,11 @@ impl platform::Driver for Bcm2835I2cDriver { pdev: &mut platform::Device, id_info: core::prelude::v1::Option<&Self::IdInfo>, ) -> Result { - dev_info!( - pdev, - "BCM2835 i2c bus device ({}) driver probe.\n", - pdev.name() - ); + dev_info!(pdev, "BCM2835 i2c bus device driver probe.\n"); let dev = Device::from_dev(pdev); - let mut i2c_dev = Bcm2835I2cDev::new(); + let i2c_dev_ptr: *mut Bcm2835I2cDev = dev.kzalloc::()?; + let i2c_dev = unsafe { Bcm2835I2cDev::from_ptr(i2c_dev_ptr) }; i2c_dev.dev = dev.clone(); i2c_dev.completion.init_completion(); @@ -618,7 +618,12 @@ impl platform::Driver for Bcm2835I2cDriver { return Err(e); }; - let dev_data = kernel::new_device_data!((), (), i2c_dev, "BCM2835_I2C device data")?; + let dev_data = kernel::new_device_data!( + (), + (), + Bcm2835I2cData { dev, i2c_dev_ptr }, + "BCM2835_I2C device data" + )?; Ok(dev_data.into()) } diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 52354a772343a3..5a108f69d19802 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -408,11 +408,13 @@ impl Adapter { } else { None }, + #[cfg(CONFIG_I2C_SLAVE)] reg_slave: if T::HAS_REG_SLAVE { Some(Adapter::::reg_slave_callback) } else { None }, + #[cfg(CONFIG_I2C_SLAVE)] unreg_slave: if T::HAS_UNREG_SLAVE { Some(Adapter::::unreg_slave_callback) } else { From 770d474d52c3a07f2f3f65b480fbc36d9b374822 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Sun, 18 Aug 2024 20:27:05 +0800 Subject: [PATCH 13/16] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E4=BF=AE=E6=94=B9bcm?= =?UTF-8?q?=5Frust=20=E6=88=90=E5=8A=9Fprobe=20=E5=8A=9F=E8=83=BD=E6=9C=AA?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 仍使用BcmData封装 Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 11 ++--------- rust/kernel/device.rs | 8 ++++---- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index bfa72cf53e0782..3f7aad502dbf88 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -110,12 +110,6 @@ struct Bcm2835I2cDev { } impl Bcm2835I2cDev { - pub(crate) fn new() -> Self { - let up = unsafe { MaybeUninit::::uninit().assume_init() }; - - up - } - unsafe fn from_ptr<'a>(ptr: *mut Self) -> &'a mut Self { unsafe { &mut *ptr.cast() } } @@ -264,7 +258,8 @@ impl Bcm2835I2cDev { clk_i2c }; - self.dev.clk_register(&mut clk_i2c.hw) + let raw = self.dev.clk_register(&mut clk_i2c.hw)? as *mut Clk; + unsafe { Ok(Box::from_raw(raw)) } } pub(crate) fn bcm2835_fill_txfifo(&mut self) { @@ -527,8 +522,6 @@ struct Bcm2835I2cData { pub(crate) dev: Device, pub(crate) i2c_dev_ptr: *mut Bcm2835I2cDev, } -unsafe impl Sync for Bcm2835I2cDev {} -unsafe impl Send for Bcm2835I2cDev {} unsafe impl Sync for Bcm2835I2cData {} unsafe impl Send for Bcm2835I2cData {} diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index 72f94b592b2497..df78be9cec63f8 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -7,7 +7,7 @@ use alloc::boxed::Box; use crate::{ bindings, - clk::Clk, + clk::{self, Clk}, clk_provider::ClkHw, dev_err, error::{code::*, from_err_ptr, to_result, Result}, @@ -223,11 +223,11 @@ impl Device { } /// Allocate a new clk which cannot be dereferenced by driver code. - pub fn clk_register(&self, clk_hw: &mut ClkHw) -> Result> { + pub fn clk_register(&self, clk_hw: &mut ClkHw) -> Result<&mut Clk> { // SAFETY: call ffi and ptr is valid - let raw = + let ptr = unsafe { from_err_ptr(bindings::devm_clk_register(self.ptr, clk_hw.as_mut_ptr()))? }; - Ok(unsafe { Box::from_raw(Clk::from_raw(raw) as *mut Clk) }) + Ok(Clk::from_raw(ptr)) } /// Allocate(kmalloc) and return the corresponding mutable pointer. From c54231a307ddde0540a741012724fbd4540eac90 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Tue, 20 Aug 2024 22:22:10 +0800 Subject: [PATCH 14/16] =?UTF-8?q?=E4=BF=AE=E6=94=B9bcm=5Frust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i2c_msg Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 12 +++--- rust/kernel/i2c.rs | 55 ++++++++++++++++++++------ 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 3f7aad502dbf88..a8b3086761d437 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -304,11 +304,12 @@ impl Bcm2835I2cDev { return; } - let msg = &curr_msg[0]; + // Safety: curr_msg is not empty due to num_msgs > 0 + let msg = curr_msg.remove(0); let last_msg = self.num_msgs == 1; self.num_msgs -= 1; - self.msg_buf = msg.buf_to_vec(); + self.msg_buf = msg.read_buf(); self.msg_buf_remaining = msg.len() as usize; if msg.flags() as u32 & I2C_M_RD != 0 { @@ -350,14 +351,13 @@ fn bcm2835_i2c_isr(this_irq: i32, data: &mut Bcm2835I2cDev) -> irq::Return { if val & BCM2835_I2C_S_DONE != 0 { match i2c_dev.curr_msg { - // Note: we represent the ptr buf with vec and the ptr to 0th element is the same as the ptr to the place in C. + // Safety: curr_msg is not empty due to num_msgs > 0 Some(ref mut msg) if msg[0].flags() as u32 & I2C_M_RD != 0 => { i2c_dev.bcm2835_drain_rxfifo(); val = i2c_dev.bcm2835_i2c_readl(BCM2835_I2C_S); } None => { dev_err!(i2c_dev.dev, "Got unexpected interrupt (from firmware?)\n"); - return irq::Return::Handled; } _ => {} } @@ -378,8 +378,8 @@ fn bcm2835_i2c_isr(this_irq: i32, data: &mut Bcm2835I2cDev) -> irq::Return { i2c_dev.bcm2835_fill_txfifo(); if i2c_dev.num_msgs != 0 && i2c_dev.msg_buf_remaining == 0 { - if let Some(ref mut curr_msg) = i2c_dev.curr_msg { - curr_msg.remove(0); + if let Some(ref mut msg) = i2c_dev.curr_msg { + msg.remove(0); } i2c_dev.bcm2835_i2c_start_transfer(); } diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 5a108f69d19802..d4b68144d16533 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -120,37 +120,55 @@ impl I2cAdapterQuirks { /// Represents i2c_msg /// -/// Note: all primitive fields are __u16 type in C, represented as u16 in Rust. -/// Note: buf is a raw pointer -/// Note: struct i2c_msg *msg is a i2c_msg ptr buf. +/// Note: usually i2c_msg buf is a continuous memory block, you may encounter 2 ways to represent it: +/// +/// ptr: &i2c_msg, len: usize +/// +/// buf: Vec +/// +/// In first case, we could step_next to the next block; In second case, we could take it as usual Vec or Slice. pub struct I2cMsg(bindings::i2c_msg); impl I2cMsg { - // Create I2CMsg buf from raw pointer - pub fn from_raw<'a>(ptr: *mut bindings::i2c_msg, len: usize) -> Vec { - let buf_ptr = unsafe { Vec::from_raw_parts(ptr.cast::(), len, len) }; - unsafe { buf_ptr } + /// Create a new instance of the Vec + pub fn from_raw(ptr: *mut bindings::i2c_msg, len: usize) -> Vec { + unsafe { + let ptr = ptr.cast::(); + Vec::from_raw_parts(ptr, len, len) + } + } + + /// Expose the raw pointer of i2c_msg of the Vec + pub fn vec_as_ptr(vec: Vec) -> *mut bindings::i2c_msg { + let ptr = vec.as_ptr() as *mut bindings::i2c_msg; + mem::forget(vec); + ptr + } + + /// Expose the raw pointer of i2c_msg of the I2cMsg + pub fn as_ptr(&self) -> *mut bindings::i2c_msg { + &self.0 as *const _ as *mut _ } /// return flags of i2c_msg pub fn flags(&self) -> u16 { - self.0.flags as u16 + self.0.flags } /// return len of i2c_msg pub fn len(&self) -> u16 { - self.0.len as u16 + self.0.len } /// return addr of i2c_msg pub fn addr(&self) -> u16 { - self.0.addr as u16 + self.0.addr } /// return buf of i2c_msg and transfer ownership of the buf - pub fn buf_to_vec(&self) -> Option> { + pub fn read_buf(&self) -> Option> { let len = self.len() as usize; - let buf = self.0.buf as *const _ as *mut u8; + let buf = unsafe { self.0.buf as *const _ as *mut u8 }; if buf.is_null() { return None; } @@ -158,6 +176,19 @@ impl I2cMsg { let vec: Vec = unsafe { Vec::from_raw_parts(buf, len, len) }; Some(vec) } + + /// a step forward to next i2c_msg + /// + /// # Safety + /// + /// You should not use this method if you use the Vec to represent the i2c_msg buf. You should ensure the bound of i2c_msg is valid. + pub unsafe fn step_next(&mut self) { + unsafe { + // ensure the bound of i2c_msg is valid + let ptr = &self.0 as *const _ as *mut bindings::i2c_msg; + self.0 = *(ptr.add(1)); + } + } } /// Represents i2c_adapter From d55bd1f8c7aee27b004458a1814ec9217d2db77c Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Tue, 20 Aug 2024 22:22:10 +0800 Subject: [PATCH 15/16] =?UTF-8?q?BCM=5FRUST=20=E6=94=B9=E8=BF=9BI2cMsg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正裸指针形式 Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 259 +++++++++++++++++++------ rust/kernel/i2c.rs | 20 +- rust/osl/src/arceos/driver/i2c/msg.rs | 53 +++-- 3 files changed, 244 insertions(+), 88 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index a8b3086761d437..9cb655021e04ea 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 //! BCM2835 master mode driver -use core::{clone::Clone, mem::MaybeUninit, ops::Deref}; +use core::{clone::Clone, convert::Into, mem::MaybeUninit, ops::Deref}; use kernel::{ bindings, c_str, @@ -12,7 +12,10 @@ use kernel::{ device::{self, Device, RawDevice}, driver::DeviceRemoval, error::to_result, - i2c::{self, I2cAdapter, I2cAdapterQuirks, I2cAlgorithm, I2cMsg, I2C_M_NOSTART, I2C_M_RD}, + i2c::{ + self, I2cAdapter, I2cAdapterQuirks, I2cAlgorithm, I2cMsg, I2C_M_IGNORE_NAK, I2C_M_NOSTART, + I2C_M_NO_RD_ACK, I2C_M_RD, I2C_M_RECV_LEN, I2C_M_REV_DIR_ADDR, I2C_M_STOP, I2C_M_TEN, + }, interrupt::{request_irq, IrqHandler, IRQF_SHARED}, io_mem::IoMem, irq, module_platform_driver, new_completion, @@ -74,7 +77,7 @@ pub const BCM2835_I2C_REDL_SHIFT: u32 = 0; pub const BCM2835_I2C_CDIV_MIN: u32 = 0x0002; pub const BCM2835_I2C_CDIV_MAX: u32 = 0xFFFE; -pub const DEBUG: i32 = 0; +pub const DEBUG: i32 = 3; /// SMBUs-recommended 35ms pub const CLK_TOUT_MS: u32 = 35; @@ -82,7 +85,7 @@ pub const CLK_TOUT_MS: u32 = 35; /// Maximum number of debug messages pub const BCM2835_DEBUG_MAX: usize = 512; struct Bcm2835Debug { - msg: I2cMsg, + msg: *mut I2cMsg, msg_idx: i32, remain: usize, status: u32, @@ -94,15 +97,16 @@ struct Bcm2835Debug { // Use Vec as a ptr buf struct Bcm2835I2cDev { dev: Device, - reg_base: *mut u8, + regs: *mut u8, irq: i32, adapter: I2cAdapter, completion: Completion, curr_msg: Option>, + curr_idx: usize, bus_clk: Box, num_msgs: i32, msg_err: u32, - msg_buf: Option>, + msg_buf: Option<*mut u8>, msg_buf_remaining: usize, debug: [Bcm2835Debug; BCM2835_DEBUG_MAX], debug_num: u32, @@ -157,7 +161,7 @@ fn clk_bcm2835_i2c_set_rate(hw: &ClkHw, rate: u64, parent_rate: u64) -> Result<( let div = to_clk_bcm2835_i2c(hw); let divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate)? as u32; - div.i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_DIV, divider); + div.i2c_dev.i2c_writel(BCM2835_I2C_DIV, divider); /* * Number of core clocks to wait after falling edge before @@ -172,7 +176,7 @@ fn clk_bcm2835_i2c_set_rate(hw: &ClkHw, rate: u64, parent_rate: u64) -> Result<( */ let redl = 1.max(divider / 4); - div.i2c_dev.bcm2835_i2c_writel( + div.i2c_dev.i2c_writel( BCM2835_I2C_DEL, ((fedl << BCM2835_I2C_FEDL_SHIFT) | (redl << BCM2835_I2C_REDL_SHIFT)) as u32, ); @@ -188,7 +192,7 @@ fn clk_bcm2835_i2c_set_rate(hw: &ClkHw, rate: u64, parent_rate: u64) -> Result<( } }; - div.i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_CLKT, clk_tout); + div.i2c_dev.i2c_writel(BCM2835_I2C_CLKT, clk_tout); Ok(()) } @@ -203,7 +207,7 @@ fn clk_bcm2835_i2c_round_rate(hw: &ClkHw, rate: u64, parent_rate: &mut u64) -> i fn clk_bcm2835_i2c_recalc_rate(hw: &ClkHw, parent_rate: u64) -> u64 { let div = to_clk_bcm2835_i2c(hw); - let divider = div.i2c_dev.bcm2835_i2c_readl(BCM2835_I2C_DIV) as u64; + let divider = div.i2c_dev.i2c_readl(BCM2835_I2C_DIV) as u64; parent_rate.div_ceil(divider) } @@ -227,19 +231,153 @@ impl ClkOps for ClkBcm2835I2cOps { } impl Bcm2835I2cDev { - pub(crate) fn bcm2835_i2c_writel(&self, reg: usize, val: u32) { - let i2c_reg = self.reg_base; + pub(crate) fn debug_add(&mut self, s: u32) { + if self.debug_num_msgs == 0 || self.debug_num >= BCM2835_DEBUG_MAX as u32 { + return; + } + + if let Some(ref curr_msg) = self.curr_msg { + let n = self.debug_num as usize; + self.debug[n].msg = &curr_msg[self.curr_idx] as *const _ as *mut _; + self.debug[n].msg_idx = self.debug_num_msgs as i32 - self.num_msgs; + self.debug[n].remain = self.msg_buf_remaining; + self.debug[n].status = s; + self.debug_num += 1; + } + } + + pub(crate) fn debug_print_status(&self, d: &Bcm2835Debug) { + let s = d.status; + + pr_info!( + "isr: remain={} , status=0x{:x} : {}{}{}{}{}{}{}{}{}{} [i2c{}]\n", + d.remain, + s, + if s & BCM2835_I2C_S_TA != 0 { "TA " } else { "" }, + if s & BCM2835_I2C_S_DONE != 0 { + "DONE " + } else { + "" + }, + if s & BCM2835_I2C_S_TXW != 0 { + "TXW " + } else { + "" + }, + if s & BCM2835_I2C_S_RXR != 0 { + "RXR " + } else { + "" + }, + if s & BCM2835_I2C_S_TXD != 0 { + "TXD " + } else { + "" + }, + if s & BCM2835_I2C_S_RXD != 0 { + "RXD " + } else { + "" + }, + if s & BCM2835_I2C_S_TXE != 0 { + "TXE " + } else { + "" + }, + if s & BCM2835_I2C_S_RXF != 0 { + "RXF " + } else { + "" + }, + if s & BCM2835_I2C_S_ERR != 0 { + "ERR " + } else { + "" + }, + if s & BCM2835_I2C_S_CLKT != 0 { + "CLKT " + } else { + "" + }, + self.adapter.nr() + ) + } + + pub(crate) fn debug_print_msg(&self, msg: &I2cMsg, i: i32, total: i32, fname: &'static str) { + let flags = msg.flags() as u32; + pr_info!( + "{fname}: msg({i}/{total}) {} addr=0x{:02x}, len={} flags={}{}{}{}{}{}{} [i2c{}]\n", + if flags & I2C_M_RD != 0 { + "read" + } else { + "write" + }, + msg.addr(), + msg.len(), + if flags & I2C_M_TEN != 0 { "TEN " } else { "" }, + if flags & I2C_M_RECV_LEN != 0 { + "RECV_LEN " + } else { + "" + }, + if flags & I2C_M_NO_RD_ACK != 0 { + "NO_RD_ACK " + } else { + "" + }, + if flags & I2C_M_IGNORE_NAK != 0 { + "IGNORE_NAK " + } else { + "" + }, + if flags & I2C_M_REV_DIR_ADDR != 0 { + "REV_DIR_ADDR " + } else { + "" + }, + if flags & I2C_M_NOSTART != 0 { + "NOSTART " + } else { + "" + }, + if flags & I2C_M_STOP != 0 { "STOP " } else { "" }, + self.adapter.nr(), + ) + } + + pub(crate) fn debug_print(&self) { + if self.debug_num >= BCM2835_DEBUG_MAX as u32 { + pr_info!("BCM2835_DEBUG_MAX reached\n"); + return; + }; + + for d in &self.debug[..self.debug_num as usize] { + if d.status == !0 { + self.debug_print_msg( + unsafe { &*d.msg }, + d.msg_idx, + self.debug_num_msgs as i32, + "start_transfer", + ) + } else { + self.debug_print_status(d) + } + } + } + + pub(crate) fn i2c_writel(&self, reg: usize, val: u32) { + let i2c_reg = self.regs; let addr = i2c_reg.wrapping_add(reg); unsafe { bindings::writel(val as _, addr as _) } } - pub(crate) fn bcm2835_i2c_readl(&self, reg: usize) -> u32 { - let i2c_reg = self.reg_base; + pub(crate) fn i2c_readl(&self, reg: usize) -> u32 { + let i2c_reg = self.regs; let addr = i2c_reg.wrapping_add(reg); unsafe { bindings::readl(addr as _) } } - pub(crate) fn bcm2835_i2c_register_div(&mut self, mclk: &Clk) -> Result> { + pub(crate) fn i2c_register_div(&mut self, mclk: &Clk) -> Result> { let name = CString::try_from_fmt(fmt!("{}_div", self.dev.name()))?; let mclk_name = mclk.name(); let parent_names = [mclk_name.as_char_ptr()]; @@ -264,17 +402,19 @@ impl Bcm2835I2cDev { pub(crate) fn bcm2835_fill_txfifo(&mut self) { while self.msg_buf_remaining > 0 { - let val: u32 = self.bcm2835_i2c_readl(BCM2835_I2C_S); - if !(val & BCM2835_I2C_S_TXD) != 0 { + let val: u32 = self.i2c_readl(BCM2835_I2C_S); + if val & BCM2835_I2C_S_TXD == 0 { break; } // May Wrong! - if let Some(mut buf) = self.msg_buf.take() { + if let Some(buf) = self.msg_buf.take() { // Safety: msg_buf_remaining > 0 - let byte = buf[0] as u32; - self.bcm2835_i2c_writel(BCM2835_I2C_FIFO, byte); - buf.remove(0); - self.msg_buf = Some(buf); + let byte = unsafe { *buf as u32 }; + self.i2c_writel(BCM2835_I2C_FIFO, byte); + self.msg_buf = unsafe { + let buf = buf.add(1); + Some(buf) + }; self.msg_buf_remaining -= 1; } } @@ -282,15 +422,17 @@ impl Bcm2835I2cDev { pub(crate) fn bcm2835_drain_rxfifo(&mut self) { while self.msg_buf_remaining > 0 { - let val: u32 = self.bcm2835_i2c_readl(BCM2835_I2C_S); + let val: u32 = self.i2c_readl(BCM2835_I2C_S); if !(val & BCM2835_I2C_S_RXD) != 0 { break; } // May Wrong! if let Some(mut buf) = self.msg_buf.take() { - buf[0] = self.bcm2835_i2c_readl(BCM2835_I2C_FIFO) as u8; - buf.remove(0); - self.msg_buf = Some(buf); + unsafe { *buf = self.i2c_readl(BCM2835_I2C_FIFO) as u8 }; + self.msg_buf = unsafe { + let buf = buf.add(1); + Some(buf) + }; self.msg_buf_remaining -= 1; } } @@ -303,9 +445,8 @@ impl Bcm2835I2cDev { if self.num_msgs == 0 { return; } - // Safety: curr_msg is not empty due to num_msgs > 0 - let msg = curr_msg.remove(0); + let msg = &curr_msg[self.curr_idx]; let last_msg = self.num_msgs == 1; self.num_msgs -= 1; @@ -322,16 +463,19 @@ impl Bcm2835I2cDev { c |= BCM2835_I2C_C_INTD; } - self.bcm2835_i2c_writel(BCM2835_I2C_A, msg.addr() as u32); - self.bcm2835_i2c_writel(BCM2835_I2C_DLEN, msg.len() as u32); - self.bcm2835_i2c_writel(BCM2835_I2C_C, c); + self.i2c_writel(BCM2835_I2C_A, msg.addr() as u32); + self.i2c_writel(BCM2835_I2C_DLEN, msg.len() as u32); + self.i2c_writel(BCM2835_I2C_C, c); self.curr_msg = Some(curr_msg); + + self.debug_add(!0); } //debug add } pub(crate) fn bcm2835_i2c_finish_transfer(&mut self) { self.curr_msg = None; + self.curr_idx = 0; self.num_msgs = 0; self.msg_buf = None; @@ -339,12 +483,11 @@ impl Bcm2835I2cDev { } } -fn bcm2835_i2c_isr(this_irq: i32, data: &mut Bcm2835I2cDev) -> irq::Return { - let i2c_dev = unsafe { &mut *(data as *mut Bcm2835I2cDev) }; +fn bcm2835_i2c_isr(this_irq: i32, i2c_dev: &mut Bcm2835I2cDev) -> irq::Return { + let mut val: u32 = i2c_dev.i2c_readl(BCM2835_I2C_S); + i2c_dev.debug_add(val); - let mut val: u32 = i2c_dev.bcm2835_i2c_readl(BCM2835_I2C_S); let err: u32 = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); - if err != 0 && (val & BCM2835_I2C_S_TA) == 0 { i2c_dev.msg_err = err; } @@ -352,9 +495,10 @@ fn bcm2835_i2c_isr(this_irq: i32, data: &mut Bcm2835I2cDev) -> irq::Return { if val & BCM2835_I2C_S_DONE != 0 { match i2c_dev.curr_msg { // Safety: curr_msg is not empty due to num_msgs > 0 - Some(ref mut msg) if msg[0].flags() as u32 & I2C_M_RD != 0 => { + Some(ref mut msgs) if msgs[i2c_dev.curr_idx].flags() as u32 & I2C_M_RD != 0 => { i2c_dev.bcm2835_drain_rxfifo(); - val = i2c_dev.bcm2835_i2c_readl(BCM2835_I2C_S); + val = i2c_dev.i2c_readl(BCM2835_I2C_S); + dbg!("isr curr_msg readl: ", val); } None => { dev_err!(i2c_dev.dev, "Got unexpected interrupt (from firmware?)\n"); @@ -378,9 +522,7 @@ fn bcm2835_i2c_isr(this_irq: i32, data: &mut Bcm2835I2cDev) -> irq::Return { i2c_dev.bcm2835_fill_txfifo(); if i2c_dev.num_msgs != 0 && i2c_dev.msg_buf_remaining == 0 { - if let Some(ref mut msg) = i2c_dev.curr_msg { - msg.remove(0); - } + i2c_dev.curr_idx += 1; i2c_dev.bcm2835_i2c_start_transfer(); } @@ -401,8 +543,8 @@ fn bcm2835_i2c_isr(this_irq: i32, data: &mut Bcm2835I2cDev) -> irq::Return { } 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( + i2c_dev.i2c_writel(BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); + i2c_dev.i2c_writel( BCM2835_I2C_S, BCM2835_I2C_CLKT as u32 | BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE, ); @@ -421,10 +563,6 @@ impl IrqHandler for Bcm2835I2cIrqHandler { } } -unsafe extern "C" fn bcm2835_i2c_isr_cb(this_irq: i32, data: *mut core::ffi::c_void) -> u32 { - bcm2835_i2c_isr(this_irq, unsafe { &mut *data.cast() }) as u32 -} - fn bcm2835_i2c_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result { let i2c_dev = unsafe { &mut (*adap.i2c_get_adapdata::()) }; let mut ignore_nak = false; @@ -434,29 +572,30 @@ fn bcm2835_i2c_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result 2 } { - // for 0..num { - // print msg - // } + for i in 0..num as usize { + i2c_dev.debug_print_msg(&msgs[i], (i + 1) as i32, num, "bcm2835_i2c_xfer") + } } - for msg in &msgs { + for msg in &msgs[0..(num - 1) as usize] { if msg.flags() as u32 & I2C_M_RD != 0 { dev_warn!( i2c_dev.dev, "only one read message supported, has to be last\n" ); - return Err(EOPENSTALE); + return Err(ENOTSUPP); } - if msg.flags() as u32 & I2C_M_NOSTART != 0 { + if msg.flags() as u32 & I2C_M_IGNORE_NAK != 0 { ignore_nak = true; } } i2c_dev.curr_msg = Some(msgs); + i2c_dev.curr_idx = 0; i2c_dev.num_msgs = num; i2c_dev.msg_err = 0; - i2c_dev.completion.reinit(); + i2c_dev.bcm2835_i2c_start_transfer(); let time_left = i2c_dev @@ -470,14 +609,14 @@ fn bcm2835_i2c_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result 1 || (DEBUG != 0 && (time_left == 0 || i2c_dev.msg_err != 0)) } { - // debug print + i2c_dev.debug_print(); } i2c_dev.debug_num_msgs = 0; i2c_dev.debug_num = 0; if time_left == 0 { - i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); + i2c_dev.i2c_writel(BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); dev_err!(i2c_dev.dev, "i2c transfer timed out\n"); return Err(ETIMEDOUT); } @@ -499,7 +638,7 @@ fn bcm2835_i2c_xfer(adap: &I2cAdapter, msgs: Vec, num: i32) -> Result u32 { - i2c::I2C_FUNC_I2C | i2c::I2C_FUNC_10BIT_ADDR | i2c::I2C_FUNC_PROTOCOL_MANGLING + i2c::I2C_FUNC_I2C | i2c::I2C_FUNC_SMBUS_EMUL | i2c::I2C_FUNC_PROTOCOL_MANGLING } struct Bcm2835I2cAlgo; @@ -545,11 +684,11 @@ impl platform::Driver for Bcm2835I2cDriver { i2c_dev.completion.init_completion(); let reg_base = pdev.ioremap_resource(0)?; - i2c_dev.reg_base = reg_base; + i2c_dev.regs = reg_base; dev_info!(pdev, "I2c bus device reg_base: {:?}\n", reg_base); let mclk = dev.clk_get()?; - i2c_dev.bus_clk = i2c_dev.bcm2835_i2c_register_div(mclk)?; + i2c_dev.bus_clk = i2c_dev.i2c_register_div(mclk)?; let mut bus_clk_rate = 0; if let Err(_) = dev @@ -603,8 +742,8 @@ impl platform::Driver for Bcm2835I2cDriver { * specifies a limit for how long the device can stretch the * clock, but core I2C doesn't. */ - i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_CLKT, 0); - i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, 0); + i2c_dev.i2c_writel(BCM2835_I2C_CLKT, 0); + i2c_dev.i2c_writel(BCM2835_I2C_C, 0); if let Err(e) = i2c_dev.adapter.i2c_add_adapter() { dev_err!(pdev, "Could not add I2C adapter\n"); diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index d4b68144d16533..1d1a6add23a8f2 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -6,8 +6,8 @@ use crate::{ types::{ForeignOwnable, Opaque}, ThisModule, }; -use alloc::vec::Vec; -use core::{ffi::c_void, marker::PhantomData, mem}; +use alloc::{collections, vec::Vec}; +use core::{ffi::c_void, marker::PhantomData, mem, ptr::null_mut}; use core::{mem::MaybeUninit, slice}; use macros::vtable; @@ -165,16 +165,16 @@ impl I2cMsg { self.0.addr } - /// return buf of i2c_msg and transfer ownership of the buf - pub fn read_buf(&self) -> Option> { + /// return the ptr to the buf. + pub fn read_buf(&self) -> Option<*mut u8> { let len = self.len() as usize; - let buf = unsafe { self.0.buf as *const _ as *mut u8 }; + let buf = self.0.buf; + if buf.is_null() { return None; } - // Safety: buf is valid for len bytes, no contiguity. - let vec: Vec = unsafe { Vec::from_raw_parts(buf, len, len) }; - Some(vec) + + Some(buf) } /// a step forward to next i2c_msg @@ -229,6 +229,10 @@ impl I2cAdapter { unsafe { self.0.timeout as usize } } + pub fn nr(&self) -> i32 { + unsafe { self.0.nr as i32 } + } + pub fn set_up( mut self, name: &CStr, diff --git a/rust/osl/src/arceos/driver/i2c/msg.rs b/rust/osl/src/arceos/driver/i2c/msg.rs index 4a187ff2b0721e..1910045c079fe4 100644 --- a/rust/osl/src/arceos/driver/i2c/msg.rs +++ b/rust/osl/src/arceos/driver/i2c/msg.rs @@ -1,9 +1,9 @@ +use crate::driver::i2c::{GeneralI2cMsg, I2cMsgFlags}; use crate::VecDeque; -use crate::driver::i2c::{I2cMsgFlags, GeneralI2cMsg}; -/// an I2C transaction segment beginning with START +/// an I2C transaction segment beginning with START #[derive(Debug)] -pub struct I2cMsg{ +pub struct I2cMsg { /// Slave address, either 7 or 10 bits. When this is a 10 bit address, /// I2C_M_TEN must be set in @flags and the adapter must support I2C_FUNC_10BIT_ADDR addr: u16, @@ -35,18 +35,31 @@ impl Default for I2cMsg { unsafe impl Send for I2cMsg {} unsafe impl Sync for I2cMsg {} -impl GeneralI2cMsg for I2cMsg { +impl GeneralI2cMsg for I2cMsg { /// Create a new I2cMsg with addr and data that need to transfer - fn new_send(addr: u16, flags: I2cMsgFlags, data: [u8;N]) -> I2cMsg { - assert!(!flags.contains(I2cMsgFlags::I2cMasterRead)); - I2cMsg { addr, flags, buf:VecDeque::from(data),recieve_cmd_cnt: 0, recieve_threshold: 0 } + fn new_send(addr: u16, flags: I2cMsgFlags, data: [u8; N]) -> I2cMsg { + assert!(!flags.contains(I2cMsgFlags::I2cMasterRead)); + I2cMsg { + addr, + flags, + buf: VecDeque::from(data), + recieve_cmd_cnt: 0, + recieve_threshold: 0, + } } /// Create a new I2cMsg with addr and an empty buf that want to recive fn new_recieve(addr: u16, flags: I2cMsgFlags, len: usize) -> I2cMsg { - assert!(flags.contains(I2cMsgFlags::I2cMasterRead)); - I2cMsg { addr, flags, buf: VecDeque::with_capacity(len), recieve_threshold: len, - send_idx: 0, recieve_idx: 0, recieve_cmd_cnt: 0} + assert!(flags.contains(I2cMsgFlags::I2cMasterRead)); + I2cMsg { + addr, + flags, + buf: VecDeque::with_capacity(len), + recieve_threshold: len, + send_idx: 0, + recieve_idx: 0, + recieve_cmd_cnt: 0, + } } /// Get msg copy flags @@ -59,8 +72,8 @@ impl GeneralI2cMsg for I2cMsg { self.flags.remove(flag); } - /// Get msg addr - pub fn addr(&self) -> u16{ + /// Get msg addr + pub fn addr(&self) -> u16 { self.addr } @@ -74,21 +87,21 @@ impl GeneralI2cMsg for I2cMsg { /// int recieve_cmd_cnt pub fn inc_recieve_cmd_cnt(&mut self) { assert!(self.flags.contains(I2cMsgFlags::I2cMasterRead)); - self.recieve_cmd_cnt +=1; + self.recieve_cmd_cnt += 1; } /// Check whether the buffer pointer has left last one - pub fn send_left_last(&self) -> bool { + pub fn send_left_last(&self) -> bool { // MasterRead means msg can be write if self.flags.contains(I2cMsgFlags::I2cMasterRead) { - self.recieve_cmd_cnt as usize == self.recieve_threshold -1 + self.recieve_cmd_cnt as usize == self.recieve_threshold - 1 } else { self.data.len() == 1 } } /// Check whether the buffer pointer has reached the end - pub fn send_end(&self) -> bool { + pub fn send_end(&self) -> bool { // MasterRead means msg can be write if self.flags.contains(I2cMsgFlags::I2cMasterRead) { self.recieve_cmd_cnt as usize == self.recieve_threshold @@ -98,14 +111,14 @@ impl GeneralI2cMsg for I2cMsg { } /// Check whether the buffer pointer has reached the end - pub fn recieve_end(&self) -> bool { + pub fn recieve_end(&self) -> bool { // MasterRead means msg can be write assert!(self.flags.contains(I2cMsgFlags::I2cMasterRead)); self.data.len() == self.recieve_threshold } /// Write 1byte at the specified location - pub fn push_byte(&mut self, byte: u8) { + pub fn push_byte(&mut self, byte: u8) { // MasterRead means msg can be write assert!(self.flags.contains(I2cMsgFlags::I2cMasterRead)); @@ -116,8 +129,8 @@ impl GeneralI2cMsg for I2cMsg { } /// Read 1byte from specified location - pub fn pop_front_byte(&mut self) -> u8 { - // MasterRead means msg can be write, don't alow read + pub fn pop_front_byte(&mut self) -> u8 { + // MasterRead means msg can be write, don't alow read assert!(!self.flags.contains(I2cMsgFlags::I2cMasterRead)); if self.send_end() { From 1f3e0f98f96711009a49cc5d5f6eb902398bc01a Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Tue, 20 Aug 2024 22:22:10 +0800 Subject: [PATCH 16/16] =?UTF-8?q?BCM=5FRUST=20=E6=94=B9=E8=BF=9BI2cMsg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正裸指针形式, 整理代码 Signed-off-by: Nostalgia --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 49 ++++++++++++++------------ rust/kernel/device.rs | 6 ++-- rust/kernel/i2c.rs | 16 +++++---- rust/kernel/of.rs | 2 +- rust/kernel/platform.rs | 5 --- 5 files changed, 40 insertions(+), 38 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 9cb655021e04ea..bcb0442ed6c91d 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 //! BCM2835 master mode driver -use core::{clone::Clone, convert::Into, mem::MaybeUninit, ops::Deref}; +use core::{clone::Clone, mem::MaybeUninit}; use kernel::{ bindings, c_str, @@ -17,7 +17,6 @@ use kernel::{ I2C_M_NO_RD_ACK, I2C_M_RD, I2C_M_RECV_LEN, I2C_M_REV_DIR_ADDR, I2C_M_STOP, I2C_M_TEN, }, interrupt::{request_irq, IrqHandler, IRQF_SHARED}, - io_mem::IoMem, irq, module_platform_driver, new_completion, of::DeviceId, platform, @@ -114,31 +113,30 @@ struct Bcm2835I2cDev { } impl Bcm2835I2cDev { - unsafe fn from_ptr<'a>(ptr: *mut Self) -> &'a mut Self { - unsafe { &mut *ptr.cast() } + fn from_raw<'a>(ptr: *mut Self) -> &'a mut Self { + unsafe { &mut *ptr } } - unsafe fn as_ptr(&self) -> *mut Self { + fn as_ptr(&self) -> *mut Self { self as *const _ as *mut _ } } -struct ClkBcm2835I2c<'c> { +struct ClkBcm2835I2c<'a> { hw: ClkHw, - i2c_dev: &'c Bcm2835I2cDev, -} - -fn to_clk_bcm2835_i2c(hw_ptr: &ClkHw) -> &mut ClkBcm2835I2c<'_> { - unsafe { &mut *(container_of!(hw_ptr, ClkBcm2835I2c<'_>, hw) as *mut ClkBcm2835I2c<'_>) } + i2c_dev: &'a Bcm2835I2cDev, } impl<'c> ClkBcm2835I2c<'c> { fn from_raw<'a>(ptr: *mut Self) -> &'a mut Self { - let ptr = ptr.cast::(); unsafe { &mut *ptr } } } +fn to_clk_bcm2835_i2c(hw_ptr: &ClkHw) -> &mut ClkBcm2835I2c<'_> { + unsafe { &mut *(container_of!(hw_ptr, ClkBcm2835I2c<'_>, hw) as *mut ClkBcm2835I2c<'_>) } +} + fn clk_bcm2835_i2c_calc_divider(rate: u64, parent_rate: u64) -> Result { let mut divider = parent_rate.div_ceil(rate) as u32; @@ -406,9 +404,7 @@ impl Bcm2835I2cDev { if val & BCM2835_I2C_S_TXD == 0 { break; } - // May Wrong! if let Some(buf) = self.msg_buf.take() { - // Safety: msg_buf_remaining > 0 let byte = unsafe { *buf as u32 }; self.i2c_writel(BCM2835_I2C_FIFO, byte); self.msg_buf = unsafe { @@ -426,7 +422,6 @@ impl Bcm2835I2cDev { if !(val & BCM2835_I2C_S_RXD) != 0 { break; } - // May Wrong! if let Some(mut buf) = self.msg_buf.take() { unsafe { *buf = self.i2c_readl(BCM2835_I2C_FIFO) as u8 }; self.msg_buf = unsafe { @@ -658,9 +653,9 @@ impl I2cAlgorithm for Bcm2835I2cAlgo { //I2cAdapterQuirks::new().set_flags(i2c::I2C_AQ_NO_CLK_STRETCH as u64); struct Bcm2835I2cData { - pub(crate) dev: Device, pub(crate) i2c_dev_ptr: *mut Bcm2835I2cDev, } + unsafe impl Sync for Bcm2835I2cData {} unsafe impl Send for Bcm2835I2cData {} @@ -679,7 +674,7 @@ impl platform::Driver for Bcm2835I2cDriver { let dev = Device::from_dev(pdev); let i2c_dev_ptr: *mut Bcm2835I2cDev = dev.kzalloc::()?; - let i2c_dev = unsafe { Bcm2835I2cDev::from_ptr(i2c_dev_ptr) }; + let i2c_dev = unsafe { Bcm2835I2cDev::from_raw(i2c_dev_ptr) }; i2c_dev.dev = dev.clone(); i2c_dev.completion.init_completion(); @@ -733,9 +728,7 @@ impl platform::Driver for Bcm2835I2cDriver { quirks, ); i2c_dev.adapter = adap; - unsafe { - i2c_dev.adapter.i2c_set_adapdata(i2c_dev.as_ptr()); - } + i2c_dev.adapter.i2c_set_adapdata(i2c_dev.as_ptr()); /* * Disable the hardware clock stretching timeout. SMBUS @@ -753,7 +746,7 @@ impl platform::Driver for Bcm2835I2cDriver { let dev_data = kernel::new_device_data!( (), (), - Bcm2835I2cData { dev, i2c_dev_ptr }, + Bcm2835I2cData { i2c_dev_ptr }, "BCM2835_I2C device data" )?; @@ -761,7 +754,7 @@ impl platform::Driver for Bcm2835I2cDriver { } fn remove(_data: &Self::Data) -> Result { - pr_info!("BCM2835 i2c bus device driver remove.\n"); + pr_info!("BCM2835 i2c bus driver remove.\n"); // impl drop for: // clk: clk_rate_exclusive_put, disable_unprepare // irq: free_irq @@ -770,6 +763,18 @@ impl platform::Driver for Bcm2835I2cDriver { } } +impl DeviceRemoval for Bcm2835I2cData { + fn device_remove(&self) { + pr_info!("BCM2835 i2c bus device remove.\n"); + unsafe { + bindings::devm_kfree( + (*self.i2c_dev_ptr).dev.raw_device(), + self.i2c_dev_ptr as *const _ as *const core::ffi::c_void, + ) + } + } +} + kernel::define_of_id_table! {BCM2835_I2C_ID_TABLE, (), [ (DeviceId::Compatible(b"brcm,bcm2711-i2c"), None), (DeviceId::Compatible(b"brcm,bcm2835-i2c"), None), diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index df78be9cec63f8..513b75db8b3403 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -3,14 +3,12 @@ //! Generic devices that are part of the kernel's driver model. //! //! C header: [`include/linux/device.h`](../../../../include/linux/device.h) -use alloc::boxed::Box; - use crate::{ bindings, - clk::{self, Clk}, + clk::Clk, clk_provider::ClkHw, dev_err, - error::{code::*, from_err_ptr, to_result, Result}, + error::{code::*, from_err_ptr, Result}, macros::pin_data, of::DeviceNode, pin_init, pr_crit, diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 1d1a6add23a8f2..d8a468c44ffb83 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -3,12 +3,15 @@ use crate::{ error::{from_result, to_result, Result}, prelude::ENOTSUPP, str::CStr, - types::{ForeignOwnable, Opaque}, + types::ForeignOwnable, ThisModule, }; -use alloc::{collections, vec::Vec}; -use core::{ffi::c_void, marker::PhantomData, mem, ptr::null_mut}; -use core::{mem::MaybeUninit, slice}; +use alloc::vec::Vec; +use core::{ + ffi::c_void, + marker::PhantomData, + mem::{self, MaybeUninit}, +}; use macros::vtable; pub const I2C_M_RD: u32 = bindings::I2C_M_RD; @@ -108,6 +111,7 @@ impl I2cAdapterQuirks { Self(up) } + #[inline] pub fn as_ptr(&self) -> *mut bindings::i2c_adapter_quirks { &self.0 as *const _ as *mut _ } @@ -212,11 +216,11 @@ impl I2cAdapter { &self.0 as *const _ as *mut _ } - pub unsafe fn i2c_get_adapdata(&self) -> *mut T { + pub fn i2c_get_adapdata(&self) -> *mut T { unsafe { bindings::dev_get_drvdata(&self.0.dev as *const _ as *mut _) as *mut T } } - pub unsafe fn i2c_set_adapdata(&mut self, data: *mut T) { + pub fn i2c_set_adapdata(&mut self, data: *mut T) { unsafe { bindings::dev_set_drvdata(&self.0.dev as *const _ as *mut _, data as *mut c_void) } } diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs index 00dceadb791c8b..127a4733177c61 100644 --- a/rust/kernel/of.rs +++ b/rust/kernel/of.rs @@ -127,7 +127,7 @@ impl DeviceNode { } } - // Note: Try to implement in a award way. Wait for imporvement. + // Note: Try to implement in a awkward way. Wait for imporvement. fn read_u32_array(&self, propname: &'static CStr, out_value: &mut u32, sz: usize) -> Result { let ret = unsafe { bindings::of_property_read_variable_u32_array( diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 44248ea515a5b6..70e495dfd298e0 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -5,21 +5,16 @@ //! Also called `platdev`, `pdev`. //! //! C header: [`include/linux/platform_device.h`](../../../../include/linux/platform_device.h) - -use core::ffi::c_void; - use crate::{ bindings, device::{self, RawDevice}, driver, error::{from_err_ptr, from_result, to_result, Error, Result}, - io_mem::Resource, of, str::CStr, types::ForeignOwnable, ThisModule, }; -use kernel::io_mem::IoMem; /// A registration of a platform driver. pub type Registration = driver::Registration>;