* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Rafael J. Wysocki @ 2026-02-24 13:28 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: <DGMR9XOWP1V0.3C9219TYPXV6J@kernel.org>
On Tue, Feb 24, 2026 at 1:12 AM Danilo Krummrich <dakr@kernel.org> wrote:
>
> On Sun Feb 22, 2026 at 5:13 PM CET, Danilo Krummrich wrote:
> > 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:
>
> When I wrote this on Sunday, I should have been much more precise about this,
> since it actually does not work perfectly fine without further changes that
> would (re-)introduce ordering constraints for drivers on the probe() side of
> things that I want to avoid.
>
> The "re-" is in braces as we never had those ordering constraints in Rust, but
> we have quite a lot of them in C, where they cause endless problems. Which is
> why I want to avoid them in Rust.
>
> > 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>()?;
> >
> > ...
> > }
> > }
>
> Let's have a look at the corresponding probe() side of things.
>
> struct SampleIrqData;
>
> // The bus device private data.
> #[pin_data]
> struct SampleDriver {
> #[pin]
> irq: irq::Registration<SampleIrqData>,
> rtc: ARef<rtc::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 rtc = rtc::Device::new(dev)?;
>
> Ok(impl_pin_init!(Self {
> irq <- irq::Registration::new(...),
> rtc,
> _: {
> devres::register(rtc::Registration::new(rtc))?;
> }
> })
> }
> }
>
> This is a problem, since even though the registration of the RTC device is the
> last thing in the initializer, rtc::Ops::read_time() above could race and
> Device::drvdata() could just fail as it might not be set yet.
>
> This is fixable, but - as mentioned - at the price of introducing ordering
> constraints for drivers.
>
> For instance, this could be solved by introducing a pci::ProbeDevice<'a> type,
> which ensures that pci::ProbeDevice::set_drvdata() can only be called from
> probe() and can only be called once, as it consumes the pci::ProbeDevice.
>
> struct SampleIrqData;
>
> // The bus device private data.
> #[pin_data]
> struct SampleDriver {
> #[pin]
> irq: irq::Registration<SampleIrqData>,
> rtc: ARef<rtc::Device>,
> ...,
> }
>
> impl pci::Driver for SampleDriver {
> fn probe<'a>(pdev: pci::ProbeDevice<'a>, info: &Self::IdInfo) -> Result {
> let dev = pdev.as_ref();
>
> let rtc = rtc::Device::new(dev)?;
>
> let data = impl_pin_init!(Self {
> irq <- irq::Registration::new(...),
> rtc,
> });
>
> // The `pci::ProbeDevice` has been consumed by value, and
> // returned a `&pci::Device<Core>`.
> let pdev = pdev.set_drvdata(data)?;
>
> devres::register(rtc::Registration::new(rtc))
> }
> }
>
> However, note how this wouldn't solve the same problem for irq::Registration, as
> it lives within the the driver's device private data.
>
> If this would be C you would probably just partially initialize the driver's
> device private data, but in Rust uninitialized data is not allowed for safety
> reasons.
>
> We could probably find other ways to somehow handle this, e.g. by introducing
> new device context states, additional callbacks, etc., but in the end it would
> only be workarounds for not having defined ownership, that eventually ends up
> being more complicated and more error prone.
>
> For this reason an irq::Registration has its own private data (which in this
> example is just an empty struct).
>
> Similarly, all other kinds of registrations (and driver entry points) have their
> own private data, such as class devices, work and workqueues, file operations,
> timers, etc.
>
> I.e. there is a clear separation of ownership and lifetime, which makes more or
> less (often more) suble ordering constraints obsolete.
>
> In fact, in the beginning I did not even plan to expose Device::drvdata() at
> all, making the driver's device private data only available in bus device
> callbacks, etc.
>
> The reason why I added it was that it was required (and makes sense) when
> drivers interact with other drivers, e.g. through an auxiliary device.
>
> I did also mention this in the commit message of commit 6f61a2637abe ("rust:
> device: introduce Device::drvdata()"):
>
> (2) Having a direct accessor to the driver's private data is not
> commonly required (at least in Rust): Bus callback methods already
> provide access to the driver's device private data through a &self
> argument, while other driver entry points such as IRQs,
> workqueues, timers, IOCTLs, etc. have their own private data with
> separate ownership and lifetime.
>
> In other words, a driver's device private data is only relevant
> for driver model contexts (such a file private is only relevant
> for file contexts).
>
> Having that said, the motivation for accessing the driver's device
> private data with Device<Bound>::drvdata() are interactions between
> drivers. For instance, when an auxiliary driver calls back into its
> parent, the parent has to be capable to derive its private data from the
> corresponding device (i.e. the parent of the auxiliary device).
>
> Let's have a look at how probe() looks like for the example below, which is what
> we do in other subsystems, such as DRM or PWM.
>
> > Example 3:
> >
> > struct SampleIrqData {
> > rtc: ARef<rtc::Device>,
> > };
> >
> > // The bus device private data.
> > #[pin_data]
> > struct SampleDriver {
> > #[pin]
> > irq: irq::Registration<SampleIrqHandler>,
> > rtc: ARef<rtc::Device<SampleRtcData>>,
> > }
> >
> > // The class device private data.
> > struct SampleRtcData {
> > 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<SampleRtcData>
> > 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 => { ... },
> > }
> > }
> > }
> >
>
> impl pci::Driver for SampleDriver {
> fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> {
> let dev = pdev.as_ref();
>
> let rtc_data = impl_pin_init!(SampleRtcData {
> io: iomap_region_sized::<BAR0_SIZE>(0, c"my_rtc/bar0")?,
> hw_variant: VendorVariant::StV1,
> });
>
> let rtc = rtc::Device::new(dev, rtc_data)?;
>
> // Internally calls `devres::register(rtc::Registration::new())`.
> rtc::Registration::register(rtc)?;
>
> Ok(impl_pin_init!(Self {
> // Give the IRQ handler a reference count of the `rtc::Device`.
> irq <- irq::Registration::new(..., rtc.clone()),
> rtc,
> })
> }
> }
>
> With this there are no (subtle) ordering constraints the driver has to get
> right; ownership and lifetimes are well defined.
>
> (I.e. whatever order a driver picks, it either works properly or it does not
> compile in the first place, which is a huge improvement over the situation we
> have in C.)
Thanks for all of this information and let me confirm my understanding.
In both Example 1 and Example 3 there is a dependency between rtc's
read_time() callback and the PCI driver probe() because calling the
former before the latter is complete would be premature (and it would
fail). However, in Example 1 the compiler does not take that
dependency into account because rtc is not passed to the callback,
while in Example 3 the dependency is visible to the compiler and it
will refuse to compile the code if the dependency may be missed.
If the above is correct, the current calling convention of RTC class
callbacks is problematic because it causes correctness checks done by
the Rust compiler to be bypassed (which may allow certain ordering
issues to be missed and functional problems to appear going forward).
That's convincing and I think that adding an RTC device pointer to the
list of parameters of RTC class callbacks on the C side would not be a
very intrusive change. Arguably, it would be less intrusive than
replacing the parent device pointer with the RTC device pointer in
them.
^ permalink raw reply
* Re: [RFC PATCH v3 1/5] rtc: add device selector for rtc_class_ops callbacks
From: Danilo Krummrich @ 2026-02-24 0:12 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: <DGLMGEZTM7E2.Y8VV9I6LI1P6@kernel.org>
On Sun Feb 22, 2026 at 5:13 PM CET, Danilo Krummrich wrote:
> 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:
When I wrote this on Sunday, I should have been much more precise about this,
since it actually does not work perfectly fine without further changes that
would (re-)introduce ordering constraints for drivers on the probe() side of
things that I want to avoid.
The "re-" is in braces as we never had those ordering constraints in Rust, but
we have quite a lot of them in C, where they cause endless problems. Which is
why I want to avoid them in Rust.
> 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>()?;
>
> ...
> }
> }
Let's have a look at the corresponding probe() side of things.
struct SampleIrqData;
// The bus device private data.
#[pin_data]
struct SampleDriver {
#[pin]
irq: irq::Registration<SampleIrqData>,
rtc: ARef<rtc::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 rtc = rtc::Device::new(dev)?;
Ok(impl_pin_init!(Self {
irq <- irq::Registration::new(...),
rtc,
_: {
devres::register(rtc::Registration::new(rtc))?;
}
})
}
}
This is a problem, since even though the registration of the RTC device is the
last thing in the initializer, rtc::Ops::read_time() above could race and
Device::drvdata() could just fail as it might not be set yet.
This is fixable, but - as mentioned - at the price of introducing ordering
constraints for drivers.
For instance, this could be solved by introducing a pci::ProbeDevice<'a> type,
which ensures that pci::ProbeDevice::set_drvdata() can only be called from
probe() and can only be called once, as it consumes the pci::ProbeDevice.
struct SampleIrqData;
// The bus device private data.
#[pin_data]
struct SampleDriver {
#[pin]
irq: irq::Registration<SampleIrqData>,
rtc: ARef<rtc::Device>,
...,
}
impl pci::Driver for SampleDriver {
fn probe<'a>(pdev: pci::ProbeDevice<'a>, info: &Self::IdInfo) -> Result {
let dev = pdev.as_ref();
let rtc = rtc::Device::new(dev)?;
let data = impl_pin_init!(Self {
irq <- irq::Registration::new(...),
rtc,
});
// The `pci::ProbeDevice` has been consumed by value, and
// returned a `&pci::Device<Core>`.
let pdev = pdev.set_drvdata(data)?;
devres::register(rtc::Registration::new(rtc))
}
}
However, note how this wouldn't solve the same problem for irq::Registration, as
it lives within the the driver's device private data.
If this would be C you would probably just partially initialize the driver's
device private data, but in Rust uninitialized data is not allowed for safety
reasons.
We could probably find other ways to somehow handle this, e.g. by introducing
new device context states, additional callbacks, etc., but in the end it would
only be workarounds for not having defined ownership, that eventually ends up
being more complicated and more error prone.
For this reason an irq::Registration has its own private data (which in this
example is just an empty struct).
Similarly, all other kinds of registrations (and driver entry points) have their
own private data, such as class devices, work and workqueues, file operations,
timers, etc.
I.e. there is a clear separation of ownership and lifetime, which makes more or
less (often more) suble ordering constraints obsolete.
In fact, in the beginning I did not even plan to expose Device::drvdata() at
all, making the driver's device private data only available in bus device
callbacks, etc.
The reason why I added it was that it was required (and makes sense) when
drivers interact with other drivers, e.g. through an auxiliary device.
I did also mention this in the commit message of commit 6f61a2637abe ("rust:
device: introduce Device::drvdata()"):
(2) Having a direct accessor to the driver's private data is not
commonly required (at least in Rust): Bus callback methods already
provide access to the driver's device private data through a &self
argument, while other driver entry points such as IRQs,
workqueues, timers, IOCTLs, etc. have their own private data with
separate ownership and lifetime.
In other words, a driver's device private data is only relevant
for driver model contexts (such a file private is only relevant
for file contexts).
Having that said, the motivation for accessing the driver's device
private data with Device<Bound>::drvdata() are interactions between
drivers. For instance, when an auxiliary driver calls back into its
parent, the parent has to be capable to derive its private data from the
corresponding device (i.e. the parent of the auxiliary device).
Let's have a look at how probe() looks like for the example below, which is what
we do in other subsystems, such as DRM or PWM.
> Example 3:
>
> struct SampleIrqData {
> rtc: ARef<rtc::Device>,
> };
>
> // The bus device private data.
> #[pin_data]
> struct SampleDriver {
> #[pin]
> irq: irq::Registration<SampleIrqHandler>,
> rtc: ARef<rtc::Device<SampleRtcData>>,
> }
>
> // The class device private data.
> struct SampleRtcData {
> 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<SampleRtcData>
> 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 => { ... },
> }
> }
> }
>
impl pci::Driver for SampleDriver {
fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> {
let dev = pdev.as_ref();
let rtc_data = impl_pin_init!(SampleRtcData {
io: iomap_region_sized::<BAR0_SIZE>(0, c"my_rtc/bar0")?,
hw_variant: VendorVariant::StV1,
});
let rtc = rtc::Device::new(dev, rtc_data)?;
// Internally calls `devres::register(rtc::Registration::new())`.
rtc::Registration::register(rtc)?;
Ok(impl_pin_init!(Self {
// Give the IRQ handler a reference count of the `rtc::Device`.
irq <- irq::Registration::new(..., rtc.clone()),
rtc,
})
}
}
With this there are no (subtle) ordering constraints the driver has to get
right; ownership and lifetimes are well defined.
(I.e. whatever order a driver picks, it either works properly or it does not
compile in the first place, which is a huge improvement over the situation we
have in C.)
^ permalink raw reply
* Re: [PATCH 3/9] dt-bindings: input: mtk-pmic-keys: add MT6392 binding definition
From: Dmitry Torokhov @ 2026-02-23 22:01 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: linux-mediatek, Fabien Parent, Val Packett, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Julien Massot,
Louis-Alexis Eyraud, Gary Bisson, Chen Zhong, linux-input,
devicetree, linux-kernel, linux-pm, linux-arm-kernel, linux-rtc
In-Reply-To: <056cbc09fcbb4a2845cece69209a2a564d993ac5.1771865015.git.l.scorcia@gmail.com>
On Mon, Feb 23, 2026 at 05:12:42PM +0000, Luca Leonardo Scorcia wrote:
> From: Fabien Parent <parent.f@gmail.com>
>
> Add the binding documentation of the mtk-pmic-keys for the MT6392 PMICs.
>
> Signed-off-by: Fabien Parent <parent.f@gmail.com>
> Signed-off-by: Val Packett <val@packett.cool>
> Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Please merge with the rest of the series.
> ---
> Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
> index b95435bd6a9b..2d3c4161a7f8 100644
> --- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
> +++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
> @@ -30,6 +30,7 @@ properties:
> - mediatek,mt6357-keys
> - mediatek,mt6358-keys
> - mediatek,mt6359-keys
> + - mediatek,mt6392-keys
> - mediatek,mt6397-keys
>
> power-off-time-sec: true
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH 6/9] regulator: mt6392: Add support for MT6392 regulator
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Louis-Alexis Eyraud,
Julien Massot, Gary Bisson, Chen Zhong, linux-input, devicetree,
linux-kernel, linux-pm, linux-arm-kernel, linux-rtc
In-Reply-To: <cover.1771865014.git.l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
The MT6392 is a regulator found on boards based on the MediaTek
MT8167, MT8516, and probably other SoCs. It is a so called PMIC and
connects as a slave to a SoC using SPI, wrapped inside PWRAP.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Co-developed-by: Val Packett <val@packett.cool>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mt6392-regulator.c | 491 +++++++++++++++++++++
include/linux/regulator/mt6392-regulator.h | 40 ++
4 files changed, 541 insertions(+)
create mode 100644 drivers/regulator/mt6392-regulator.c
create mode 100644 include/linux/regulator/mt6392-regulator.h
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index d2335276cce5..66876d730807 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -991,6 +991,15 @@ config REGULATOR_MT6380
This driver supports the control of different power rails of device
through regulator interface.
+config REGULATOR_MT6392
+ tristate "MediaTek MT6392 PMIC"
+ depends on MFD_MT6397
+ help
+ Say y here to select this option to enable the power regulator of
+ MediaTek MT6392 PMIC.
+ This driver supports the control of different power rails of device
+ through regulator interface.
+
config REGULATOR_MT6397
tristate "MediaTek MT6397 PMIC"
depends on MFD_MT6397
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 1beba1493241..db5145cfcf36 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -117,6 +117,7 @@ obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o
obj-$(CONFIG_REGULATOR_MT6363) += mt6363-regulator.o
obj-$(CONFIG_REGULATOR_MT6370) += mt6370-regulator.o
obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
+obj-$(CONFIG_REGULATOR_MT6392) += mt6392-regulator.o
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o
diff --git a/drivers/regulator/mt6392-regulator.c b/drivers/regulator/mt6392-regulator.c
new file mode 100644
index 000000000000..1ac5cdf4eb7f
--- /dev/null
+++ b/drivers/regulator/mt6392-regulator.c
@@ -0,0 +1,491 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2020 MediaTek Inc.
+// Copyright (c) 2020 BayLibre, SAS.
+// Author: Chen Zhong <chen.zhong@mediatek.com>
+// Author: Fabien Parent <fparent@baylibre.com>
+//
+// Based on mt6397-regulator.c
+
+#include <linux/module.h>
+#include <linux/linear_range.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/mfd/mt6392/registers.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/mt6392-regulator.h>
+#include <linux/regulator/of_regulator.h>
+
+#define MT6392_BUCK_MODE_AUTO 0
+#define MT6392_BUCK_MODE_FORCE_PWM 1
+#define MT6392_LDO_MODE_NORMAL 0
+#define MT6392_LDO_MODE_LP 1
+
+/*
+ * MT6392 regulators' information
+ *
+ * @desc: standard fields of regulator description.
+ * @qi: Mask for query enable signal status of regulators
+ * @vselon_reg: Register sections for hardware control mode of bucks
+ * @vselctrl_reg: Register for controlling the buck control mode.
+ * @vselctrl_mask: Mask for query buck's voltage control mode.
+ */
+struct mt6392_regulator_info {
+ struct regulator_desc desc;
+ u32 qi;
+ u32 vselon_reg;
+ u32 vselctrl_reg;
+ u32 vselctrl_mask;
+ u32 modeset_reg;
+ u32 modeset_mask;
+};
+
+#define MT6392_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
+ vosel, vosel_mask, voselon, vosel_ctrl, \
+ _modeset_reg, _modeset_mask, rampdelay) \
+[MT6392_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6392_volt_range_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6392_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min)/step + 1, \
+ .linear_ranges = volt_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .vsel_reg = vosel, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(0), \
+ .ramp_delay = rampdelay, \
+ }, \
+ .qi = BIT(13), \
+ .vselon_reg = voselon, \
+ .vselctrl_reg = vosel_ctrl, \
+ .vselctrl_mask = BIT(1), \
+ .modeset_reg = _modeset_reg, \
+ .modeset_mask = _modeset_mask, \
+}
+
+#define MT6392_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
+ vosel_mask, _modeset_reg, _modeset_mask, entime) \
+[MT6392_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6392_volt_table_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6392_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = ARRAY_SIZE(ldo_volt_table), \
+ .volt_table = ldo_volt_table, \
+ .vsel_reg = vosel, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(enbit), \
+ .enable_time = entime, \
+ }, \
+ .qi = BIT(15), \
+ .modeset_reg = _modeset_reg, \
+ .modeset_mask = _modeset_mask, \
+}
+
+#define MT6392_LDO_LINEAR(match, vreg, min, max, step, volt_ranges, \
+ enreg, enbit, vosel, vosel_mask, _modeset_reg, \
+ _modeset_mask, entime) \
+[MT6392_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6392_volt_ldo_range_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6392_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min)/step + 1, \
+ .linear_ranges = volt_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .vsel_reg = vosel, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(enbit), \
+ .enable_time = entime, \
+ }, \
+ .qi = BIT(15), \
+ .modeset_reg = _modeset_reg, \
+ .modeset_mask = _modeset_mask, \
+}
+
+#define MT6392_REG_FIXED(match, vreg, enreg, enbit, volt, \
+ _modeset_reg, _modeset_mask, entime) \
+[MT6392_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6392_volt_fixed_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6392_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = 1, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(enbit), \
+ .enable_time = entime, \
+ .min_uV = volt, \
+ }, \
+ .qi = BIT(15), \
+ .modeset_reg = _modeset_reg, \
+ .modeset_mask = _modeset_mask, \
+}
+
+#define MT6392_REG_FIXED_NO_MODE(match, vreg, enreg, enbit, volt, \
+ entime) \
+[MT6392_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6392_volt_fixed_no_mode_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6392_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = 1, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(enbit), \
+ .enable_time = entime, \
+ .min_uV = volt, \
+ }, \
+ .qi = BIT(15), \
+}
+
+static const struct linear_range buck_volt_range1[] = {
+ REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
+};
+
+static const struct linear_range buck_volt_range2[] = {
+ REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),
+};
+
+static const u32 ldo_volt_table1[] = {
+ 1800000, 1900000, 2000000, 2200000,
+};
+
+static const struct linear_range ldo_volt_range2[] = {
+ REGULATOR_LINEAR_RANGE(3300000, 0, 3, 100000),
+};
+
+static const u32 ldo_volt_table3[] = {
+ 1800000, 3300000,
+};
+
+static const u32 ldo_volt_table4[] = {
+ 3000000, 3300000,
+};
+
+static const u32 ldo_volt_table5[] = {
+ 1200000, 1300000, 1500000, 1800000, 2000000, 2800000, 3000000, 3300000,
+};
+
+static const u32 ldo_volt_table6[] = {
+ 1240000, 1390000,
+};
+
+static const u32 ldo_volt_table7[] = {
+ 1200000, 1300000, 1500000, 1800000,
+};
+
+static const u32 ldo_volt_table8[] = {
+ 1800000, 2000000,
+};
+
+static int mt6392_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ int ret, val = 0;
+ struct mt6392_regulator_info *info = rdev_get_drvdata(rdev);
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ val = MT6392_BUCK_MODE_FORCE_PWM;
+ break;
+ case REGULATOR_MODE_NORMAL:
+ val = MT6392_BUCK_MODE_AUTO;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val <<= ffs(info->modeset_mask) - 1;
+
+ ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
+ info->modeset_mask, val);
+
+ return ret;
+}
+
+static unsigned int mt6392_buck_get_mode(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ unsigned int mode;
+ int ret;
+ struct mt6392_regulator_info *info = rdev_get_drvdata(rdev);
+
+ ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
+ if (ret < 0)
+ return ret;
+
+ val &= info->modeset_mask;
+ val >>= ffs(info->modeset_mask) - 1;
+
+ if (val & 0x1)
+ mode = REGULATOR_MODE_FAST;
+ else
+ mode = REGULATOR_MODE_NORMAL;
+
+ return mode;
+}
+
+static int mt6392_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ int ret, val = 0;
+ struct mt6392_regulator_info *info = rdev_get_drvdata(rdev);
+
+ switch (mode) {
+ case REGULATOR_MODE_STANDBY:
+ val = MT6392_LDO_MODE_LP;
+ break;
+ case REGULATOR_MODE_NORMAL:
+ val = MT6392_LDO_MODE_NORMAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val <<= ffs(info->modeset_mask) - 1;
+
+ ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
+ info->modeset_mask, val);
+
+ return ret;
+}
+
+static unsigned int mt6392_ldo_get_mode(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ unsigned int mode;
+ int ret;
+ struct mt6392_regulator_info *info = rdev_get_drvdata(rdev);
+
+ ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
+ if (ret < 0)
+ return ret;
+
+ val &= info->modeset_mask;
+ val >>= ffs(info->modeset_mask) - 1;
+
+ if (val & 0x1)
+ mode = REGULATOR_MODE_STANDBY;
+ else
+ mode = REGULATOR_MODE_NORMAL;
+
+ return mode;
+}
+
+static const struct regulator_ops mt6392_volt_range_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6392_buck_set_mode,
+ .get_mode = mt6392_buck_get_mode,
+};
+
+static const struct regulator_ops mt6392_volt_table_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_iterate,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6392_ldo_set_mode,
+ .get_mode = mt6392_ldo_get_mode,
+};
+
+static const struct regulator_ops mt6392_volt_ldo_range_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6392_ldo_set_mode,
+ .get_mode = mt6392_ldo_get_mode,
+};
+
+static const struct regulator_ops mt6392_volt_fixed_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6392_ldo_set_mode,
+ .get_mode = mt6392_ldo_get_mode,
+};
+
+static const struct regulator_ops mt6392_volt_fixed_no_mode_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+/* The array is indexed by id(MT6392_ID_XXX) */
+static struct mt6392_regulator_info mt6392_regulators[] = {
+ MT6392_BUCK("buck_vproc", VPROC, 700000, 1493750, 6250,
+ buck_volt_range1, MT6392_VPROC_CON7, MT6392_VPROC_CON9, 0x7f,
+ MT6392_VPROC_CON10, MT6392_VPROC_CON5, MT6392_VPROC_CON2,
+ 0x100, 12500),
+ MT6392_BUCK("buck_vsys", VSYS, 1400000, 2987500, 12500,
+ buck_volt_range2, MT6392_VSYS_CON7, MT6392_VSYS_CON9, 0x7f,
+ MT6392_VSYS_CON10, MT6392_VSYS_CON5, MT6392_VSYS_CON2, 0x100,
+ 25000),
+ MT6392_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
+ buck_volt_range1, MT6392_VCORE_CON7, MT6392_VCORE_CON9, 0x7f,
+ MT6392_VCORE_CON10, MT6392_VCORE_CON5, MT6392_VCORE_CON2,
+ 0x100, 12500),
+ MT6392_REG_FIXED("ldo_vxo22", VXO22, MT6392_ANALDO_CON1, 10, 2200000,
+ MT6392_ANALDO_CON1, 0x2, 110),
+ MT6392_LDO("ldo_vaud22", VAUD22, ldo_volt_table1,
+ MT6392_ANALDO_CON2, 14, MT6392_ANALDO_CON8, 0x60,
+ MT6392_ANALDO_CON2, 0x2, 264),
+ MT6392_REG_FIXED_NO_MODE("ldo_vcama", VCAMA, MT6392_ANALDO_CON4, 15,
+ 2800000, 264),
+ MT6392_REG_FIXED("ldo_vaud28", VAUD28, MT6392_ANALDO_CON23, 14, 2800000,
+ MT6392_ANALDO_CON23, 0x2, 264),
+ MT6392_REG_FIXED("ldo_vadc18", VADC18, MT6392_ANALDO_CON25, 14, 1800000,
+ MT6392_ANALDO_CON25, 0x2, 264),
+ MT6392_LDO_LINEAR("ldo_vcn35", VCN35, 3300000, 3600000, 100000,
+ ldo_volt_range2, MT6392_ANALDO_CON21, 12, MT6392_ANALDO_CON16,
+ 0xC, MT6392_ANALDO_CON21, 0x2, 264),
+ MT6392_REG_FIXED("ldo_vio28", VIO28, MT6392_DIGLDO_CON0, 14, 2800000,
+ MT6392_DIGLDO_CON0, 0x2, 264),
+ MT6392_REG_FIXED("ldo_vusb", VUSB, MT6392_DIGLDO_CON2, 14, 3300000,
+ MT6392_DIGLDO_CON2, 0x2, 264),
+ MT6392_LDO("ldo_vmc", VMC, ldo_volt_table3,
+ MT6392_DIGLDO_CON3, 12, MT6392_DIGLDO_CON24, 0x10,
+ MT6392_DIGLDO_CON3, 0x2, 264),
+ MT6392_LDO("ldo_vmch", VMCH, ldo_volt_table4,
+ MT6392_DIGLDO_CON5, 14, MT6392_DIGLDO_CON26, 0x80,
+ MT6392_DIGLDO_CON5, 0x2, 264),
+ MT6392_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table4,
+ MT6392_DIGLDO_CON6, 14, MT6392_DIGLDO_CON27, 0x80,
+ MT6392_DIGLDO_CON6, 0x2, 264),
+ MT6392_LDO("ldo_vgp1", VGP1, ldo_volt_table5,
+ MT6392_DIGLDO_CON7, 15, MT6392_DIGLDO_CON28, 0xE0,
+ MT6392_DIGLDO_CON7, 0x2, 264),
+ MT6392_LDO("ldo_vgp2", VGP2, ldo_volt_table5,
+ MT6392_DIGLDO_CON8, 15, MT6392_DIGLDO_CON29, 0xE0,
+ MT6392_DIGLDO_CON8, 0x2, 264),
+ MT6392_REG_FIXED("ldo_vcn18", VCN18, MT6392_DIGLDO_CON11, 14, 1800000,
+ MT6392_DIGLDO_CON11, 0x2, 264),
+ MT6392_LDO("ldo_vcamaf", VCAMAF, ldo_volt_table5,
+ MT6392_DIGLDO_CON31, 15, MT6392_DIGLDO_CON32, 0xE0,
+ MT6392_DIGLDO_CON31, 0x2, 264),
+ MT6392_LDO("ldo_vm", VM, ldo_volt_table6,
+ MT6392_DIGLDO_CON47, 14, MT6392_DIGLDO_CON48, 0x30,
+ MT6392_DIGLDO_CON47, 0x2, 264),
+ MT6392_REG_FIXED("ldo_vio18", VIO18, MT6392_DIGLDO_CON49, 14, 1800000,
+ MT6392_DIGLDO_CON49, 0x2, 264),
+ MT6392_LDO("ldo_vcamd", VCAMD, ldo_volt_table7,
+ MT6392_DIGLDO_CON51, 14, MT6392_DIGLDO_CON52, 0x60,
+ MT6392_DIGLDO_CON51, 0x2, 264),
+ MT6392_REG_FIXED("ldo_vcamio", VCAMIO, MT6392_DIGLDO_CON53, 14, 1800000,
+ MT6392_DIGLDO_CON53, 0x2, 264),
+ MT6392_REG_FIXED("ldo_vm25", VM25, MT6392_DIGLDO_CON55, 14, 2500000,
+ MT6392_DIGLDO_CON55, 0x2, 264),
+ MT6392_LDO("ldo_vefuse", VEFUSE, ldo_volt_table8,
+ MT6392_DIGLDO_CON57, 14, MT6392_DIGLDO_CON58, 0x10,
+ MT6392_DIGLDO_CON57, 0x2, 264),
+};
+
+static int mt6392_set_buck_vosel_reg(struct platform_device *pdev)
+{
+ struct mt6397_chip *mt6392 = dev_get_drvdata(pdev->dev.parent);
+ int i;
+ u32 regval;
+
+ for (i = 0; i < MT6392_MAX_REGULATOR; i++) {
+ if (mt6392_regulators[i].vselctrl_reg) {
+ if (regmap_read(mt6392->regmap,
+ mt6392_regulators[i].vselctrl_reg,
+ ®val) < 0) {
+ dev_err(&pdev->dev,
+ "Failed to read buck ctrl\n");
+ return -EIO;
+ }
+
+ if (regval & mt6392_regulators[i].vselctrl_mask) {
+ mt6392_regulators[i].desc.vsel_reg =
+ mt6392_regulators[i].vselon_reg;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mt6392_regulator_probe(struct platform_device *pdev)
+{
+ struct mt6397_chip *mt6392 = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_config config = {};
+ struct regulator_dev *rdev;
+ int i;
+
+ /* Query buck controller to select activated voltage register part */
+ if (mt6392_set_buck_vosel_reg(pdev))
+ return -EIO;
+
+ for (i = 0; i < MT6392_MAX_REGULATOR; i++) {
+ config.dev = &pdev->dev;
+ config.driver_data = &mt6392_regulators[i];
+ config.regmap = mt6392->regmap;
+
+ rdev = devm_regulator_register(&pdev->dev,
+ &mt6392_regulators[i].desc,
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ mt6392_regulators[i].desc.name);
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id mt6392_platform_ids[] = {
+ {"mt6392-regulator", 0},
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, mt6392_platform_ids);
+
+static struct platform_driver mt6392_regulator_driver = {
+ .driver = {
+ .name = "mt6392-regulator",
+ },
+ .probe = mt6392_regulator_probe,
+ .id_table = mt6392_platform_ids,
+};
+
+module_platform_driver(mt6392_regulator_driver);
+
+MODULE_AUTHOR("Chen Zhong <chen.zhong@mediatek.com>");
+MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6392 PMIC");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/regulator/mt6392-regulator.h b/include/linux/regulator/mt6392-regulator.h
new file mode 100644
index 000000000000..dfcbcacb5ad4
--- /dev/null
+++ b/include/linux/regulator/mt6392-regulator.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ */
+
+#ifndef __LINUX_REGULATOR_MT6392_H
+#define __LINUX_REGULATOR_MT6392_H
+
+enum {
+ MT6392_ID_VPROC = 0,
+ MT6392_ID_VSYS,
+ MT6392_ID_VCORE,
+ MT6392_ID_VXO22,
+ MT6392_ID_VAUD22,
+ MT6392_ID_VCAMA,
+ MT6392_ID_VAUD28,
+ MT6392_ID_VADC18,
+ MT6392_ID_VCN35,
+ MT6392_ID_VIO28,
+ MT6392_ID_VUSB = 10,
+ MT6392_ID_VMC,
+ MT6392_ID_VMCH,
+ MT6392_ID_VEMC3V3,
+ MT6392_ID_VGP1,
+ MT6392_ID_VGP2,
+ MT6392_ID_VCN18,
+ MT6392_ID_VCAMAF,
+ MT6392_ID_VM,
+ MT6392_ID_VIO18,
+ MT6392_ID_VCAMD,
+ MT6392_ID_VCAMIO,
+ MT6392_ID_VM25,
+ MT6392_ID_VEFUSE,
+ MT6392_ID_RG_MAX,
+};
+
+#define MT6392_MAX_REGULATOR MT6392_ID_RG_MAX
+
+#endif /* __LINUX_REGULATOR_MT6392_H */
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 7/9] input: keyboard: mtk-pmic-keys: add MT6392 support
From: Dmitry Torokhov @ 2026-02-23 17:55 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: linux-mediatek, Val Packett, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sen Chu, Sean Wang, Macpaul Lin, Lee Jones,
Matthias Brugger, AngeloGioacchino Del Regno, Liam Girdwood,
Mark Brown, Eddie Huang, Alexandre Belloni, Gary Bisson,
Julien Massot, Louis-Alexis Eyraud, Fabien Parent, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-rtc
In-Reply-To: <2c96591313084d240ac94b9d42d91d984fa9bce7.1771865015.git.l.scorcia@gmail.com>
On Mon, Feb 23, 2026 at 05:12:46PM +0000, Luca Leonardo Scorcia wrote:
> From: Val Packett <val@packett.cool>
>
> Add support for the MT6392 PMIC to the keys driver.
>
> Signed-off-by: Val Packett <val@packett.cool>
> Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Please feel free to merge with the rest of the series.
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH 9/9] arm64: dts: mt6392: add mt6392 PMIC dtsi
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Val Packett, Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Julien Massot,
Louis-Alexis Eyraud, Gary Bisson, Fabien Parent, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-rtc
In-Reply-To: <cover.1771865014.git.l.scorcia@gmail.com>
From: Val Packett <val@packett.cool>
Add the dts to be included by all boards using the MT6392 PMIC.
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
arch/arm64/boot/dts/mediatek/mt6392.dtsi | 133 +++++++++++++++++++++++
1 file changed, 133 insertions(+)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6392.dtsi
diff --git a/arch/arm64/boot/dts/mediatek/mt6392.dtsi b/arch/arm64/boot/dts/mediatek/mt6392.dtsi
new file mode 100644
index 000000000000..d0d86ae0f073
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6392.dtsi
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Copyright (c) 2024 Val Packett <val@packett.cool>
+ */
+
+#include <dt-bindings/input/input.h>
+
+&pwrap {
+ pmic: pmic {
+ compatible = "mediatek,mt6392";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ regulators {
+ compatible = "mediatek,mt6392-regulator";
+
+ mt6392_vproc_reg: buck_vproc {
+ regulator-name = "vproc";
+ };
+
+ mt6392_vsys_reg: buck_vsys {
+ regulator-name = "vsys";
+ };
+
+ mt6392_vcore_reg: buck_vcore {
+ regulator-name = "vcore";
+ };
+
+ mt6392_vxo22_reg: ldo_vxo22 {
+ regulator-name = "vxo22";
+ };
+
+ mt6392_vaud22_reg: ldo_vaud22 {
+ regulator-name = "vaud22";
+ };
+
+ mt6392_vcama_reg: ldo_vcama {
+ regulator-name = "vcama";
+ };
+
+ mt6392_vaud28_reg: ldo_vaud28 {
+ regulator-name = "vaud28";
+ };
+
+ mt6392_vadc18_reg: ldo_vadc18 {
+ regulator-name = "vadc18";
+ };
+
+ mt6392_vcn35_reg: ldo_vcn35 {
+ regulator-name = "vcn35";
+ };
+
+ mt6392_vio28_reg: ldo_vio28 {
+ regulator-name = "vio28";
+ };
+
+ mt6392_vusb_reg: ldo_vusb {
+ regulator-name = "vusb";
+ };
+
+ mt6392_vmc_reg: ldo_vmc {
+ regulator-name = "vmc";
+ };
+
+ mt6392_vmch_reg: ldo_vmch {
+ regulator-name = "vmch";
+ };
+
+ mt6392_vemc3v3_reg: ldo_vemc3v3 {
+ regulator-name = "vemc3v3";
+ };
+
+ mt6392_vgp1_reg: ldo_vgp1 {
+ regulator-name = "vgp1";
+ };
+
+ mt6392_vgp2_reg: ldo_vgp2 {
+ regulator-name = "vgp2";
+ };
+
+ mt6392_vcn18_reg: ldo_vcn18 {
+ regulator-name = "vcn18";
+ };
+
+ mt6392_vcamaf_reg: ldo_vcamaf {
+ regulator-name = "vcamaf";
+ };
+
+ mt6392_vm_reg: ldo_vm {
+ regulator-name = "vm";
+ };
+
+ mt6392_vio18_reg: ldo_vio18 {
+ regulator-name = "vio18";
+ };
+
+ mt6392_vcamd_reg: ldo_vcamd {
+ regulator-name = "vcamd";
+ };
+
+ mt6392_vcamio_reg: ldo_vcamio {
+ regulator-name = "vcamio";
+ };
+
+ mt6392_vm25_reg: ldo_vm25 {
+ regulator-name = "vm25";
+ };
+
+ mt6392_vefuse_reg: ldo_vefuse {
+ regulator-name = "vefuse";
+ };
+ };
+
+ rtc {
+ compatible = "mediatek,mt6392-rtc";
+ };
+
+ keys {
+ compatible = "mediatek,mt6392-keys";
+
+ key-power {
+ linux,keycodes = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ key-home {
+ linux,keycodes = <KEY_HOME>;
+ wakeup-source;
+ };
+ };
+ };
+};
--
2.43.0
^ permalink raw reply related
* [PATCH 8/9] rtc: mt6397: add compatible for MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Val Packett, Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Louis-Alexis Eyraud,
Julien Massot, Gary Bisson, Fabien Parent, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-rtc
In-Reply-To: <cover.1771865014.git.l.scorcia@gmail.com>
From: Val Packett <val@packett.cool>
Add a compatible, using the same data as the MT6397.
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
drivers/rtc/rtc-mt6397.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c
index 692c00ff544b..6b67d917f8d5 100644
--- a/drivers/rtc/rtc-mt6397.c
+++ b/drivers/rtc/rtc-mt6397.c
@@ -334,6 +334,7 @@ static const struct of_device_id mt6397_rtc_of_match[] = {
{ .compatible = "mediatek,mt6323-rtc", .data = &mt6397_rtc_data },
{ .compatible = "mediatek,mt6357-rtc", .data = &mt6358_rtc_data },
{ .compatible = "mediatek,mt6358-rtc", .data = &mt6358_rtc_data },
+ { .compatible = "mediatek,mt6392-rtc", .data = &mt6397_rtc_data },
{ .compatible = "mediatek,mt6397-rtc", .data = &mt6397_rtc_data },
{ }
};
--
2.43.0
^ permalink raw reply related
* [PATCH 7/9] input: keyboard: mtk-pmic-keys: add MT6392 support
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Val Packett, Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Gary Bisson, Julien Massot,
Louis-Alexis Eyraud, Fabien Parent, Chen Zhong, linux-input,
devicetree, linux-kernel, linux-pm, linux-arm-kernel, linux-rtc
In-Reply-To: <cover.1771865014.git.l.scorcia@gmail.com>
From: Val Packett <val@packett.cool>
Add support for the MT6392 PMIC to the keys driver.
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
drivers/input/keyboard/mtk-pmic-keys.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
index c78d9f6d97c4..3b9a5b6bc470 100644
--- a/drivers/input/keyboard/mtk-pmic-keys.c
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -13,6 +13,7 @@
#include <linux/mfd/mt6357/registers.h>
#include <linux/mfd/mt6358/registers.h>
#include <linux/mfd/mt6359/registers.h>
+#include <linux/mfd/mt6392/registers.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/registers.h>
#include <linux/module.h>
@@ -69,6 +70,17 @@ static const struct mtk_pmic_regs mt6397_regs = {
.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
};
+static const struct mtk_pmic_regs mt6392_regs = {
+ .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6392_CHRSTATUS,
+ 0x2, MT6392_INT_MISC_CON, 0x10, MTK_PMIC_PWRKEY_RST),
+ .keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6392_CHRSTATUS,
+ 0x4, MT6392_INT_MISC_CON, 0x8, MTK_PMIC_HOMEKEY_RST),
+ .pmic_rst_reg = MT6392_TOP_RST_MISC,
+ .rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
+};
+
static const struct mtk_pmic_regs mt6323_regs = {
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
@@ -301,6 +313,9 @@ static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = {
{
.compatible = "mediatek,mt6397-keys",
.data = &mt6397_regs,
+ }, {
+ .compatible = "mediatek,mt6392-keys",
+ .data = &mt6392_regs,
}, {
.compatible = "mediatek,mt6323-keys",
.data = &mt6323_regs,
--
2.43.0
^ permalink raw reply related
* [PATCH 5/9] soc: mediatek: mtk-pmic-wrap: add compatible for MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Val Packett, Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Louis-Alexis Eyraud,
Julien Massot, Gary Bisson, Fabien Parent, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-rtc
In-Reply-To: <cover.1771865014.git.l.scorcia@gmail.com>
From: Val Packett <val@packett.cool>
The MT6392 PMIC is equivalent to the MT6323 in terms of pwrap.
Add the compatible to use the same configuration.
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
drivers/soc/mediatek/mtk-pmic-wrap.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 0bcd85826375..4b8d49c6f34c 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -2249,6 +2249,7 @@ static const struct pwrap_slv_type pmic_mt6397 = {
static const struct of_device_id of_slave_match_tbl[] = {
{ .compatible = "mediatek,mt6323", .data = &pmic_mt6323 },
+ { .compatible = "mediatek,mt6392", .data = &pmic_mt6323 },
{ .compatible = "mediatek,mt6331", .data = &pmic_mt6331 },
{ .compatible = "mediatek,mt6351", .data = &pmic_mt6351 },
{ .compatible = "mediatek,mt6357", .data = &pmic_mt6357 },
--
2.43.0
^ permalink raw reply related
* [PATCH 4/9] mfd: mt6397: Add support for MT6392 pmic
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Gary Bisson, Louis-Alexis Eyraud,
Julien Massot, Chen Zhong, linux-input, devicetree, linux-kernel,
linux-pm, linux-arm-kernel, linux-rtc
In-Reply-To: <cover.1771865014.git.l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Update the MT6397 MFD driver to support the MT6392 PMIC.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
drivers/mfd/mt6397-core.c | 43 +++
drivers/mfd/mt6397-irq.c | 8 +
include/linux/mfd/mt6392/core.h | 42 +++
include/linux/mfd/mt6392/registers.h | 487 +++++++++++++++++++++++++++
include/linux/mfd/mt6397/core.h | 1 +
5 files changed, 581 insertions(+)
create mode 100644 include/linux/mfd/mt6392/core.h
create mode 100644 include/linux/mfd/mt6392/registers.h
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 3e58d0764c7e..f2ab684d882b 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -18,6 +18,7 @@
#include <linux/mfd/mt6357/core.h>
#include <linux/mfd/mt6358/core.h>
#include <linux/mfd/mt6359/core.h>
+#include <linux/mfd/mt6392/core.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6323/registers.h>
#include <linux/mfd/mt6328/registers.h>
@@ -25,6 +26,7 @@
#include <linux/mfd/mt6357/registers.h>
#include <linux/mfd/mt6358/registers.h>
#include <linux/mfd/mt6359/registers.h>
+#include <linux/mfd/mt6392/registers.h>
#include <linux/mfd/mt6397/registers.h>
#define MT6323_RTC_BASE 0x8000
@@ -39,6 +41,9 @@
#define MT6358_RTC_BASE 0x0588
#define MT6358_RTC_SIZE 0x3c
+#define MT6392_RTC_BASE 0x8000
+#define MT6392_RTC_SIZE 0x3e
+
#define MT6397_RTC_BASE 0xe000
#define MT6397_RTC_SIZE 0x3e
@@ -65,6 +70,11 @@ static const struct resource mt6358_rtc_resources[] = {
DEFINE_RES_IRQ(MT6358_IRQ_RTC),
};
+static const struct resource mt6392_rtc_resources[] = {
+ DEFINE_RES_MEM(MT6392_RTC_BASE, MT6392_RTC_SIZE),
+ DEFINE_RES_IRQ(MT6392_IRQ_RTC),
+};
+
static const struct resource mt6397_rtc_resources[] = {
DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE),
DEFINE_RES_IRQ(MT6397_IRQ_RTC),
@@ -114,6 +124,11 @@ static const struct resource mt6331_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_HOMEKEY, "homekey"),
};
+static const struct resource mt6392_keys_resources[] = {
+ DEFINE_RES_IRQ_NAMED(MT6392_IRQ_PWRKEY, "powerkey"),
+ DEFINE_RES_IRQ_NAMED(MT6392_IRQ_FCHRKEY, "homekey"),
+};
+
static const struct resource mt6397_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6397_IRQ_PWRKEY, "powerkey"),
DEFINE_RES_IRQ_NAMED(MT6397_IRQ_HOMEKEY, "homekey"),
@@ -253,6 +268,23 @@ static const struct mfd_cell mt6359_devs[] = {
},
};
+static const struct mfd_cell mt6392_devs[] = {
+ {
+ .name = "mt6397-rtc",
+ .num_resources = ARRAY_SIZE(mt6392_rtc_resources),
+ .resources = mt6392_rtc_resources,
+ .of_compatible = "mediatek,mt6392-rtc",
+ }, {
+ .name = "mt6392-regulator",
+ .of_compatible = "mediatek,mt6392-regulator",
+ }, {
+ .name = "mtk-pmic-keys",
+ .num_resources = ARRAY_SIZE(mt6392_keys_resources),
+ .resources = mt6392_keys_resources,
+ .of_compatible = "mediatek,mt6392-keys"
+ },
+};
+
static const struct mfd_cell mt6397_devs[] = {
{
.name = "mt6397-rtc",
@@ -335,6 +367,14 @@ static const struct chip_data mt6359_core = {
.irq_init = mt6358_irq_init,
};
+static const struct chip_data mt6392_core = {
+ .cid_addr = MT6392_CID,
+ .cid_shift = 0,
+ .cells = mt6392_devs,
+ .cell_size = ARRAY_SIZE(mt6392_devs),
+ .irq_init = mt6397_irq_init,
+};
+
static const struct chip_data mt6397_core = {
.cid_addr = MT6397_CID,
.cid_shift = 0,
@@ -416,6 +456,9 @@ static const struct of_device_id mt6397_of_match[] = {
}, {
.compatible = "mediatek,mt6359",
.data = &mt6359_core,
+ }, {
+ .compatible = "mediatek,mt6392",
+ .data = &mt6392_core,
}, {
.compatible = "mediatek,mt6397",
.data = &mt6397_core,
diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
index 5d2e5459f744..80ea5b92d232 100644
--- a/drivers/mfd/mt6397-irq.c
+++ b/drivers/mfd/mt6397-irq.c
@@ -15,6 +15,8 @@
#include <linux/mfd/mt6328/registers.h>
#include <linux/mfd/mt6331/core.h>
#include <linux/mfd/mt6331/registers.h>
+#include <linux/mfd/mt6392/core.h>
+#include <linux/mfd/mt6392/registers.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/registers.h>
@@ -203,6 +205,12 @@ int mt6397_irq_init(struct mt6397_chip *chip)
chip->int_status[0] = MT6397_INT_STATUS0;
chip->int_status[1] = MT6397_INT_STATUS1;
break;
+ case MT6392_CHIP_ID:
+ chip->int_con[0] = MT6392_INT_CON0;
+ chip->int_con[1] = MT6392_INT_CON1;
+ chip->int_status[0] = MT6392_INT_STATUS0;
+ chip->int_status[1] = MT6392_INT_STATUS1;
+ break;
default:
dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
diff --git a/include/linux/mfd/mt6392/core.h b/include/linux/mfd/mt6392/core.h
new file mode 100644
index 000000000000..4780dab4da92
--- /dev/null
+++ b/include/linux/mfd/mt6392/core.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ */
+
+#ifndef __MFD_MT6392_CORE_H__
+#define __MFD_MT6392_CORE_H__
+
+enum mt6392_irq_numbers {
+ MT6392_IRQ_SPKL_AB = 0,
+ MT6392_IRQ_SPKL,
+ MT6392_IRQ_BAT_L,
+ MT6392_IRQ_BAT_H,
+ MT6392_IRQ_WATCHDOG,
+ MT6392_IRQ_PWRKEY,
+ MT6392_IRQ_THR_L,
+ MT6392_IRQ_THR_H,
+ MT6392_IRQ_VBATON_UNDET,
+ MT6392_IRQ_BVALID_DET,
+ MT6392_IRQ_CHRDET,
+ MT6392_IRQ_OV,
+ MT6392_IRQ_LDO = 16,
+ MT6392_IRQ_FCHRKEY,
+ MT6392_IRQ_RELEASE_PWRKEY,
+ MT6392_IRQ_RELEASE_FCHRKEY,
+ MT6392_IRQ_RTC,
+ MT6392_IRQ_VPROC,
+ MT6392_IRQ_VSYS,
+ MT6392_IRQ_VCORE,
+ MT6392_IRQ_TYPE_C_CC,
+ MT6392_IRQ_TYPEC_H_MAX,
+ MT6392_IRQ_TYPEC_H_MIN,
+ MT6392_IRQ_TYPEC_L_MAX,
+ MT6392_IRQ_TYPEC_L_MIN,
+ MT6392_IRQ_THR_MAX,
+ MT6392_IRQ_THR_MIN,
+ MT6392_IRQ_NAG_C_DLTV,
+ MT6392_IRQ_NR,
+};
+
+#endif /* __MFD_MT6392_CORE_H__ */
diff --git a/include/linux/mfd/mt6392/registers.h b/include/linux/mfd/mt6392/registers.h
new file mode 100644
index 000000000000..4f3a6db830d1
--- /dev/null
+++ b/include/linux/mfd/mt6392/registers.h
@@ -0,0 +1,487 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ */
+
+#ifndef __MFD_MT6392_REGISTERS_H__
+#define __MFD_MT6392_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6392_CHR_CON0 0x0000
+#define MT6392_CHR_CON1 0x0002
+#define MT6392_CHR_CON2 0x0004
+#define MT6392_CHR_CON3 0x0006
+#define MT6392_CHR_CON4 0x0008
+#define MT6392_CHR_CON5 0x000A
+#define MT6392_CHR_CON6 0x000C
+#define MT6392_CHR_CON7 0x000E
+#define MT6392_CHR_CON8 0x0010
+#define MT6392_CHR_CON9 0x0012
+#define MT6392_CHR_CON10 0x0014
+#define MT6392_CHR_CON11 0x0016
+#define MT6392_CHR_CON12 0x0018
+#define MT6392_CHR_CON13 0x001A
+#define MT6392_CHR_CON14 0x001C
+#define MT6392_CHR_CON15 0x001E
+#define MT6392_CHR_CON16 0x0020
+#define MT6392_CHR_CON17 0x0022
+#define MT6392_CHR_CON18 0x0024
+#define MT6392_CHR_CON19 0x0026
+#define MT6392_CHR_CON20 0x0028
+#define MT6392_CHR_CON21 0x002A
+#define MT6392_CHR_CON22 0x002C
+#define MT6392_CHR_CON23 0x002E
+#define MT6392_CHR_CON24 0x0030
+#define MT6392_CHR_CON25 0x0032
+#define MT6392_CHR_CON26 0x0034
+#define MT6392_CHR_CON27 0x0036
+#define MT6392_CHR_CON28 0x0038
+#define MT6392_CHR_CON29 0x003A
+#define MT6392_STRUP_CON0 0x003C
+#define MT6392_STRUP_CON2 0x003E
+#define MT6392_STRUP_CON3 0x0040
+#define MT6392_STRUP_CON4 0x0042
+#define MT6392_STRUP_CON5 0x0044
+#define MT6392_STRUP_CON6 0x0046
+#define MT6392_STRUP_CON7 0x0048
+#define MT6392_STRUP_CON8 0x004A
+#define MT6392_STRUP_CON9 0x004C
+#define MT6392_STRUP_CON10 0x004E
+#define MT6392_STRUP_CON11 0x0050
+#define MT6392_SPK_CON0 0x0052
+#define MT6392_SPK_CON1 0x0054
+#define MT6392_SPK_CON2 0x0056
+#define MT6392_SPK_CON6 0x005E
+#define MT6392_SPK_CON7 0x0060
+#define MT6392_SPK_CON8 0x0062
+#define MT6392_SPK_CON9 0x0064
+#define MT6392_SPK_CON10 0x0066
+#define MT6392_SPK_CON11 0x0068
+#define MT6392_SPK_CON12 0x006A
+#define MT6392_STRUP_CON12 0x006E
+#define MT6392_STRUP_CON13 0x0070
+#define MT6392_STRUP_CON14 0x0072
+#define MT6392_STRUP_CON15 0x0074
+#define MT6392_STRUP_CON16 0x0076
+#define MT6392_STRUP_CON17 0x0078
+#define MT6392_STRUP_CON18 0x007A
+#define MT6392_STRUP_CON19 0x007C
+#define MT6392_STRUP_CON20 0x007E
+#define MT6392_CID 0x0100
+#define MT6392_TOP_CKPDN0 0x0102
+#define MT6392_TOP_CKPDN0_SET 0x0104
+#define MT6392_TOP_CKPDN0_CLR 0x0106
+#define MT6392_TOP_CKPDN1 0x0108
+#define MT6392_TOP_CKPDN1_SET 0x010A
+#define MT6392_TOP_CKPDN1_CLR 0x010C
+#define MT6392_TOP_CKPDN2 0x010E
+#define MT6392_TOP_CKPDN2_SET 0x0110
+#define MT6392_TOP_CKPDN2_CLR 0x0112
+#define MT6392_TOP_RST_CON 0x0114
+#define MT6392_TOP_RST_CON_SET 0x0116
+#define MT6392_TOP_RST_CON_CLR 0x0118
+#define MT6392_TOP_RST_MISC 0x011A
+#define MT6392_TOP_RST_MISC_SET 0x011C
+#define MT6392_TOP_RST_MISC_CLR 0x011E
+#define MT6392_TOP_CKCON0 0x0120
+#define MT6392_TOP_CKCON0_SET 0x0122
+#define MT6392_TOP_CKCON0_CLR 0x0124
+#define MT6392_TOP_CKCON1 0x0126
+#define MT6392_TOP_CKCON1_SET 0x0128
+#define MT6392_TOP_CKCON1_CLR 0x012A
+#define MT6392_TOP_CKTST0 0x012C
+#define MT6392_TOP_CKTST1 0x012E
+#define MT6392_TOP_CKTST2 0x0130
+#define MT6392_TEST_OUT 0x0132
+#define MT6392_TEST_CON0 0x0134
+#define MT6392_TEST_CON1 0x0136
+#define MT6392_EN_STATUS0 0x0138
+#define MT6392_EN_STATUS1 0x013A
+#define MT6392_OCSTATUS0 0x013C
+#define MT6392_OCSTATUS1 0x013E
+#define MT6392_PGSTATUS 0x0140
+#define MT6392_CHRSTATUS 0x0142
+#define MT6392_TDSEL_CON 0x0144
+#define MT6392_RDSEL_CON 0x0146
+#define MT6392_SMT_CON0 0x0148
+#define MT6392_SMT_CON1 0x014A
+#define MT6392_DRV_CON0 0x0152
+#define MT6392_DRV_CON1 0x0154
+#define MT6392_INT_CON0 0x0160
+#define MT6392_INT_CON0_SET 0x0162
+#define MT6392_INT_CON0_CLR 0x0164
+#define MT6392_INT_CON1 0x0166
+#define MT6392_INT_CON1_SET 0x0168
+#define MT6392_INT_CON1_CLR 0x016A
+#define MT6392_INT_MISC_CON 0x016C
+#define MT6392_INT_MISC_CON_SET 0x016E
+#define MT6392_INT_MISC_CON_CLR 0x0170
+#define MT6392_INT_STATUS0 0x0172
+#define MT6392_INT_STATUS1 0x0174
+#define MT6392_OC_GEAR_0 0x0176
+#define MT6392_OC_GEAR_1 0x0178
+#define MT6392_OC_GEAR_2 0x017A
+#define MT6392_OC_CTL_VPROC 0x017C
+#define MT6392_OC_CTL_VSYS 0x017E
+#define MT6392_OC_CTL_VCORE 0x0180
+#define MT6392_FQMTR_CON0 0x0182
+#define MT6392_FQMTR_CON1 0x0184
+#define MT6392_FQMTR_CON2 0x0186
+#define MT6392_RG_SPI_CON 0x0188
+#define MT6392_DEW_DIO_EN 0x018A
+#define MT6392_DEW_READ_TEST 0x018C
+#define MT6392_DEW_WRITE_TEST 0x018E
+#define MT6392_DEW_CRC_SWRST 0x0190
+#define MT6392_DEW_CRC_EN 0x0192
+#define MT6392_DEW_CRC_VAL 0x0194
+#define MT6392_DEW_DBG_MON_SEL 0x0196
+#define MT6392_DEW_CIPHER_KEY_SEL 0x0198
+#define MT6392_DEW_CIPHER_IV_SEL 0x019A
+#define MT6392_DEW_CIPHER_EN 0x019C
+#define MT6392_DEW_CIPHER_RDY 0x019E
+#define MT6392_DEW_CIPHER_MODE 0x01A0
+#define MT6392_DEW_CIPHER_SWRST 0x01A2
+#define MT6392_DEW_RDDMY_NO 0x01A4
+#define MT6392_DEW_RDATA_DLY_SEL 0x01A6
+#define MT6392_CLK_TRIM_CON0 0x01A8
+#define MT6392_BUCK_CON0 0x0200
+#define MT6392_BUCK_CON1 0x0202
+#define MT6392_BUCK_CON2 0x0204
+#define MT6392_BUCK_CON3 0x0206
+#define MT6392_BUCK_CON4 0x0208
+#define MT6392_BUCK_CON5 0x020A
+#define MT6392_VPROC_CON0 0x020C
+#define MT6392_VPROC_CON1 0x020E
+#define MT6392_VPROC_CON2 0x0210
+#define MT6392_VPROC_CON3 0x0212
+#define MT6392_VPROC_CON4 0x0214
+#define MT6392_VPROC_CON5 0x0216
+#define MT6392_VPROC_CON7 0x021A
+#define MT6392_VPROC_CON8 0x021C
+#define MT6392_VPROC_CON9 0x021E
+#define MT6392_VPROC_CON10 0x0220
+#define MT6392_VPROC_CON11 0x0222
+#define MT6392_VPROC_CON12 0x0224
+#define MT6392_VPROC_CON13 0x0226
+#define MT6392_VPROC_CON14 0x0228
+#define MT6392_VPROC_CON15 0x022A
+#define MT6392_VPROC_CON18 0x0230
+#define MT6392_VSYS_CON0 0x0232
+#define MT6392_VSYS_CON1 0x0234
+#define MT6392_VSYS_CON2 0x0236
+#define MT6392_VSYS_CON3 0x0238
+#define MT6392_VSYS_CON4 0x023A
+#define MT6392_VSYS_CON5 0x023C
+#define MT6392_VSYS_CON7 0x0240
+#define MT6392_VSYS_CON8 0x0242
+#define MT6392_VSYS_CON9 0x0244
+#define MT6392_VSYS_CON10 0x0246
+#define MT6392_VSYS_CON11 0x0248
+#define MT6392_VSYS_CON12 0x024A
+#define MT6392_VSYS_CON13 0x024C
+#define MT6392_VSYS_CON14 0x024E
+#define MT6392_VSYS_CON15 0x0250
+#define MT6392_VSYS_CON18 0x0256
+#define MT6392_BUCK_OC_CON0 0x0258
+#define MT6392_BUCK_OC_CON1 0x025A
+#define MT6392_BUCK_OC_CON2 0x025C
+#define MT6392_BUCK_OC_CON3 0x025E
+#define MT6392_BUCK_OC_CON4 0x0260
+#define MT6392_BUCK_OC_VPROC_CON0 0x0262
+#define MT6392_BUCK_OC_VCORE_CON0 0x0264
+#define MT6392_BUCK_OC_VSYS_CON0 0x0266
+#define MT6392_BUCK_ANA_MON_CON0 0x0268
+#define MT6392_BUCK_EFUSE_OC_CON0 0x026A
+#define MT6392_VCORE_CON0 0x0300
+#define MT6392_VCORE_CON1 0x0302
+#define MT6392_VCORE_CON2 0x0304
+#define MT6392_VCORE_CON3 0x0306
+#define MT6392_VCORE_CON4 0x0308
+#define MT6392_VCORE_CON5 0x030A
+#define MT6392_VCORE_CON7 0x030E
+#define MT6392_VCORE_CON8 0x0310
+#define MT6392_VCORE_CON9 0x0312
+#define MT6392_VCORE_CON10 0x0314
+#define MT6392_VCORE_CON11 0x0316
+#define MT6392_VCORE_CON12 0x0318
+#define MT6392_VCORE_CON13 0x031A
+#define MT6392_VCORE_CON14 0x031C
+#define MT6392_VCORE_CON15 0x031E
+#define MT6392_VCORE_CON18 0x0324
+#define MT6392_BUCK_K_CON0 0x032A
+#define MT6392_BUCK_K_CON1 0x032C
+#define MT6392_BUCK_K_CON2 0x032E
+#define MT6392_ANALDO_CON0 0x0400
+#define MT6392_ANALDO_CON1 0x0402
+#define MT6392_ANALDO_CON2 0x0404
+#define MT6392_ANALDO_CON3 0x0406
+#define MT6392_ANALDO_CON4 0x0408
+#define MT6392_ANALDO_CON6 0x040C
+#define MT6392_ANALDO_CON7 0x040E
+#define MT6392_ANALDO_CON8 0x0410
+#define MT6392_ANALDO_CON10 0x0412
+#define MT6392_ANALDO_CON15 0x0414
+#define MT6392_ANALDO_CON16 0x0416
+#define MT6392_ANALDO_CON17 0x0418
+#define MT6392_ANALDO_CON21 0x0420
+#define MT6392_ANALDO_CON22 0x0422
+#define MT6392_ANALDO_CON23 0x0424
+#define MT6392_ANALDO_CON24 0x0426
+#define MT6392_ANALDO_CON25 0x0428
+#define MT6392_ANALDO_CON26 0x042A
+#define MT6392_ANALDO_CON27 0x042C
+#define MT6392_ANALDO_CON28 0x042E
+#define MT6392_ANALDO_CON29 0x0430
+#define MT6392_DIGLDO_CON0 0x0500
+#define MT6392_DIGLDO_CON2 0x0502
+#define MT6392_DIGLDO_CON3 0x0504
+#define MT6392_DIGLDO_CON5 0x0506
+#define MT6392_DIGLDO_CON6 0x0508
+#define MT6392_DIGLDO_CON7 0x050A
+#define MT6392_DIGLDO_CON8 0x050C
+#define MT6392_DIGLDO_CON10 0x0510
+#define MT6392_DIGLDO_CON11 0x0512
+#define MT6392_DIGLDO_CON12 0x0514
+#define MT6392_DIGLDO_CON15 0x051A
+#define MT6392_DIGLDO_CON20 0x0524
+#define MT6392_DIGLDO_CON21 0x0526
+#define MT6392_DIGLDO_CON23 0x0528
+#define MT6392_DIGLDO_CON24 0x052A
+#define MT6392_DIGLDO_CON26 0x052C
+#define MT6392_DIGLDO_CON27 0x052E
+#define MT6392_DIGLDO_CON28 0x0530
+#define MT6392_DIGLDO_CON29 0x0532
+#define MT6392_DIGLDO_CON30 0x0534
+#define MT6392_DIGLDO_CON31 0x0536
+#define MT6392_DIGLDO_CON32 0x0538
+#define MT6392_DIGLDO_CON33 0x053A
+#define MT6392_DIGLDO_CON36 0x0540
+#define MT6392_DIGLDO_CON41 0x0546
+#define MT6392_DIGLDO_CON44 0x054C
+#define MT6392_DIGLDO_CON47 0x0552
+#define MT6392_DIGLDO_CON48 0x0554
+#define MT6392_DIGLDO_CON49 0x0556
+#define MT6392_DIGLDO_CON50 0x0558
+#define MT6392_DIGLDO_CON51 0x055A
+#define MT6392_DIGLDO_CON52 0x055C
+#define MT6392_DIGLDO_CON53 0x055E
+#define MT6392_DIGLDO_CON54 0x0560
+#define MT6392_DIGLDO_CON55 0x0562
+#define MT6392_DIGLDO_CON56 0x0564
+#define MT6392_DIGLDO_CON57 0x0566
+#define MT6392_DIGLDO_CON58 0x0568
+#define MT6392_DIGLDO_CON59 0x056A
+#define MT6392_DIGLDO_CON60 0x056C
+#define MT6392_DIGLDO_CON61 0x056E
+#define MT6392_DIGLDO_CON62 0x0570
+#define MT6392_DIGLDO_CON63 0x0572
+#define MT6392_EFUSE_CON0 0x0600
+#define MT6392_EFUSE_CON1 0x0602
+#define MT6392_EFUSE_CON2 0x0604
+#define MT6392_EFUSE_CON3 0x0606
+#define MT6392_EFUSE_CON4 0x0608
+#define MT6392_EFUSE_CON5 0x060A
+#define MT6392_EFUSE_CON6 0x060C
+#define MT6392_EFUSE_VAL_0_15 0x060E
+#define MT6392_EFUSE_VAL_16_31 0x0610
+#define MT6392_EFUSE_VAL_32_47 0x0612
+#define MT6392_EFUSE_VAL_48_63 0x0614
+#define MT6392_EFUSE_VAL_64_79 0x0616
+#define MT6392_EFUSE_VAL_80_95 0x0618
+#define MT6392_EFUSE_VAL_96_111 0x061A
+#define MT6392_EFUSE_VAL_112_127 0x061C
+#define MT6392_EFUSE_VAL_128_143 0x061E
+#define MT6392_EFUSE_VAL_144_159 0x0620
+#define MT6392_EFUSE_VAL_160_175 0x0622
+#define MT6392_EFUSE_VAL_176_191 0x0624
+#define MT6392_EFUSE_VAL_192_207 0x0626
+#define MT6392_EFUSE_VAL_208_223 0x0628
+#define MT6392_EFUSE_VAL_224_239 0x062A
+#define MT6392_EFUSE_VAL_240_255 0x062C
+#define MT6392_EFUSE_VAL_256_271 0x062E
+#define MT6392_EFUSE_VAL_272_287 0x0630
+#define MT6392_EFUSE_VAL_288_303 0x0632
+#define MT6392_EFUSE_VAL_304_319 0x0634
+#define MT6392_EFUSE_VAL_320_335 0x0636
+#define MT6392_EFUSE_VAL_336_351 0x0638
+#define MT6392_EFUSE_VAL_352_367 0x063A
+#define MT6392_EFUSE_VAL_368_383 0x063C
+#define MT6392_EFUSE_VAL_384_399 0x063E
+#define MT6392_EFUSE_VAL_400_415 0x0640
+#define MT6392_EFUSE_VAL_416_431 0x0642
+#define MT6392_RTC_MIX_CON0 0x0644
+#define MT6392_RTC_MIX_CON1 0x0646
+#define MT6392_EFUSE_VAL_432_447 0x0648
+#define MT6392_EFUSE_VAL_448_463 0x064A
+#define MT6392_EFUSE_VAL_464_479 0x064C
+#define MT6392_EFUSE_VAL_480_495 0x064E
+#define MT6392_EFUSE_VAL_496_511 0x0650
+#define MT6392_EFUSE_DOUT_0_15 0x0652
+#define MT6392_EFUSE_DOUT_16_31 0x0654
+#define MT6392_EFUSE_DOUT_32_47 0x0656
+#define MT6392_EFUSE_DOUT_48_63 0x0658
+#define MT6392_EFUSE_DOUT_64_79 0x065A
+#define MT6392_EFUSE_DOUT_80_95 0x065C
+#define MT6392_EFUSE_DOUT_96_111 0x065E
+#define MT6392_EFUSE_DOUT_112_127 0x0660
+#define MT6392_EFUSE_DOUT_128_143 0x0662
+#define MT6392_EFUSE_DOUT_144_159 0x0664
+#define MT6392_EFUSE_DOUT_160_175 0x0666
+#define MT6392_EFUSE_DOUT_176_191 0x0668
+#define MT6392_EFUSE_DOUT_192_207 0x066A
+#define MT6392_EFUSE_DOUT_208_223 0x066C
+#define MT6392_EFUSE_DOUT_224_239 0x066E
+#define MT6392_EFUSE_DOUT_240_255 0x0670
+#define MT6392_EFUSE_DOUT_256_271 0x0672
+#define MT6392_EFUSE_DOUT_272_287 0x0674
+#define MT6392_EFUSE_DOUT_288_303 0x0676
+#define MT6392_EFUSE_DOUT_304_319 0x0678
+#define MT6392_EFUSE_DOUT_320_335 0x067A
+#define MT6392_EFUSE_DOUT_336_351 0x067C
+#define MT6392_EFUSE_DOUT_352_367 0x067E
+#define MT6392_EFUSE_DOUT_368_383 0x0680
+#define MT6392_EFUSE_DOUT_384_399 0x0682
+#define MT6392_EFUSE_DOUT_400_415 0x0684
+#define MT6392_EFUSE_DOUT_416_431 0x0686
+#define MT6392_EFUSE_DOUT_432_447 0x0688
+#define MT6392_EFUSE_DOUT_448_463 0x068A
+#define MT6392_EFUSE_DOUT_464_479 0x068C
+#define MT6392_EFUSE_DOUT_480_495 0x068E
+#define MT6392_EFUSE_DOUT_496_511 0x0690
+#define MT6392_EFUSE_CON7 0x0692
+#define MT6392_EFUSE_CON8 0x0694
+#define MT6392_EFUSE_CON9 0x0696
+#define MT6392_AUXADC_ADC0 0x0700
+#define MT6392_AUXADC_ADC1 0x0702
+#define MT6392_AUXADC_ADC2 0x0704
+#define MT6392_AUXADC_ADC3 0x0706
+#define MT6392_AUXADC_ADC4 0x0708
+#define MT6392_AUXADC_ADC5 0x070A
+#define MT6392_AUXADC_ADC6 0x070C
+#define MT6392_AUXADC_ADC7 0x070E
+#define MT6392_AUXADC_ADC8 0x0710
+#define MT6392_AUXADC_ADC9 0x0712
+#define MT6392_AUXADC_ADC10 0x0714
+#define MT6392_AUXADC_ADC11 0x0716
+#define MT6392_AUXADC_ADC12 0x0718
+#define MT6392_AUXADC_ADC13 0x071A
+#define MT6392_AUXADC_ADC14 0x071C
+#define MT6392_AUXADC_ADC15 0x071E
+#define MT6392_AUXADC_ADC16 0x0720
+#define MT6392_AUXADC_ADC17 0x0722
+#define MT6392_AUXADC_ADC18 0x0724
+#define MT6392_AUXADC_ADC19 0x0726
+#define MT6392_AUXADC_ADC20 0x0728
+#define MT6392_AUXADC_ADC21 0x072A
+#define MT6392_AUXADC_ADC22 0x072C
+#define MT6392_AUXADC_STA0 0x072E
+#define MT6392_AUXADC_STA1 0x0730
+#define MT6392_AUXADC_RQST0 0x0732
+#define MT6392_AUXADC_RQST0_SET 0x0734
+#define MT6392_AUXADC_RQST0_CLR 0x0736
+#define MT6392_AUXADC_CON0 0x0738
+#define MT6392_AUXADC_CON0_SET 0x073A
+#define MT6392_AUXADC_CON0_CLR 0x073C
+#define MT6392_AUXADC_CON1 0x073E
+#define MT6392_AUXADC_CON2 0x0740
+#define MT6392_AUXADC_CON3 0x0742
+#define MT6392_AUXADC_CON4 0x0744
+#define MT6392_AUXADC_CON5 0x0746
+#define MT6392_AUXADC_CON6 0x0748
+#define MT6392_AUXADC_CON7 0x074A
+#define MT6392_AUXADC_CON8 0x074C
+#define MT6392_AUXADC_CON9 0x074E
+#define MT6392_AUXADC_CON10 0x0750
+#define MT6392_AUXADC_CON11 0x0752
+#define MT6392_AUXADC_CON12 0x0754
+#define MT6392_AUXADC_CON13 0x0756
+#define MT6392_AUXADC_CON14 0x0758
+#define MT6392_AUXADC_CON15 0x075A
+#define MT6392_AUXADC_CON16 0x075C
+#define MT6392_AUXADC_AUTORPT0 0x075E
+#define MT6392_AUXADC_LBAT0 0x0760
+#define MT6392_AUXADC_LBAT1 0x0762
+#define MT6392_AUXADC_LBAT2 0x0764
+#define MT6392_AUXADC_LBAT3 0x0766
+#define MT6392_AUXADC_LBAT4 0x0768
+#define MT6392_AUXADC_LBAT5 0x076A
+#define MT6392_AUXADC_LBAT6 0x076C
+#define MT6392_AUXADC_THR0 0x076E
+#define MT6392_AUXADC_THR1 0x0770
+#define MT6392_AUXADC_THR2 0x0772
+#define MT6392_AUXADC_THR3 0x0774
+#define MT6392_AUXADC_THR4 0x0776
+#define MT6392_AUXADC_THR5 0x0778
+#define MT6392_AUXADC_THR6 0x077A
+#define MT6392_AUXADC_EFUSE0 0x077C
+#define MT6392_AUXADC_EFUSE1 0x077E
+#define MT6392_AUXADC_EFUSE2 0x0780
+#define MT6392_AUXADC_EFUSE3 0x0782
+#define MT6392_AUXADC_EFUSE4 0x0784
+#define MT6392_AUXADC_EFUSE5 0x0786
+#define MT6392_AUXADC_NAG_0 0x0788
+#define MT6392_AUXADC_NAG_1 0x078A
+#define MT6392_AUXADC_NAG_2 0x078C
+#define MT6392_AUXADC_NAG_3 0x078E
+#define MT6392_AUXADC_NAG_4 0x0790
+#define MT6392_AUXADC_NAG_5 0x0792
+#define MT6392_AUXADC_NAG_6 0x0794
+#define MT6392_AUXADC_NAG_7 0x0796
+#define MT6392_AUXADC_NAG_8 0x0798
+#define MT6392_AUXADC_TYPEC_H_1 0x079A
+#define MT6392_AUXADC_TYPEC_H_2 0x079C
+#define MT6392_AUXADC_TYPEC_H_3 0x079E
+#define MT6392_AUXADC_TYPEC_H_4 0x07A0
+#define MT6392_AUXADC_TYPEC_H_5 0x07A2
+#define MT6392_AUXADC_TYPEC_H_6 0x07A4
+#define MT6392_AUXADC_TYPEC_H_7 0x07A6
+#define MT6392_AUXADC_TYPEC_L_1 0x07A8
+#define MT6392_AUXADC_TYPEC_L_2 0x07AA
+#define MT6392_AUXADC_TYPEC_L_3 0x07AC
+#define MT6392_AUXADC_TYPEC_L_4 0x07AE
+#define MT6392_AUXADC_TYPEC_L_5 0x07B0
+#define MT6392_AUXADC_TYPEC_L_6 0x07B2
+#define MT6392_AUXADC_TYPEC_L_7 0x07B4
+#define MT6392_AUXADC_NAG_9 0x07B6
+#define MT6392_TYPE_C_PHY_RG_0 0x0800
+#define MT6392_TYPE_C_PHY_RG_CC_RESERVE_CSR 0x0802
+#define MT6392_TYPE_C_VCMP_CTRL 0x0804
+#define MT6392_TYPE_C_CTRL 0x0806
+#define MT6392_TYPE_C_CC_SW_CTRL 0x080a
+#define MT6392_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL 0x080c
+#define MT6392_TYPE_C_CC_VOL_DEBOUNCE_CNT_VAL 0x080e
+#define MT6392_TYPE_C_DRP_SRC_CNT_VAL_0 0x0810
+#define MT6392_TYPE_C_DRP_SNK_CNT_VAL_0 0x0814
+#define MT6392_TYPE_C_DRP_TRY_CNT_VAL_0 0x0818
+#define MT6392_TYPE_C_CC_SRC_DEFAULT_DAC_VAL 0x0820
+#define MT6392_TYPE_C_CC_SRC_15_DAC_VAL 0x0822
+#define MT6392_TYPE_C_CC_SRC_30_DAC_VAL 0x0824
+#define MT6392_TYPE_C_CC_SNK_DAC_VAL_0 0x0828
+#define MT6392_TYPE_C_CC_SNK_DAC_VAL_1 0x082a
+#define MT6392_TYPE_C_INTR_EN_0 0x0830
+#define MT6392_TYPE_C_INTR_EN_2 0x0834
+#define MT6392_TYPE_C_INTR_0 0x0838
+#define MT6392_TYPE_C_INTR_2 0x083C
+#define MT6392_TYPE_C_CC_STATUS 0x0840
+#define MT6392_TYPE_C_PWR_STATUS 0x0842
+#define MT6392_TYPE_C_PHY_RG_CC1_RESISTENCE_0 0x0844
+#define MT6392_TYPE_C_PHY_RG_CC1_RESISTENCE_1 0x0846
+#define MT6392_TYPE_C_PHY_RG_CC2_RESISTENCE_0 0x0848
+#define MT6392_TYPE_C_PHY_RG_CC2_RESISTENCE_1 0x084a
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_0 0x0860
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_0 0x0864
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_1 0x0866
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_1 0x0868
+#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_2 0x086c
+#define MT6392_TYPE_C_CC_DAC_CALI_CTRL 0x0870
+#define MT6392_TYPE_C_CC_DAC_CALI_RESULT 0x0872
+#define MT6392_TYPE_C_DEBUG_PORT_SELECT_0 0x0880
+#define MT6392_TYPE_C_DEBUG_PORT_SELECT_1 0x0882
+#define MT6392_TYPE_C_DEBUG_MODE_SELECT 0x0884
+#define MT6392_TYPE_C_DEBUG_OUT_READ_0 0x0888
+#define MT6392_TYPE_C_DEBUG_OUT_READ_1 0x088a
+#define MT6392_TYPE_C_SW_DEBUG_PORT_0 0x088c
+#define MT6392_TYPE_C_SW_DEBUG_PORT_1 0x088e
+
+#endif /* __MFD_MT6392_REGISTERS_H__ */
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
index b774c3a4bb62..d665d0777065 100644
--- a/include/linux/mfd/mt6397/core.h
+++ b/include/linux/mfd/mt6397/core.h
@@ -20,6 +20,7 @@ enum chip_id {
MT6359_CHIP_ID = 0x59,
MT6366_CHIP_ID = 0x66,
MT6391_CHIP_ID = 0x91,
+ MT6392_CHIP_ID = 0x92,
MT6397_CHIP_ID = 0x97,
};
--
2.43.0
^ permalink raw reply related
* [PATCH 3/9] dt-bindings: input: mtk-pmic-keys: add MT6392 binding definition
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Julien Massot,
Louis-Alexis Eyraud, Gary Bisson, Chen Zhong, linux-input,
devicetree, linux-kernel, linux-pm, linux-arm-kernel, linux-rtc
In-Reply-To: <cover.1771865014.git.l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Add the binding documentation of the mtk-pmic-keys for the MT6392 PMICs.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
index b95435bd6a9b..2d3c4161a7f8 100644
--- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
+++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
@@ -30,6 +30,7 @@ properties:
- mediatek,mt6357-keys
- mediatek,mt6358-keys
- mediatek,mt6359-keys
+ - mediatek,mt6392-keys
- mediatek,mt6397-keys
power-off-time-sec: true
--
2.43.0
^ permalink raw reply related
* [PATCH 2/9] dt-bindings: regulator: add support for MT6392
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Julien Massot,
Louis-Alexis Eyraud, Gary Bisson, Chen Zhong, linux-input,
devicetree, linux-kernel, linux-pm, linux-arm-kernel, linux-rtc
In-Reply-To: <cover.1771865014.git.l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Add binding documentation of the regulator for MT6392 SoCs.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
index 5f422d311d4d..b61fce8f09c0 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
@@ -94,6 +94,7 @@ properties:
- mediatek,mt6328-regulator
- mediatek,mt6358-regulator
- mediatek,mt6359-regulator
+ - mediatek,mt6392-regulator
- mediatek,mt6397-regulator
- items:
- enum:
--
2.43.0
^ permalink raw reply related
* [PATCH 1/9] dt-bindings: mfd: mt6397: Add bindings for MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Fabien Parent, Val Packett, Luca Leonardo Scorcia,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Gary Bisson, Julien Massot,
Louis-Alexis Eyraud, Chen Zhong, linux-input, devicetree,
linux-kernel, linux-pm, linux-arm-kernel, linux-rtc
In-Reply-To: <cover.1771865014.git.l.scorcia@gmail.com>
From: Fabien Parent <parent.f@gmail.com>
Add the currently supported bindings for the MT6392 PMIC.
Signed-off-by: Fabien Parent <parent.f@gmail.com>
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
index 6a89b479d10f..5f422d311d4d 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
@@ -39,6 +39,7 @@ properties:
- mediatek,mt6328
- mediatek,mt6358
- mediatek,mt6359
+ - mediatek,mt6392
- mediatek,mt6397
- items:
- enum:
@@ -67,6 +68,7 @@ properties:
- mediatek,mt6323-rtc
- mediatek,mt6331-rtc
- mediatek,mt6358-rtc
+ - mediatek,mt6392-rtc
- mediatek,mt6397-rtc
- items:
- enum:
--
2.43.0
^ permalink raw reply related
* [PATCH 0/9] Add support for mt6392 PMIC
From: Luca Leonardo Scorcia @ 2026-02-23 17:12 UTC (permalink / raw)
To: linux-mediatek
Cc: Luca Leonardo Scorcia, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown,
Eddie Huang, Alexandre Belloni, Julien Massot,
Louis-Alexis Eyraud, Gary Bisson, Val Packett, Fabien Parent,
Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-rtc
The MediaTek mt6392 PMIC is usually found on devices powered by
the mt8516/mt8167 SoC, and is yet another mt6397 variant.
This series is mostly based around patches submitted a couple
years ago by Fabien Parent and not merged and from Val Packett's
submission from Jan 2025 that included extra cleanups, fixes, and a
new dtsi file similar to ones that exist for other PMICs. Some
comments weren't addressed and the series was ultimately not merged.
This series only enables three functions: regulators, keys, and RTC.
I have added a handful of device tree improvements to fix some
dtbs_check errors and addressed the comments from last year's
reviews. The series has been tested on Xiaomi Mi Smart Clock x04g.
Fabien Parent (5):
dt-bindings: mfd: mt6397: Add bindings for MT6392 PMIC
dt-bindings: regulator: add support for MT6392
dt-bindings: input: mtk-pmic-keys: add MT6392 binding definition
mfd: mt6397: Add support for MT6392 pmic
regulator: mt6392: Add support for MT6392 regulator
Val Packett (4):
soc: mediatek: mtk-pmic-wrap: add compatible for MT6392 PMIC
input: keyboard: mtk-pmic-keys: add MT6392 support
rtc: mt6397: add compatible for MT6392 PMIC
arm64: dts: mt6392: add mt6392 PMIC dtsi
.../bindings/input/mediatek,pmic-keys.yaml | 1 +
.../bindings/mfd/mediatek,mt6397.yaml | 3 +
arch/arm64/boot/dts/mediatek/mt6392.dtsi | 133 +++++
drivers/input/keyboard/mtk-pmic-keys.c | 15 +
drivers/mfd/mt6397-core.c | 43 ++
drivers/mfd/mt6397-irq.c | 8 +
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mt6392-regulator.c | 491 ++++++++++++++++++
drivers/rtc/rtc-mt6397.c | 1 +
drivers/soc/mediatek/mtk-pmic-wrap.c | 1 +
include/linux/mfd/mt6392/core.h | 42 ++
include/linux/mfd/mt6392/registers.h | 487 +++++++++++++++++
include/linux/mfd/mt6397/core.h | 1 +
include/linux/regulator/mt6392-regulator.h | 40 ++
15 files changed, 1276 insertions(+)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6392.dtsi
create mode 100644 drivers/regulator/mt6392-regulator.c
create mode 100644 include/linux/mfd/mt6392/core.h
create mode 100644 include/linux/mfd/mt6392/registers.h
create mode 100644 include/linux/regulator/mt6392-regulator.h
--
2.43.0
^ permalink raw reply
* [PATCH AUTOSEL 6.19-6.1] rtc: zynqmp: correct frequency value
From: Sasha Levin @ 2026-02-23 16:17 UTC (permalink / raw)
To: patches, stable
Cc: Tomas Melin, Harini T, Michal Simek, Alexandre Belloni,
Sasha Levin, linux-rtc, linux-arm-kernel, linux-kernel
In-Reply-To: <20260223161707.2714732-1-sashal@kernel.org>
From: Tomas Melin <tomas.melin@vaisala.com>
[ Upstream commit 2724fb4d429cbb724dcb6fa17953040918ebe3a2 ]
Fix calibration value in case a clock reference is provided.
The actual calibration value written into register is
frequency - 1.
Reviewed-by: Harini T <harini.t@amd.com>
Tested-by: Harini T <harini.t@amd.com>
Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
Acked-by: Michal Simek <michal.simek@amd.com>
Link: https://patch.msgid.link/20260122-zynqmp-rtc-updates-v4-1-d4edb966b499@vaisala.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Analysis
### What the commit fixes
This commit fixes an off-by-one error in the RTC calibration value when
the frequency is obtained from a clock reference (via `clk_get_rate()`).
The ZynqMP RTC hardware register expects a calibration value of
`frequency - 1`, but the code was writing the raw frequency value
directly.
**Evidence:**
- `RTC_CALIB_DEF` = `0x7FFF` = 32767 = 32768 - 1 (the default is already
correctly decremented)
- The `"calibration"` DT property presumably provides the register-ready
value (already freq-1)
- But `clk_get_rate()` returns the raw clock rate (e.g., 32768), so it
needs the `-1` adjustment
- Without the fix, the RTC counts one extra tick per second, causing
time drift
### Code change assessment
The fix adds an `else` branch with `xrtcdev->freq--` when the frequency
comes from `clk_get_rate()` (i.e., when `xrtcdev->freq` is non-zero from
the clock). This is a 2-line addition, surgically targeted.
### Dependency analysis
The clock name fix `2a388ff22d2cb` ("rtc: zynqmp: Fix optional clock
name property") was already tagged `Cc: stable@kernel.org` and is
targeted at v6.14-rc1. Before that fix, the driver was looking for clock
name "rtc_clk" instead of "rtc" (matching the DT binding), so the clock-
based frequency path was effectively dead code. With `2a388ff22d2cb`
being backported to stable, the clock can now actually be found, making
this off-by-one bug reachable.
The underlying calibration infrastructure was introduced in
`07dcc6f9c762` (v6.0-rc1), so stable trees v6.1.y and later have the
affected code.
### Stable criteria evaluation
- **Fixes a real bug:** Yes - incorrect RTC calibration causes time
drift
- **Obviously correct:** Yes - the register needs freq-1, this subtracts
1
- **Small and contained:** Yes - 2 lines in one file
- **No new features:** Correct - purely fixes calibration logic
- **Tested:** Yes - has Tested-by and Reviewed-by from AMD engineer,
Acked-by from Michal Simek
### Risk assessment
**Very low risk.** The change only affects the path where a clock
reference provides the frequency. It cannot break the default path
(`RTC_CALIB_DEF`) or the DT `"calibration"` property path. The worst
case if something were wrong would be an RTC running at the wrong rate -
exactly the same as the current bug.
### Verification
- Read the full driver source: confirmed `RTC_CALIB_DEF` = 0x7FFF =
32767 (line 40)
- Verified `clk_get_rate()` returns raw frequency, not register value,
per kernel API
- `git show 85cab027d4e31`: confirmed previous calibration fix changed
default from 0x198233 to 0x7FFF (32768-1)
- `git show 07dcc6f9c762`: confirmed this is the commit that introduced
clock-based calibration (v6.0-rc1)
- `git describe --contains 2a388ff22d2cb`: confirmed clock name fix is
in v6.14-rc1, already tagged for stable
- `git describe --contains 07dcc6f9c762`: confirmed calibration support
is in v6.0-rc1, present in all current stable trees
- The fix directly corresponds to the relationship: `RTC_CALIB_DEF`
(default) = 0x7FFF = 32768 - 1, confirming the register semantics
This is a small, well-tested fix for incorrect RTC timekeeping. It's a
companion to the already-stable-tagged clock name fix. Without this fix,
any board using the ZynqMP RTC with a clock reference will have
incorrect time calibration.
**YES**
drivers/rtc/rtc-zynqmp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
index 3baa2b481d9f2..856bc1678e7d3 100644
--- a/drivers/rtc/rtc-zynqmp.c
+++ b/drivers/rtc/rtc-zynqmp.c
@@ -345,7 +345,10 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
&xrtcdev->freq);
if (ret)
xrtcdev->freq = RTC_CALIB_DEF;
+ } else {
+ xrtcdev->freq--;
}
+
ret = readl(xrtcdev->reg_base + RTC_CALIB_RD);
if (!ret)
writel(xrtcdev->freq, (xrtcdev->reg_base + RTC_CALIB_WR));
--
2.51.0
^ permalink raw reply related
* [PATCH v1 0/8] ACPI: x86/rtc-cmos: Bind rtc-cmos to platform devices
From: Rafael J. Wysocki @ 2026-02-23 15:27 UTC (permalink / raw)
To: Linux ACPI; +Cc: LKML, x86 Maintainers, linux-rtc, Alexandre Belloni
Currently, on x86 the CMOS RTC is represented by a PNP device which
generally works, but the amount of avoidable code entanglement related
to that is a bit over the top.
First of all, in order to create a PNP device for the CMOS RTC, the ACPI
PNP meta-driver needs to be aware of that device, but adding the CMOS
RTC device IDs to acpi_pnp_device_ids[] was not sufficient for this
purpose because of the CMOS RTC ACPI address space driver that added an
ACPI scan handler for the CMOS RTC. That scan handler simply installs
the requisite ACPI address space handler for the CMOS RTC address space,
but it also claims the CMOS RTC device which prevents the ACPI PNP scan
handler from taking care of it. That's why there is is_cmos_rtc_device()
that needs to be additionally called by acpi_is_pnp_device().
Second, add_rtc_cmos() needs to check whether or not the CMOS RTC device
is present so it knows whether or not to create a fallback platform
device for the CMOS RTC. The way it does that is somewhat less than
elegant.
Finally, the rtc-cmos driver carries a PNP driver interface so it can
bind to the CMOS RTC device.
Moreover, on some systems the CMOS RTC device is the only PNP device in
use, so if it is represented by a device of a different type, the PNP
subsystem can be compiled out entirely on those systems.
That can be achieved with the help of the observation that the rtc-cmos
driver actually can work with platform devices already and the only
change that needs to be made to it in order to make that happen on x86
is to add CMOS RTC device IDs to it along with the related
MODULE_DEVICE_TABLE() declaration, which is done in patch [4/8].
However, for the above to work, the requisite platform devices actually
need to be created and patch [3/8] updates the CMOS RTC ACPI scan
handler used by the CMOS RTC ACPI address space handler to do just that.
It also adds a bool variable to be used by add_rtc_cmos() to check
whether or not to add a fallback platform device for the CMOS RTC.
Before that happens, patches [1-2/8] prepare the CMOS RTC ACPI address
space handler for the subsequent changes by rearranging it and fixing
its interactions with the ACPI time and alarm device (TAD) driver.
The next three patches, [5-7/8] simply drop some code that is not
necessary any more. Patch [5/8] drops CMOS RTC support from the ACPI
PNP meta-driver, patch [6/8] drops the walk over PNP devices from
add_rtc_cmos(), and patch [7/8] drops the PNP driver interface from
the rtc-cmos driver.
Patch [8/8] is a bonus cleanup adding the ACPI TAD device ID to the
CMOS RTC ACPI scan handler in the CMOS RTC address space driver, so
it will create an ACPI TAD platform device after installing the CMOS
RTC address space handler. After that change, the ACPI TAD driver
doesn't need to attempt to install the CMOS RTC ACPI address space
handler any more and can be simplified quite a bit.
After all of that, the CMOS RTC device IDs are only used in 2 places
(instead of 5) and well over 100 lines of code that is not super-nice
go away.
^ permalink raw reply
* [PATCH v1 1/8] ACPI: x86: cmos_rtc: Clean up address space handler driver
From: Rafael J. Wysocki @ 2026-02-23 15:28 UTC (permalink / raw)
To: Linux ACPI; +Cc: LKML, x86 Maintainers, linux-rtc, Alexandre Belloni
In-Reply-To: <5983325.DvuYhMxLoT@rafael.j.wysocki>
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Make multiple changes that do not alter functionality to the CMOS RTC
ACPI address space handler driver, including the following:
- Drop the unused .detach() callback from cmos_rtc_handler.
- Rename acpi_cmos_rtc_attach_handler() to acpi_cmos_rtc_attach().
- Rearrange acpi_cmos_rtc_space_handler() to reduce the number of
redundant checks and make white space follow the coding style.
- Adjust an error message in acpi_install_cmos_rtc_space_handler()
and make the white space follow the coding style.
- Rearrange acpi_remove_cmos_rtc_space_handler() and adjust an error
message in it.
No intentional functional impact.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/x86/cmos_rtc.c | 61 +++++++++++++++++++------------------
1 file changed, 32 insertions(+), 29 deletions(-)
diff --git a/drivers/acpi/x86/cmos_rtc.c b/drivers/acpi/x86/cmos_rtc.c
index 51643ff6fe5f..977234da9fc1 100644
--- a/drivers/acpi/x86/cmos_rtc.c
+++ b/drivers/acpi/x86/cmos_rtc.c
@@ -24,31 +24,35 @@ static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
{}
};
-static acpi_status
-acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address,
- u32 bits, u64 *value64,
- void *handler_context, void *region_context)
+static acpi_status acpi_cmos_rtc_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bits, u64 *value64,
+ void *handler_context,
+ void *region_context)
{
- int i;
+ unsigned int i, bytes = DIV_ROUND_UP(bits, 8);
u8 *value = (u8 *)value64;
if (address > 0xff || !value64)
return AE_BAD_PARAMETER;
- if (function != ACPI_WRITE && function != ACPI_READ)
- return AE_BAD_PARAMETER;
+ guard(spinlock_irq)(&rtc_lock);
+
+ if (function == ACPI_WRITE) {
+ for (i = 0; i < bytes; i++, address++, value++)
+ CMOS_WRITE(*value, address);
- spin_lock_irq(&rtc_lock);
+ return AE_OK;
+ }
- for (i = 0; i < DIV_ROUND_UP(bits, 8); ++i, ++address, ++value)
- if (function == ACPI_READ)
+ if (function == ACPI_READ) {
+ for (i = 0; i < bytes; i++, address++, value++)
*value = CMOS_READ(address);
- else
- CMOS_WRITE(*value, address);
- spin_unlock_irq(&rtc_lock);
+ return AE_OK;
+ }
- return AE_OK;
+ return AE_BAD_PARAMETER;
}
int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
@@ -56,11 +60,11 @@ int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
acpi_status status;
status = acpi_install_address_space_handler(handle,
- ACPI_ADR_SPACE_CMOS,
- &acpi_cmos_rtc_space_handler,
- NULL, NULL);
+ ACPI_ADR_SPACE_CMOS,
+ acpi_cmos_rtc_space_handler,
+ NULL, NULL);
if (ACPI_FAILURE(status)) {
- pr_err("Error installing CMOS-RTC region handler\n");
+ pr_err("Failed to install CMOS-RTC address space handler\n");
return -ENODEV;
}
@@ -70,26 +74,25 @@ EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler);
void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
{
- if (ACPI_FAILURE(acpi_remove_address_space_handler(handle,
- ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler)))
- pr_err("Error removing CMOS-RTC region handler\n");
+ acpi_status status;
+
+ status = acpi_remove_address_space_handler(handle,
+ ACPI_ADR_SPACE_CMOS,
+ acpi_cmos_rtc_space_handler);
+ if (ACPI_FAILURE(status))
+ pr_err("Failed to remove CMOS-RTC address space handler\n");
}
EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler);
-static int acpi_cmos_rtc_attach_handler(struct acpi_device *adev, const struct acpi_device_id *id)
+static int acpi_cmos_rtc_attach(struct acpi_device *adev,
+ const struct acpi_device_id *id)
{
return acpi_install_cmos_rtc_space_handler(adev->handle);
}
-static void acpi_cmos_rtc_detach_handler(struct acpi_device *adev)
-{
- acpi_remove_cmos_rtc_space_handler(adev->handle);
-}
-
static struct acpi_scan_handler cmos_rtc_handler = {
.ids = acpi_cmos_rtc_ids,
- .attach = acpi_cmos_rtc_attach_handler,
- .detach = acpi_cmos_rtc_detach_handler,
+ .attach = acpi_cmos_rtc_attach,
};
void __init acpi_cmos_rtc_init(void)
--
2.51.0
^ permalink raw reply related
* [PATCH v1 2/8] ACPI: x86: cmos_rtc: Improve coordination with ACPI TAD driver
From: Rafael J. Wysocki @ 2026-02-23 15:28 UTC (permalink / raw)
To: Linux ACPI; +Cc: LKML, x86 Maintainers, linux-rtc, Alexandre Belloni
In-Reply-To: <5983325.DvuYhMxLoT@rafael.j.wysocki>
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
If a CMOS RTC (PNP0B00/PNP0B01/PNP0B02) device coexists with an ACPI
TAD (timer and event alarm device, ACPI000E), the ACPI TAD driver will
attempt to install the CMOS RTC address space hanlder that has been
installed already and the TAD probing will fail.
Avoid that by changing acpi_install_cmos_rtc_space_handler() to return
zero and acpi_remove_cmos_rtc_space_handler() to do nothing if the CMOS
RTC address space handler has been installed already.
Fixes: 596ca52a56da ("ACPI: TAD: Install SystemCMOS address space handler for ACPI000E")
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/x86/cmos_rtc.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/x86/cmos_rtc.c b/drivers/acpi/x86/cmos_rtc.c
index 977234da9fc1..45db7e51cbe6 100644
--- a/drivers/acpi/x86/cmos_rtc.c
+++ b/drivers/acpi/x86/cmos_rtc.c
@@ -24,6 +24,8 @@ static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
{}
};
+static bool cmos_rtc_space_handler_present __read_mostly;
+
static acpi_status acpi_cmos_rtc_space_handler(u32 function,
acpi_physical_address address,
u32 bits, u64 *value64,
@@ -59,6 +61,9 @@ int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
{
acpi_status status;
+ if (cmos_rtc_space_handler_present)
+ return 0;
+
status = acpi_install_address_space_handler(handle,
ACPI_ADR_SPACE_CMOS,
acpi_cmos_rtc_space_handler,
@@ -68,6 +73,8 @@ int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
return -ENODEV;
}
+ cmos_rtc_space_handler_present = true;
+
return 1;
}
EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler);
@@ -76,6 +83,9 @@ void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
{
acpi_status status;
+ if (cmos_rtc_space_handler_present)
+ return;
+
status = acpi_remove_address_space_handler(handle,
ACPI_ADR_SPACE_CMOS,
acpi_cmos_rtc_space_handler);
@@ -87,7 +97,13 @@ EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler);
static int acpi_cmos_rtc_attach(struct acpi_device *adev,
const struct acpi_device_id *id)
{
- return acpi_install_cmos_rtc_space_handler(adev->handle);
+ int ret;
+
+ ret = acpi_install_cmos_rtc_space_handler(adev->handle);
+ if (ret < 0)
+ return ret;
+
+ return 1;
}
static struct acpi_scan_handler cmos_rtc_handler = {
--
2.51.0
^ permalink raw reply related
* [PATCH v1 3/8] ACPI: x86: cmos_rtc: Create a CMOS RTC platform device
From: Rafael J. Wysocki @ 2026-02-23 15:29 UTC (permalink / raw)
To: Linux ACPI; +Cc: LKML, x86 Maintainers, linux-rtc, Alexandre Belloni
In-Reply-To: <5983325.DvuYhMxLoT@rafael.j.wysocki>
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Make the CMOS RTC ACPI scan handler create a platform device that will
be used subsequently by rtc-cmos for driver binding on x86 systems with
ACPI and update add_rtc_cmos() to skip registering a fallback platform
device for the CMOS RTC when the above one has been registered.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
arch/x86/kernel/rtc.c | 4 ++++
drivers/acpi/x86/cmos_rtc.c | 8 ++++++++
include/linux/acpi.h | 4 ++++
3 files changed, 16 insertions(+)
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 51a849a79c98..b112178e8185 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -2,6 +2,7 @@
/*
* RTC related functions
*/
+#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/mc146818rtc.h>
#include <linux/export.h>
@@ -146,6 +147,9 @@ static __init int add_rtc_cmos(void)
}
}
#endif
+ if (cmos_rtc_platform_device_present)
+ return 0;
+
if (!x86_platform.legacy.rtc)
return -ENODEV;
diff --git a/drivers/acpi/x86/cmos_rtc.c b/drivers/acpi/x86/cmos_rtc.c
index 45db7e51cbe6..bdd66dfd4a44 100644
--- a/drivers/acpi/x86/cmos_rtc.c
+++ b/drivers/acpi/x86/cmos_rtc.c
@@ -24,6 +24,8 @@ static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
{}
};
+bool cmos_rtc_platform_device_present;
+
static bool cmos_rtc_space_handler_present __read_mostly;
static acpi_status acpi_cmos_rtc_space_handler(u32 function,
@@ -103,6 +105,12 @@ static int acpi_cmos_rtc_attach(struct acpi_device *adev,
if (ret < 0)
return ret;
+ if (IS_ERR_OR_NULL(acpi_create_platform_device(adev, NULL))) {
+ pr_err("Failed to create CMOS-RTC platform device\n");
+ return 0;
+ } else {
+ cmos_rtc_platform_device_present = true;
+ }
return 1;
}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4d2f0bed7a06..2bdb801cee01 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -791,6 +791,8 @@ const char *acpi_get_subsystem_id(acpi_handle handle);
int acpi_mrrm_max_mem_region(void);
#endif
+extern bool cmos_rtc_platform_device_present;
+
#else /* !CONFIG_ACPI */
#define acpi_disabled 1
@@ -1116,6 +1118,8 @@ static inline int acpi_mrrm_max_mem_region(void)
return 1;
}
+#define cmos_rtc_platform_device_present false
+
#endif /* !CONFIG_ACPI */
#ifdef CONFIG_ACPI_HMAT
--
2.51.0
^ permalink raw reply related
* [PATCH v1 4/8] ACPI: x86/rtc-cmos: Use platform device for driver binding
From: Rafael J. Wysocki @ 2026-02-23 15:30 UTC (permalink / raw)
To: Linux ACPI; +Cc: LKML, x86 Maintainers, linux-rtc, Alexandre Belloni
In-Reply-To: <5983325.DvuYhMxLoT@rafael.j.wysocki>
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Modify the rtc-cmos driver to bind to a platform device on systems with
ACPI via acpi_match_table and advertise the CMOST RTC ACPI device IDs
for driver auto-loading. Note that adding the requisite device IDs to
it and exposing them via MODULE_DEVICE_TABLE() is sufficient for this
purpose.
Since the ACPI device IDs in question are the same as for the CMOS RTC
ACPI scan handler, put them into a common header file and use the
definition from there in both places.
Additionally, to prevent a PNP device from being created for the CMOS
RTC if a platform one is present already, make is_cmos_rtc_device()
check cmos_rtc_platform_device_present introduced previously.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/acpi_pnp.c | 2 +-
drivers/acpi/x86/cmos_rtc.c | 5 +----
drivers/rtc/rtc-cmos.c | 10 ++++++++++
include/linux/acpi.h | 6 ++++++
4 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c
index 85d9f78619a2..4ad8f56d1a5d 100644
--- a/drivers/acpi/acpi_pnp.c
+++ b/drivers/acpi/acpi_pnp.c
@@ -368,7 +368,7 @@ static int is_cmos_rtc_device(struct acpi_device *adev)
{ "PNP0B02" },
{""},
};
- return !acpi_match_device_ids(adev, ids);
+ return !cmos_rtc_platform_device_present && !acpi_match_device_ids(adev, ids);
}
bool acpi_is_pnp_device(struct acpi_device *adev)
diff --git a/drivers/acpi/x86/cmos_rtc.c b/drivers/acpi/x86/cmos_rtc.c
index bdd66dfd4a44..a6df5b991c96 100644
--- a/drivers/acpi/x86/cmos_rtc.c
+++ b/drivers/acpi/x86/cmos_rtc.c
@@ -18,10 +18,7 @@
#include "../internal.h"
static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
- { "PNP0B00" },
- { "PNP0B01" },
- { "PNP0B02" },
- {}
+ ACPI_CMOS_RTC_IDS
};
bool cmos_rtc_platform_device_present;
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 0743c6acd6e2..7457f42fd6f0 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -27,6 +27,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -1476,6 +1477,14 @@ static __init void cmos_of_init(struct platform_device *pdev)
#else
static inline void cmos_of_init(struct platform_device *pdev) {}
#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
+ ACPI_CMOS_RTC_IDS
+};
+MODULE_DEVICE_TABLE(acpi, acpi_cmos_rtc_ids);
+#endif
+
/*----------------------------------------------------------------*/
/* Platform setup should have set up an RTC device, when PNP is
@@ -1530,6 +1539,7 @@ static struct platform_driver cmos_platform_driver = {
.name = driver_name,
.pm = &cmos_pm_ops,
.of_match_table = of_match_ptr(of_cmos_match),
+ .acpi_match_table = ACPI_PTR(acpi_cmos_rtc_ids),
}
};
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 2bdb801cee01..5ecdcdaf31aa 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -791,6 +791,12 @@ const char *acpi_get_subsystem_id(acpi_handle handle);
int acpi_mrrm_max_mem_region(void);
#endif
+#define ACPI_CMOS_RTC_IDS \
+ { "PNP0B00", }, \
+ { "PNP0B01", }, \
+ { "PNP0B02", }, \
+ { "", }
+
extern bool cmos_rtc_platform_device_present;
#else /* !CONFIG_ACPI */
--
2.51.0
^ permalink raw reply related
* [PATCH v1 5/8] ACPI: PNP: Drop CMOS RTC PNP device support
From: Rafael J. Wysocki @ 2026-02-23 15:31 UTC (permalink / raw)
To: Linux ACPI; +Cc: LKML, x86 Maintainers, linux-rtc, Alexandre Belloni
In-Reply-To: <5983325.DvuYhMxLoT@rafael.j.wysocki>
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
A previous change updated is_cmos_rtc_device() to effectively never
allow PNP devices to be created for the CMOS RTC on x86 with ACPI
and the PNP bus type is only used on x86, so the CMOS RTC device IDs
can be dropped from acpi_pnp_device_ids[] and is_cmos_rtc_device() can
go away completely.
Update the code accordingly.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/acpi_pnp.c | 22 +---------------------
1 file changed, 1 insertion(+), 21 deletions(-)
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c
index 4ad8f56d1a5d..da886923b008 100644
--- a/drivers/acpi/acpi_pnp.c
+++ b/drivers/acpi/acpi_pnp.c
@@ -125,10 +125,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
{"PNP0401"}, /* ECP Printer Port */
/* apple-gmux */
{"APP000B"},
- /* rtc_cmos */
- {"PNP0b00"},
- {"PNP0b01"},
- {"PNP0b02"},
/* c6xdigio */
{"PNP0400"}, /* Standard LPT Printer Port */
{"PNP0401"}, /* ECP Printer Port */
@@ -355,25 +351,9 @@ static struct acpi_scan_handler acpi_pnp_handler = {
.attach = acpi_pnp_attach,
};
-/*
- * For CMOS RTC devices, the PNP ACPI scan handler does not work, because
- * there is a CMOS RTC ACPI scan handler installed already, so we need to
- * check those devices and enumerate them to the PNP bus directly.
- */
-static int is_cmos_rtc_device(struct acpi_device *adev)
-{
- static const struct acpi_device_id ids[] = {
- { "PNP0B00" },
- { "PNP0B01" },
- { "PNP0B02" },
- {""},
- };
- return !cmos_rtc_platform_device_present && !acpi_match_device_ids(adev, ids);
-}
-
bool acpi_is_pnp_device(struct acpi_device *adev)
{
- return adev->handler == &acpi_pnp_handler || is_cmos_rtc_device(adev);
+ return adev->handler == &acpi_pnp_handler;
}
EXPORT_SYMBOL_GPL(acpi_is_pnp_device);
--
2.51.0
^ permalink raw reply related
* [PATCH v1 6/8] x86: rtc: Drop PNP device check
From: Rafael J. Wysocki @ 2026-02-23 15:31 UTC (permalink / raw)
To: Linux ACPI; +Cc: LKML, x86 Maintainers, linux-rtc, Alexandre Belloni
In-Reply-To: <5983325.DvuYhMxLoT@rafael.j.wysocki>
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Previous changes effectively prevented PNP devices from being created
for the CMOS RTC on x86 with ACPI.
Although in principle a CMOS RTC PNP device may exist on an x86 system
without ACPI (that is, an x86 system where there is no ACPI at all, not
one booted with ACPI disabled), such systems were there in the field ~30
years ago and most likely they would not be able to run a contemporary
Linux kernel.
For the above reasons, drop the PNP device check from add_rtc_cmos().
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
arch/x86/kernel/rtc.c | 17 +----------------
1 file changed, 1 insertion(+), 16 deletions(-)
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index b112178e8185..314b062a15de 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -6,7 +6,6 @@
#include <linux/platform_device.h>
#include <linux/mc146818rtc.h>
#include <linux/export.h>
-#include <linux/pnp.h>
#include <asm/vsyscall.h>
#include <asm/x86_init.h>
@@ -134,19 +133,6 @@ static struct platform_device rtc_device = {
static __init int add_rtc_cmos(void)
{
-#ifdef CONFIG_PNP
- static const char * const ids[] __initconst =
- { "PNP0b00", "PNP0b01", "PNP0b02", };
- struct pnp_dev *dev;
- int i;
-
- pnp_for_each_dev(dev) {
- for (i = 0; i < ARRAY_SIZE(ids); i++) {
- if (compare_pnp_id(dev->id, ids[i]) != 0)
- return 0;
- }
- }
-#endif
if (cmos_rtc_platform_device_present)
return 0;
@@ -154,8 +140,7 @@ static __init int add_rtc_cmos(void)
return -ENODEV;
platform_device_register(&rtc_device);
- dev_info(&rtc_device.dev,
- "registered platform RTC device (no PNP device found)\n");
+ dev_info(&rtc_device.dev, "registered fallback platform RTC device\n");
return 0;
}
--
2.51.0
^ permalink raw reply related
* [PATCH v1 7/8] rtc: cmos: Drop PNP device support
From: Rafael J. Wysocki @ 2026-02-23 15:32 UTC (permalink / raw)
To: Linux ACPI; +Cc: LKML, x86 Maintainers, linux-rtc, Alexandre Belloni
In-Reply-To: <5983325.DvuYhMxLoT@rafael.j.wysocki>
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Previous changes effectively prevented PNP devices from being created
for the CMOS RTC on x86 with ACPI.
Although in principle a CMOS RTC PNP device may exist on an x86 system
without ACPI (that is, an x86 system where there is no ACPI at all, not
one booted with ACPI disabled), such systems were there in the field ~30
years ago and most likely they would not be able to run a contemporary
Linux kernel.
For the above reasons, drop the PNP device support from the rtc-cmos
driver.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/rtc/rtc-cmos.c | 113 +++--------------------------------------
1 file changed, 8 insertions(+), 105 deletions(-)
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 7457f42fd6f0..9ac5bab846c1 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -1370,85 +1370,6 @@ static int __maybe_unused cmos_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume);
-/*----------------------------------------------------------------*/
-
-/* On non-x86 systems, a "CMOS" RTC lives most naturally on platform_bus.
- * ACPI systems always list these as PNPACPI devices, and pre-ACPI PCs
- * probably list them in similar PNPBIOS tables; so PNP is more common.
- *
- * We don't use legacy "poke at the hardware" probing. Ancient PCs that
- * predate even PNPBIOS should set up platform_bus devices.
- */
-
-#ifdef CONFIG_PNP
-
-#include <linux/pnp.h>
-
-static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
-{
- int irq;
-
- if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) {
- irq = 0;
-#ifdef CONFIG_X86
- /* Some machines contain a PNP entry for the RTC, but
- * don't define the IRQ. It should always be safe to
- * hardcode it on systems with a legacy PIC.
- */
- if (nr_legacy_irqs())
- irq = RTC_IRQ;
-#endif
- } else {
- irq = pnp_irq(pnp, 0);
- }
-
- return cmos_do_probe(&pnp->dev, pnp_get_resource(pnp, IORESOURCE_IO, 0), irq);
-}
-
-static void cmos_pnp_remove(struct pnp_dev *pnp)
-{
- cmos_do_remove(&pnp->dev);
-}
-
-static void cmos_pnp_shutdown(struct pnp_dev *pnp)
-{
- struct device *dev = &pnp->dev;
- struct cmos_rtc *cmos = dev_get_drvdata(dev);
-
- if (system_state == SYSTEM_POWER_OFF) {
- int retval = cmos_poweroff(dev);
-
- if (cmos_aie_poweroff(dev) < 0 && !retval)
- return;
- }
-
- cmos_do_shutdown(cmos->irq);
-}
-
-static const struct pnp_device_id rtc_ids[] = {
- { .id = "PNP0b00", },
- { .id = "PNP0b01", },
- { .id = "PNP0b02", },
- { },
-};
-MODULE_DEVICE_TABLE(pnp, rtc_ids);
-
-static struct pnp_driver cmos_pnp_driver = {
- .name = driver_name,
- .id_table = rtc_ids,
- .probe = cmos_pnp_probe,
- .remove = cmos_pnp_remove,
- .shutdown = cmos_pnp_shutdown,
-
- /* flag ensures resume() gets called, and stops syslog spam */
- .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
- .driver = {
- .pm = &cmos_pm_ops,
- },
-};
-
-#endif /* CONFIG_PNP */
-
#ifdef CONFIG_OF
static const struct of_device_id of_cmos_match[] = {
{
@@ -1543,45 +1464,27 @@ static struct platform_driver cmos_platform_driver = {
}
};
-#ifdef CONFIG_PNP
-static bool pnp_driver_registered;
-#endif
static bool platform_driver_registered;
static int __init cmos_init(void)
{
- int retval = 0;
+ int retval;
-#ifdef CONFIG_PNP
- retval = pnp_register_driver(&cmos_pnp_driver);
- if (retval == 0)
- pnp_driver_registered = true;
-#endif
+ if (cmos_rtc.dev)
+ return 0;
- if (!cmos_rtc.dev) {
- retval = platform_driver_probe(&cmos_platform_driver,
- cmos_platform_probe);
- if (retval == 0)
- platform_driver_registered = true;
- }
+ retval = platform_driver_probe(&cmos_platform_driver, cmos_platform_probe);
+ if (retval)
+ return retval;
- if (retval == 0)
- return 0;
+ platform_driver_registered = true;
-#ifdef CONFIG_PNP
- if (pnp_driver_registered)
- pnp_unregister_driver(&cmos_pnp_driver);
-#endif
- return retval;
+ return 0;
}
module_init(cmos_init);
static void __exit cmos_exit(void)
{
-#ifdef CONFIG_PNP
- if (pnp_driver_registered)
- pnp_unregister_driver(&cmos_pnp_driver);
-#endif
if (platform_driver_registered)
platform_driver_unregister(&cmos_platform_driver);
}
--
2.51.0
^ permalink raw reply related
* [PATCH v1 8/8] ACPI: TAD/x86: cmos_rtc: Consolidate address space handler setup
From: Rafael J. Wysocki @ 2026-02-23 15:33 UTC (permalink / raw)
To: Linux ACPI; +Cc: LKML, x86 Maintainers, linux-rtc, Alexandre Belloni
In-Reply-To: <5983325.DvuYhMxLoT@rafael.j.wysocki>
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
On x86, as a rule the CMOS RTC address space handler is set up by the
CMOS RTC ACPI scan handler attach callback, acpi_cmos_rtc_attach(),
but if the ACPI namespace does not contain a CMOS RTC device object,
the CMOS RTC address space handler installation is taken care of the
ACPI TAD (Timer and Alarm Device) driver.
This is not particularly straightforward and can be avoided by adding
the ACPI TAD device ID to the CMOS RTC ACPI scan handler which will
cause it to create a platform device for ACPI TAD after installing
the CMOS RTC address space handler. One related detail that needs to
be taken care of, though, is that the creation of an ACPI TAD platform
device should not cause cmos_rtc_platform_device_present to be set,
since this may cause add_rtc_cmos() to suppress the creation of a
fallback CMOS RTC platform device which may not be the right thing
to do (for instance, due to the fact that the ACPI TAD driver is
missing an RTC class device interface).
After doing the above, the CMOS RTC address space handler installation
and removal can be dropped from the ACPI TAD driver (which allows it to
be simplified quite a bit), acpi_remove_cmos_rtc_space_handler() can
be dropped and acpi_install_cmos_rtc_space_handler() can be made static.
Update the code as per the above.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/acpi_tad.c | 27 +++++----------------------
drivers/acpi/x86/cmos_rtc.c | 26 +++++---------------------
include/acpi/acpi_bus.h | 9 ---------
3 files changed, 10 insertions(+), 52 deletions(-)
diff --git a/drivers/acpi/acpi_tad.c b/drivers/acpi/acpi_tad.c
index 6d870d97ada6..4f5089fc023d 100644
--- a/drivers/acpi/acpi_tad.c
+++ b/drivers/acpi/acpi_tad.c
@@ -563,7 +563,6 @@ static int acpi_tad_disable_timer(struct device *dev, u32 timer_id)
static void acpi_tad_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_tad_driver_data *dd = dev_get_drvdata(dev);
device_init_wakeup(dev, false);
@@ -587,7 +586,6 @@ static void acpi_tad_remove(struct platform_device *pdev)
pm_runtime_suspend(dev);
pm_runtime_disable(dev);
- acpi_remove_cmos_rtc_space_handler(handle);
}
static int acpi_tad_probe(struct platform_device *pdev)
@@ -599,11 +597,6 @@ static int acpi_tad_probe(struct platform_device *pdev)
unsigned long long caps;
int ret;
- ret = acpi_install_cmos_rtc_space_handler(handle);
- if (ret < 0) {
- dev_info(dev, "Unable to install space handler\n");
- return -ENODEV;
- }
/*
* Initialization failure messages are mostly about firmware issues, so
* print them at the "info" level.
@@ -611,27 +604,22 @@ static int acpi_tad_probe(struct platform_device *pdev)
status = acpi_evaluate_integer(handle, "_GCP", NULL, &caps);
if (ACPI_FAILURE(status)) {
dev_info(dev, "Unable to get capabilities\n");
- ret = -ENODEV;
- goto remove_handler;
+ return -ENODEV;
}
if (!(caps & ACPI_TAD_AC_WAKE)) {
dev_info(dev, "Unsupported capabilities\n");
- ret = -ENODEV;
- goto remove_handler;
+ return -ENODEV;
}
if (!acpi_has_method(handle, "_PRW")) {
dev_info(dev, "Missing _PRW\n");
- ret = -ENODEV;
- goto remove_handler;
+ return -ENODEV;
}
dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL);
- if (!dd) {
- ret = -ENOMEM;
- goto remove_handler;
- }
+ if (!dd)
+ return -ENOMEM;
dd->capabilities = caps;
dev_set_drvdata(dev, dd);
@@ -673,11 +661,6 @@ static int acpi_tad_probe(struct platform_device *pdev)
fail:
acpi_tad_remove(pdev);
- /* Don't fallthrough because cmos rtc space handler is removed in acpi_tad_remove() */
- return ret;
-
-remove_handler:
- acpi_remove_cmos_rtc_space_handler(handle);
return ret;
}
diff --git a/drivers/acpi/x86/cmos_rtc.c b/drivers/acpi/x86/cmos_rtc.c
index a6df5b991c96..ced334e19896 100644
--- a/drivers/acpi/x86/cmos_rtc.c
+++ b/drivers/acpi/x86/cmos_rtc.c
@@ -18,13 +18,12 @@
#include "../internal.h"
static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
+ { "ACPI000E", 1 }, /* ACPI Time and Alarm Device (TAD) */
ACPI_CMOS_RTC_IDS
};
bool cmos_rtc_platform_device_present;
-static bool cmos_rtc_space_handler_present __read_mostly;
-
static acpi_status acpi_cmos_rtc_space_handler(u32 function,
acpi_physical_address address,
u32 bits, u64 *value64,
@@ -56,8 +55,9 @@ static acpi_status acpi_cmos_rtc_space_handler(u32 function,
return AE_BAD_PARAMETER;
}
-int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
+static int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
{
+ static bool cmos_rtc_space_handler_present __read_mostly;
acpi_status status;
if (cmos_rtc_space_handler_present)
@@ -76,22 +76,6 @@ int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
return 1;
}
-EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler);
-
-void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
-{
- acpi_status status;
-
- if (cmos_rtc_space_handler_present)
- return;
-
- status = acpi_remove_address_space_handler(handle,
- ACPI_ADR_SPACE_CMOS,
- acpi_cmos_rtc_space_handler);
- if (ACPI_FAILURE(status))
- pr_err("Failed to remove CMOS-RTC address space handler\n");
-}
-EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler);
static int acpi_cmos_rtc_attach(struct acpi_device *adev,
const struct acpi_device_id *id)
@@ -103,9 +87,9 @@ static int acpi_cmos_rtc_attach(struct acpi_device *adev,
return ret;
if (IS_ERR_OR_NULL(acpi_create_platform_device(adev, NULL))) {
- pr_err("Failed to create CMOS-RTC platform device\n");
+ pr_err("Failed to create a platform device for %s\n", (char *)id->id);
return 0;
- } else {
+ } else if (!id->driver_data) {
cmos_rtc_platform_device_present = true;
}
return 1;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index aad1a95e6863..be6d9032a161 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -760,8 +760,6 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev);
#ifdef CONFIG_X86
bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status);
bool acpi_quirk_skip_acpi_ac_and_battery(void);
-int acpi_install_cmos_rtc_space_handler(acpi_handle handle);
-void acpi_remove_cmos_rtc_space_handler(acpi_handle handle);
int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip);
#else
static inline bool acpi_device_override_status(struct acpi_device *adev,
@@ -773,13 +771,6 @@ static inline bool acpi_quirk_skip_acpi_ac_and_battery(void)
{
return false;
}
-static inline int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
-{
- return 1;
-}
-static inline void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
-{
-}
static inline int
acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
{
--
2.51.0
^ permalink raw reply related
* 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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox