Skip to content

Commit

Permalink
Refactor bcm2835_rust: xfer
Browse files Browse the repository at this point in the history
Add bcm2835_i2c_xfer
Add Error: EREMOTEIO
Add bcm2835_i2c_func

Signed-off-by: Nostalgia <[email protected]>
  • Loading branch information
lvyuemeng committed Aug 3, 2024
1 parent ae5885d commit d489098
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 5 deletions.
78 changes: 77 additions & 1 deletion drivers/i2c/busses/i2c_bcm2835_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

//! BCM2835 master mode driver
use core::num;

use kernel::driver::DeviceRemoval;
use kernel::error::to_result;
use kernel::i2c;
use kernel::i2c::I2cAdapter;
use kernel::prelude::*;
Expand Down Expand Up @@ -442,7 +445,80 @@ fn bcm2835_i2c_isr(this_irq: i32, data: *mut core::ffi::c_void) -> irq::Return {
}
}

fn bcm2835_i2c_xfer(adap: I2cAdapter, msgs: Vec<I2cMsg>, num: i32) -> Result<()> {}
fn bcm2835_i2c_xfer(adap: I2cAdapter, msgs: Vec<I2cMsg>, num: i32) -> Result<()> {
let i2c_dev = unsafe { &mut *(adap.data as *mut Bcm2835I2cDev) };
let ignore_nak = false;

if unsafe { DEBUG != 0 } {
i2c_dev.debug_num_msgs = num;
}

if unsafe { DEBUG > 2 } {
//for 0..num {
// print msg
//}
}

for msg in &msgs {
if msg.flags() & I2C_M_RD != 0 {
dev_warn!(
i2c_dev.dev,
"only one read message supported, has to be last\n"
);
return Err(EOPENSTALE);
}
if msg.flags() & I2C_M_NOSTART != 0 {
ignore_nak = true;
}
}

i2c_dev.curr_msg = Some(msgs);
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
.completion
.wait_for_completion_timeout_sec(adap.timeout());

i2c_dev.bcm2835_i2c_finish_transfer();

if ignore_nak {
i2c_dev.msg_err &= !BCM2835_I2C_S_ERR;
}

if unsafe { DEBUG > 1 || (DEBUG && (!time_left || i2c_dev.msg_err)) } {
// 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);
dev_err!(i2c_dev.dev, "i2c transfer timed out\n");
return Err(ETIMEDOUT);
}

if !i2c_dev.msg_err != 0 {
return to_result(num);
}

if unsafe { DEBUG != 0 } {
dev_err!(i2c_dev.dev, "i2c transfer failed: {}\n", i2c_dev.msg_err);
}

if i2c_dev.msg_err & BCM2835_I2C_S_ERR != 0 {
return Err(EREMOTEIO);
}

Err(EIO);
}

fn bcm2835_i2c_func(adap: I2cAdapter) -> u32 {
i2c::I2C_FUNC_I2C | i2c::I2C_FUNC_10BIT_ADDR | i2c::I2C_FUNC_PROTOCOL_MANGLING
}

struct Bcm2835I2cAlgo;

Expand Down
1 change: 1 addition & 0 deletions rust/kernel/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub mod code {
};
}

declare_err!(EREMOTEIO,"Remote I/O error.");
declare_err!(ETIMEDOUT, "Operation timeout");
declare_err!(EPERM, "Operation not permitted.");
declare_err!(ENOENT, "No such file or directory.");
Expand Down
37 changes: 33 additions & 4 deletions rust/kernel/i2c.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::marker::PhantomData;

use crate::{str, types::Opaque};
use crate::{platform::Adapter, str, types::Opaque};
use alloc::vec::Vec;
use macros::vtable;

Expand All @@ -13,7 +13,33 @@ pub const I2C_M_IGNORE_NAK: u32 = bindings::I2C_M_IGNORE_NAK;
pub const I2C_M_REV_DIR_ADDR: u32 = bindings::I2C_M_REV_DIR_ADDR;
pub const I2C_M_NOSTART: u32 = bindings::I2C_M_NOSTART;
pub const I2C_M_STOP: u32 = bindings::I2C_M_STOP;

pub const I2C_FUNC_I2C: u32 = bindings::I2C_FUNC_I2C;
pub const I2C_FUNC_10BIT_ADDR: u32 = bindings::I2C_FUNC_10BIT_ADDR;
pub const I2C_FUNC_PROTOCOL_MANGLING: u32 = bindings::I2C_FUNC_PROTOCOL_MANGLING;
pub const I2C_FUNC_SMBUS_PEC: u32 = bindings::I2C_FUNC_SMBUS_PEC;
pub const I2C_FUNC_NOSTART: u32 = bindings::I2C_FUNC_NOSTART;
pub const I2C_FUNC_SLAVE: u32 = bindings::I2C_FUNC_SLAVE;
pub const I2C_FUNC_SMBUS_BLOCK_PROC_CALL: u32 = bindings::I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
pub const I2C_FUNC_SMBUS_QUICK: u32 = bindings::I2C_FUNC_SMBUS_QUICK;
pub const I2C_FUNC_SMBUS_READ_BYTE: u32 = bindings::I2C_FUNC_SMBUS_READ_BYTE;
pub const I2C_FUNC_SMBUS_WRITE_BYTE: u32 = bindings::I2C_FUNC_SMBUS_WRITE_BYTE;
pub const I2C_FUNC_SMBUS_READ_BYTE_DATA: u32 = bindings::I2C_FUNC_SMBUS_READ_BYTE_DATA;
pub const I2C_FUNC_SMBUS_WRITE_BYTE_DATA: u32 = bindings::I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
pub const I2C_FUNC_SMBUS_READ_WORD_DATA: u32 = bindings::I2C_FUNC_SMBUS_READ_WORD_DATA;
pub const I2C_FUNC_SMBUS_WRITE_WORD_DATA: u32 = bindings::I2C_FUNC_SMBUS_WRITE_WORD_DATA;
pub const I2C_FUNC_SMBUS_PROC_CALL: u32 = bindings::I2C_FUNC_SMBUS_PROC_CALL;
pub const I2C_FUNC_SMBUS_READ_BLOCK_DATA: u32 = bindings::I2C_FUNC_SMBUS_READ_BLOCK_DATA;
pub const I2C_FUNC_SMBUS_WRITE_BLOCK_DATA: u32 = bindings::I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
pub const I2C_FUNC_SMBUS_READ_I2C_BLOCK: u32 = bindings::I2C_FUNC_SMBUS_READ_I2C_BLOCK;
pub const I2C_FUNC_SMBUS_WRITE_I2C_BLOCK: u32 = bindings::I2C_FUNC_SMBUS_WRITE_I2C_BLOCK;
pub const I2C_FUNC_SMBUS_HOST_NOTIFY: u32 = bindings::I2C_FUNC_SMBUS_HOST_NOTIFY;
pub const I2C_FUNC_SMBUS_BYTE: u32 = bindings::I2C_FUNC_SMBUS_BYTE;
pub const I2C_FUNC_SMBUS_BYTE_DATA: u32 = bindings::I2C_FUNC_SMBUS_BYTE_DATA;
pub const I2C_FUNC_SMBUS_WORD_DATA: u32 = bindings::I2C_FUNC_SMBUS_WORD_DATA;
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;
/// Represents i2c_msg
///
pub struct I2cMsg(bindings::i2c_msg);
Expand Down Expand Up @@ -56,7 +82,6 @@ impl Default for I2cMsg {
/// Represents i2c_adapter
///
pub struct I2cAdapter(Opaque<bindings::i2c_adapter>);

impl I2cAdapter {
pub fn as_ptr(&self) -> *const bindings::i2c_adapter {
self.0.get() as *const bindings::i2c_adapter
Expand All @@ -68,9 +93,13 @@ impl I2cAdapter {

pub fn i2c_get_adapdata<T>(&self) -> *mut T {
unsafe {
bindings::i2c_get_adapdata(self.0.as_ptr() as *mut bindings::i2c_adapter) as *mut T
bindings::dev_get_drvdata(self.0.as_ptr() as *mut bindings::i2c_adapter) as *mut T
}
}

pub fn timeout(&self) -> i32 {
self.0.get().timeout as i32
}
}
/// Represents i2c_smbus_data
///
Expand Down

0 comments on commit d489098

Please sign in to comment.