Skip to content

Commit fb48d76

Browse files
committed
Merge remote-tracking branch 'origin/nostalgia' into rpi-6.6.y
2 parents 8ee6672 + 282d76a commit fb48d76

File tree

9 files changed

+211
-31
lines changed

9 files changed

+211
-31
lines changed

drivers/i2c/busses/i2c_bcm2835_rust.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22

33
//! BCM2835 master mode driver
4-
5-
use core::ops::Not;
6-
74
use kernel::{
85
bindings,
96
clk::Clk,
@@ -74,9 +71,6 @@ pub const BCM2835_I2C_REDL_SHIFT: u32 = 0;
7471
pub const BCM2835_I2C_CDIV_MIN: u32 = 0x0002;
7572
pub const BCM2835_I2C_CDIV_MAX: u32 = 0xFFFE;
7673

77-
// Debug and Clk_tout_ms is static mut in C code.
78-
// Take as const for now.
79-
8074
pub const DEBUG: i32 = 0;
8175

8276
/// SMBUs-recommended 35ms
@@ -133,8 +127,8 @@ struct ClkBcm2835I2c<'c> {
133127

134128
impl<'c> ClkBcm2835I2c<'c> {
135129
fn from_raw<'a>(ptr: *mut Self) -> &'a mut Self {
136-
let prt = ptr.cast::<Self>();
137-
unsafe { &mut *prt }
130+
let ptr = ptr.cast::<Self>();
131+
unsafe { &mut *ptr }
138132
}
139133
}
140134

@@ -196,12 +190,12 @@ fn clk_bcm2835_i2c_set_rate(hw: &ClkHw, rate: u64, parent_rate: u64) -> Result<(
196190
Ok(())
197191
}
198192

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

204-
parent_rate.div_ceil(divider) as i32
198+
parent_rate.div_ceil(divider) as i64
205199
}
206200

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

655649
let dev_data =
656650
kernel::new_device_data!((), (), Bcm2835I2cData {}, "BCM2835_I2C device data")?;
651+
/*
652+
* Disable the hardware clock stretching timeout. SMBUS
653+
* specifies a limit for how long the device can stretch the
654+
* clock, but core I2C doesn't.
655+
*/
656+
i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_CLKT, 0);
657+
i2c_dev.bcm2835_i2c_writel(BCM2835_I2C_C, 0);
657658
Ok(dev_data.into())
658659
}
659660

rust/bindings/bindings_helper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include <linux/clk-provider.h>
3434
#include <linux/clkdev.h>
3535
#include <linux/i2c.h>
36+
#include <linux/interrupt.h>
37+
#include <linux/swait.h>
3638

3739
/* `bindgen` gets confused at certain things. */
3840
const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;

rust/kernel/completion.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,7 @@
55
//! C header: [`include/linux/completion.h`]
66
//!
77
8-
use crate::{
9-
types::Opaque,
10-
str::CStr,
11-
sync::LockClassKey,
12-
prelude::PinInit,
13-
bindings,
14-
};
8+
use crate::{bindings, prelude::PinInit, str::CStr, sync::LockClassKey, types::Opaque};
159

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

76-
/// completion reinit
69+
/// completion reinit
7770
pub fn reinit(&self) {
78-
unsafe {(*(self.0.get())).done = 0;}
71+
unsafe {
72+
(*(self.0.get())).done = 0;
73+
}
7974
}
8075

8176
/// This waits to be signaled for completion of a specific task. It is NOT
8277
/// interruptible and there is no timeout.
8378
pub fn wait_for_completion(&self) {
8479
// SAFETY: call ffi and ptr is valid
85-
unsafe{
86-
bindings::wait_for_completion(self.0.get())
87-
}
80+
unsafe { bindings::wait_for_completion(self.0.get()) }
8881
}
8982

90-
/// complete
83+
/// complete
9184
pub fn complete(&self) {
9285
// SAFETY: call ffi and ptr is valid
86+
unsafe { bindings::complete(self.0.get()) }
87+
}
88+
89+
/// Initialize a dynamically allocated completion
90+
pub fn init_completion(&self) {
9391
unsafe {
94-
bindings::complete(self.0.get())
92+
(*(self.0.get())).done = 0;
93+
let wait = &mut (*(self.0.get())).wait;
94+
let name = concat!(stringify!(wait), "\0").as_ptr() as *const core::ffi::c_char;
95+
let key = LockClassKey().as_ptr();
96+
bindings::__init_swait_queue_head(wait, name, key);
9597
}
9698
}
9799

@@ -104,10 +106,10 @@ impl Completion {
104106
return 0;
105107
}
106108

107-
if left_jiff/(bindings::HZ as usize) == 0 {
109+
if left_jiff / (bindings::HZ as usize) == 0 {
108110
return 1;
109111
} else {
110-
return left_jiff/(bindings::HZ as usize);
112+
return left_jiff / (bindings::HZ as usize);
111113
}
112114
}
113115

