Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rust: add regulator consumer abstraction #1040

Draft
wants to merge 23 commits into
base: rust-dev
Choose a base branch
from

Conversation

Fabo
Copy link

@Fabo Fabo commented Nov 14, 2023

I'm currently working on a driver that needs the regulator consumer abstraction. The driver that will use it is not yet ready but I thought I would push here the abstraction in case anyone needs it as well.

I do not consider the abstraction finished. I need to revise the documentation and do more testing.

The abstraction itself depends on https://lore.kernel.org/rust-for-linux/[email protected]/ and is based on rust-dev (but could be rebased without issue on rust-next later on.

I also added a sample, but that one depends on a few things that I pulled from the rust branch such as OF, platform driver abstractions.

@fbq fbq force-pushed the rust-dev branch 2 times, most recently from 5e2b9bc to 5cd4b93 Compare December 14, 2023 20:06
@fbq fbq force-pushed the rust-dev branch 2 times, most recently from 03ec649 to 8f7e376 Compare December 28, 2023 19:38
@fbq fbq force-pushed the rust-dev branch 2 times, most recently from 9bdbf5d to ddbd3ca Compare January 22, 2024 21:49
@fbq fbq force-pushed the rust-dev branch 3 times, most recently from 7b0b25e to ba2f66a Compare February 5, 2024 18:00
@fbq fbq force-pushed the rust-dev branch 3 times, most recently from 596f12c to 6bdd6e6 Compare February 19, 2024 01:41
@Fabo Fabo force-pushed the fparent/rust-regulator branch 6 times, most recently from 848cd82 to 152c1b6 Compare February 21, 2024 05:43
@Fabo Fabo force-pushed the fparent/rust-regulator branch 4 times, most recently from baa41ff to c13f777 Compare March 1, 2024 20:52
@Fabo Fabo force-pushed the fparent/rust-regulator branch 3 times, most recently from 6bf7bdd to 82b010e Compare March 7, 2024 02:00
wedsonaf and others added 23 commits September 2, 2024 12:45
We'll need it, for example, when calling `register_filesystem` to
initialise a file system registration.

Signed-off-by: Wedson Almeida Filho <[email protected]>
This allows modules to be initialised in-place in pinned memory, which
enables the usage of pinned types (e.g., mutexes, spinlocks, driver
registrations, etc.) in modules without any extra allocations.

Drivers that don't need this may continue to implement `Module` without
any changes.

Signed-off-by: Wedson Almeida Filho <[email protected]>
In a subsequent patch we introduce the `Registration` abstraction used
to register driver structures. Some subsystems require the module name on
driver registration (e.g. PCI in __pci_register_driver()), hence pass
the module name to `Module::init`.

Signed-off-by: Danilo Krummrich <[email protected]>
Implement the generic `Registration` type and the `DriverOps` trait.

The `Registration` structure is the common type that represents a driver
registration and is typically bound to the lifetime of a module. However,
it doesn't implement actual calls to the kernel's driver core to register
drivers itself.

Instead the `DriverOps` trait is provided to subsystems, which have to
implement `DriverOps::register` and `DrvierOps::unregister`. Subsystems
have to provide an implementation for both of those methods where the
subsystem specific variants to register / unregister a driver have to
implemented.

For instance, the PCI subsystem would call __pci_register_driver() from
`DriverOps::register` and pci_unregister_driver() from
`DrvierOps::unregister`.

This patch is based on previous work from Wedson Almeida Filho.

Co-developed-by: Wedson Almeida Filho <[email protected]>
Signed-off-by: Wedson Almeida Filho <[email protected]>
Signed-off-by: Danilo Krummrich <[email protected]>
Most subsystems use some kind of ID to match devices and drivers. Hence,
we have to provide Rust drivers an abstraction to register an ID table
for the driver to match.

