All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rob Herring <robh@kernel.org>
To: Fabien Parent <parent.f@gmail.com>
Cc: "Saravana Kannan" <saravanak@google.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Rafael J. Wysocki" <rafael@kernel.org>,
	"Wolfram Sang" <wsa+renesas@sang-engineering.com>,
	"Mark Brown" <broonie@kernel.org>,
	"Liam Girdwood" <lgirdwood@gmail.com>,
	"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Bjorn Andersson" <andersson@kernel.org>,
	"Konrad Dybcio" <konradybcio@kernel.org>,
	devicetree@vger.kernel.org, rust-for-linux@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org,
	linux-arm-msm@vger.kernel.org, vinod.koul@linaro.org,
	"Fabien Parent" <fabien.parent@linaro.org>,
	"Fiona Behrens" <me@kloenk.dev>
Subject: Re: [PATCH 1/9] rust: i2c: add basic I2C client abstraction
Date: Thu, 19 Dec 2024 07:03:23 -0600	[thread overview]
Message-ID: <20241219130323.GA4049504-robh@kernel.org> (raw)
In-Reply-To: <20241218-ncv6336-v1-1-b8d973747f7a@gmail.com>

On Wed, Dec 18, 2024 at 03:36:31PM -0800, Fabien Parent wrote:
> From: Fiona Behrens <me@kloenk.dev>
> 
> Implement an abstraction to write I2C device drivers. The abstraction
> is pretty basic and provides just the infrastructure to probe
> a device from I2C/OF device_id and abstract `i2c_client`.
> The client will be used by the Regmap abstraction to perform
> I/O on the I2C bus.
> 
> Signed-off-by: Fiona Behrens <me@kloenk.dev>
> Co-developed-by: Fabien Parent <fabien.parent@linaro.org>
> Signed-off-by: Fabien Parent <fabien.parent@linaro.org>
> ---
>  MAINTAINERS                     |   1 +
>  rust/bindings/bindings_helper.h |   1 +
>  rust/helpers/helpers.c          |   1 +
>  rust/helpers/i2c.c              |  13 ++
>  rust/kernel/i2c.rs              | 288 ++++++++++++++++++++++++++++++++++++++++
>  rust/kernel/lib.rs              |   2 +
>  6 files changed, 306 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 6b9e10551392c185b9314c9f94edeaf6e85af58f..961fe4ed39605bf489d1d9e473f47bccb692ff14 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -10796,6 +10796,7 @@ F:	include/linux/i2c-smbus.h
>  F:	include/linux/i2c.h
>  F:	include/uapi/linux/i2c-*.h
>  F:	include/uapi/linux/i2c.h
> +F:	rust/kernel/i2c.rs
>  
>  I2C SUBSYSTEM HOST DRIVERS
>  M:	Andi Shyti <andi.shyti@kernel.org>
> diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
> index e9fdceb568b8f94e602ee498323e5768a40a6cba..a882efb90bfc27960ef1fd5f2dc8cc40533a1c27 100644
> --- a/rust/bindings/bindings_helper.h
> +++ b/rust/bindings/bindings_helper.h
> @@ -16,6 +16,7 @@
>  #include <linux/file.h>
>  #include <linux/firmware.h>
>  #include <linux/fs.h>
> +#include <linux/i2c.h>
>  #include <linux/jiffies.h>
>  #include <linux/jump_label.h>
>  #include <linux/mdio.h>
> diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
> index 0640b7e115be1553549312dcfdf842bcae3bde1b..630e903f516ee14a51f46ff0bcc68e8f9a64021a 100644
> --- a/rust/helpers/helpers.c
> +++ b/rust/helpers/helpers.c
> @@ -15,6 +15,7 @@
>  #include "device.c"
>  #include "err.c"
>  #include "fs.c"
> +#include "i2c.c"
>  #include "io.c"
>  #include "jump_label.c"
>  #include "kunit.c"
> diff --git a/rust/helpers/i2c.c b/rust/helpers/i2c.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..8ffdc454e7597cc61909da5b3597057aeb5f7299
> --- /dev/null
> +++ b/rust/helpers/i2c.c
> @@ -0,0 +1,13 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/i2c.h>
> +
> +void *rust_helper_i2c_get_clientdata(const struct i2c_client *client)
> +{
> +	return i2c_get_clientdata(client);
> +}
> +
> +void rust_helper_i2c_set_clientdata(struct i2c_client *client, void *data)
> +{
> +	i2c_set_clientdata(client, data);
> +}
> diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs
> new file mode 100644
> index 0000000000000000000000000000000000000000..efa03335e5b59e72738380e94213976b2464c25b
> --- /dev/null
> +++ b/rust/kernel/i2c.rs
> @@ -0,0 +1,288 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Abstractions for the I2C bus.
> +//!
> +//! C header: [`include/linux/i2c.h`](srctree/include/linux/i2c.h)
> +
> +use crate::{
> +    bindings, container_of,
> +    device::Device,
> +    device_id::{self, RawDeviceId},
> +    driver,
> +    error::{to_result, Result},
> +    of,
> +    prelude::*,
> +    str::CStr,
> +    types::{ARef, ForeignOwnable, Opaque},
> +    ThisModule,
> +};
> +
> +/// Abstraction for `bindings::i2c_device_id`.
> +#[repr(transparent)]
> +#[derive(Clone, Copy)]
> +pub struct DeviceId(bindings::i2c_device_id);
> +
> +impl DeviceId {
> +    /// Create a new device id from an I2C name.
> +    pub const fn new(name: &CStr) -> Self {
> +        let src = name.as_bytes_with_nul();
> +        // TODO: Replace with `bindings::i2c_device_id::default()` once stabilized for `const`.
> +        // SAFETY: FFI type is valid to be zero-initialized.
> +        let mut i2c: bindings::i2c_device_id = unsafe { core::mem::zeroed() };
> +
> +        let mut i = 0;
> +        while i < src.len() {
> +            i2c.name[i] = src[i] as _;
> +            i += 1;
> +        }

You can simplify this now that char maps to u8 (in rust next).

> +
> +        Self(i2c)
> +    }
> +}
> +
> +// SAFETY:
> +// * `DeviceId` is a `#[repr(transparent)` wrapper of `i2c_device_id` and does not add
> +//   additional invariants, so it's safe to transmute to `RawType`.
> +// * `DRIVER_DATA_OFFSET` is the offset to the `data` field.
> +unsafe impl RawDeviceId for DeviceId {
> +    type RawType = bindings::i2c_device_id;
> +
> +    const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::i2c_device_id, driver_data);
> +
> +    fn index(&self) -> usize {
> +        self.0.driver_data as _
> +    }
> +}
> +
> +/// I2C [`DeviceId`] table.
> +pub type IdTable<T> = &'static dyn device_id::IdTable<DeviceId, T>;
> +
> +/// An adapter for the registration of I2C drivers.
> +#[doc(hidden)]
> +pub struct Adapter<T: Driver + 'static>(T);
> +
> +impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
> +    type RegType = bindings::i2c_driver;
> +
> +    fn register(
> +        i2cdrv: &Opaque<Self::RegType>,
> +        name: &'static CStr,
> +        module: &'static ThisModule,
> +    ) -> Result {
> +        // SAFETY: It's safe to set the fields of `struct i2c_driver` on initialization.
> +        unsafe {
> +            (*i2cdrv.get()).driver.name = name.as_char_ptr();
> +            (*i2cdrv.get()).probe = Some(Self::probe_callback);
> +            (*i2cdrv.get()).remove = Some(Self::remove_callback);
> +            if let Some(t) = T::I2C_ID_TABLE {
> +                (*i2cdrv.get()).id_table = t.as_ptr();
> +            }
> +            if let Some(t) = T::OF_ID_TABLE {
> +                (*i2cdrv.get()).driver.of_match_table = t.as_ptr();
> +            }
> +        }
> +
> +        // SAFETY: `i2cdrv` is guaranteed to be a valid `RegType`.
> +        to_result(unsafe { bindings::i2c_register_driver(module.0, i2cdrv.get()) })
> +    }
> +
> +    fn unregister(i2cdrv: &Opaque<Self::RegType>) {
> +        // SAFETY: `i2cdrv` is guaranteed to be a valid `RegType`.
> +        unsafe { bindings::i2c_del_driver(i2cdrv.get()) };
> +    }
> +}
> +
> +impl<T: Driver> Adapter<T> {
> +    /// Get the [`Self::IdInfo`] that matched during probe.
> +    fn id_info(client: &mut Client) -> Option<&'static T::IdInfo> {
> +        let id = <Self as driver::Adapter>::id_info(client.as_ref());
> +        if id.is_some() {
> +            return id;
> +        }
> +
> +        // SAFETY: `client` and `client.as_raw()` are guaranteed to be valid.
> +        let id = unsafe { bindings::i2c_client_get_device_id(client.as_raw()) };
> +        if !id.is_null() {
> +            // SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct i2c_device_id` and
> +            // does not add additional invariants, so it's safe to transmute.
> +            let id = unsafe { &*id.cast::<DeviceId>() };
> +            return Some(T::I2C_ID_TABLE?.info(id.index()));
> +        }

You aren't handling the DT based matching.

Rob

  reply	other threads:[~2024-12-19 13:03 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-18 23:36 [PATCH 0/9] Regulator driver with I2C/Regmap Rust abstractions Fabien Parent
2024-12-18 23:36 ` [PATCH 1/9] rust: i2c: add basic I2C client abstraction Fabien Parent
2024-12-19 13:03   ` Rob Herring [this message]
2024-12-19 15:33     ` Fabien Parent
2024-12-18 23:36 ` [PATCH 2/9] rust: add abstraction for regmap Fabien Parent
2024-12-20 13:16   ` Mark Brown
2024-12-18 23:36 ` [PATCH 3/9] rust: error: add declaration for ENOTRECOVERABLE error Fabien Parent
2024-12-18 23:36 ` [PATCH 4/9] rust: regulator: add abstraction for Regulator's modes Fabien Parent
2024-12-18 23:36 ` [PATCH 5/9] rust: regulator: add Regulator Driver abstraction Fabien Parent
2024-12-19 10:26   ` Danilo Krummrich
2024-12-19 16:00     ` Fabien Parent
2024-12-19 18:58       ` Mark Brown
2024-12-18 23:36 ` [PATCH 6/9] rust: regulator: add support for regmap Fabien Parent
2024-12-18 23:36 ` [PATCH 7/9] dt-bindings: regulator: add binding for ncv6336 regulator Fabien Parent
2024-12-19  9:28   ` Krzysztof Kozlowski
2024-12-19 16:13     ` Fabien Parent
2024-12-21 20:20       ` Krzysztof Kozlowski
2024-12-18 23:36 ` [PATCH 8/9] regulator: add driver " Fabien Parent
2024-12-19 10:19   ` Dirk Behme
2024-12-20 14:50   ` Mark Brown
2024-12-18 23:36 ` [PATCH 9/9] arm64: dts: qcom: apq8039-t2: add node " Fabien Parent

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241219130323.GA4049504-robh@kernel.org \
    --to=robh@kernel.org \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=andersson@kernel.org \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=broonie@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=fabien.parent@linaro.org \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=konradybcio@kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=me@kloenk.dev \
    --cc=ojeda@kernel.org \
    --cc=parent.f@gmail.com \
    --cc=rafael@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=saravanak@google.com \
    --cc=tmgross@umich.edu \
    --cc=vinod.koul@linaro.org \
    --cc=wsa+renesas@sang-engineering.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.