@@ -117,7 +119,9 @@ impl Completion {
117119
fn wait_for_completion_timeout(&self, jiff: usize) -> usize {
118120
// SAFETY: call ffi and ptr is valid
119121
unsafe {
120-
bindings::wait_for_completion_timeout(self.0.get(), jiff.try_into().unwrap()).try_into().unwrap()
122+
bindings::wait_for_completion_timeout(self.0.get(), jiff.try_into().unwrap())
123+
.try_into()
124+
.unwrap()
121125
}
122126
}
123127
}

rust/kernel/device.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::{
1111
dev_err,
1212
error::{code::*, from_err_ptr, to_result, Result},
1313
macros::pin_data,
14+
of::DeviceNode,
1415
pin_init, pr_crit,
1516
str::CStr,
1617
sync::{
@@ -213,6 +214,13 @@ impl Device {
213214
Ok(Clk::from_raw(raw))
214215
}
215216

217+
/// Get node from dev
218+
pub fn of_node(&self) -> &mut DeviceNode {
219+
// safety: IS_ENABLED(CONFIG_OF) || dev ptr is valid
220+
let ptr = unsafe { (*(self.raw_device())).of_node };
221+
DeviceNode::from_raw(ptr)
222+
}
223+
216224
/// Allocate a new clock, register it and return an opaque cookie
217225
pub fn clk_register(&self, clk_hw: &mut ClkHw) -> Result<&mut Clk> {
218226
// SAFETY: call ffi and ptr is valid
@@ -288,7 +296,6 @@ impl Clone for Device {
288296
Device::from_dev(self)
289297
}
290298
}
291-
292299
/// Device data.
293300
///
294301
/// When a device is removed (for whatever reason, for example, because the device was unplugged or

rust/kernel/i2c.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
str::CStr,
66
types::{ForeignOwnable, Opaque},
77
};
8-
use alloc::vec::{self, Vec};
8+
use alloc::vec::Vec;
99
use core::mem::MaybeUninit;
1010
use core::{ffi::c_void, marker::PhantomData};
1111
use macros::vtable;
@@ -178,6 +178,14 @@ impl I2cAdapter {
178178
pub fn timeout(&self) -> usize {
179179
unsafe { self.0.timeout as usize }
180180
}
181+
182+
//pub fn set_up(self)
183+
}
184+
185+
impl Drop for I2cAdapter {
186+
fn drop(&mut self) {
187+
unsafe { bindings::i2c_del_adapter(self.as_ptr()) }
188+
}
181189
}
182190
/// Represents i2c_smbus_data
183191
///

rust/kernel/interrupt.rs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Generic devices that are part of the kernel's driver model.
4+
//!
5+
//! C header: [`include/linux/device.h`](../../../../include/linux/.h)
6+
7+
use crate::{
8+
device::{Device, RawDevice},
9+
error::{to_result, Result},
10+
irq,
11+
str::CStr,
12+
};
13+
use core::{marker::PhantomData, task::Context};
14+
15+
pub const IRQF_TRIGGER_NONE: u32 = bindings::IRQF_TRIGGER_NONE;
16+
pub const IRQF_TRIGGER_RISING: u32 = bindings::IRQF_TRIGGER_RISING;
17+
pub const IRQF_TRIGGER_FALLING: u32 = bindings::IRQF_TRIGGER_FALLING;
18+
pub const IRQF_TRIGGER_HIGH: u32 = bindings::IRQF_TRIGGER_HIGH;
19+
pub const IRQF_TRIGGER_LOW: u32 = bindings::IRQF_TRIGGER_LOW;
20+
pub const IRQF_TRIGGER_MASK: u32 = bindings::IRQF_TRIGGER_MASK;
21+
pub const IRQF_TRIGGER_PROBE: u32 = bindings::IRQF_TRIGGER_PROBE;
22+
pub const IRQF_SHARED: u32 = bindings::IRQF_SHARED;
23+
pub const IRQF_PROBE_SHARED: u32 = bindings::IRQF_PROBE_SHARED;
24+
pub const __IRQF_TIMER: u32 = bindings::__IRQF_TIMER;
25+
pub const IRQF_PERCPU: u32 = bindings::IRQF_PERCPU;
26+
pub const IRQF_NOBALANCING: u32 = bindings::IRQF_NOBALANCING;
27+
pub const IRQF_IRQPOLL: u32 = bindings::IRQF_IRQPOLL;
28+
pub const IRQF_ONESHOT: u32 = bindings::IRQF_ONESHOT;
29+
pub const IRQF_NO_SUSPEND: u32 = bindings::IRQF_NO_SUSPEND;
30+
pub const IRQF_FORCE_RESUME: u32 = bindings::IRQF_FORCE_RESUME;
31+
pub const IRQF_NO_THREAD: u32 = bindings::IRQF_NO_THREAD;
32+
pub const IRQF_EARLY_RESUME: u32 = bindings::IRQF_EARLY_RESUME;
33+
pub const IRQF_COND_SUSPEND: u32 = bindings::IRQF_COND_SUSPEND;
34+
pub const IRQF_NO_AUTOEN: u32 = bindings::IRQF_NO_AUTOEN;
35+
pub const IRQF_NO_DEBUG: u32 = bindings::IRQF_NO_DEBUG;
36+
pub const IRQF_TIMER: u32 = bindings::IRQF_TIMER;
37+
pub const IRQ_NOTCONNECTED: u32 = bindings::IRQ_NOTCONNECTED;
38+
39+
pub trait IrqHandler {
40+
/// User data that will be accessible to all operations
41+
type Context;
42+
43+
fn handler(irq: i32, ctx: &mut Self::Context) -> irq::Return;
44+
}
45+
46+
pub(crate) struct Adapter<T, H>(PhantomData<T>, PhantomData<H>)
47+
where
48+
H: IrqHandler<Context = T>;
49+
50+
impl<T, H> Adapter<T, H>
51+
where
52+
H: IrqHandler<Context = T>,
53+
{
54+
unsafe extern "C" fn handler_callback(
55+
arg1: i32,
56+
arg2: *mut core::ffi::c_void,
57+
) -> bindings::irqreturn_t {
58+
let dev = unsafe { &mut *(arg2 as *const _ as *mut _) };
59+
H::handler(arg1, dev) as bindings::irqreturn_t
60+
}
61+
62+
const VTABLE: bindings::irq_handler_t = Some(Self::handler_callback);
63+
64+
const fn build() -> &'static bindings::irq_handler_t {
65+
&Self::VTABLE
66+
}
67+
}
68+
69+
pub fn request_irq<T, H>(irq: u32, handler: H, flags: u64, name: &'static CStr, dev: &T) -> Result
70+
where
71+
H: IrqHandler<Context = T>,
72+
{
73+
let ret = unsafe {
74+
bindings::request_threaded_irq(
75+
irq,
76+
*Adapter::<T, H>::build(),
77+
None,
78+
flags,
79+
name.as_char_ptr(),
80+
dev as *const _ as *mut core::ffi::c_void,
81+
)
82+
};
83+
to_result(ret)
84+
}
85+
86+
pub fn request_percpu_irq<T, H>(
87+
irq: u32,
88+
handler: H,
89+
dev_name: &'static CStr,
90+
percpu_dev_id: &T,
91+
) -> Result
92+
where
93+
H: IrqHandler<Context = T>,
94+
{
95+
let ret = unsafe {
96+
bindings::__request_percpu_irq(
97+
irq,
98+
*Adapter::<T, H>::build(),
99+
0,
100+
dev_name.as_char_ptr(),
101+
percpu_dev_id as *const _ as *mut core::ffi::c_void,
102+
)
103+
};
104+
to_result(ret)
105+
}
106+
107+
pub fn devm_request_irq<T, H>(
108+
dev: Device,
109+
irq: u32,
110+
handler: H,
111+
flags: u64,
112+
dev_name: &'static CStr,
113+
dev_id: &T,
114+
) -> Result
115+
where
116+
H: IrqHandler<Context = T>,
117+
{
118+
let ret = unsafe {
119+
bindings::devm_request_threaded_irq(
120+
dev.raw_device(),
121+
irq,
122+
*Adapter::<T, H>::build(),
123+
None,
124+
flags,
125+
dev_name.as_char_ptr(),
126+
dev_id as *const _ as *mut core::ffi::c_void,
127+
)
128+
};
129+
to_result(ret)
130+
}

rust/kernel/io_pgtable.rs

Whitespace-only changes.

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ pub mod task;
7878
pub mod timekeeping;
7979
pub mod types;
8080
pub mod user_ptr;
81+
pub mod interrupt;
8182

8283
use core::marker::PhantomData;
8384

rust/kernel/of.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,30 @@ impl DeviceId {
8888
id
8989
}
9090
}
91+
92+
pub struct Property(bindings::property);
93+
94+
impl Property {
95+
#[inline]
96+
pub fn as_ptr(&self) -> *const bindings::property {
97+
&self.0
98+
}
99+
}
100+
101+
pub struct DeviceNode(bindings::device_node);
102+
103+
impl DeviceNode {
104+
pub fn from_raw<'a>(ptr: *mut bindings::device_node) -> &'a mut Self {
105+
let ptr = ptr.cast::<Self>();
106+
unsafe { &mut *ptr }
107+
}
108+
109+
#[inline]
110+
pub fn as_ptr(&self) -> *const bindings::device_node {
111+
&self.0
112+
}
113+
114+
pub fn flags(&self) -> u64 {
115+
self.0._flags
116+
}
117+
}

0 commit comments

Comments
 (0)