Generally, those IDs are subsystem specific and hence need to be
implemented by the corresponding subsystem. However, the `IdArray`,
`IdTable` and `RawDeviceId` types provide a generalized implementation
that makes the life of subsystems easier to do so.

Co-developed-by: Asahi Lina <[email protected]>
Signed-off-by: Asahi Lina <[email protected]>
Signed-off-by: Wedson Almeida Filho <[email protected]>
Co-developed-by: Danilo Krummrich <[email protected]>
Signed-off-by: Danilo Krummrich <[email protected]>
Add a simple abstraction to guard critical code sections with an rcu
read lock.

Co-developed-by: Andreas Hindborg <[email protected]>
Signed-off-by: Andreas Hindborg <[email protected]>
Signed-off-by: Wedson Almeida Filho <[email protected]>
Signed-off-by: Danilo Krummrich <[email protected]>
Revocable allows access to objects to be safely revoked at run time.

This is useful, for example, for resources allocated during device probe;
when the device is removed, the driver should stop accessing the device
resources even if another state is kept in memory due to existing
references (i.e., device context data is ref-counted and has a non-zero
refcount after removal of the device).

Signed-off-by: Wedson Almeida Filho <[email protected]>
Signed-off-by: Danilo Krummrich <[email protected]>
Implement `dev_*` print macros for `device::Device`.

They behave like the macros with the same names in C, i.e., they print
messages to the kernel ring buffer with the given level, prefixing the
messages with corresponding device information.

Signed-off-by: Wedson Almeida Filho <[email protected]>
Signed-off-by: Danilo Krummrich <[email protected]>
I/O memory is typically either mapped through direct calls to ioremap()
or subsystem / bus specific ones such as pci_iomap().

Even though subsystem / bus specific functions to map I/O memory are
based on ioremap() / iounmap() it is not desirable to re-implement them
in Rust.

Instead, implement a base type for I/O mapped memory, which generically
provides the corresponding accessors, such as `Io::readb` or
`Io:try_readb`.

`Io` supports an optional const generic, such that a driver can indicate
the minimal expected and required size of the mapping at compile time.
Correspondingly, calls to the 'non-try' accessors, support compile time
checks of the I/O memory offset to read / write, while the 'try'
accessors, provide boundary checks on runtime.

`Io` is meant to be embedded into a structure (e.g. pci::Bar or
io::IoMem) which creates the actual I/O memory mapping and initializes
`Io` accordingly.

To ensure that I/O mapped memory can't out-live the device it may be
bound to, subsystems should embedd the corresponding I/O memory type
(e.g. pci::Bar) into a `Devres` container, such that it gets revoked
once the device is unbound.

Co-developed-by: Philipp Stanner <[email protected]>
Signed-off-by: Philipp Stanner <[email protected]>
Signed-off-by: Danilo Krummrich <[email protected]>
Add a Rust abstraction for the kernel's devres (device resource
management) implementation.

The Devres type acts as a container to manage the lifetime and
accessibility of device bound resources. Therefore it registers a
devres callback and revokes access to the resource on invocation.

Users of the Devres abstraction can simply free the corresponding
resources in their Drop implementation, which is invoked when either the
Devres instance goes out of scope or the devres callback leads to the
resource being revoked, which implies a call to drop_in_place().

Signed-off-by: Danilo Krummrich <[email protected]>
…s generation

In order for modpost to work and correctly generate module aliases from
device ID tables, it needs those tables to exist as global symbols with
a specific name. Additionally, modpost checks the size of the symbol, so
it cannot contain trailing data.

To support this, split IdArrayIds out of IdArray. The former contains
just the IDs. Then split out the device table definition macro from the
macro that defines the device table for a given bus driver, and add
another macro to declare a device table as a module device table.
Drivers can now define their ID table once, and then specify that it
should be used for both the driver and the module:

