Linux RTC
 help / color / mirror / Atom feed
* Re: [PATCH v2 06/12] mfd: sec: add support for S2MU005 PMIC
From: Kaustabh Chakraborty @ 2026-02-23 13:56 UTC (permalink / raw)
  To: Sander Vanheule, Kaustabh Chakraborty, André Draszik,
	Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, Alexandre Belloni, Jonathan Corbet,
	Shuah Khan
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc
In-Reply-To: <4cf24e281fac45637fedf40944d8b5230c0e22d9.camel@svanheule.net>

On 2026-02-20 17:56 +01:00, Sander Vanheule wrote:
> Hi,
>
> On Thu, 2026-02-05 at 21:02 +0530, Kaustabh Chakraborty wrote:
>> On 2026-02-04 15:23 +00:00, André Draszik wrote:
>> > On Mon, 2026-01-26 at 00:37 +0530, Kaustabh Chakraborty wrote:
>> > > +static const struct regmap_config s2mu005_regmap_config = {
>> > > +	.reg_bits = 8,
>> > > +	.val_bits = 8,
>> > > +};
>> > 
>> > No cache? And what is the .max_register value?
>> > 
>> 
>> This was in the previous revision, but I ended up removing it because
>> (at least I thought at that time) interfered with interrupts firing in
>> some way. The actual issue was unrelated, so I will add it back.
>> 
>> However, there is also another thing I see in logs:
>> 
>> sec-pmic-i2c 2-003d: using zero-initialized flat cache, this may cause
>> unexpected behavior
>> 
>> This is due to REGCACHE_FLAT, I am not sure if I should just ignore
>> this.
>
> Sorry to be late to the party, but I'm somewhat responsible for that warning, so
> allow me to chime in :-)
>
> What you are might have been seeing is REGCACHE_FLAT giving you "cached" values
> of 0x0, while the hardware actually has something else. This can cause omitted
> writes, existing (bootloader) config to overwritten, etc.
>
> As André suggested, using .num_reg_defaults_raw is a possibility, but then you
> have to remember that the register defaults are taken to be what the hardware
> state is at that moment, including pre-probe changes. These defaults are used to
> seed the cache (so far, so good), but this may break the contract of
> regmap_sync() if you ever want to use that after actually resetting the PMIC.
>
> If you want to use the flat cache, I would suggest you use REGCACHE_FLAT_S,
> which will track what has already been read from/written to hardware. You will
> also need to specifiy .max_register.

I had figured that out by going through the logs, thanks. :)

>
> I see the other regmap_config-s in this driver also use REGCACHE_FLAT, so you
> may want to consider switching those over as well if these are also showing the
> new warning.
>
>
> Best,
> Sander


^ permalink raw reply

* [PATCH v2 2/2] rtc: max77686: convert to i2c_new_ancillary_device
From: Svyatoslav Ryhel @ 2026-02-23  6:43 UTC (permalink / raw)
  To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Rob Herring,
	Conor Dooley, Alexandre Belloni, Svyatoslav Ryhel
  Cc: linux-kernel, devicetree, linux-rtc
In-Reply-To: <20260223064343.12516-1-clamor95@gmail.com>

Convert RTC I2C device creation from devm_i2c_new_dummy_device() to
i2c_new_ancillary_device() to enable the use of a device tree-specified
RTC address instead of a hardcoded value. If the device tree does not
provide an address, use hardcoded values as a fallback.

This addresses an issue with the MAX77663 PMIC, which can have the RTC at
different I2C positions (either 0x48, like the MAX77714, or 0x68, like
the MAX77620). The MAX77620 value is used as the default. The I2C position
of the MAX77663 is factory-set and cannot be detected from the chip
itself.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 drivers/rtc/rtc-max77686.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 69ea3ce75b5a..3cdfd78a07cc 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -686,6 +686,11 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
 	return ret;
 }
 
+static void max77686_rtc_release_dev(void *client)
+{
+	i2c_unregister_device(client);
+}
+
 static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
 {
 	struct device *parent = info->dev->parent;
@@ -713,12 +718,17 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
 		goto add_rtc_irq;
 	}
 
-	client = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter,
-					   info->drv_data->rtc_i2c_addr);
+	client = i2c_new_ancillary_device(parent_i2c, "rtc",
+					  info->drv_data->rtc_i2c_addr);
 	if (IS_ERR(client))
 		return dev_err_probe(info->dev, PTR_ERR(client),
 				     "Failed to allocate I2C device for RTC\n");
 
+	ret = devm_add_action_or_reset(info->dev, max77686_rtc_release_dev,
+				       client);
+	if (ret)
+		return ret;
+
 	info->rtc_regmap = devm_regmap_init_i2c(client,
 						info->drv_data->regmap_config);
 	if (IS_ERR(info->rtc_regmap))
-- 
2.51.0


^ permalink raw reply related

* [PATCH v2 1/2] dt-bindings: mfd: max77620: document optional RTC address for max77663
From: Svyatoslav Ryhel @ 2026-02-23  6:43 UTC (permalink / raw)
  To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Rob Herring,
	Conor Dooley, Alexandre Belloni, Svyatoslav Ryhel
  Cc: linux-kernel, devicetree, linux-rtc
In-Reply-To: <20260223064343.12516-1-clamor95@gmail.com>

Document an optional second I2C address for the MAX77663 PMIC's RTC
device, to be used if the MAX77663 RTC is located at a non-default I2C
address.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 Documentation/devicetree/bindings/mfd/max77620.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mfd/max77620.txt b/Documentation/devicetree/bindings/mfd/max77620.txt
index 5a642a51d58e..0bbb42e5dcfe 100644
--- a/Documentation/devicetree/bindings/mfd/max77620.txt
+++ b/Documentation/devicetree/bindings/mfd/max77620.txt
@@ -6,10 +6,12 @@ Required properties:
 		"maxim,max77620"
 		"maxim,max20024"
 		"maxim,max77663"
-- reg: I2C device address.
+- reg: I2C device address. In case of MAX77663 there can be 2 addresses,
+       second one specifies position of RTC.
 
 Optional properties:
 -------------------
+- reg-names:		If 2 addresses are specified then, must be "pmic", "rtc"
 - interrupts:		The interrupt on the parent the controller is
 			connected to.
 - interrupt-controller: Marks the device node as an interrupt controller.
-- 
2.51.0


^ permalink raw reply related

* [PATCH v2 0/2] rtc: max77686: convert to i2c_new_ancillary_device
From: Svyatoslav Ryhel @ 2026-02-23  6:43 UTC (permalink / raw)
  To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Rob Herring,
	Conor Dooley, Alexandre Belloni, Svyatoslav Ryhel
  Cc: linux-kernel, devicetree, linux-rtc

Convert RTC I2C device creation from devm_i2c_new_dummy_device() to
i2c_new_ancillary_device() to enable the use of a device tree-specified
RTC address instead of a hardcoded value. If the device tree does not
provide an address, use hardcoded values as a fallback.

This addresses an issue with the MAX77663 PMIC, which can have the RTC at
different I2C positions (either 0x48, like the MAX77714, or 0x68, like
the MAX77620). The MAX77620 value is used as the default. The I2C position
of the MAX77663 is factory-set and cannot be detected from the chip
itself.

I have tested this patch on LG Optimus Vu P895 with max77663 PMIC and
non-default RTC position. RTC is registered correctly.

---
Changes in v2
- dropped patch that changes max77686 and adjusted max77620 where max77663
  is described.
---

Svyatoslav Ryhel (2):
  dt-bindings: mfd: max77620: document optional RTC address for max77663
  rtc: max77686: convert to i2c_new_ancillary_device

 Documentation/devicetree/bindings/mfd/max77620.txt |  4 +++-
 drivers/rtc/rtc-max77686.c                         | 14 ++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

-- 
2.51.0


^ permalink raw reply

* [PATCH] rtc: pic32: allow driver to be compiled with COMPILE_TEST
From: Brian Masney @ 2026-02-22 23:30 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: linux-rtc, linux-kernel, Brian Masney

This driver currently only supports builds against a PIC32 target. Now
that commit ed65ae9f6c6b ("rtc: pic32: update include to use pic32.h
from platform_data") is merged, it's possible to compile this driver on
other architectures.

To avoid future breakage of this driver in the future, let's update the
Kconfig so that it can be built with COMPILE_TEST enabled on all
architectures.

Signed-off-by: Brian Masney <bmasney@redhat.com>
---
 drivers/rtc/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index b46ac73a2124e62f9232e9667da91fcb7ce36a62..364afc73f8abd2ade7e7570ba59c0f1aa0bbe78e 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1986,7 +1986,7 @@ config RTC_DRV_XGENE
 
 config RTC_DRV_PIC32
 	tristate "Microchip PIC32 RTC"
-	depends on MACH_PIC32
+	depends on MACH_PIC32 || COMPILE_TEST
 	default y
 	help
 	   If you say yes here you get support for the PIC32 RTC module.

---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20260222-rtc-pic32-fce9ce197535

Best regards,
-- 
Brian Masney <bmasney@redhat.com>


^ permalink raw reply related

* Re: [GIT PULL] RTC for 7.0
From: pr-tracker-bot @ 2026-02-22 20:18 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: Linus Torvalds, linux-rtc, linux-kernel
In-Reply-To: <202602220133264688bffa@mail.local>

The pull request you sent on Sun, 22 Feb 2026 02:33:26 +0100:

> git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git tags/rtc-7.0

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/5f2eac7767493bf23e6552db82ab25de0dccd54f

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html

^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Danilo Krummrich @ 2026-02-22 16:13 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Alexandre Belloni, Alvin Sun, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, linux-rtc, rust-for-linux, Greg Kroah-Hartman
In-Reply-To: <CAJZ5v0gtiQxBCknkaOzLKrDqUQfhKh_UjQkvgxJBL4UthbCOkg@mail.gmail.com>

On Sun Feb 22, 2026 at 3:01 PM CET, Rafael J. Wysocki wrote:
> General considerations aside, regarding the $subject patch, I don't
> think that it is an improvement because it would confuse the existing
> RTC class device interface quite a bit.
>
> Regarding whether or not switching over the RTC class device interface
> to passing RTC device pointers to its class callbacks is a good idea,
> I think that the difference really boils down to what data needs to be
> accessed by the driver.
>
> As it stands today, in an RTC class callback, the driver gets directly
> to the parent of the given RTC device and if it does not need to get
> to the RTC device at all, that's convenient.  However, if the driver
> needs to get to the RTC device, it will most likely need to use
> driver_data in the parent device for this purpose (and store the RTC
> device pointer).
>
> If the interface were changed to pass RTC device pointers to class
> callbacks, the driver would get to the RTC device and from there it
> would need to get to the parent device in the majority of cases.  Even
> though getting from an RTC device to its parent device is
> straightforward (and does not require using driver_data at all), in
> some drivers that would be an extra step that would make the picture
> somewhat less clear than it is today (and arguably less clear than it
> really needs to be).  Still, the change of the interface might allow
> some other drivers that do access the RTC device in class callback
> functions to be simplified.
>
> Granted, the above options had already been there when the RTC class
> interface was designed and the choice was made at that time.  Revising
> it now would require clear technical reasons IMV.
>
> How hard would it be for Rust to cope with the existing calling
> convention in the RTC class?

There is no limitation from the Rust side of things, as mentioned in [1], this
should work perfectly fine, but it might be slightly less convinient:

Example 1:

	impl rtc::Ops for MyRtcOps {
	    type BusDeviceType = platform::Device<Bound>;

	    fn read_time(
	        parent: &platform::Device<Bound>,
	        time: &mut rtc::Time,
	    ) -> Result {
	        let drvdata = pdev.as_ref().drvdata::<MyDriver>()?;

	        ...
	    }
	}

We can improve this by avoiding that the driver has to extract its bus device
private data all the time by doing this instead:

Example 2:

	impl rtc::Ops for MyRtcOps {
	    type BusDeviceType = platform::Device<Bound>;
	    type BusDeviceData = MyDriver;

	    fn read_time(
	        parent: &platform::Device<Bound>,
	        drvdata: &MyDriver,
	        time: &mut rtc::Time,
	    ) -> Result {
	        ...
	    }
	}

However, this would require to type the rtc::Device over the bus device private
data type, which works perfectly fine, but arguably is a bit odd.

The alternative to make it convinient for drivers and avoid this oddity is to
just let drivers store the data that needs to be accessed from class device
callbacks in the class device private data and data that is only needed in bus
device callbacks in the bus device private data. Additionally, drivers can of
course save a refcount of the class device in their bus device private data as
well.

This is mostly what patch 5 of this series currently does (with a few
modifications) and I personally think it's the most clean approach in terms of
how it turns out for drivers:

Example 3:

	// The bus device private data.
	#[pin_data]
	struct MyDriver {
	    #[pin]
	    irq: irq::Registration<MyIrqHandler>,
	}

	// The class device private data.
	struct MyRtcData {
	    io: Devres<IoMem<PL031_REG_SIZE>>,
	    hw_variant: VendorVariant,
	}

	impl rtc::Ops for MyRtcOps {
	    type BusDeviceType = platform::Device<Bound>;

	    fn read_time(
	        rtc: &rtc::Device<MyRtcData>
	        parent: &platform::Device<Bound>,
	        time: &mut rtc::Time,
	    ) -> Result {
	        let io = rtc.io.access(parent)?;

	        match rtc.hw_variant {
	            VendorVariant::Arm | VendorVariant::StV1 => {
	                let my_time = io.read(...);

	                my_time.write_into(time);
	            },
	            VendorVariant::StV2 => { ... },
	        }
	    }
	}

(Note how we can directly access the `io` and `hw_variant` fields from `rtc`.)

If the data from struct MyRtcData is also needed from other bus callbacks, we
can simply extend struct MyDriver:

	#[pin_data]
	struct MyDriver {
	    #[pin]
	    irq: irq::Registration<MyIrqHandler>,
	    rtc: ARef<rtc::Device<MyRtcData>>,
	}

But again, I just want to make sure we do not encourage to just throw all the
private data a driver may potentially have into the bus device private data
struct.

Besides that, it is of course a subsystem decision and I don't want to be
presumptuous or anything.

My recommendation is to go with something like in (3), otherwise I'd choose (1)
and (2) is my least favorite as I think it is a bit odd to type a class device
over bus device private data.

[1] https://lore.kernel.org/all/DGLLJ541SEJW.160MET6OCQHKS@kernel.org/

^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Rafael J. Wysocki @ 2026-02-22 15:43 UTC (permalink / raw)
  To: Danilo Krummrich, Alvin Sun
  Cc: Alexandre Belloni, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, linux-rtc, rust-for-linux, Greg Kroah-Hartman
In-Reply-To: <DGLLJ541SEJW.160MET6OCQHKS@kernel.org>

On Sun, Feb 22, 2026 at 4:29 PM Danilo Krummrich <dakr@kernel.org> wrote:
>
> On Sun Feb 22, 2026 at 1:25 PM CET, Rafael J. Wysocki wrote:
> > On Sat, Feb 21, 2026 at 3:33 PM Danilo Krummrich <dakr@kernel.org> wrote:
> >>
> >> On Sat Feb 21, 2026 at 12:19 PM CET, Rafael J. Wysocki wrote:
> >> > On Sat, Feb 21, 2026 at 12:16 PM Alexandre Belloni
> >> > <alexandre.belloni@bootlin.com> wrote:
> >> >> > > Out of 29 drivers, 18 are doing so.
> >> >
> >> > The vast majority of around 50 platform drivers I've inspected
> >> > recently use platform_set_drvdata() or equivalent in probe.
> >>
> >> This thread seems to contain quite a bit of confusion and misunderstandings --
> >> let me try to clarify.
> >>
> >>   (1) How Rust handles bus device private data.
> >>
> >>   In Rust the probe() function of a bus implementation (platform, PCI, etc.)
> >>   returns an initializer (impl PinInit<T, Error>) for the driver's device
> >>   private data.
> >>
> >>   The bus implementation takes this initializer and passes it (together with the
> >>   underlying struct device) to the driver-core. The driver-core allocates the
> >>   required memory, initializes the memory with the given initializer and stores
> >>   a pointer to the corresponding object with dev_set_drvdata().
> >>
> >>   So, technically, in Rust all platform drivers call platform_set_drvdata().
> >
> > So do I understand correctly that the driver is required to tell the
> > core what type its driver_data will be and then the core will allocate
> > memory for it and clean it up on remove?
>
> Yes, but it's not really that the driver actively has to tell the driver-core,
> etc.
>
> probe() functions return an initializer for the driver's device private data, so
> the type is known anyways.
>
>             fn probe(
>                 pdev: &pci::Device<Core>,
>                 info: &Self::IdInfo,
>             ) -> impl PinInit<T, Error> {
>                 ...
>             }
>
> So, the return type is a fallible initializer for T, where T is the type of the
> driver's device private data.
>
> I assume this may sound a bit odd with little or no Rust experience. Hence, for
> people without much Rust experience reading along a quick explanation:
>
> On the more general side of things, Rust has a very powerful type system, which
> includes generics, hence modeling such kind of things with generics is pretty
> straight forward and preferred over passing void pointers.
>
> But there is also a much more specific reason; In C dev_get_drvdata() has two
> pitfalls:
>
>   (1) The pointer returned by dev_get_drvdata() is only valid as long as the
>       bus device is bound to the driver.
>
>   (2) The driver has to cast the pointer returned by dev_get_drvdata() to the
>       correct type.
>
> Since Rust is a memory safe language, we can't allow UB for safe APIs. Hence,
> the Rust Device::drvdata() [1] method has to consider both (1) and (2).
>
> (1) is rather simple as we have a type state found bound devices, i.e.
> Device<Bound>, so drvdata() is simply only implemented for Device<Bound>.
>
> (2) is much more tricky as we can't statically type the device over its private
> data, as a single device instance can be bound to multiple drivers at runtime.
>
> Hence, we need a runtime check, which the driver-core does for us. When a driver
> calls the drvdata() method it looks like this:
>
>         fn foo(dev: &Device<Bound>) -> Result {
>             let data = dev.drvdata::<MyDataType>()?;
>
>             data.bar();
>         }
>
> The driver-core takes care of checking that the private data associated with
> `dev` actually is of type MyDataType. If this is not the case, the call simply
> fails.
>
> The alternative would be an infallible unsafe API, such as:
>
>         fn foo(dev: &Device<Bound>) -> Result {
>             // SAFETY:
>             // - `dev` is guaranteed to be bound, because ...
>             // - The private data type of `dev` is guaranteed to be
>             //   `MyDataType`, since ...
>             let data = unsafe { dev.drvdata::<MyDataType>() };
>
>             data.bar();
>         }
>
> [1] https://rust.docs.kernel.org/kernel/device/struct.Device.html#method.drvdata
>
> >>   (Note that this is also true when the driver's device private data type is
> >>   empty (i.e. it has no fields). In this case it could still have a destructor
> >>   that must be called when the device private data structure is destroyed. Of
> >>   course there is no real memory allocation when the struct's size is zero.)
> >
> > So in the simplest case when the driver doesn't need driver_data at
> > all, it will just use a struct with no fields as that driver_data
> > type, IIUC.
>
> Yes, it would look like this:
>
>         struct SampleDriver;
>
>         impl pci::Driver for SampleDriver {
>             fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> {
>                 if !validate_something() {
>                     return Err(EINVAL);
>                 }
>
>                 Ok(Self)
>             }
>         }
>
> >>   But at the same time, this is what leads to a lot of lifetime problems and
> >>   memory bugs and it is one of those things that Rust aims at avoiding by being
> >>   very strict about initialization, ownership and lifetimes.
> >
> > As a general rule, I agree, but I would advise against applying
> > general rules automatically everywhere.
> >
> >>   However, I do also recognize that drivers creating an RTC device are typically
> >>   very simple and in practice I would not be surprised if it turns out that it
> >>   happens that drivers keep the struct rtc_device alive from probe() until the
> >>   bus device is unbound from the driver, i.e. lifetimes just end up being almost
> >>   the same. But I don't know if that's always the case.
> >>
> >>   Regardless of that, I think it would be good to keep driver authors finding a
> >>   common pattern, where class device callbacks carry the corresponding class
> >>   device struct (instead of the parent base struct device).
> >
> > TBH I'm not really convinced about this particular thing and I think I
> > can provide an illustrative example.
> >
> > Namely, quite incidentally, I've recently set out to add an RTC class
> > device to an existing driver, which is the ACPI time and alarm device
> > (TAD) one.  The TAD functionality is based on ACPI control methods
> > provided by the platform firmware and it may (or may not) include
> > RTC-equivalent functions.  So far, the driver has been providing a
> > completely custom sysfs interface to user space, but since more and
> > more platforms contain an ACPI TAD and some of them may not contain a
> > "traditional" RTC, having an RTC class device interface in that driver
> > may be quite useful.
> >
> > I have a prototype of the requisite change (I'll post it shortly for
> > reference) and it turns out that because the RTC class callbacks take
> > the parent device pointer as an argument, wrapping them around the
> > existing driver routines backing the existing sysfs interface is
> > super-straightforward.  Had the RTC class passed an RTC device pointer
> > to those callbacks, the driver would have had to do something to get
> > back from it to the parent device (which is what the driver really
> > works with).  If there are more similar drivers, that would have led
> > to some code duplication that is in fact unnecessary.
>
> The type system in Rust is powerfuly enough, so drivers can even get the exact
> type of the parent device the RTC device has as an additional argument to the
> callback. The infrastructure for this is in place and it is used by subsystems.
> I.e. in RTC we can do something like this:
>
>         impl rtc::Ops for MyRtcOps {
>             type BusDeviceType = platform::Device<Bound>;
>
>             fn read_time(
>                 rtc: &rtc::Device<MyRtcData>,
>                 parent: &platform::Device<Bound>,
>                 time: rtc::Time,
>             ) -> Result {
>                 ...
>             }
>         }
>
> where the corresponding rtc::Device::register() method would ensure that the
> associated BusDeviceType matches the parent device type that is passed to
> rtc::Device::register().
>
> A real example of this can be found in the LED class device abstractions [2].
>
> Note that in contrast to a bus device, class devices can be statically typed
> over their private data: rtc::Device<MyRtcData>.
>
> We usually also implment the Deref trait, such that rtc::Device<MyRtcData>
> automatically dereferences to MyRtcData.
>
> Having that said, if RTC drivers *never* have any private data that should be
> associated with the RTC device exclusively (i.e. data that is only relevant in
> the context of class device callbacks and class device infrastructure in
> general, or logically belongs to the class device), then the `rdev` argument
> would indeed be always unused and hence pointless.
>
> I usually would assume that there are such cases, but if that's really never the
> case for any RTC drivers, then I agree we should change the above code to:
>
>         impl rtc::Ops for MyRtcOps {
>             type BusDeviceType = platform::Device<Bound>;
>
>             fn read_time(
>                 parent: &platform::Device<Bound>,
>                 time: rtc::Time,
>             ) -> Result {
>                 ...
>             }
>         }
>
> This way it is at least clear what kind of device is passed through the class
> device callbacks.
>
> [2] https://lore.kernel.org/all/20260207-rust_leds-v12-1-fdb518417b75@posteo.de/
>
> > Moreover, the RTC device pointer doesn't even need to be stored
> > anywhere in that driver because the driver need not use it directly at
> > all and the RTC device object memory is freed by the core when the
> > driver unbinds.
>
> I don't think that is true, I think there are a few drivers accessing the RTC
> device from IRQs or workqueues.

I was referring to the specific case I had in mind, I didn't mean that
this was always the case.  Sorry for being unclear.

> Besides that, quite a lot of RTC drivers actually seem to save a pointer to the
> struct rtc_device within their bus device private data, e.g. [3] and [4].
>
> [3] https://elixir.bootlin.com/linux/v6.19.2/source/drivers/rtc/rtc-ac100.c#L91
> [4] https://elixir.bootlin.com/linux/v6.19.2/source/drivers/rtc/rtc-cros-ec.c#L30

Right.

> >>   Especially on the Rust side we now have the chance to make the experience of
> >>   writing drivers as consistent as possible, which should help (new) driver
> >>   authors a lot in terms of learning the driver lifetime patterns.
> >
> > Well, I'm not sure if "the experience of writing drivers as consistent
> > as possible" is more important than less code duplication and simpler
> > code.
>
> Yeah, it always depends, and if there *really* is no point in having any class
> device private data in RTC, then that's of course fine too.
>
> I just want to make sure we do not encourage to just through all the private
> data a driver may potentially have into the bus device private data struct.
>
> I saw this a lot in C drivers and it actually causes ownership and lifetime
> problems.

Sure.

Alexandre doesn't seem to be convinced that it is necessary to change
the RTC class device interface, so if there are any existing RTC
drivers that would benefit from doing so, it would be good to refer to
them specifically as examples.  Alvin, can you find any?

^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Danilo Krummrich @ 2026-02-22 15:29 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Alexandre Belloni, Alvin Sun, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, linux-rtc, rust-for-linux, Greg Kroah-Hartman
In-Reply-To: <CAJZ5v0gtrpFKPV0LPzfz4JHkEqwK1XRoqO8peWYKw_4j5ti1MA@mail.gmail.com>

On Sun Feb 22, 2026 at 1:25 PM CET, Rafael J. Wysocki wrote:
> On Sat, Feb 21, 2026 at 3:33 PM Danilo Krummrich <dakr@kernel.org> wrote:
>>
>> On Sat Feb 21, 2026 at 12:19 PM CET, Rafael J. Wysocki wrote:
>> > On Sat, Feb 21, 2026 at 12:16 PM Alexandre Belloni
>> > <alexandre.belloni@bootlin.com> wrote:
>> >> > > Out of 29 drivers, 18 are doing so.
>> >
>> > The vast majority of around 50 platform drivers I've inspected
>> > recently use platform_set_drvdata() or equivalent in probe.
>>
>> This thread seems to contain quite a bit of confusion and misunderstandings --
>> let me try to clarify.
>>
>>   (1) How Rust handles bus device private data.
>>
>>   In Rust the probe() function of a bus implementation (platform, PCI, etc.)
>>   returns an initializer (impl PinInit<T, Error>) for the driver's device
>>   private data.
>>
>>   The bus implementation takes this initializer and passes it (together with the
>>   underlying struct device) to the driver-core. The driver-core allocates the
>>   required memory, initializes the memory with the given initializer and stores
>>   a pointer to the corresponding object with dev_set_drvdata().
>>
>>   So, technically, in Rust all platform drivers call platform_set_drvdata().
>
> So do I understand correctly that the driver is required to tell the
> core what type its driver_data will be and then the core will allocate
> memory for it and clean it up on remove?

Yes, but it's not really that the driver actively has to tell the driver-core,
etc.

probe() functions return an initializer for the driver's device private data, so
the type is known anyways.

	    fn probe(
	        pdev: &pci::Device<Core>,
	        info: &Self::IdInfo,
	    ) -> impl PinInit<T, Error> {
	        ...
	    }

So, the return type is a fallible initializer for T, where T is the type of the
driver's device private data.

I assume this may sound a bit odd with little or no Rust experience. Hence, for
people without much Rust experience reading along a quick explanation:

On the more general side of things, Rust has a very powerful type system, which
includes generics, hence modeling such kind of things with generics is pretty
straight forward and preferred over passing void pointers.

But there is also a much more specific reason; In C dev_get_drvdata() has two
pitfalls:

  (1) The pointer returned by dev_get_drvdata() is only valid as long as the
      bus device is bound to the driver.

  (2) The driver has to cast the pointer returned by dev_get_drvdata() to the
      correct type.

Since Rust is a memory safe language, we can't allow UB for safe APIs. Hence,
the Rust Device::drvdata() [1] method has to consider both (1) and (2).

(1) is rather simple as we have a type state found bound devices, i.e.
Device<Bound>, so drvdata() is simply only implemented for Device<Bound>.

(2) is much more tricky as we can't statically type the device over its private
data, as a single device instance can be bound to multiple drivers at runtime.

Hence, we need a runtime check, which the driver-core does for us. When a driver
calls the drvdata() method it looks like this:

	fn foo(dev: &Device<Bound>) -> Result {
	    let data = dev.drvdata::<MyDataType>()?;

	    data.bar();
	}

The driver-core takes care of checking that the private data associated with
`dev` actually is of type MyDataType. If this is not the case, the call simply
fails.

The alternative would be an infallible unsafe API, such as:

	fn foo(dev: &Device<Bound>) -> Result {
	    // SAFETY:
	    // - `dev` is guaranteed to be bound, because ...
	    // - The private data type of `dev` is guaranteed to be
	    //   `MyDataType`, since ...
	    let data = unsafe { dev.drvdata::<MyDataType>() };

	    data.bar();
	}

[1] https://rust.docs.kernel.org/kernel/device/struct.Device.html#method.drvdata

>>   (Note that this is also true when the driver's device private data type is
>>   empty (i.e. it has no fields). In this case it could still have a destructor
>>   that must be called when the device private data structure is destroyed. Of
>>   course there is no real memory allocation when the struct's size is zero.)
>
> So in the simplest case when the driver doesn't need driver_data at
> all, it will just use a struct with no fields as that driver_data
> type, IIUC.

Yes, it would look like this:

	struct SampleDriver;
	
	impl pci::Driver for SampleDriver {
	    fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> {
	        if !validate_something() {
	            return Err(EINVAL);
	        }
	
	        Ok(Self)
	    }
	}

>>   But at the same time, this is what leads to a lot of lifetime problems and
>>   memory bugs and it is one of those things that Rust aims at avoiding by being
>>   very strict about initialization, ownership and lifetimes.
>
> As a general rule, I agree, but I would advise against applying
> general rules automatically everywhere.
>
>>   However, I do also recognize that drivers creating an RTC device are typically
>>   very simple and in practice I would not be surprised if it turns out that it
>>   happens that drivers keep the struct rtc_device alive from probe() until the
>>   bus device is unbound from the driver, i.e. lifetimes just end up being almost
>>   the same. But I don't know if that's always the case.
>>
>>   Regardless of that, I think it would be good to keep driver authors finding a
>>   common pattern, where class device callbacks carry the corresponding class
>>   device struct (instead of the parent base struct device).
>
> TBH I'm not really convinced about this particular thing and I think I
> can provide an illustrative example.
>
> Namely, quite incidentally, I've recently set out to add an RTC class
> device to an existing driver, which is the ACPI time and alarm device
> (TAD) one.  The TAD functionality is based on ACPI control methods
> provided by the platform firmware and it may (or may not) include
> RTC-equivalent functions.  So far, the driver has been providing a
> completely custom sysfs interface to user space, but since more and
> more platforms contain an ACPI TAD and some of them may not contain a
> "traditional" RTC, having an RTC class device interface in that driver
> may be quite useful.
>
> I have a prototype of the requisite change (I'll post it shortly for
> reference) and it turns out that because the RTC class callbacks take
> the parent device pointer as an argument, wrapping them around the
> existing driver routines backing the existing sysfs interface is
> super-straightforward.  Had the RTC class passed an RTC device pointer
> to those callbacks, the driver would have had to do something to get
> back from it to the parent device (which is what the driver really
> works with).  If there are more similar drivers, that would have led
> to some code duplication that is in fact unnecessary.

The type system in Rust is powerfuly enough, so drivers can even get the exact
type of the parent device the RTC device has as an additional argument to the
callback. The infrastructure for this is in place and it is used by subsystems.
I.e. in RTC we can do something like this:

	impl rtc::Ops for MyRtcOps {
	    type BusDeviceType = platform::Device<Bound>;
	
	    fn read_time(
	        rtc: &rtc::Device<MyRtcData>,
	        parent: &platform::Device<Bound>,
	        time: rtc::Time,
	    ) -> Result {
	        ...
	    }
	}

where the corresponding rtc::Device::register() method would ensure that the
associated BusDeviceType matches the parent device type that is passed to
rtc::Device::register().

A real example of this can be found in the LED class device abstractions [2].

Note that in contrast to a bus device, class devices can be statically typed
over their private data: rtc::Device<MyRtcData>.

We usually also implment the Deref trait, such that rtc::Device<MyRtcData>
automatically dereferences to MyRtcData.

Having that said, if RTC drivers *never* have any private data that should be
associated with the RTC device exclusively (i.e. data that is only relevant in
the context of class device callbacks and class device infrastructure in
general, or logically belongs to the class device), then the `rdev` argument
would indeed be always unused and hence pointless.

I usually would assume that there are such cases, but if that's really never the
case for any RTC drivers, then I agree we should change the above code to:

	impl rtc::Ops for MyRtcOps {
	    type BusDeviceType = platform::Device<Bound>;
	
	    fn read_time(
	        parent: &platform::Device<Bound>,
	        time: rtc::Time,
	    ) -> Result {
	        ...
	    }
	}

This way it is at least clear what kind of device is passed through the class
device callbacks.

[2] https://lore.kernel.org/all/20260207-rust_leds-v12-1-fdb518417b75@posteo.de/

> Moreover, the RTC device pointer doesn't even need to be stored
> anywhere in that driver because the driver need not use it directly at
> all and the RTC device object memory is freed by the core when the
> driver unbinds.

I don't think that is true, I think there are a few drivers accessing the RTC
device from IRQs or workqueues.

Besides that, quite a lot of RTC drivers actually seem to save a pointer to the
struct rtc_device within their bus device private data, e.g. [3] and [4].

[3] https://elixir.bootlin.com/linux/v6.19.2/source/drivers/rtc/rtc-ac100.c#L91
[4] https://elixir.bootlin.com/linux/v6.19.2/source/drivers/rtc/rtc-cros-ec.c#L30

>>   Especially on the Rust side we now have the chance to make the experience of
>>   writing drivers as consistent as possible, which should help (new) driver
>>   authors a lot in terms of learning the driver lifetime patterns.
>
> Well, I'm not sure if "the experience of writing drivers as consistent
> as possible" is more important than less code duplication and simpler
> code.

Yeah, it always depends, and if there *really* is no point in having any class
device private data in RTC, then that's of course fine too.

I just want to make sure we do not encourage to just through all the private
data a driver may potentially have into the bus device private data struct.

I saw this a lot in C drivers and it actually causes ownership and lifetime
problems.

^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Rafael J. Wysocki @ 2026-02-22 14:24 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Danilo Krummrich, Alexandre Belloni, Alvin Sun, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, linux-rtc,
	rust-for-linux, Greg Kroah-Hartman
In-Reply-To: <CAJZ5v0gtrpFKPV0LPzfz4JHkEqwK1XRoqO8peWYKw_4j5ti1MA@mail.gmail.com>

On Sun, Feb 22, 2026 at 1:25 PM Rafael J. Wysocki <rafael@kernel.org> wrote:
>
> On Sat, Feb 21, 2026 at 3:33 PM Danilo Krummrich <dakr@kernel.org> wrote:
> >
> > On Sat Feb 21, 2026 at 12:19 PM CET, Rafael J. Wysocki wrote:
> > > On Sat, Feb 21, 2026 at 12:16 PM Alexandre Belloni
> > > <alexandre.belloni@bootlin.com> wrote:
> > >> > > Out of 29 drivers, 18 are doing so.
> > >
> > > The vast majority of around 50 platform drivers I've inspected
> > > recently use platform_set_drvdata() or equivalent in probe.
> >
> > This thread seems to contain quite a bit of confusion and misunderstandings --
> > let me try to clarify.
> >
> >   (1) How Rust handles bus device private data.
> >
> >   In Rust the probe() function of a bus implementation (platform, PCI, etc.)
> >   returns an initializer (impl PinInit<T, Error>) for the driver's device
> >   private data.
> >
> >   The bus implementation takes this initializer and passes it (together with the
> >   underlying struct device) to the driver-core. The driver-core allocates the
> >   required memory, initializes the memory with the given initializer and stores
> >   a pointer to the corresponding object with dev_set_drvdata().
> >
> >   So, technically, in Rust all platform drivers call platform_set_drvdata().
>
> So do I understand correctly that the driver is required to tell the
> core what type its driver_data will be and then the core will allocate
> memory for it and clean it up on remove?
>
> >   (Note that this is also true when the driver's device private data type is
> >   empty (i.e. it has no fields). In this case it could still have a destructor
> >   that must be called when the device private data structure is destroyed. Of
> >   course there is no real memory allocation when the struct's size is zero.)
>
> So in the simplest case when the driver doesn't need driver_data at
> all, it will just use a struct with no fields as that driver_data
> type, IIUC.
>
> >   The driver's device private data can only be accessed when the bus device is
> >   bound to the driver, i.e. the driver can only access it with a &Device<Bound>;
> >   it (the driver's device private data) is automatically freed by the
> >   driver-core when remove() and all devres callbacks have been completed.
>
> Well, that's what happens on the C side of things too most of the time
> because driver_data is allocated at probe time, very often using
> devm_kzalloc() or equivalent.
>
> >   I.e. the rules are - of course - the same as on the C side, but they are
> >   enforced by the type system and the driver-core code.
>
> OK
>
> >   (2) Bus device private data vs. class device private data.
> >
> >   The change to pass a struct rtc_device in class device callbacks of RTC,
> >   rather than the base struct device of the corresponding bus device (e.g. AMBA,
> >   platform, etc.) should not aim at storing all data in rtc->dev.private_data
> >   that was previously stored in rtc->dev.parent->private_data.
> >
> >   Instead, it gives drivers the option to differentiate in terms of ownership
> >   and lifetime.
> >
> >   While the bus device private data has a very defined lifetime from probe()
> >   until the device is unbound from the driver, class device private data might
> >   live shorter than this, or might even out-live driver unbind in some cases. It
> >   really depends on the lifetime of the class device itself, which is not
> >   generally defined.
> >
> >   Now, from a C side point of view this may not look like a big deal, as it
> >   (unfortunately) is not that uncommon that struct fields are just initialized
> >   and destroyed whenever needed and the code just takes it into account.
> >
> >   But at the same time, this is what leads to a lot of lifetime problems and
> >   memory bugs and it is one of those things that Rust aims at avoiding by being
> >   very strict about initialization, ownership and lifetimes.
>
> As a general rule, I agree, but I would advise against applying
> general rules automatically everywhere.
>
> >   However, I do also recognize that drivers creating an RTC device are typically
> >   very simple and in practice I would not be surprised if it turns out that it
> >   happens that drivers keep the struct rtc_device alive from probe() until the
> >   bus device is unbound from the driver, i.e. lifetimes just end up being almost
> >   the same. But I don't know if that's always the case.
> >
> >   Regardless of that, I think it would be good to keep driver authors finding a
> >   common pattern, where class device callbacks carry the corresponding class
> >   device struct (instead of the parent base struct device).
>
> TBH I'm not really convinced about this particular thing and I think I
> can provide an illustrative example.
>
> Namely, quite incidentally, I've recently set out to add an RTC class
> device to an existing driver, which is the ACPI time and alarm device
> (TAD) one.  The TAD functionality is based on ACPI control methods
> provided by the platform firmware and it may (or may not) include
> RTC-equivalent functions.  So far, the driver has been providing a
> completely custom sysfs interface to user space, but since more and
> more platforms contain an ACPI TAD and some of them may not contain a
> "traditional" RTC, having an RTC class device interface in that driver
> may be quite useful.
>
> I have a prototype of the requisite change (I'll post it shortly for
> reference) and it turns out that because the RTC class callbacks take
> the parent device pointer as an argument, wrapping them around the
> existing driver routines backing the existing sysfs interface is
> super-straightforward.  Had the RTC class passed an RTC device pointer
> to those callbacks, the driver would have had to do something to get
> back from it to the parent device (which is what the driver really
> works with).  If there are more similar drivers, that would have led
> to some code duplication that is in fact unnecessary.
>
> Moreover, the RTC device pointer doesn't even need to be stored
> anywhere in that driver because the driver need not use it directly at
> all and the RTC device object memory is freed by the core when the
> driver unbinds.

The above is referring specifically to this patch:

https://lore.kernel.org/linux-acpi/10819001.nUPlyArG6x@rafael.j.wysocki/

^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Rafael J. Wysocki @ 2026-02-22 14:01 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: Alexandre Belloni, Rafael J. Wysocki, Alvin Sun, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, linux-rtc,
	rust-for-linux, Greg Kroah-Hartman
In-Reply-To: <DGLI4H9M0T6D.25RTLDVU5JRBE@kernel.org>

On Sun, Feb 22, 2026 at 1:49 PM Danilo Krummrich <dakr@kernel.org> wrote:
>
> On Sun Feb 22, 2026 at 1:05 AM CET, Alexandre Belloni wrote:
> > On 21/02/2026 15:33:48+0100, Danilo Krummrich wrote:
> >>   (2) Bus device private data vs. class device private data.
> >>
> >>   The change to pass a struct rtc_device in class device callbacks of RTC,
> >>   rather than the base struct device of the corresponding bus device (e.g. AMBA,
> >>   platform, etc.) should not aim at storing all data in rtc->dev.private_data
> >>   that was previously stored in rtc->dev.parent->private_data.
> >>
> >
> > But what you explain here is that the drive is forbidden to use
> > rtc->dev.parent->private_data at all because the rust core is already
> > using it. What I'm saying is that it won't work because more than half
> > of the drivers currently need it.
>
> I think I was explaining the exact opposite, i.e. the driver's bus device
> private data is stored in the exact same way as in C, but it has a defined
> lifetime (from probe() until remove() and all devres callbacks have been
> completed) and is managed by the driver-core.
>
> Look at this example:
>
>         // The bus device private data.
>         struct SampleDriver {
>            foo: u32,
>            bar: u32,
>         }
>
>         impl pci::Driver for SampleDriver {
>             fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> {
>                 // Return the driver's bus device private data. The driver-core
>                 // will do all the work for us and eventually call
>                 // `dev_set_drvdata()` on the base `struct device` of `pdev`.

So that's how I thought it would work.

>                 Ok(Foo {
>                     foo: 42,
>                     bar: 24,
>                 })
>             }
>
>             fn unbind(pdev: &pci::Device<Core>, self: Pin<&Self>) {
>                 // Use the driver's device private data from the method's `self` argument.
>                 dev_info!(pdev, "foo: {}, bar: {}\n", self.foo, self.bar);
>
>                 // There's also the `Device<Bound>::drvdata()` accessor, let's
>                 // use that as well.
>
>                 // Get a generic `device::Device` from the `pci::Device`.
>                 let dev = pdev.as_ref();
>
>                 // Get the `drvdata`; we have to assert the type and let the driver-core
>                 // validate that the asserted type is correct.
>                 let drvdata = dev.drvdata::<SampleDriver>()?;
>
>                 dev_info!(pdev, "foo: {}, bar: {}\n", drvdata.foo, drvdata.bar);
>             }
>         }

This helps, thanks!

> >> This thread seems to contain quite a bit of confusion and misunderstandings --
> >> let me try to clarify.
> >>
> >>   (1) How Rust handles bus device private data.
> >>
> >>   In Rust the probe() function of a bus implementation (platform, PCI, etc.)
> >>   returns an initializer (impl PinInit<T, Error>) for the driver's device
> >>   private data.
> >>
> >>   The bus implementation takes this initializer and passes it (together with the
> >>   underlying struct device) to the driver-core. The driver-core allocates the
> >>   required memory, initializes the memory with the given initializer and stores
> >>   a pointer to the corresponding object with dev_set_drvdata().
> >>
> >>   So, technically, in Rust all platform drivers call platform_set_drvdata().
> >>
> >>   (Note that this is also true when the driver's device private data type is
> >>   empty (i.e. it has no fields). In this case it could still have a destructor
> >>   that must be called when the device private data structure is destroyed. Of
> >>   course there is no real memory allocation when the struct's size is zero.)
> >>
> >>   The driver's device private data can only be accessed when the bus device is
> >>   bound to the driver, i.e. the driver can only access it with a &Device<Bound>;
> >>   it (the driver's device private data) is automatically freed by the
> >>   driver-core when remove() and all devres callbacks have been completed.
> >>
> >>   I.e. the rules are - of course - the same as on the C side, but they are
> >>   enforced by the type system and the driver-core code.
> >>
> >
> > This still doesn't explain how you get the class private data that you
> > need when you are in a driver callback that is called from the bus (e.g.
> > suspend/resume) from what you explain, the driver doesn't have any
> > chance to pass it. The whole goal of a device driver is to be the glue
> > between a class device and a bus device as essentially this is the exact
> > physical device, just represented differently.
>
> It is not always as simple as "one bus device corresponds to one class device".
>
> Sometimes drivers have to deal with multiple class devices for a single bus
> device, sometimes they are separated through the auxiliary bus or MFD.
>
> For instance, take struct net_device. In the context of cfg80211 wireless
> drivers may create arbitrary struct net_device instances, depending on how often
> the add_virtual_intf() callback is called (through netlink); example in [1].
>
> Now, regarding your question "How to access class device private data from bus
> device callbacks?". Nothing prevents a driver from embedding the class device in
> its bus device private data in one or the other way.
>
> In the net device example above, the driver would probably keep a list (or
> xarray, etc.) of net devices in its bus device private data, as they can be
> created and removed at any point of time.
>
> (Note that this is also a good example for when the class device private data
> lives shorter than the bus device private data.)
>
> Here is an example of this looks like in code using a DRM device as class
> device.
>
>         struct SampleIrqData;
>
>         // The class device private data.
>         struct SampleDrm {
>             sched: drm::GpuScheduler,
>         }
>
>         // The bus device private data.
>         #[pin_data]
>         struct SampleDriver {
>             #[pin]
>             irq: irq::Registration<SampleIrqData>,
>             drm: ARef<drm::Device<SampleDrm>, // Refcount of a `drm::Device`.
>         }
>
>         impl pci::Driver for SampleDriver {
>             fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> {
>                 let dev = pdev.as_ref();
>
>                 let drm = drm::Device::new(dev, SampleDrm::new()?)?;
>                 drm.register();
>
>                 Ok(impl_pin_init!(Self {
>                     irq <- irq::Registration::new(...);
>                     drm,
>                 })
>             }
>
>             fn unbind(pdev: &pci::Device<Core>, self: Pin<&Self>) {
>                 self.irq.synchronize();
>                 self.drm.flush_scheduler();
>             }
>         }
>
> Note that the irq::Registration is dropped when the bus device is unbound,
> whereas the GpuScheduler is dropped when the DRM device is dropped.
>
> Of course, depending on the actual class device this difference may be more or
> less important, i.e. absolutely crucial in the net device example, less
> important for RTC apparently. But it is always good to be precise about
> ownership and lifetime of data.
>
> As I already mentioned, I don't think it is good to fold ownership and lifetime
> for bus and class devices together in cases where it happens that they are
> mostly identical, i.e.:
>
> >>   I think it would be good to keep driver authors finding a common pattern,
> >>   where class device callbacks carry the corresponding class device struct
> >>   (instead of the parent base struct device).
> >>
> >>   Especially on the Rust side we now have the chance to make the experience
> >>   of writing drivers as consistent as possible, which should help (new)
> >>   driver authors a lot in terms of learning the driver lifetime patterns.
>
> [1] https://elixir.bootlin.com/linux/v6.19.2/source/drivers/net/wireless/microchip/wilc1000/netdev.c#L948

General considerations aside, regarding the $subject patch, I don't
think that it is an improvement because it would confuse the existing
RTC class device interface quite a bit.

Regarding whether or not switching over the RTC class device interface
to passing RTC device pointers to its class callbacks is a good idea,
I think that the difference really boils down to what data needs to be
accessed by the driver.

As it stands today, in an RTC class callback, the driver gets directly
to the parent of the given RTC device and if it does not need to get
to the RTC device at all, that's convenient.  However, if the driver
needs to get to the RTC device, it will most likely need to use
driver_data in the parent device for this purpose (and store the RTC
device pointer).

If the interface were changed to pass RTC device pointers to class
callbacks, the driver would get to the RTC device and from there it
would need to get to the parent device in the majority of cases.  Even
though getting from an RTC device to its parent device is
straightforward (and does not require using driver_data at all), in
some drivers that would be an extra step that would make the picture
somewhat less clear than it is today (and arguably less clear than it
really needs to be).  Still, the change of the interface might allow
some other drivers that do access the RTC device in class callback
functions to be simplified.

Granted, the above options had already been there when the RTC class
interface was designed and the choice was made at that time.  Revising
it now would require clear technical reasons IMV.

How hard would it be for Rust to cope with the existing calling
convention in the RTC class?

^ permalink raw reply

* [PATCH 6/6] regulator: sc2731: Add platform_device_id table
From: Otto Pflüger @ 2026-02-22 13:16 UTC (permalink / raw)
  To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Lee Jones, Pavel Machek,
	Liam Girdwood, Mark Brown, Sebastian Reichel
  Cc: linux-rtc, devicetree, linux-kernel, linux-leds, linux-pm,
	Otto Pflüger
In-Reply-To: <20260222-sc27xx-mfd-cells-v1-0-69526fe74c77@abscue.de>

Make the regulator driver for the SC2731 PMIC probe automatically. Using
a platform_device_id table instead of DT compatible matching avoids the
need for a separate compatible property in the "regulators" node, which
simplifies the DT bindings and makes the parent MFD device responsible
for selecting the correct regulator driver for the PMIC.

However, this means that the regulator device is not automatically
associated with the "regulators" node. Tell the regulator core to
perform device tree lookups using the parent MFD device instead of
the regulator sub-device and set the .regulators_node member in all
regulator definitions so that the "regulators" sub-node is used.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/regulator/sc2731-regulator.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/regulator/sc2731-regulator.c b/drivers/regulator/sc2731-regulator.c
index 5447e1a47d15..93c8156c5110 100644
--- a/drivers/regulator/sc2731-regulator.c
+++ b/drivers/regulator/sc2731-regulator.c
@@ -131,6 +131,7 @@ static const struct regulator_ops sc2731_regu_linear_ops = {
 			  vstep, vmin, vmax) {			\
 	.name			= #_id,				\
 	.of_match		= of_match_ptr(#_id),		\
+	.regulators_node	= of_match_ptr("regulators"),	\
 	.ops			= &sc2731_regu_linear_ops,	\
 	.type			= REGULATOR_VOLTAGE,		\
 	.id			= SC2731_##_id,			\
@@ -226,7 +227,7 @@ static int sc2731_regulator_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	config.dev = &pdev->dev;
+	config.dev = pdev->dev.parent;
 	config.regmap = regmap;
 
 	for (i = 0; i < ARRAY_SIZE(regulators); i++) {
@@ -242,12 +243,19 @@ static int sc2731_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct platform_device_id sc2731_regulator_id_table[] = {
+	{ "sc2731-regulator" },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sc2731_regulator_id_table);
+
 static struct platform_driver sc2731_regulator_driver = {
 	.driver = {
 		.name = "sc27xx-regulator",
 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
 	},
 	.probe = sc2731_regulator_probe,
+	.id_table = sc2731_regulator_id_table,
 };
 
 module_platform_driver(sc2731_regulator_driver);

-- 
2.51.0


^ permalink raw reply related

* [PATCH 5/6] power: reset: sc27xx: Add platform_device_id table
From: Otto Pflüger @ 2026-02-22 13:16 UTC (permalink / raw)
  To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Lee Jones, Pavel Machek,
	Liam Girdwood, Mark Brown, Sebastian Reichel
  Cc: linux-rtc, devicetree, linux-kernel, linux-leds, linux-pm,
	Otto Pflüger
In-Reply-To: <20260222-sc27xx-mfd-cells-v1-0-69526fe74c77@abscue.de>

Make the poweroff driver for SC27xx-series PMICs probe automatically.
Since the device representing the poweroff functionality of the SC27xx
PMIC is not supposed to have a dedicated device tree node without any
corresponding DT resources [1], an of_device_id table cannot be used
here. Instead, use a platform_device_id table to match the poweroff
sub-device instantiated by the parent MFD driver.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>

[1]: https://lore.kernel.org/all/20251002025344.GA2958334-robh@kernel.org/
---
 drivers/power/reset/sc27xx-poweroff.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/power/reset/sc27xx-poweroff.c b/drivers/power/reset/sc27xx-poweroff.c
index 393bd1c33b73..6376706bf561 100644
--- a/drivers/power/reset/sc27xx-poweroff.c
+++ b/drivers/power/reset/sc27xx-poweroff.c
@@ -6,6 +6,7 @@
 
 #include <linux/cpu.h>
 #include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
@@ -70,11 +71,18 @@ static int sc27xx_poweroff_probe(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct platform_device_id sc27xx_poweroff_id_table[] = {
+	{ "sc2731-poweroff" },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sc27xx_poweroff_id_table);
+
 static struct platform_driver sc27xx_poweroff_driver = {
 	.probe = sc27xx_poweroff_probe,
 	.driver = {
 		.name = "sc27xx-poweroff",
 	},
+	.id_table = sc27xx_poweroff_id_table,
 };
 module_platform_driver(sc27xx_poweroff_driver);
 

-- 
2.51.0


^ permalink raw reply related

* [PATCH 4/6] mfd: sprd-sc27xx: Switch to devm_mfd_add_devices()
From: Otto Pflüger @ 2026-02-22 13:16 UTC (permalink / raw)
  To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Lee Jones, Pavel Machek,
	Liam Girdwood, Mark Brown, Sebastian Reichel
  Cc: linux-rtc, devicetree, linux-kernel, linux-leds, linux-pm,
	Otto Pflüger
In-Reply-To: <20260222-sc27xx-mfd-cells-v1-0-69526fe74c77@abscue.de>

To allow instantiating subdevices such as the regulator and poweroff
devices that do not have corresponding device tree nodes with a
"compatible" property, use devm_mfd_add_devices() with MFD cells instead
of devm_of_platform_populate(). Since different PMICs in the SC27xx
series contain different components, use separate MFD cell tables for
each PMIC model. Define cells for all components that have upstream
drivers at this point.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/mfd/sprd-sc27xx-spi.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c
index d6b4350779e6..57941bec4c2e 100644
--- a/drivers/mfd/sprd-sc27xx-spi.c
+++ b/drivers/mfd/sprd-sc27xx-spi.c
@@ -48,6 +48,31 @@ struct sprd_pmic_data {
 	u32 irq_base;
 	u32 num_irqs;
 	u32 charger_det;
+	const struct mfd_cell *cells;
+	int num_cells;
+};
+
+static const struct mfd_cell sc2730_devices[] = {
+	MFD_CELL_OF("sc2730-adc", NULL, NULL, 0, 0, "sprd,sc2730-adc"),
+	MFD_CELL_OF("sc2730-bltc", NULL, NULL, 0, 0, "sprd,sc2730-bltc"),
+	MFD_CELL_OF("sc2730-efuse", NULL, NULL, 0, 0, "sprd,sc2730-efuse"),
+	MFD_CELL_OF("sc2730-eic", NULL, NULL, 0, 0, "sprd,sc2730-eic"),
+	MFD_CELL_OF("sc2730-fgu", NULL, NULL, 0, 0, "sprd,sc2730-fgu"),
+	MFD_CELL_OF("sc2730-rtc", NULL, NULL, 0, 0, "sprd,sc2730-rtc"),
+	MFD_CELL_OF("sc2730-vibrator", NULL, NULL, 0, 0, "sprd,sc2730-vibrator"),
+};
+
+static const struct mfd_cell sc2731_devices[] = {
+	MFD_CELL_OF("sc2731-adc", NULL, NULL, 0, 0, "sprd,sc2731-adc"),
+	MFD_CELL_OF("sc2731-bltc", NULL, NULL, 0, 0, "sprd,sc2731-bltc"),
+	MFD_CELL_OF("sc2731-charger", NULL, NULL, 0, 0, "sprd,sc2731-charger"),
+	MFD_CELL_OF("sc2731-efuse", NULL, NULL, 0, 0, "sprd,sc2731-efuse"),
+	MFD_CELL_OF("sc2731-eic", NULL, NULL, 0, 0, "sprd,sc2731-eic"),
+	MFD_CELL_OF("sc2731-fgu", NULL, NULL, 0, 0, "sprd,sc2731-fgu"),
+	MFD_CELL_NAME("sc2731-poweroff"),
+	MFD_CELL_NAME("sc2731-regulator"),
+	MFD_CELL_OF("sc2731-rtc", NULL, NULL, 0, 0, "sprd,sc2731-rtc"),
+	MFD_CELL_OF("sc2731-vibrator", NULL, NULL, 0, 0, "sprd,sc2731-vibrator"),
 };
 
 /*
@@ -59,12 +84,16 @@ static const struct sprd_pmic_data sc2730_data = {
 	.irq_base = SPRD_SC2730_IRQ_BASE,
 	.num_irqs = SPRD_SC2730_IRQ_NUMS,
 	.charger_det = SPRD_SC2730_CHG_DET,
+	.cells = sc2730_devices,
+	.num_cells = ARRAY_SIZE(sc2730_devices),
 };
 
 static const struct sprd_pmic_data sc2731_data = {
 	.irq_base = SPRD_SC2731_IRQ_BASE,
 	.num_irqs = SPRD_SC2731_IRQ_NUMS,
 	.charger_det = SPRD_SC2731_CHG_DET,
+	.cells = sc2731_devices,
+	.num_cells = ARRAY_SIZE(sc2731_devices),
 };
 
 enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev)
@@ -204,7 +233,9 @@ static int sprd_pmic_probe(struct spi_device *spi)
 		return ret;
 	}
 
-	ret = devm_of_platform_populate(&spi->dev);
+	ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO,
+				   pdata->cells, pdata->num_cells, NULL, 0,
+				   regmap_irq_get_domain(ddata->irq_data));
 	if (ret) {
 		dev_err(&spi->dev, "Failed to populate sub-devices %d\n", ret);
 		return ret;

-- 
2.51.0


^ permalink raw reply related

* [PATCH 3/6] regulator: dt-bindings: sc2731: Deprecate compatible property
From: Otto Pflüger @ 2026-02-22 13:16 UTC (permalink / raw)
  To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Lee Jones, Pavel Machek,
	Liam Girdwood, Mark Brown, Sebastian Reichel
  Cc: linux-rtc, devicetree, linux-kernel, linux-leds, linux-pm,
	Otto Pflüger
In-Reply-To: <20260222-sc27xx-mfd-cells-v1-0-69526fe74c77@abscue.de>

The node containing the regulators is always a child of the main PMIC
node, which already has a compatible property identifying the type of
PMIC. This makes the compatible in the child node redundant. Mark it
as deprecated and remove it from the required property list and the
examples.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 Documentation/devicetree/bindings/mfd/sprd,sc2731.yaml                | 2 --
 .../devicetree/bindings/regulator/sprd,sc2731-regulator.yaml          | 4 +---
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/sprd,sc2731.yaml b/Documentation/devicetree/bindings/mfd/sprd,sc2731.yaml
index b023e1ef8d3c..12b3258daef5 100644
--- a/Documentation/devicetree/bindings/mfd/sprd,sc2731.yaml
+++ b/Documentation/devicetree/bindings/mfd/sprd,sc2731.yaml
@@ -222,8 +222,6 @@ examples:
         };
 
         regulators {
-          compatible = "sprd,sc2731-regulator";
-
           BUCK_CPU0 {
             regulator-name = "vddarm0";
             regulator-min-microvolt = <400000>;
diff --git a/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml b/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml
index 9bd752bab68e..7af20a4781b7 100644
--- a/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml
@@ -26,6 +26,7 @@ description: |
 
 properties:
   compatible:
+    deprecated: true
     const: sprd,sc2731-regulator
 
 patternProperties:
@@ -39,8 +40,5 @@ patternProperties:
     $ref: regulator.yaml#
     unevaluatedProperties: false
 
-required:
-  - compatible
-
 additionalProperties: false
 ...

-- 
2.51.0


^ permalink raw reply related

* [PATCH 1/6] dt-bindings: rtc: sc2731: Add compatible for SC2730
From: Otto Pflüger @ 2026-02-22 13:16 UTC (permalink / raw)
  To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Lee Jones, Pavel Machek,
	Liam Girdwood, Mark Brown, Sebastian Reichel
  Cc: linux-rtc, devicetree, linux-kernel, linux-leds, linux-pm,
	Otto Pflüger
In-Reply-To: <20260222-sc27xx-mfd-cells-v1-0-69526fe74c77@abscue.de>

The RTC block found in the SC2730 PMIC is compatible with the one found
in the SC2731 PMIC.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml b/Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml
index 5756f617df36..1deae2f4f09d 100644
--- a/Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml
@@ -13,7 +13,12 @@ maintainers:
 
 properties:
   compatible:
-    const: sprd,sc2731-rtc
+    oneOf:
+      - items:
+          - enum:
+              - sprd,sc2730-rtc
+          - const: sprd,sc2731-rtc
+      - const: sprd,sc2731-rtc
 
   reg:
     maxItems: 1

-- 
2.51.0


^ permalink raw reply related

* [PATCH 2/6] dt-bindings: leds: sc2731: Add compatible for SC2730
From: Otto Pflüger @ 2026-02-22 13:16 UTC (permalink / raw)
  To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Lee Jones, Pavel Machek,
	Liam Girdwood, Mark Brown, Sebastian Reichel
  Cc: linux-rtc, devicetree, linux-kernel, linux-leds, linux-pm,
	Otto Pflüger
In-Reply-To: <20260222-sc27xx-mfd-cells-v1-0-69526fe74c77@abscue.de>

The LED controller found in the SC2730 PMIC is compatible with the one
found in the SC2731 PMIC.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml b/Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml
index 97535d6dc47a..2ae5cc31e623 100644
--- a/Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml
+++ b/Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml
@@ -18,7 +18,12 @@ description: |
 
 properties:
   compatible:
-    const: sprd,sc2731-bltc
+    oneOf:
+      - items:
+          - enum:
+              - sprd,sc2730-bltc
+          - const: sprd,sc2731-bltc
+      - const: sprd,sc2731-bltc
 
   reg:
     maxItems: 1

-- 
2.51.0


^ permalink raw reply related

* [PATCH 0/6] mfd: sc27xx: Use MFD cells and devm_mfd_add_devices()
From: Otto Pflüger @ 2026-02-22 13:16 UTC (permalink / raw)
  To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Lee Jones, Pavel Machek,
	Liam Girdwood, Mark Brown, Sebastian Reichel
  Cc: linux-rtc, devicetree, linux-kernel, linux-leds, linux-pm,
	Otto Pflüger

These changes resulted from the need to decouple the the Linux device
driver hierarchy from the device tree bindings for two different series
introducing regulator [1] and poweroff [2] support for the SC2730 PMIC.

There are different PMICs in the SC27xx series, including SC2730 and
SC2731. These have a lot of similarities, but some differences too. For
instance, they contain compatible RTC blocks, but completely different
sets of regulators.

On the Linux side, each PMIC block needs its own driver. The MFD driver
currently uses devm_of_platform_populate() to load the drivers for the
components of the PMIC, which only works when each component has its own
sub-node with a "compatible" property that is used to select a driver
for the device.

When viewed from the device tree side, the parent node representing the
PMIC already contains a "compatible" property that distinguishes the
different PMICs. While the device tree bindings currently do require a
separate "compatible" property for each sub-node (ADC, fuel gauge,
regulators, ...), this is essentially redundant since the node name and
the parent compatible uniquely identify the component. Moreover, some
parts of the PMIC such as the poweroff/reboot controller do not even
need a corresponding device tree node.

Change the MFD driver to use MFD cells instead, which allows it to
instantiate sub-devices both with and without device tree nodes.
Devices that do not have a separate device tree node with its own
"compatible" property can be matched by their platform device ID.
Use this to hook up the existing SC2731 poweroff and regulator drivers,
which were previously not loaded at all due to the lack of an ID table.

In the device tree bindings, deprecate the redundant "compatible"
property for the "regulators" node. While it might make sense to do this
for the other components too, there are a few reasons to only change the
regulators at this point:
 - The regulators node is special since it is not as independent as the
   other components. For instance, it is the only child node of the PMIC
   that does not have a "reg" property. The set of regulators also
   differs much more between different PMIC models than the register
   layout of the other components.
 - We already have some other PMICs where only the regulators are
   treated specially like this, such as MediaTek MT6359 and MT6370.
 - It was suggested to remove the "compatible" property for the new
   SC2730 regulator bindings I am preparing in [2]. The bindings for
   the other components do not need any significant changes at the
   moment.
 - Unlike the poweroff and regulator components, the other parts are
   already working with the existing drivers and bindings.

For the other components that still have a "compatible" property used
for matching MFD cells, ensure that an SC2730-specific compatible is
defined in the bindings so that it can be listed in the SC2730-specific
device table in the MFD driver.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>

[1]: https://lore.kernel.org/all/20250926-sc2730-reboot-v1-0-62ebfd3d31bb@abscue.de/
[2]: https://lore.kernel.org/all/20260220-sc2730-regulators-v1-0-3f2bbc9ecf14@abscue.de/

---
Otto Pflüger (6):
      dt-bindings: rtc: sc2731: Add compatible for SC2730
      dt-bindings: leds: sc2731: Add compatible for SC2730
      regulator: dt-bindings: sc2731: Deprecate compatible property
      mfd: sprd-sc27xx: Switch to devm_mfd_add_devices()
      power: reset: sc27xx: Add platform_device_id table
      regulator: sc2731: Add platform_device_id table

 .../devicetree/bindings/leds/sprd,sc2731-bltc.yaml |  7 ++++-
 .../devicetree/bindings/mfd/sprd,sc2731.yaml       |  2 --
 .../bindings/regulator/sprd,sc2731-regulator.yaml  |  4 +--
 .../devicetree/bindings/rtc/sprd,sc2731-rtc.yaml   |  7 ++++-
 drivers/mfd/sprd-sc27xx-spi.c                      | 33 +++++++++++++++++++++-
 drivers/power/reset/sc27xx-poweroff.c              |  8 ++++++
 drivers/regulator/sc2731-regulator.c               | 10 ++++++-
 7 files changed, 62 insertions(+), 9 deletions(-)
---
base-commit: d4906ae14a5f136ceb671bb14cedbf13fa560da6
change-id: 20260221-sc27xx-mfd-cells-dab7905f3aae

Best regards,
-- 
Otto Pflüger <otto.pflueger@abscue.de>


^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Danilo Krummrich @ 2026-02-22 12:49 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Rafael J. Wysocki, Alvin Sun, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, linux-rtc, rust-for-linux, Greg Kroah-Hartman
In-Reply-To: <20260222000556ea1938c0@mail.local>

On Sun Feb 22, 2026 at 1:05 AM CET, Alexandre Belloni wrote:
> On 21/02/2026 15:33:48+0100, Danilo Krummrich wrote:
>>   (2) Bus device private data vs. class device private data.
>> 
>>   The change to pass a struct rtc_device in class device callbacks of RTC,
>>   rather than the base struct device of the corresponding bus device (e.g. AMBA,
>>   platform, etc.) should not aim at storing all data in rtc->dev.private_data
>>   that was previously stored in rtc->dev.parent->private_data.
>> 
>
> But what you explain here is that the drive is forbidden to use
> rtc->dev.parent->private_data at all because the rust core is already
> using it. What I'm saying is that it won't work because more than half
> of the drivers currently need it.

I think I was explaining the exact opposite, i.e. the driver's bus device
private data is stored in the exact same way as in C, but it has a defined
lifetime (from probe() until remove() and all devres callbacks have been
completed) and is managed by the driver-core.

Look at this example:

	// The bus device private data.
	struct SampleDriver {
	   foo: u32,
	   bar: u32,
	}
	
	impl pci::Driver for SampleDriver {
	    fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> {
	        // Return the driver's bus device private data. The driver-core
	        // will do all the work for us and eventually call
	        // `dev_set_drvdata()` on the base `struct device` of `pdev`.
	        Ok(Foo {
	            foo: 42,
	            bar: 24,
	        })
	    }
	
	    fn unbind(pdev: &pci::Device<Core>, self: Pin<&Self>) {
	        // Use the driver's device private data from the method's `self` argument.
	        dev_info!(pdev, "foo: {}, bar: {}\n", self.foo, self.bar);
	
	        // There's also the `Device<Bound>::drvdata()` accessor, let's
	        // use that as well.
	
	        // Get a generic `device::Device` from the `pci::Device`.
	        let dev = pdev.as_ref();
	
	        // Get the `drvdata`; we have to assert the type and let the driver-core
	        // validate that the asserted type is correct.
	        let drvdata = dev.drvdata::<SampleDriver>()?;
	
	        dev_info!(pdev, "foo: {}, bar: {}\n", drvdata.foo, drvdata.bar);
	    }
	}

>> This thread seems to contain quite a bit of confusion and misunderstandings --
>> let me try to clarify.
>> 
>>   (1) How Rust handles bus device private data.
>> 
>>   In Rust the probe() function of a bus implementation (platform, PCI, etc.)
>>   returns an initializer (impl PinInit<T, Error>) for the driver's device
>>   private data.
>> 
>>   The bus implementation takes this initializer and passes it (together with the
>>   underlying struct device) to the driver-core. The driver-core allocates the
>>   required memory, initializes the memory with the given initializer and stores
>>   a pointer to the corresponding object with dev_set_drvdata().
>> 
>>   So, technically, in Rust all platform drivers call platform_set_drvdata().
>> 
>>   (Note that this is also true when the driver's device private data type is
>>   empty (i.e. it has no fields). In this case it could still have a destructor
>>   that must be called when the device private data structure is destroyed. Of
>>   course there is no real memory allocation when the struct's size is zero.)
>> 
>>   The driver's device private data can only be accessed when the bus device is
>>   bound to the driver, i.e. the driver can only access it with a &Device<Bound>;
>>   it (the driver's device private data) is automatically freed by the
>>   driver-core when remove() and all devres callbacks have been completed.
>> 
>>   I.e. the rules are - of course - the same as on the C side, but they are
>>   enforced by the type system and the driver-core code.
>> 
>
> This still doesn't explain how you get the class private data that you
> need when you are in a driver callback that is called from the bus (e.g.
> suspend/resume) from what you explain, the driver doesn't have any
> chance to pass it. The whole goal of a device driver is to be the glue
> between a class device and a bus device as essentially this is the exact
> physical device, just represented differently.

It is not always as simple as "one bus device corresponds to one class device".

Sometimes drivers have to deal with multiple class devices for a single bus
device, sometimes they are separated through the auxiliary bus or MFD.

For instance, take struct net_device. In the context of cfg80211 wireless
drivers may create arbitrary struct net_device instances, depending on how often
the add_virtual_intf() callback is called (through netlink); example in [1].

Now, regarding your question "How to access class device private data from bus
device callbacks?". Nothing prevents a driver from embedding the class device in
its bus device private data in one or the other way.

In the net device example above, the driver would probably keep a list (or
xarray, etc.) of net devices in its bus device private data, as they can be
created and removed at any point of time.

(Note that this is also a good example for when the class device private data
lives shorter than the bus device private data.)

Here is an example of this looks like in code using a DRM device as class
device.

	struct SampleIrqData;

	// The class device private data.
	struct SampleDrm {
	    sched: drm::GpuScheduler,
	}

	// The bus device private data.
	#[pin_data]
	struct SampleDriver {
	    #[pin]
	    irq: irq::Registration<SampleIrqData>,
	    drm: ARef<drm::Device<SampleDrm>, // Refcount of a `drm::Device`.
	}
	
	impl pci::Driver for SampleDriver {
	    fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> {
	        let dev = pdev.as_ref();

	        let drm = drm::Device::new(dev, SampleDrm::new()?)?;
	        drm.register();

	        Ok(impl_pin_init!(Self {
	            irq <- irq::Registration::new(...);
	            drm,
	        })
	    }
	
	    fn unbind(pdev: &pci::Device<Core>, self: Pin<&Self>) {
	        self.irq.synchronize();
	        self.drm.flush_scheduler();
	    }
	}

Note that the irq::Registration is dropped when the bus device is unbound,
whereas the GpuScheduler is dropped when the DRM device is dropped.

Of course, depending on the actual class device this difference may be more or
less important, i.e. absolutely crucial in the net device example, less
important for RTC apparently. But it is always good to be precise about
ownership and lifetime of data.

As I already mentioned, I don't think it is good to fold ownership and lifetime
for bus and class devices together in cases where it happens that they are
mostly identical, i.e.:

>>   I think it would be good to keep driver authors finding a common pattern,
>>   where class device callbacks carry the corresponding class device struct
>>   (instead of the parent base struct device).
>>
>>   Especially on the Rust side we now have the chance to make the experience
>>   of writing drivers as consistent as possible, which should help (new)
>>   driver authors a lot in terms of learning the driver lifetime patterns.

[1] https://elixir.bootlin.com/linux/v6.19.2/source/drivers/net/wireless/microchip/wilc1000/netdev.c#L948

^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Rafael J. Wysocki @ 2026-02-22 12:25 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: Rafael J. Wysocki, Alexandre Belloni, Alvin Sun, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, linux-rtc,
	rust-for-linux, Greg Kroah-Hartman
In-Reply-To: <DGKPPQI0QE73.S8I1M5NCI2BV@kernel.org>

On Sat, Feb 21, 2026 at 3:33 PM Danilo Krummrich <dakr@kernel.org> wrote:
>
> On Sat Feb 21, 2026 at 12:19 PM CET, Rafael J. Wysocki wrote:
> > On Sat, Feb 21, 2026 at 12:16 PM Alexandre Belloni
> > <alexandre.belloni@bootlin.com> wrote:
> >> > > Out of 29 drivers, 18 are doing so.
> >
> > The vast majority of around 50 platform drivers I've inspected
> > recently use platform_set_drvdata() or equivalent in probe.
>
> This thread seems to contain quite a bit of confusion and misunderstandings --
> let me try to clarify.
>
>   (1) How Rust handles bus device private data.
>
>   In Rust the probe() function of a bus implementation (platform, PCI, etc.)
>   returns an initializer (impl PinInit<T, Error>) for the driver's device
>   private data.
>
>   The bus implementation takes this initializer and passes it (together with the
>   underlying struct device) to the driver-core. The driver-core allocates the
>   required memory, initializes the memory with the given initializer and stores
>   a pointer to the corresponding object with dev_set_drvdata().
>
>   So, technically, in Rust all platform drivers call platform_set_drvdata().

So do I understand correctly that the driver is required to tell the
core what type its driver_data will be and then the core will allocate
memory for it and clean it up on remove?

>   (Note that this is also true when the driver's device private data type is
>   empty (i.e. it has no fields). In this case it could still have a destructor
>   that must be called when the device private data structure is destroyed. Of
>   course there is no real memory allocation when the struct's size is zero.)

So in the simplest case when the driver doesn't need driver_data at
all, it will just use a struct with no fields as that driver_data
type, IIUC.

>   The driver's device private data can only be accessed when the bus device is
>   bound to the driver, i.e. the driver can only access it with a &Device<Bound>;
>   it (the driver's device private data) is automatically freed by the
>   driver-core when remove() and all devres callbacks have been completed.

Well, that's what happens on the C side of things too most of the time
because driver_data is allocated at probe time, very often using
devm_kzalloc() or equivalent.

>   I.e. the rules are - of course - the same as on the C side, but they are
>   enforced by the type system and the driver-core code.

OK

>   (2) Bus device private data vs. class device private data.
>
>   The change to pass a struct rtc_device in class device callbacks of RTC,
>   rather than the base struct device of the corresponding bus device (e.g. AMBA,
>   platform, etc.) should not aim at storing all data in rtc->dev.private_data
>   that was previously stored in rtc->dev.parent->private_data.
>
>   Instead, it gives drivers the option to differentiate in terms of ownership
>   and lifetime.
>
>   While the bus device private data has a very defined lifetime from probe()
>   until the device is unbound from the driver, class device private data might
>   live shorter than this, or might even out-live driver unbind in some cases. It
>   really depends on the lifetime of the class device itself, which is not
>   generally defined.
>
>   Now, from a C side point of view this may not look like a big deal, as it
>   (unfortunately) is not that uncommon that struct fields are just initialized
>   and destroyed whenever needed and the code just takes it into account.
>
>   But at the same time, this is what leads to a lot of lifetime problems and
>   memory bugs and it is one of those things that Rust aims at avoiding by being
>   very strict about initialization, ownership and lifetimes.

As a general rule, I agree, but I would advise against applying
general rules automatically everywhere.

>   However, I do also recognize that drivers creating an RTC device are typically
>   very simple and in practice I would not be surprised if it turns out that it
>   happens that drivers keep the struct rtc_device alive from probe() until the
>   bus device is unbound from the driver, i.e. lifetimes just end up being almost
>   the same. But I don't know if that's always the case.
>
>   Regardless of that, I think it would be good to keep driver authors finding a
>   common pattern, where class device callbacks carry the corresponding class
>   device struct (instead of the parent base struct device).

TBH I'm not really convinced about this particular thing and I think I
can provide an illustrative example.

Namely, quite incidentally, I've recently set out to add an RTC class
device to an existing driver, which is the ACPI time and alarm device
(TAD) one.  The TAD functionality is based on ACPI control methods
provided by the platform firmware and it may (or may not) include
RTC-equivalent functions.  So far, the driver has been providing a
completely custom sysfs interface to user space, but since more and
more platforms contain an ACPI TAD and some of them may not contain a
"traditional" RTC, having an RTC class device interface in that driver
may be quite useful.

I have a prototype of the requisite change (I'll post it shortly for
reference) and it turns out that because the RTC class callbacks take
the parent device pointer as an argument, wrapping them around the
existing driver routines backing the existing sysfs interface is
super-straightforward.  Had the RTC class passed an RTC device pointer
to those callbacks, the driver would have had to do something to get
back from it to the parent device (which is what the driver really
works with).  If there are more similar drivers, that would have led
to some code duplication that is in fact unnecessary.

Moreover, the RTC device pointer doesn't even need to be stored
anywhere in that driver because the driver need not use it directly at
all and the RTC device object memory is freed by the core when the
driver unbinds.

>   Especially on the Rust side we now have the chance to make the experience of
>   writing drivers as consistent as possible, which should help (new) driver
>   authors a lot in terms of learning the driver lifetime patterns.

Well, I'm not sure if "the experience of writing drivers as consistent
as possible" is more important than less code duplication and simpler
code.

^ permalink raw reply

* Re: [PATCH 0/7] rtc: sun6i: Add support for Allwinner A733 SoC
From: Jernej Škrabec @ 2026-02-22 10:41 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Chen-Yu Tsai, Samuel Holland,
	Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Maxime Ripard, Junhui Liu
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel, linux-rtc,
	devicetree, Junhui Liu
In-Reply-To: <20260121-a733-rtc-v1-0-d359437f23a7@pigmoral.tech>

Hi!

Dne sreda, 21. januar 2026 ob 11:59:06 Srednjeevropski standardni čas je Junhui Liu napisal(a):
> Add support for the Allwinner A733 RTC and its internal Clock Control
> Unit (CCU). Reuse the rtc-sun6i rtc driver while introducing a new
> SoC-specific RTC CCU driver to handle the hardware's evolved clock
> structure.
> 
> To facilitate this addition and improve driver modularity, transition
> the binding between the RTC and its internal CCU from direct
> cross-subsystem function calls to the auxiliary bus. Also extract shared
> IOSC and 32kHz clock logic into a standalone ccu_rtc module for reuse
> across newer SoC generations.
> 
> The A733 implementation supports hardware detection of three external
> crystal frequencies (19.2MHz, 24MHz and 26MHz), which is represented in
> the driver via read-only mux operations. Implement logic to derive a
> normalized 32kHz reference from these DCXO sources using fixed
> pre-dividers. Additionally, provide several new DCXO gate clocks for
> peripherals, including SerDes, HDMI, and UFS.

This work looks nice, but I have some questions/comments:
- you're missing RTC SPI clock, which is needed for RTC, at least according
  to vendor 5.15 DT. Could it be that this bit set by vendor U-Boot so you
  missed it during testing? Manual says that it's disabled by default.
- Vendor DT has strange RTC CCU phandles for UFS and HDMI. In first case
  uses RTC wakeup and in second DCXO, which doesn't make any sense. Did you
  do any experimentation with these clocks? It wouldn't be the first time
  that either code or manual contained some kind of error.

Btw, switch last two patches. With current order during bisection you would
get a complaint that A733 RTC CCU driver is not present.

Best regards,
Jernej



^ permalink raw reply

* [GIT PULL] RTC for 7.0
From: Alexandre Belloni @ 2026-02-22  1:33 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-rtc, linux-kernel

Hello Linus,

Here is the RTC subsystem pull request for 7.0. There are a few fixes
and improvement this cycle.

The following changes since commit 8f0b4cce4481fb22653697cced8d0d04027cb1e8:

  Linux 6.19-rc1 (2025-12-14 16:05:07 +1200)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git tags/rtc-7.0

for you to fetch changes up to 969c3cca0f3b88682cd833cee4cf01b0915629a3:

  rtc: ds1390: fix number of bytes read from RTC (2026-02-20 23:12:25 +0100)

----------------------------------------------------------------
RTC for 7.0

Drivers:
 - loongson: Loongson-2K0300 support
 - s35390a: nvmem support
 - zynqmp: rework calibration

----------------------------------------------------------------
Andreas Gabriel-Platschek (1):
      rtc: ds1390: fix number of bytes read from RTC

Anthony Pighin (Nokia) (1):
      rtc: interface: Alarm race handling should not discard preceding error

Binbin Zhou (3):
      dt-bindings: rtc: loongson: Correct Loongson-1C interrupts property
      dt-bindings: rtc: loongson: Document Loongson-2K0300 compatible
      rtc: loongson: Add Loongson-2K0300 support

Jinjie Ruan (1):
      rtc: class: Remove duplicate check for alarm

John Keeping (1):
      rtc: pcf8563: use correct of_node for output clock

Lorenz Brun (1):
      rtc: s35390a: implement nvmem support

Ovidiu Panait (1):
      dt-bindings: rtc: renesas,rz-rtca3: Add RZ/V2N support

Peter Robinson (1):
      rtc: nvvrs: Add ARCH_TEGRA to the NV VRS RTC driver

Randy Dunlap (1):
      rtc: max31335: use correct CONFIG symbol in IS_REACHABLE()

Rouven Czerwinski (1):
      rtc: optee: simplify OP-TEE context match

Sebastian Andrzej Siewior (1):
      rtc: amlogic-a4: Remove IRQF_ONESHOT

Svyatoslav Ryhel (1):
      dt-bindings: rtc: cpcap: convert to schema

Tomas Melin (5):
      rtc: zynqmp: correct frequency value
      rtc: zynqmp: check calibration max value
      rtc: zynqmp: rework read_offset
      rtc: zynqmp: rework set_offset
      rtc: zynqmp: use dynamic max and min offset ranges

 .../devicetree/bindings/rtc/cpcap-rtc.txt          | 18 ------
 .../devicetree/bindings/rtc/loongson,rtc.yaml      | 13 ++++
 .../bindings/rtc/motorola,cpcap-rtc.yaml           | 32 +++++++++
 .../devicetree/bindings/rtc/renesas,rz-rtca3.yaml  |  5 +-
 drivers/rtc/Kconfig                                |  1 +
 drivers/rtc/class.c                                |  2 +-
 drivers/rtc/interface.c                            |  2 +-
 drivers/rtc/rtc-amlogic-a4.c                       |  2 +-
 drivers/rtc/rtc-ds1390.c                           |  2 +-
 drivers/rtc/rtc-loongson.c                         | 71 +++++++++++++-------
 drivers/rtc/rtc-max31335.c                         |  6 +-
 drivers/rtc/rtc-optee.c                            |  5 +-
 drivers/rtc/rtc-pcf8563.c                          |  2 +-
 drivers/rtc/rtc-s35390a.c                          | 32 +++++++++
 drivers/rtc/rtc-zynqmp.c                           | 75 ++++++++++++----------
 15 files changed, 179 insertions(+), 89 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/rtc/cpcap-rtc.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/motorola,cpcap-rtc.yaml

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Alexandre Belloni @ 2026-02-22  0:05 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: Rafael J. Wysocki, Alvin Sun, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, linux-rtc, rust-for-linux, Greg Kroah-Hartman
In-Reply-To: <DGKPPQI0QE73.S8I1M5NCI2BV@kernel.org>

On 21/02/2026 15:33:48+0100, Danilo Krummrich wrote:
> On Sat Feb 21, 2026 at 12:19 PM CET, Rafael J. Wysocki wrote:
> > On Sat, Feb 21, 2026 at 12:16 PM Alexandre Belloni
> > <alexandre.belloni@bootlin.com> wrote:
> >> > > Out of 29 drivers, 18 are doing so.
> >
> > The vast majority of around 50 platform drivers I've inspected
> > recently use platform_set_drvdata() or equivalent in probe.
> 
> This thread seems to contain quite a bit of confusion and misunderstandings --
> let me try to clarify.
> 
>   (1) How Rust handles bus device private data.
> 
>   In Rust the probe() function of a bus implementation (platform, PCI, etc.)
>   returns an initializer (impl PinInit<T, Error>) for the driver's device
>   private data.
> 
>   The bus implementation takes this initializer and passes it (together with the
>   underlying struct device) to the driver-core. The driver-core allocates the
>   required memory, initializes the memory with the given initializer and stores
>   a pointer to the corresponding object with dev_set_drvdata().
> 
>   So, technically, in Rust all platform drivers call platform_set_drvdata().
> 
>   (Note that this is also true when the driver's device private data type is
>   empty (i.e. it has no fields). In this case it could still have a destructor
>   that must be called when the device private data structure is destroyed. Of
>   course there is no real memory allocation when the struct's size is zero.)
> 
>   The driver's device private data can only be accessed when the bus device is
>   bound to the driver, i.e. the driver can only access it with a &Device<Bound>;
>   it (the driver's device private data) is automatically freed by the
>   driver-core when remove() and all devres callbacks have been completed.
> 
>   I.e. the rules are - of course - the same as on the C side, but they are
>   enforced by the type system and the driver-core code.
> 

This still doesn't explain how you get the class private data that you
need when you are in a driver callback that is called from the bus (e.g.
suspend/resume) from what you explain, the driver doesn't have any
chance to pass it. The whole goal of a device driver is to be the glue
between a class device and a bus device as essentially this is the exact
physical device, just represented differently.

An i2c RTC is not either an i2c device or an RTC, it is a single device
and we need to be able to tell the framework when something happens on
the bus or we need to be able to talk on the bus when we want to do
something with the device.


>   (2) Bus device private data vs. class device private data.
> 
>   The change to pass a struct rtc_device in class device callbacks of RTC,
>   rather than the base struct device of the corresponding bus device (e.g. AMBA,
>   platform, etc.) should not aim at storing all data in rtc->dev.private_data
>   that was previously stored in rtc->dev.parent->private_data.
> 

But what you explain here is that the drive is forbidden to use
rtc->dev.parent->private_data at all because the rust core is already
using it. What I'm saying is that it won't work because more than half
of the drivers currently need it.

I get that you are trying to avoid most of the issues by using devres
but I'm pretty sure there are cases where this doesn't work.

>   Instead, it gives drivers the option to differentiate in terms of ownership
>   and lifetime.
> 
>   While the bus device private data has a very defined lifetime from probe()
>   until the device is unbound from the driver, class device private data might
>   live shorter than this, or might even out-live driver unbind in some cases. It
>   really depends on the lifetime of the class device itself, which is not
>   generally defined.
> 
>   Now, from a C side point of view this may not look like a big deal, as it
>   (unfortunately) is not that uncommon that struct fields are just initialized
>   and destroyed whenever needed and the code just takes it into account.
> 
>   But at the same time, this is what leads to a lot of lifetime problems and
>   memory bugs and it is one of those things that Rust aims at avoiding by being
>   very strict about initialization, ownership and lifetimes.
> 
>   However, I do also recognize that drivers creating an RTC device are typically
>   very simple and in practice I would not be surprised if it turns out that it
>   happens that drivers keep the struct rtc_device alive from probe() until the
>   bus device is unbound from the driver, i.e. lifetimes just end up being almost
>   the same. But I don't know if that's always the case.
> 
>   Regardless of that, I think it would be good to keep driver authors finding a
>   common pattern, where class device callbacks carry the corresponding class
>   device struct (instead of the parent base struct device).
> 
>   Especially on the Rust side we now have the chance to make the experience of
>   writing drivers as consistent as possible, which should help (new) driver
>   authors a lot in terms of learning the driver lifetime patterns.
> 

The whole point of the RTC is to outlive the system but as Linux can't do
anything with the RTC unless it has a bus device to talk to, the class
device and the bus device have the exact same lifetime and we do handle
device appearing and disappearing from the bus. You may think RTC
drivers afe simple but there are plenty of lifetime issues that you will
never get with any other devices because they simply die with the
system.


-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Danilo Krummrich @ 2026-02-21 17:53 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Alvin Sun, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, linux-rtc, rust-for-linux, Greg Kroah-Hartman,
	Rafael J. Wysocki
In-Reply-To: <20260221111619162a41a1@mail.local>

On Sat Feb 21, 2026 at 12:16 PM CET, Alexandre Belloni wrote:
> On 21/02/2026 17:31:09+0800, Alvin Sun wrote:
>> As in platform.rs [1] and i2c.rs [2], set_drvdata is always called by
>> the bus Adapter's probe_callback, not by the device driver.
>> 
>> [1]:
>> https://elixir.bootlin.com/linux/v6.19-rc5/source/rust/kernel/platform.rs#L80
>> [2]:
>> https://elixir.bootlin.com/linux/v6.19-rc5/source/rust/kernel/i2c.rs#L160
>> 
>> In Rust the Adapter already sets drvdata on the bus device in probe. If
>> the driver also calls amba_set_drvdata() there, it overwrites that
>> pointer; on remove/shutdown the framework then gets wrong data and can
>> hit use-after-free or crashes. So only the framework must set drvdata
>> on the bus device.
>
> But this is wrong, how do you then handle the class device on
> suspend/resume or on .remove?

I think you misunderstand what Alvin is saying here. We do have bus device
private data in all drivers. It's just that drivers do not set it randomly
through dev_set_drvdata() et al. Please see [1] for details.

[1] https://lore.kernel.org/all/DGKPPQI0QE73.S8I1M5NCI2BV@kernel.org/

^ permalink raw reply

* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Alvin Sun @ 2026-02-21 16:32 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Danilo Krummrich, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, linux-rtc, rust-for-linux, Greg Kroah-Hartman,
	Rafael J. Wysocki
In-Reply-To: <20260221111619162a41a1@mail.local>


On 2/21/26 19:16, Alexandre Belloni wrote:
> On 21/02/2026 17:31:09+0800, Alvin Sun wrote:
>> As in platform.rs [1] and i2c.rs [2], set_drvdata is always called by
>> the bus Adapter's probe_callback, not by the device driver.
>>
>> [1]:
>> https://elixir.bootlin.com/linux/v6.19-rc5/source/rust/kernel/platform.rs#L80
>> [2]:
>> https://elixir.bootlin.com/linux/v6.19-rc5/source/rust/kernel/i2c.rs#L160
>>
>> In Rust the Adapter already sets drvdata on the bus device in probe. If
>> the driver also calls amba_set_drvdata() there, it overwrites that
>> pointer; on remove/shutdown the framework then gets wrong data and can
>> hit use-after-free or crashes. So only the framework must set drvdata
>> on the bus device.
> But this is wrong, how do you then handle the class device on
> suspend/resume or on .remove?

There is a patch adding runtime PM for Tyr (platform device driver):

https://gitlab.freedesktop.org/panfrost/linux/-/merge_requests/60/diffs#dbdd2c5024317f2c80128c91a823e224b3a41550_240_256

If you are interested in adding Rust support for RTC, We can do some
research on top of it for RTC Rust drivers.

>
>> This applies only to the Rust implementation; in C, calling
>> amba_set_drvdata() is fine. In the Rust design the bus device owns the
>> bus device's drvdata and the class device owns the class device's
>> drvdata, so the class driver must not set drvdata on the bus device.
>>
>> This is my understanding of the Rust device driver abstraction design.
>> Danilo is the authority on this.
>>
>> Best regards,
>> Ke Sun
>>
>>> Out of 29 drivers, 18 are doing so.
>>>

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox