Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/nostalgia' into rpi-6.6.y
Browse files Browse the repository at this point in the history
  • Loading branch information
creatoy committed Aug 12, 2024
2 parents 8ee6672 + 282d76a commit fb48d76
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 31 deletions.
21 changes: 11 additions & 10 deletions drivers/i2c/busses/i2c_bcm2835_rust.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// SPDX-License-Identifier: GPL-2.0

//! BCM2835 master mode driver
use core::ops::Not;

use kernel::{
bindings,
clk::Clk,
Expand Down Expand Up @@ -74,9 +71,6 @@ pub const BCM2835_I2C_REDL_SHIFT: u32 = 0;
pub const BCM2835_I2C_CDIV_MIN: u32 = 0x0002;
pub const BCM2835_I2C_CDIV_MAX: u32 = 0xFFFE;

// Debug and Clk_tout_ms is static mut in C code.
// Take as const for now.

pub const DEBUG: i32 = 0;

/// SMBUs-recommended 35ms
Expand Down Expand Up @@ -133,8 +127,8 @@ struct ClkBcm2835I2c<'c> {

impl<'c> ClkBcm2835I2c<'c> {
fn from_raw<'a>(ptr: *mut Self) -> &'a mut Self {
let prt = ptr.cast::<Self>();
unsafe { &mut *prt }
let ptr = ptr.cast::<Self>();
unsafe { &mut *ptr }
}
}

Expand Down Expand Up @@ -196,12 +190,12 @@ fn clk_bcm2835_i2c_set_rate(hw: &ClkHw, rate: u64, parent_rate: u64) -> Result<(
Ok(())
}

fn clk_bcm2835_i2c_round_rate(hw: &ClkHw, rate: u64, parent_rate: &mut u64) -> i32 {
fn clk_bcm2835_i2c_round_rate(hw: &ClkHw, rate: u64, parent_rate: &mut u64) -> i64 {
let Ok(divider) = clk_bcm2835_i2c_calc_divider(rate, *parent_rate) else {
return 0;
};

parent_rate.div_ceil(divider) as i32
parent_rate.div_ceil(divider) as i64
}

fn clk_bcm2835_i2c_recalc_rate(hw: &ClkHw, parent_rate: u64) -> u64 {
Expand Down Expand Up @@ -654,6 +648,13 @@ impl platform::Driver for Bcm2835I2cDriver {

let dev_data =
kernel::new_device_data!((), (), Bcm2835I2cData {}, "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())
}

Expand Down
2 changes: 2 additions & 0 deletions rust/bindings/bindings_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/swait.h>

/* `bindgen` gets confused at certain things. */
const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
Expand Down
42 changes: 23 additions & 19 deletions rust/kernel/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@
//! C header: [`include/linux/completion.h`]
//!
use crate::{
types::Opaque,
str::CStr,
sync::LockClassKey,
prelude::PinInit,
bindings,
};
use crate::{bindings, prelude::PinInit, str::CStr, sync::LockClassKey, types::Opaque};

/// Linux completion wrapper
///
Expand Down Expand Up @@ -42,8 +36,7 @@ impl Completion {
/// Creates a new instance of [`Completion`].
#[inline]
#[allow(clippy::new_ret_no_self)]
pub fn new(name: &'static CStr, key: LockClassKey) -> impl PinInit<Self>
{
pub fn new(name: &'static CStr, key: LockClassKey) -> impl PinInit<Self> {
unsafe {
kernel::init::pin_init_from_closure(move |slot| {
let slot = Self::raw_get(slot);
Expand Down Expand Up @@ -73,25 +66,34 @@ impl Completion {
unsafe { Opaque::raw_get(core::ptr::addr_of!((*ptr).0)) }
}

/// completion reinit
/// completion reinit
pub fn reinit(&self) {
unsafe {(*(self.0.get())).done = 0;}
unsafe {
(*(self.0.get())).done = 0;
}
}

/// This waits to be signaled for completion of a specific task. It is NOT
/// interruptible and there is no timeout.
pub fn wait_for_completion(&self) {
// SAFETY: call ffi and ptr is valid
unsafe{
bindings::wait_for_completion(self.0.get())
}
unsafe { bindings::wait_for_completion(self.0.get()) }
}

/// complete
/// complete
pub fn complete(&self) {
// SAFETY: call ffi and ptr is valid
unsafe { bindings::complete(self.0.get()) }
}

/// Initialize a dynamically allocated completion
pub fn init_completion(&self) {
unsafe {
bindings::complete(self.0.get())
(*(self.0.get())).done = 0;
let wait = &mut (*(self.0.get())).wait;
let name = concat!(stringify!(wait), "\0").as_ptr() as *const core::ffi::c_char;
let key = LockClassKey().as_ptr();
bindings::__init_swait_queue_head(wait, name, key);
}
}

Expand All @@ -104,10 +106,10 @@ impl Completion {
return 0;
}

if left_jiff/(bindings::HZ as usize) == 0 {
if left_jiff / (bindings::HZ as usize) == 0 {
return 1;
} else {
return left_jiff/(bindings::HZ as usize);
return left_jiff / (bindings::HZ as usize);
}
}

Expand All @@ -117,7 +119,9 @@ impl Completion {
fn wait_for_completion_timeout(&self, jiff: usize) -> usize {
// SAFETY: call ffi and ptr is valid
unsafe {
bindings::wait_for_completion_timeout(self.0.get(), jiff.try_into().unwrap()).try_into().unwrap()
bindings::wait_for_completion_timeout(self.0.get(), jiff.try_into().unwrap())
.try_into()
.unwrap()
}
}
}
9 changes: 8 additions & 1 deletion rust/kernel/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
dev_err,
error::{code::*, from_err_ptr, to_result, Result},
macros::pin_data,
of::DeviceNode,
pin_init, pr_crit,
str::CStr,
sync::{
Expand Down Expand Up @@ -213,6 +214,13 @@ impl Device {
Ok(Clk::from_raw(raw))
}

/// Get node from dev
pub fn of_node(&self) -> &mut DeviceNode {
// safety: IS_ENABLED(CONFIG_OF) || dev ptr is valid
let ptr = unsafe { (*(self.raw_device())).of_node };
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<&mut Clk> {
// SAFETY: call ffi and ptr is valid
Expand Down Expand Up @@ -288,7 +296,6 @@ impl Clone for Device {
Device::from_dev(self)
}
}

/// Device data.
///
/// When a device is removed (for whatever reason, for example, because the device was unplugged or
Expand Down
10 changes: 9 additions & 1 deletion rust/kernel/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
str::CStr,
types::{ForeignOwnable, Opaque},
};
use alloc::vec::{self, Vec};
use alloc::vec::Vec;
use core::mem::MaybeUninit;
use core::{ffi::c_void, marker::PhantomData};
use macros::vtable;
Expand Down Expand Up @@ -178,6 +178,14 @@ impl I2cAdapter {
pub fn timeout(&self) -> usize {
unsafe { self.0.timeout as usize }
}

//pub fn set_up(self)
}

impl Drop for I2cAdapter {
fn drop(&mut self) {
unsafe { bindings::i2c_del_adapter(self.as_ptr()) }
}
}
/// Represents i2c_smbus_data
///
Expand Down
130 changes: 130 additions & 0 deletions rust/kernel/interrupt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// SPDX-License-Identifier: GPL-2.0

//! Generic devices that are part of the kernel's driver model.
//!
//! C header: [`include/linux/device.h`](../../../../include/linux/.h)
use crate::{
device::{Device, RawDevice},
error::{to_result, Result},
irq,
str::CStr,
};
use core::{marker::PhantomData, task::Context};

pub const IRQF_TRIGGER_NONE: u32 = bindings::IRQF_TRIGGER_NONE;
pub const IRQF_TRIGGER_RISING: u32 = bindings::IRQF_TRIGGER_RISING;
pub const IRQF_TRIGGER_FALLING: u32 = bindings::IRQF_TRIGGER_FALLING;
pub const IRQF_TRIGGER_HIGH: u32 = bindings::IRQF_TRIGGER_HIGH;
pub const IRQF_TRIGGER_LOW: u32 = bindings::IRQF_TRIGGER_LOW;
pub const IRQF_TRIGGER_MASK: u32 = bindings::IRQF_TRIGGER_MASK;
pub const IRQF_TRIGGER_PROBE: u32 = bindings::IRQF_TRIGGER_PROBE;
pub const IRQF_SHARED: u32 = bindings::IRQF_SHARED;
pub const IRQF_PROBE_SHARED: u32 = bindings::IRQF_PROBE_SHARED;
pub const __IRQF_TIMER: u32 = bindings::__IRQF_TIMER;
pub const IRQF_PERCPU: u32 = bindings::IRQF_PERCPU;
pub const IRQF_NOBALANCING: u32 = bindings::IRQF_NOBALANCING;
pub const IRQF_IRQPOLL: u32 = bindings::IRQF_IRQPOLL;
pub const IRQF_ONESHOT: u32 = bindings::IRQF_ONESHOT;
pub const IRQF_NO_SUSPEND: u32 = bindings::IRQF_NO_SUSPEND;
pub const IRQF_FORCE_RESUME: u32 = bindings::IRQF_FORCE_RESUME;
pub const IRQF_NO_THREAD: u32 = bindings::IRQF_NO_THREAD;
pub const IRQF_EARLY_RESUME: u32 = bindings::IRQF_EARLY_RESUME;
pub const IRQF_COND_SUSPEND: u32 = bindings::IRQF_COND_SUSPEND;
pub const IRQF_NO_AUTOEN: u32 = bindings::IRQF_NO_AUTOEN;
pub const IRQF_NO_DEBUG: u32 = bindings::IRQF_NO_DEBUG;
pub const IRQF_TIMER: u32 = bindings::IRQF_TIMER;
pub const IRQ_NOTCONNECTED: u32 = bindings::IRQ_NOTCONNECTED;

pub trait IrqHandler {
/// User data that will be accessible to all operations
type Context;

fn handler(irq: i32, ctx: &mut Self::Context) -> irq::Return;
}

pub(crate) struct Adapter<T, H>(PhantomData<T>, PhantomData<H>)
where
H: IrqHandler<Context = T>;

impl<T, H> Adapter<T, H>
where
H: IrqHandler<Context = T>,
{
unsafe extern "C" fn handler_callback(
arg1: i32,
arg2: *mut core::ffi::c_void,
) -> bindings::irqreturn_t {
let dev = unsafe { &mut *(arg2 as *const _ as *mut _) };
H::handler(arg1, dev) as bindings::irqreturn_t
}

const VTABLE: bindings::irq_handler_t = Some(Self::handler_callback);

const fn build() -> &'static bindings::irq_handler_t {
&Self::VTABLE
}
}

pub fn request_irq<T, H>(irq: u32, handler: H, flags: u64, name: &'static CStr, dev: &T) -> Result
where
H: IrqHandler<Context = T>,
{
let ret = unsafe {
bindings::request_threaded_irq(
irq,
*Adapter::<T, H>::build(),
None,
flags,
name.as_char_ptr(),
dev as *const _ as *mut core::ffi::c_void,
)
};
to_result(ret)
}

pub fn request_percpu_irq<T, H>(
irq: u32,
handler: H,
dev_name: &'static CStr,
percpu_dev_id: &T,
) -> Result
where
H: IrqHandler<Context = T>,
{
let ret = unsafe {
bindings::__request_percpu_irq(
irq,
*Adapter::<T, H>::build(),
0,
dev_name.as_char_ptr(),
percpu_dev_id as *const _ as *mut core::ffi::c_void,
)
};
to_result(ret)
}

pub fn devm_request_irq<T, H>(
dev: Device,
irq: u32,
handler: H,
flags: u64,
dev_name: &'static CStr,
dev_id: &T,
) -> Result
where
H: IrqHandler<Context = T>,
{
let ret = unsafe {
bindings::devm_request_threaded_irq(
dev.raw_device(),
irq,
*Adapter::<T, H>::build(),
None,
flags,
dev_name.as_char_ptr(),
dev_id as *const _ as *mut core::ffi::c_void,
)
};
to_result(ret)
}
Empty file added rust/kernel/io_pgtable.rs
Empty file.
1 change: 1 addition & 0 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub mod task;
pub mod timekeeping;
pub mod types;
pub mod user_ptr;
pub mod interrupt;

use core::marker::PhantomData;

Expand Down
27 changes: 27 additions & 0 deletions rust/kernel/of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,30 @@ impl DeviceId {
id
}
}

pub struct Property(bindings::property);

impl Property {
#[inline]
pub fn as_ptr(&self) -> *const bindings::property {
&self.0
}
}

pub struct DeviceNode(bindings::device_node);

impl DeviceNode {
pub fn from_raw<'a>(ptr: *mut bindings::device_node) -> &'a mut Self {
let ptr = ptr.cast::<Self>();
unsafe { &mut *ptr }
}

#[inline]
pub fn as_ptr(&self) -> *const bindings::device_node {
&self.0
}

pub fn flags(&self) -> u64 {
self.0._flags
}
}

0 comments on commit fb48d76

Please sign in to comment.