// Generic OF Device ID table.
kernel::define_of_id_table! {ASAHI_ID_TABLE, &'static hw::HwConfig, [
(of::DeviceId::Compatible(b"apple,agx-t8103"), Some(&hw::t8103::HWCONFIG)),
(of::DeviceId::Compatible(b"apple,agx-t8112"), Some(&hw::t8112::HWCONFIG)),
// ...
]}

/// Platform Driver implementation for `AsahiDriver`.
impl platform::Driver for AsahiDriver {
/// Data associated with each hardware ID.
type IdInfo = &'static hw::HwConfig;

// Assign the above OF ID table to this driver.
kernel::driver_of_id_table!(ASAHI_ID_TABLE);

// ...
}

// Export the OF ID table as a module ID table, to make modpost/autoloading work.
kernel::module_of_id_table!(MOD_TABLE, ASAHI_ID_TABLE);

Signed-off-by: Asahi Lina <[email protected]>
(cherry picked from commit 9d4f135)
Signed-off-by: Fabien Parent <[email protected]>
impl Deref doesn't work in const context. Add a function
that is similar to implementing `deref` but that can
be used in `const` context.

Signed-off-by: Fabien Parent <[email protected]>
Add a new Rust abstraction that allows writing drivers for I2C based
devices.

Signed-off-by: Finn Behrens <[email protected]>
Co-developed-by: Fabien Parent <[email protected]>
Signed-off-by: Fabien Parent <[email protected]>
Create a function that is equivalent to Linux's GENMASK macro.

Signed-off-by: Fabien Parent <[email protected]>
The following code is currently working fine and will generate a struct
named "Test0":

	kernel::macros::paste! {
	    struct [<Test 0>];
	}

But if we need to use a "macro variable" like this:

	macro_rules! test {
	    ($i: literal) => {
		kernel::macros::paste! {
		    struct [<Test $i>];
		}
	    };
	}

	test!(0);

The code above will make the paste! macro panic:

	error: proc macro panicked
	  --> drivers/regulator/ncv6336.rs:25:9
	   |
	25 | /         kernel::macros::paste! {
	26 | |             struct [<Test $i>];
	27 | |         }
	   | |_________^
	...
	31 |   test!(0);
	   |   -------- in this macro invocation
	   |
	   = help: message: unexpected token in paste segments

The reason of this panic is that "macro variables" are creating
`Groups` [0], with the `None` delimiter [1], and currently `Groups`are not
handled by the paste! macro.

This commit adds support for TokenTree::Group token where the delimiter
is None in order to make the previous code snippet now work.

[0] https://doc.rust-lang.org/proc_macro/struct.Group.html
[1] https://doc.rust-lang.org/proc_macro/enum.Delimiter.html#variant.None

Signed-off-by: Fabien Parent <[email protected]>
Add a macro that can be used to repeat code.

It allows to use the following syntax:
	foreach!(i in 0..=4) {
		paste! {
			struct [<Bit $i>];
		}
	}

This will be used by the Regmap abstraction in order to prevent
redefining the same bit several times, hence prevent fields to
overlap.

Signed-off-by: Fabien Parent <[email protected]>
Add an abstraction to regmap for Rust.

Signed-off-by: Fabien Parent <[email protected]>
Add a missing errno for ENOTRECOVERABLE.

Signed-off-by: Fabien Parent <[email protected]>
Add a rust abstraction for the regulator consumer API.

Signed-off-by: Fabien Parent <[email protected]>
This commit adds a Rust abstraction to write Regulator drivers. Only
the features used by the NCV6336 driver were added to this abstraction.

Signed-off-by: Fabien Parent <[email protected]>
The regulator API offer many helpers to help simplifies drivers that
use the regmap API. This commit adds partial support for it, only the
function needed by the NCV6336 driver were added.

In case CONFIG_REGMAP=n, we create a dummy Regmap implementation in
order to avoid to have to surround a lot of the declarations and
statements with #[cfg(CONFIG_REGMAP)].

Signed-off-by: Fabien Parent <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants