* Re: [PATCH] cpufreq: cleanup dead code in Kconfig
From: Viresh Kumar @ 2026-03-31 7:55 UTC (permalink / raw)
To: Julian Braha; +Cc: rafael, linux-pm, linux-kernel
In-Reply-To: <20260331074242.39986-1-julianbraha@gmail.com>
On 31-03-26, 08:42, Julian Braha wrote:
> There is already an 'if CPU_FREQ' condition wrapping these config
> options, making the 'depends on' statement for each a duplicate
> dependency (dead code).
>
> I propose leaving the outer 'if CPU_FREQ...endif' and
> removing the individual 'depends on' statement from each option.
>
> This dead code was found by kconfirm, a static analysis tool for Kconfig.
>
> Signed-off-by: Julian Braha <julianbraha@gmail.com>
> ---
> drivers/cpufreq/Kconfig | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
> index 78702a08364f..db83f3365698 100644
> --- a/drivers/cpufreq/Kconfig
> +++ b/drivers/cpufreq/Kconfig
> @@ -163,7 +163,6 @@ config CPU_FREQ_GOV_ONDEMAND
>
> config CPU_FREQ_GOV_CONSERVATIVE
> tristate "'conservative' cpufreq governor"
> - depends on CPU_FREQ
> select CPU_FREQ_GOV_COMMON
> help
> 'conservative' - this driver is rather similar to the 'ondemand'
> @@ -188,7 +187,7 @@ config CPU_FREQ_GOV_CONSERVATIVE
>
> config CPU_FREQ_GOV_SCHEDUTIL
> bool "'schedutil' cpufreq policy governor"
> - depends on CPU_FREQ && SMP
> + depends on SMP
> select CPU_FREQ_GOV_ATTR_SET
> select IRQ_WORK
> help
> @@ -365,6 +364,6 @@ config ACPI_CPPC_CPUFREQ_FIE
>
> If in doubt, say N.
>
> -endif
> +endif # CPU_FREQ
>
> endmenu
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* Re: (subset) [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Bartosz Golaszewski @ 2026-03-31 7:55 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski,
Manivannan Sadhasivam
Cc: Bartosz Golaszewski, linux-serial, linux-kernel, linux-kbuild,
platform-driver-x86, linux-pci, devicetree, linux-arm-msm,
linux-bluetooth, linux-pm, Stephan Gerhold, Dmitry Baryshkov,
linux-acpi, Hans de Goede
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
On Thu, 26 Mar 2026 13:36:28 +0530, Manivannan Sadhasivam wrote:
> This series is the continuation of the series [1] that added the initial support
> for the PCIe M.2 connectors. This series extends it by adding support for Key E
> connectors. These connectors are used to connect the Wireless Connectivity
> devices such as WiFi, BT, NFC and GNSS devices to the host machine over
> interfaces such as PCIe/SDIO, USB/UART and NFC. This series adds support for
> connectors that expose PCIe interface for WiFi and UART interface for BT. Other
> interfaces are left for future improvements.
>
> [...]
Applied, thanks!
[1/8] serdev: Convert to_serdev_*() helpers to macros and use container_of_const()
https://git.kernel.org/brgl/c/e7fef85039ccdba67d97b2a09f313aceeb6691c8
[2/8] serdev: Add an API to find the serdev controller associated with the devicetree node
https://git.kernel.org/brgl/c/a2b4814190af5944b276c5fd708d95ea146106b3
[3/8] serdev: Do not return -ENODEV from of_serdev_register_devices() if external connector is used
https://git.kernel.org/brgl/c/92fa16ecad07dddc5703f7e2ff342441b04c45af
[4/8] dt-bindings: serial: Document the graph port
https://git.kernel.org/brgl/c/1785c7bc1495e4e22377edffaf0ff8c3c697647d
[5/8] dt-bindings: connector: Add PCIe M.2 Mechanical Key E connector
https://git.kernel.org/brgl/c/5970c1dafb8adbeab5f6d9a22a4ad5b1c0067888
[7/8] power: sequencing: pcie-m2: Add support for PCIe M.2 Key E connectors
https://git.kernel.org/brgl/c/0d38285a12a283e12cd589ad5bb46c6f4a8cc647
[8/8] power: sequencing: pcie-m2: Create serdev device for WCN7850 bluetooth
https://git.kernel.org/brgl/c/3f736aecbdc8e4faf2ed82c981812a6bfc76ea98
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH RESEND 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor
From: Yaxiong Tian @ 2026-03-31 8:02 UTC (permalink / raw)
To: Jie Zhan, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <5ac69894-aa0d-475f-8950-a0ff98f9fa2e@hisilicon.com>
在 2026/3/31 15:16, Jie Zhan 写道:
>
> On 3/19/2026 5:17 PM, Yaxiong Tian wrote:
>> Since devfreq_remove_governor() may clear the device's current governor
>> in certain situations, while governors actually exist independently
>> of the device, directly returning EINVAL in this case is inaccurate.
>>
>> To fix this issue, remove this check and add relevant logic for when
>> df->governor is NULL.
>>
>> Fixes: 483d557ee9a3 ("PM / devfreq: Clean up the devfreq instance name in sysfs attr")
>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>> ---
>> drivers/devfreq/devfreq.c | 15 ++++++++++++---
>> 1 file changed, 12 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>> index 0bf320123e3a..4a312f3c2421 100644
>> --- a/drivers/devfreq/devfreq.c
>> +++ b/drivers/devfreq/devfreq.c
>> @@ -1425,9 +1425,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>> char str_governor[DEVFREQ_NAME_LEN + 1];
>> const struct devfreq_governor *governor, *prev_governor;
>>
>> - if (!df->governor)
>> - return -EINVAL;
>> -
>> ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>> if (ret != 1)
>> return -EINVAL;
>> @@ -1438,6 +1435,18 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>> ret = PTR_ERR(governor);
>> goto out;
>> }
>> +
>> + if (!df->governor) {
>> + df->governor = governor;
>> + ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>> + if (ret) {
>> + dev_warn(dev, "%s: Governor %s not started(%d)\n",
>> + __func__, df->governor->name, ret);
>> + df->governor = NULL;
>> + }
>> + goto out;
>> + }
>> +
> The sequence that starts the governor, and stops, and then re-starts looks
> quite weird.
> Can you do a NULL pointer check before the IMMUTABLE flag check and
> stopping governor, rather than this?
This patch only addresses the issue raised in the commit message. As for
the original
start, stop, and then restart sequence, I haven't found any problems
with it so far.
>> if (df->governor == governor) {
>> ret = 0;
>> goto out;
^ permalink raw reply
* Re: [PATCH RESEND 4/4] PM / devfreq: Optimize error return value of governor_show()
From: Yaxiong Tian @ 2026-03-31 8:03 UTC (permalink / raw)
To: Jie Zhan, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <9f58b042-d420-4e9b-a26b-b95bc6e11fac@hisilicon.com>
在 2026/3/31 15:21, Jie Zhan 写道:
>
> On 3/19/2026 5:17 PM, Yaxiong Tian wrote:
>> When df->governor is NULL, governor_show() returns -EINVAL, which
>> confuses users.
>>
>> To fix this issue, return -ENOENT to indicate that no governor is
>> currently set for the device.
>>
>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>> ---
>> drivers/devfreq/devfreq.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>> index 4a312f3c2421..7cc60711fafd 100644
>> --- a/drivers/devfreq/devfreq.c
>> +++ b/drivers/devfreq/devfreq.c
>> @@ -1412,7 +1412,7 @@ static ssize_t governor_show(struct device *dev,
>> struct devfreq *df = to_devfreq(dev);
>>
>> if (!df->governor)
>> - return -EINVAL;
>> + return -ENOENT;
> What about -ENODEV?
I think a governor is not a device, so -ENOENT would be more appropriate.
>>
>> return sprintf(buf, "%s\n", df->governor->name);
>> }
^ permalink raw reply
* Re: [PATCH v5 1/2] thermal/qcom/lmh: support SDM670 and its CPU clusters
From: Konrad Dybcio @ 2026-03-31 8:30 UTC (permalink / raw)
To: Richard Acayan, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Amit Kucheria, Thara Gopinath,
Rafael J. Wysocki, Daniel Lezcano, Zhang Rui, Lukasz Luba,
linux-arm-msm, devicetree, linux-pm
In-Reply-To: <20260330165237.101045-2-mailingradian@gmail.com>
On 3/30/26 6:52 PM, Richard Acayan wrote:
> The LMh driver was made for Qualcomm SoCs with clusters of 4 CPUs, but
> some SoCs divide the CPUs into different sizes of clusters. In SDM670,
> the first 6 CPUs are in the little cluster and the next 2 are in the big
> cluster. Define the clusters in the match data and define the different
> cluster configuration for SDM670.
>
> Currently, this tolerates linking to any CPU in a given cluster.
>
> Signed-off-by: Richard Acayan <mailingradian@gmail.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
[...]
> + if (cpu_id < 0) {
> + dev_err(dev, "Wrong CPU id associated with LMh node\n");
> + return -EINVAL;
> + }
nit: try to use 'return dev_err_probe(dev, ret, "....") in the future
Konrad
^ permalink raw reply
* Re: [PATCH v4 1/9] dt-bindings: mfd: mt6397: Add MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-03-31 8:36 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: linux-mediatek, Fabien Parent, Val Packett, Dmitry Torokhov,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sen Chu,
Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Liam Girdwood,
Mark Brown, Louis-Alexis Eyraud, Gary Bisson, Julien Massot,
Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-gpio
In-Reply-To: <20260331-flawless-bronze-lorikeet-59a6ff@quoll>
> > - required:
> > - - compatible
>
> Not really, this affects existing ABI and might make the child schema
> being applied. Basically regulators node can be anything now.
>
> This is definitely not a binding we want. The syntax for parent schema
> when listing only compatibles is requiring this compatible. You cannot
> have here whatever empty node.
Hi, it felt quite strange to me too, but that's what I thought you
meant with your previous suggestion [1].
To keep the required attribute I would be happy to reintroduce the
compatible here, in the regulator schema and the pmic dtsi.
Before I do that and resubmit, could you please help me understand
what you meant before?
Thank you!
[1] https://lists.infradead.org/pipermail/linux-mediatek/2026-March/105060.html
--
Luca Leonardo Scorcia
l.scorcia@gmail.com
^ permalink raw reply
* Re: [PATCH v5 2/2] arm64: dts: qcom: sdm670: add thermal zones and thermal devices
From: Konrad Dybcio @ 2026-03-31 8:36 UTC (permalink / raw)
To: Richard Acayan, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Amit Kucheria, Thara Gopinath,
Rafael J. Wysocki, Daniel Lezcano, Zhang Rui, Lukasz Luba,
linux-arm-msm, devicetree, linux-pm
In-Reply-To: <20260330165237.101045-3-mailingradian@gmail.com>
On 3/30/26 6:52 PM, Richard Acayan wrote:
> Add thermal zones to safeguard from overheating to high temperatures,
> along with the thermal sensors (TSENS) and CPU frequency limits (LMh).
> The temperatures are very high, but should still be safeguard for
> devices that do not specify their own thermal zones.
>
> Signed-off-by: Richard Acayan <mailingradian@gmail.com>
> ---
[...]
> + thermal-zones {
> + aoss0-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
You can drop all polling on TSENS thermal zones - we get interrupts
for when thresholds are crossed
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: interconnect: document the RPMh Network-On-Chip interconnect in Hawi SoC
From: Krzysztof Kozlowski @ 2026-03-31 8:42 UTC (permalink / raw)
To: Vivek Aknurwar
Cc: Georgi Djakov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-arm-msm, linux-pm, devicetree, linux-kernel, Mike Tipton
In-Reply-To: <20260330-icc-hawi-v1-1-4b54a9e7d38c@oss.qualcomm.com>
On Mon, Mar 30, 2026 at 05:40:00PM -0700, Vivek Aknurwar wrote:
> Document the RPMh Network-On-Chip Interconnect of the Hawi platform.
Test your patches before you send, not after. I am not reviewing this.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 2/2] interconnect: qcom: add Hawi interconnect provider driver
From: Krzysztof Kozlowski @ 2026-03-31 8:45 UTC (permalink / raw)
To: Vivek Aknurwar
Cc: Georgi Djakov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-arm-msm, linux-pm, devicetree, linux-kernel, Mike Tipton
In-Reply-To: <20260330-icc-hawi-v1-2-4b54a9e7d38c@oss.qualcomm.com>
On Mon, Mar 30, 2026 at 05:40:01PM -0700, Vivek Aknurwar wrote:
> Add driver for the Qualcomm interconnect buses found in Hawi
> based platforms. The topology consists of several NoCs that are
> controlled by a remote processor that collects the aggregated
> bandwidth for each master-slave pairs.
>
> Signed-off-by: Vivek Aknurwar <vivek.aknurwar@oss.qualcomm.com>
> ---
> drivers/interconnect/qcom/Kconfig | 9 +
> drivers/interconnect/qcom/Makefile | 2 +
> drivers/interconnect/qcom/hawi.c | 2021 ++++++++++++++++++++++++++++++++++++
Can you finally stop sending code based on downstream?
You just made same mistakes I have been fixing for more than 3 years
now.
NAK
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 2/2] interconnect: qcom: add Hawi interconnect provider driver
From: Krzysztof Kozlowski @ 2026-03-31 8:48 UTC (permalink / raw)
To: Vivek Aknurwar
Cc: Georgi Djakov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-arm-msm, linux-pm, devicetree, linux-kernel, Mike Tipton
In-Reply-To: <20260331-sly-centipede-of-opportunity-590509@quoll>
On 31/03/2026 10:45, Krzysztof Kozlowski wrote:
> On Mon, Mar 30, 2026 at 05:40:01PM -0700, Vivek Aknurwar wrote:
>> Add driver for the Qualcomm interconnect buses found in Hawi
>> based platforms. The topology consists of several NoCs that are
>> controlled by a remote processor that collects the aggregated
>> bandwidth for each master-slave pairs.
>>
>> Signed-off-by: Vivek Aknurwar <vivek.aknurwar@oss.qualcomm.com>
>> ---
>> drivers/interconnect/qcom/Kconfig | 9 +
>> drivers/interconnect/qcom/Makefile | 2 +
>> drivers/interconnect/qcom/hawi.c | 2021 ++++++++++++++++++++++++++++++++++++
>
> Can you finally stop sending code based on downstream?
>
> You just made same mistakes I have been fixing for more than 3 years
> now.
Oh, no, I was wrong - my grep pattern was incomplete. The code is
finally fixed!
Sorry for the noise.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH RESEND 1/4] PM / devfreq: Fix possible null pointer issue in devfreq_add_governor()
From: Jie Zhan @ 2026-03-31 8:49 UTC (permalink / raw)
To: Yaxiong Tian, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <aa7ee42d-0685-4a70-a084-bf0bdfa82e4a@kylinos.cn>
On 3/31/2026 3:49 PM, Yaxiong Tian wrote:
>
> 在 2026/3/31 15:04, Jie Zhan 写道:
>>
>> On 3/19/2026 5:16 PM, Yaxiong Tian wrote:
>>> When a user removes a governor using devfreq_remove_governor(), if
>>> the current device is using this governor, devfreq->governor will
>>> be set to NULL. When the user registers any governor
>>> using devfreq_add_governor(), since devfreq->governor is NULL, a
>>> null pointer error occurs in strncmp().
>>>
>>> For example: A user loads the userspace gov through a module, then
>>> a device selects userspace. When unloading the userspace module and
>>> then loading it again, the null pointer error occurs:
>>>
>>> Unable to handle kernel NULL pointer dereference at virtual address
>>> 0000000000000010
>>> Mem abort info:
>>> ESR = 0x0000000096000004
>>> EC = 0x25: DABT (current EL), IL = 32 bits
>>> *******************skip *********************
>>> Call trace:
>>> __pi_strncmp+0x20/0x1b8
>>> devfreq_userspace_init+0x1c/0xff8 [governor_userspace]
>>> do_one_initcall+0x4c/0x278
>>> do_init_module+0x5c/0x218
>>> load_module+0x1f1c/0x1fc8
>>> init_module_from_file+0x8c/0xd0
>>> __arm64_sys_finit_module+0x220/0x3d8
>>> invoke_syscall+0x48/0x110
>>> el0_svc_common.constprop.0+0xbc/0xe8
>>> do_el0_svc+0x20/0x30
>>> el0_svc+0x24/0xb8
>>> el0t_64_sync_handler+0xb8/0xc0
>>> el0t_64_sync+0x14c/0x150
>>>
>>> To fix this issue, modify the relevant logic in devfreq_add_governor():
>>> Only check whether the new governor matches the existing one when
>>> devfreq->governor exists. When devfreq->governor is NULL, directly
>>> select the new governor and perform the DEVFREQ_GOV_START operation.
>>>
>>> Fixes: 1b5c1be2c88e ("PM / devfreq: map devfreq drivers to governor using name")
>>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>>> ---
>>> drivers/devfreq/devfreq.c | 24 +++++++++++-------------
>>> 1 file changed, 11 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>> index 54f0b18536db..63ce6e25abe2 100644
>>> --- a/drivers/devfreq/devfreq.c
>>> +++ b/drivers/devfreq/devfreq.c
>>> @@ -1288,23 +1288,21 @@ int devfreq_add_governor(struct devfreq_governor *governor)
>>> int ret = 0;
>>> struct device *dev = devfreq->dev.parent;
>>> - if (!strncmp(devfreq->governor->name, governor->name,
>>> + if (devfreq->governor && !strncmp(devfreq->governor->name, governor->name,
>>> DEVFREQ_NAME_LEN)) {
>> Probaly do:
>> if (!devfreq->governor)
>> continue;
>> so as to keep the line short and the "else if (!devfreq->governor) {" below
>> can be removed.
> If that's the case, a dev without a governor would not be able to add a new governor.
It's not about adding.
The whole point here (the block inside list_for_each_entry()) is a very
rare safe check that you're adding a governor of the same name of a
governor used by an existing devfreq device. If so, stop the old one and
start the new one.
Therefore, it doesn't have to start/restart it if devfreq->governor is
NULL.
>>
>> and also:
>> if (!strncmp(devfreq->governor->name, governor->name,
>> DEVFREQ_NAME_LEN))
>> continue;
>> so we don't have to indent that much.
>
> Currently, governor->name can be set arbitrarily, so duplicate names are possible.
>
> But they could still be two different governors. Leaving it unchanged seems fine to me.
>
Sorry, my mistake!
I mean:
if (strncmp(devfreq->governor->name, governor->name,
DEVFREQ_NAME_LEN))
continue;
>>
>>> /* The following should never occur */
>>> - if (devfreq->governor) {
>>> + dev_warn(dev,
>>> + "%s: Governor %s already present\n",
>>> + __func__, devfreq->governor->name);
>>> + ret = devfreq->governor->event_handler(devfreq,
>>> + DEVFREQ_GOV_STOP, NULL);
>>> + if (ret) {
>>> dev_warn(dev,
>>> - "%s: Governor %s already present\n",
>>> - __func__, devfreq->governor->name);
>>> - ret = devfreq->governor->event_handler(devfreq,
>>> - DEVFREQ_GOV_STOP, NULL);
>>> - if (ret) {
>>> - dev_warn(dev,
>>> - "%s: Governor %s stop = %d\n",
>>> - __func__,
>>> - devfreq->governor->name, ret);
>>> - }
>>> - /* Fall through */
>>> + "%s: Governor %s stop = %d\n",
>>> + __func__,
>>> + devfreq->governor->name, ret);
>>> }
>>> + } else if (!devfreq->governor) {
>>> devfreq->governor = governor;
>>> ret = devfreq->governor->event_handler(devfreq,
>>> DEVFREQ_GOV_START, NULL);
^ permalink raw reply
* Re: [PATCH RESEND 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor
From: Jie Zhan @ 2026-03-31 8:53 UTC (permalink / raw)
To: Yaxiong Tian, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <ebee5d1c-f42f-4b51-aa98-2a015ee61706@kylinos.cn>
On 3/31/2026 4:02 PM, Yaxiong Tian wrote:
>
> 在 2026/3/31 15:16, Jie Zhan 写道:
>>
>> On 3/19/2026 5:17 PM, Yaxiong Tian wrote:
>>> Since devfreq_remove_governor() may clear the device's current governor
>>> in certain situations, while governors actually exist independently
>>> of the device, directly returning EINVAL in this case is inaccurate.
>>>
>>> To fix this issue, remove this check and add relevant logic for when
>>> df->governor is NULL.
>>>
>>> Fixes: 483d557ee9a3 ("PM / devfreq: Clean up the devfreq instance name in sysfs attr")
>>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>>> ---
>>> drivers/devfreq/devfreq.c | 15 ++++++++++++---
>>> 1 file changed, 12 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>> index 0bf320123e3a..4a312f3c2421 100644
>>> --- a/drivers/devfreq/devfreq.c
>>> +++ b/drivers/devfreq/devfreq.c
>>> @@ -1425,9 +1425,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>> char str_governor[DEVFREQ_NAME_LEN + 1];
>>> const struct devfreq_governor *governor, *prev_governor;
>>> - if (!df->governor)
>>> - return -EINVAL;
>>> -
>>> ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>>> if (ret != 1)
>>> return -EINVAL;
>>> @@ -1438,6 +1435,18 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>> ret = PTR_ERR(governor);
>>> goto out;
>>> }
>>> +
>>> + if (!df->governor) {
>>> + df->governor = governor;
>>> + ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>>> + if (ret) {
>>> + dev_warn(dev, "%s: Governor %s not started(%d)\n",
>>> + __func__, df->governor->name, ret);
>>> + df->governor = NULL;
>>> + }
>>> + goto out;
>>> + }
>>> +
>> The sequence that starts the governor, and stops, and then re-starts looks
>> quite weird.
>> Can you do a NULL pointer check before the IMMUTABLE flag check and
>> stopping governor, rather than this?
>
> This patch only addresses the issue raised in the commit message. As for the original
>
> start, stop, and then restart sequence, I haven't found any problems with it so far.
>
You just added the first 'start' here.
Please see the other process in governor_store().
>>> if (df->governor == governor) {
>>> ret = 0;
>>> goto out;
^ permalink raw reply
* Re: (subset) [PATCH v8 00/10] pmdomain: samsung: add support for Google GS101
From: Ulf Hansson @ 2026-03-31 9:01 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Alim Akhtar, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
Liam Girdwood, Mark Brown, André Draszik, Peter Griffin,
Tudor Ambarus, Juan Yescas, Will McVicker, kernel-team,
linux-arm-kernel, linux-samsung-soc, devicetree, linux-kernel,
linux-pm, Marek Szyprowski
In-Reply-To: <c4d6b758-474b-409d-b553-fa4ec1df494e@kernel.org>
On Mon, 30 Mar 2026 at 15:38, Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On 30/03/2026 15:30, Ulf Hansson wrote:
> >
> > Usually we want bindings to go along with their respective drivers on
> > a subsystem basis.
> >
> > Both patch2 and patch4 updates DT bindings for the power-domain providers.
>
> Patch 2 yes. Patch 4 not. That's why I did not take patch 2.
>
> >
> > Why shouldn't the bindings go along with the driver changes here?
>
> Patch #2 is pmdomain, so with pmdomain drivers thus your tree. Patch #4
> is not pmdomain, so not with pmdomain drivers, so not your tree... At
> least I do not see any pmdomain parts in that patch #4. It's a Samsung
> SoC PMU driver and none of further driver patches touch that PMU driver.
Yes, you are right that the PMU driver isn't touched.
Although, the PMU DT description added in patch3 and extended in
patch4, allows power-domain providers to be described in its child
nodes. Those child nodes use the same compatible string as the
power-domain providers described in patch2.
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH v3] cpufreq/amd-pstate: Cache the max frequency in cpudata
From: Gautham R. Shenoy @ 2026-03-31 9:12 UTC (permalink / raw)
To: Mario Limonciello
Cc: Perry Yuan, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK,
Mario Limonciello (AMD)
In-Reply-To: <20260326193620.649441-1-mario.limonciello@amd.com>
Hello Mario,
On Thu, Mar 26, 2026 at 02:36:20PM -0500, Mario Limonciello wrote:
> From: "Mario Limonciello (AMD)" <superm1@kernel.org>
>
> The value of maximum frequency is fixed and never changes. Doing
> calculations every time based off of perf is unnecessary.
>
> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
This one looks good to me. Thanks for fixing this.
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
--
Thanks and Regards
gautham.
> ---
> v3:
> * rebase on Gautham's CPPC perf priority series
> * add kdoc
> ---
> drivers/cpufreq/amd-pstate.c | 27 +++++++++------------------
> drivers/cpufreq/amd-pstate.h | 2 ++
> 2 files changed, 11 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index ed9fd4155a256..f207252eb5f5f 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -826,15 +826,13 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
> static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on)
> {
> struct amd_cpudata *cpudata = policy->driver_data;
> - union perf_cached perf = READ_ONCE(cpudata->perf);
> - u32 nominal_freq, max_freq;
> + u32 nominal_freq;
> int ret = 0;
>
> nominal_freq = READ_ONCE(cpudata->nominal_freq);
> - max_freq = perf_to_freq(perf, cpudata->nominal_freq, perf.highest_perf);
>
> if (on)
> - policy->cpuinfo.max_freq = max_freq;
> + policy->cpuinfo.max_freq = cpudata->max_freq;
> else if (policy->cpuinfo.max_freq > nominal_freq)
> policy->cpuinfo.max_freq = nominal_freq;
>
> @@ -1021,13 +1019,15 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
>
> WRITE_ONCE(cpudata->nominal_freq, nominal_freq);
>
> + /* max_freq is calculated according to (nominal_freq * highest_perf)/nominal_perf */
> max_freq = perf_to_freq(perf, nominal_freq, perf.highest_perf);
> + WRITE_ONCE(cpudata->max_freq, max_freq);
> +
> lowest_nonlinear_freq = perf_to_freq(perf, nominal_freq, perf.lowest_nonlinear_perf);
> WRITE_ONCE(cpudata->lowest_nonlinear_freq, lowest_nonlinear_freq);
>
> /**
> * Below values need to be initialized correctly, otherwise driver will fail to load
> - * max_freq is calculated according to (nominal_freq * highest_perf)/nominal_perf
> * lowest_nonlinear_freq is a value between [min_freq, nominal_freq]
> * Check _CPC in ACPI table objects if any values are incorrect
> */
> @@ -1090,9 +1090,7 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
> policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf,
> cpudata->nominal_freq,
> perf.lowest_perf);
> - policy->cpuinfo.max_freq = policy->max = perf_to_freq(perf,
> - cpudata->nominal_freq,
> - perf.highest_perf);
> + policy->cpuinfo.max_freq = policy->max = cpudata->max_freq;
>
> policy->driver_data = cpudata;
> ret = amd_pstate_cppc_enable(policy);
> @@ -1167,14 +1165,9 @@ static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
> static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy,
> char *buf)
> {
> - struct amd_cpudata *cpudata;
> - union perf_cached perf;
> -
> - cpudata = policy->driver_data;
> - perf = READ_ONCE(cpudata->perf);
> + struct amd_cpudata *cpudata = policy->driver_data;
>
> - return sysfs_emit(buf, "%u\n",
> - perf_to_freq(perf, cpudata->nominal_freq, perf.highest_perf));
> + return sysfs_emit(buf, "%u\n", cpudata->max_freq);
> }
>
> static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *policy,
> @@ -1702,9 +1695,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
> policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf,
> cpudata->nominal_freq,
> perf.lowest_perf);
> - policy->cpuinfo.max_freq = policy->max = perf_to_freq(perf,
> - cpudata->nominal_freq,
> - perf.highest_perf);
> + policy->cpuinfo.max_freq = policy->max = cpudata->max_freq;
> policy->driver_data = cpudata;
>
> ret = amd_pstate_cppc_enable(policy);
> diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
> index faead0b19a8a4..32b8b26ce388f 100644
> --- a/drivers/cpufreq/amd-pstate.h
> +++ b/drivers/cpufreq/amd-pstate.h
> @@ -73,6 +73,7 @@ struct amd_aperf_mperf {
> * @min_limit_freq: Cached value of policy->min (in khz)
> * @max_limit_freq: Cached value of policy->max (in khz)
> * @nominal_freq: the frequency (in khz) that mapped to nominal_perf
> + * @max_freq: in ideal conditions the maximum frequency (in khz) possible frequency
> * @lowest_nonlinear_freq: the frequency (in khz) that mapped to lowest_nonlinear_perf
> * @floor_freq: Cached value of the user requested floor_freq
> * @cur: Difference of Aperf/Mperf/tsc count between last and current sample
> @@ -103,6 +104,7 @@ struct amd_cpudata {
> u32 min_limit_freq;
> u32 max_limit_freq;
> u32 nominal_freq;
> + u32 max_freq;
> u32 lowest_nonlinear_freq;
> u32 floor_freq;
>
> --
> 2.53.0
>
^ permalink raw reply
* Re: [PATCH RESEND 1/4] PM / devfreq: Fix possible null pointer issue in devfreq_add_governor()
From: Yaxiong Tian @ 2026-03-31 9:17 UTC (permalink / raw)
To: Jie Zhan, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <a7c1c3ce-7938-4dcf-83be-32cf4aceb965@hisilicon.com>
在 2026/3/31 16:49, Jie Zhan 写道:
>
> On 3/31/2026 3:49 PM, Yaxiong Tian wrote:
>> 在 2026/3/31 15:04, Jie Zhan 写道:
>>> On 3/19/2026 5:16 PM, Yaxiong Tian wrote:
>>>> When a user removes a governor using devfreq_remove_governor(), if
>>>> the current device is using this governor, devfreq->governor will
>>>> be set to NULL. When the user registers any governor
>>>> using devfreq_add_governor(), since devfreq->governor is NULL, a
>>>> null pointer error occurs in strncmp().
>>>>
>>>> For example: A user loads the userspace gov through a module, then
>>>> a device selects userspace. When unloading the userspace module and
>>>> then loading it again, the null pointer error occurs:
>>>>
>>>> Unable to handle kernel NULL pointer dereference at virtual address
>>>> 0000000000000010
>>>> Mem abort info:
>>>> ESR = 0x0000000096000004
>>>> EC = 0x25: DABT (current EL), IL = 32 bits
>>>> *******************skip *********************
>>>> Call trace:
>>>> __pi_strncmp+0x20/0x1b8
>>>> devfreq_userspace_init+0x1c/0xff8 [governor_userspace]
>>>> do_one_initcall+0x4c/0x278
>>>> do_init_module+0x5c/0x218
>>>> load_module+0x1f1c/0x1fc8
>>>> init_module_from_file+0x8c/0xd0
>>>> __arm64_sys_finit_module+0x220/0x3d8
>>>> invoke_syscall+0x48/0x110
>>>> el0_svc_common.constprop.0+0xbc/0xe8
>>>> do_el0_svc+0x20/0x30
>>>> el0_svc+0x24/0xb8
>>>> el0t_64_sync_handler+0xb8/0xc0
>>>> el0t_64_sync+0x14c/0x150
>>>>
>>>> To fix this issue, modify the relevant logic in devfreq_add_governor():
>>>> Only check whether the new governor matches the existing one when
>>>> devfreq->governor exists. When devfreq->governor is NULL, directly
>>>> select the new governor and perform the DEVFREQ_GOV_START operation.
>>>>
>>>> Fixes: 1b5c1be2c88e ("PM / devfreq: map devfreq drivers to governor using name")
>>>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>>>> ---
>>>> drivers/devfreq/devfreq.c | 24 +++++++++++-------------
>>>> 1 file changed, 11 insertions(+), 13 deletions(-)
>>>>
>>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>>> index 54f0b18536db..63ce6e25abe2 100644
>>>> --- a/drivers/devfreq/devfreq.c
>>>> +++ b/drivers/devfreq/devfreq.c
>>>> @@ -1288,23 +1288,21 @@ int devfreq_add_governor(struct devfreq_governor *governor)
>>>> int ret = 0;
>>>> struct device *dev = devfreq->dev.parent;
>>>> - if (!strncmp(devfreq->governor->name, governor->name,
>>>> + if (devfreq->governor && !strncmp(devfreq->governor->name, governor->name,
>>>> DEVFREQ_NAME_LEN)) {
>>> Probaly do:
>>> if (!devfreq->governor)
>>> continue;
>>> so as to keep the line short and the "else if (!devfreq->governor) {" below
>>> can be removed.
>> If that's the case, a dev without a governor would not be able to add a new governor.
> It's not about adding.
>
> The whole point here (the block inside list_for_each_entry()) is a very
> rare safe check that you're adding a governor of the same name of a
> governor used by an existing devfreq device. If so, stop the old one and
> start the new one.
>
> Therefore, it doesn't have to start/restart it if devfreq->governor is
> NULL.
In the current patch, it directly start when devfreq->governor is NULL,
and only follows the same-name logic you mentioned when it is non-NULL.
There isn't the issue you mentioned.
>>> and also:
>>> if (!strncmp(devfreq->governor->name, governor->name,
>>> DEVFREQ_NAME_LEN))
>>> continue;
>>> so we don't have to indent that much.
>> Currently, governor->name can be set arbitrarily, so duplicate names are possible.
>>
>> But they could still be two different governors. Leaving it unchanged seems fine to me.
>>
> Sorry, my mistake!
>
> I mean:
> if (strncmp(devfreq->governor->name, governor->name,
> DEVFREQ_NAME_LEN))
> continue;
>
>>>> /* The following should never occur */
>>>> - if (devfreq->governor) {
>>>> + dev_warn(dev,
>>>> + "%s: Governor %s already present\n",
>>>> + __func__, devfreq->governor->name);
>>>> + ret = devfreq->governor->event_handler(devfreq,
>>>> + DEVFREQ_GOV_STOP, NULL);
>>>> + if (ret) {
>>>> dev_warn(dev,
>>>> - "%s: Governor %s already present\n",
>>>> - __func__, devfreq->governor->name);
>>>> - ret = devfreq->governor->event_handler(devfreq,
>>>> - DEVFREQ_GOV_STOP, NULL);
>>>> - if (ret) {
>>>> - dev_warn(dev,
>>>> - "%s: Governor %s stop = %d\n",
>>>> - __func__,
>>>> - devfreq->governor->name, ret);
>>>> - }
>>>> - /* Fall through */
>>>> + "%s: Governor %s stop = %d\n",
>>>> + __func__,
>>>> + devfreq->governor->name, ret);
>>>> }
>>>> + } else if (!devfreq->governor) {
>>>> devfreq->governor = governor;
>>>> ret = devfreq->governor->event_handler(devfreq,
>>>> DEVFREQ_GOV_START, NULL);
^ permalink raw reply
* Re: [PATCH RESEND 1/4] PM / devfreq: Fix possible null pointer issue in devfreq_add_governor()
From: Jie Zhan @ 2026-03-31 9:28 UTC (permalink / raw)
To: Yaxiong Tian, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <d5853c28-fd17-439b-b4c2-c3ae949f7636@kylinos.cn>
On 3/31/2026 5:17 PM, Yaxiong Tian wrote:
>
> 在 2026/3/31 16:49, Jie Zhan 写道:
>>
>> On 3/31/2026 3:49 PM, Yaxiong Tian wrote:
>>> 在 2026/3/31 15:04, Jie Zhan 写道:
>>>> On 3/19/2026 5:16 PM, Yaxiong Tian wrote:
>>>>> When a user removes a governor using devfreq_remove_governor(), if
>>>>> the current device is using this governor, devfreq->governor will
>>>>> be set to NULL. When the user registers any governor
>>>>> using devfreq_add_governor(), since devfreq->governor is NULL, a
>>>>> null pointer error occurs in strncmp().
>>>>>
>>>>> For example: A user loads the userspace gov through a module, then
>>>>> a device selects userspace. When unloading the userspace module and
>>>>> then loading it again, the null pointer error occurs:
>>>>>
>>>>> Unable to handle kernel NULL pointer dereference at virtual address
>>>>> 0000000000000010
>>>>> Mem abort info:
>>>>> ESR = 0x0000000096000004
>>>>> EC = 0x25: DABT (current EL), IL = 32 bits
>>>>> *******************skip *********************
>>>>> Call trace:
>>>>> __pi_strncmp+0x20/0x1b8
>>>>> devfreq_userspace_init+0x1c/0xff8 [governor_userspace]
>>>>> do_one_initcall+0x4c/0x278
>>>>> do_init_module+0x5c/0x218
>>>>> load_module+0x1f1c/0x1fc8
>>>>> init_module_from_file+0x8c/0xd0
>>>>> __arm64_sys_finit_module+0x220/0x3d8
>>>>> invoke_syscall+0x48/0x110
>>>>> el0_svc_common.constprop.0+0xbc/0xe8
>>>>> do_el0_svc+0x20/0x30
>>>>> el0_svc+0x24/0xb8
>>>>> el0t_64_sync_handler+0xb8/0xc0
>>>>> el0t_64_sync+0x14c/0x150
>>>>>
>>>>> To fix this issue, modify the relevant logic in devfreq_add_governor():
>>>>> Only check whether the new governor matches the existing one when
>>>>> devfreq->governor exists. When devfreq->governor is NULL, directly
>>>>> select the new governor and perform the DEVFREQ_GOV_START operation.
>>>>>
>>>>> Fixes: 1b5c1be2c88e ("PM / devfreq: map devfreq drivers to governor using name")
>>>>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>>>>> ---
>>>>> drivers/devfreq/devfreq.c | 24 +++++++++++-------------
>>>>> 1 file changed, 11 insertions(+), 13 deletions(-)
>>>>>
>>>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>>>> index 54f0b18536db..63ce6e25abe2 100644
>>>>> --- a/drivers/devfreq/devfreq.c
>>>>> +++ b/drivers/devfreq/devfreq.c
>>>>> @@ -1288,23 +1288,21 @@ int devfreq_add_governor(struct devfreq_governor *governor)
>>>>> int ret = 0;
>>>>> struct device *dev = devfreq->dev.parent;
>>>>> - if (!strncmp(devfreq->governor->name, governor->name,
>>>>> + if (devfreq->governor && !strncmp(devfreq->governor->name, governor->name,
>>>>> DEVFREQ_NAME_LEN)) {
>>>> Probaly do:
>>>> if (!devfreq->governor)
>>>> continue;
>>>> so as to keep the line short and the "else if (!devfreq->governor) {" below
>>>> can be removed.
>>> If that's the case, a dev without a governor would not be able to add a new governor.
>> It's not about adding.
>>
>> The whole point here (the block inside list_for_each_entry()) is a very
>> rare safe check that you're adding a governor of the same name of a
>> governor used by an existing devfreq device. If so, stop the old one and
>> start the new one.
>>
>> Therefore, it doesn't have to start/restart it if devfreq->governor is
>> NULL.
> In the current patch, it directly start when devfreq->governor is NULL, and only follows the same-name logic you mentioned when it is non-NULL.
>
> There isn't the issue you mentioned.
>
Ok, so create_sysfs_files() is skipped...
For example, setting 'userspace' as the governor won't create its belonging
files.
I'd recommend sticking with the existing logic here and avoid adding a new
block."
>>>> and also:
>>>> if (!strncmp(devfreq->governor->name, governor->name,
>>>> DEVFREQ_NAME_LEN))
>>>> continue;
>>>> so we don't have to indent that much.
>>> Currently, governor->name can be set arbitrarily, so duplicate names are possible.
>>>
>>> But they could still be two different governors. Leaving it unchanged seems fine to me.
>>>
>> Sorry, my mistake!
>>
>> I mean:
>> if (strncmp(devfreq->governor->name, governor->name,
>> DEVFREQ_NAME_LEN))
>> continue;
>>
>>>>> /* The following should never occur */
>>>>> - if (devfreq->governor) {
>>>>> + dev_warn(dev,
>>>>> + "%s: Governor %s already present\n",
>>>>> + __func__, devfreq->governor->name);
>>>>> + ret = devfreq->governor->event_handler(devfreq,
>>>>> + DEVFREQ_GOV_STOP, NULL);
>>>>> + if (ret) {
>>>>> dev_warn(dev,
>>>>> - "%s: Governor %s already present\n",
>>>>> - __func__, devfreq->governor->name);
>>>>> - ret = devfreq->governor->event_handler(devfreq,
>>>>> - DEVFREQ_GOV_STOP, NULL);
>>>>> - if (ret) {
>>>>> - dev_warn(dev,
>>>>> - "%s: Governor %s stop = %d\n",
>>>>> - __func__,
>>>>> - devfreq->governor->name, ret);
>>>>> - }
>>>>> - /* Fall through */
>>>>> + "%s: Governor %s stop = %d\n",
>>>>> + __func__,
>>>>> + devfreq->governor->name, ret);
>>>>> }
>>>>> + } else if (!devfreq->governor) {
>>>>> devfreq->governor = governor;
>>>>> ret = devfreq->governor->event_handler(devfreq,
>>>>> DEVFREQ_GOV_START, NULL);
^ permalink raw reply
* Re: [PATCH v2] thermal: core: Address thermal zone removal races with resume
From: Lukasz Luba @ 2026-03-31 9:28 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Daniel Lezcano, Mauricio Faria de Oliveira, LKML, Linux PM
In-Reply-To: <CAJZ5v0i82o40kS8=KsWjpB1QaCWLTrk9jmM8ZymW_tdz6b0sRA@mail.gmail.com>
On 3/30/26 12:41, Rafael J. Wysocki wrote:
> On Mon, Mar 30, 2026 at 11:14 AM Lukasz Luba <lukasz.luba@arm.com> wrote:
>>
>>
>>
>> On 3/27/26 09:49, Rafael J. Wysocki wrote:
>>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>>
>>> Since thermal_zone_pm_complete() and thermal_zone_device_resume()
>>> re-initialize the poll_queue delayed work for the given thermal zone,
>>> the cancel_delayed_work_sync() in thermal_zone_device_unregister()
>>> may miss some already running work items and the thermal zone may
>>> be freed prematurely [1].
>>>
>>> There are two failing scenarios that both start with
>>> running thermal_pm_notify_complete() right before invoking
>>> thermal_zone_device_unregister() for one of the thermal zones.
>>>
>>> In the first scenario, there is a work item already running for
>>> the given thermal zone when thermal_pm_notify_complete() calls
>>> thermal_zone_pm_complete() for that thermal zone and it continues to
>>> run when thermal_zone_device_unregister() starts. Since the poll_queue
>>> delayed work has been re-initialized by thermal_pm_notify_complete(), the
>>> running work item will be missed by the cancel_delayed_work_sync() in
>>> thermal_zone_device_unregister() and if it continues to run past the
>>> freeing of the thermal zone object, a use-after-free will occur.
>>>
>>> In the second scenario, thermal_zone_device_resume() queued up by
>>> thermal_pm_notify_complete() runs right after the thermal_zone_exit()
>>> called by thermal_zone_device_unregister() has returned. The poll_queue
>>> delayed work is re-initialized by it before cancel_delayed_work_sync() is
>>> called by thermal_zone_device_unregister(), so it may continue to run
>>> after the freeing of the thermal zone object, which also leads to a
>>> use-after-free.
>>>
>>> Address the first failing scenario by ensuring that no thermal work
>>> items will be running when thermal_pm_notify_complete() is called.
>>> For this purpose, first move the cancel_delayed_work() call from
>>> thermal_zone_pm_complete() to thermal_zone_pm_prepare() to prevent
>>> new work from entering the workqueue going forward. Next, switch
>>> over to using a dedicated workqueue for thermal events and update
>>> the code in thermal_pm_notify() to flush that workqueue after
>>> thermal_pm_notify_prepare() has returned which will take care of
>>> all leftover thermal work already on the workqueue (that leftover
>>> work would do nothing useful anyway because all of the thermal zones
>>> have been flagged as suspended).
>>>
>>> The second failing scenario is addressed by adding a tz->state check
>>> to thermal_zone_device_resume() to prevent it from re-initializing
>>> the poll_queue delayed work if the thermal zone is going away.
>>>
>>> Note that the above changes will also facilitate relocating the suspend
>>> and resume of thermal zones closer to the suspend and resume of devices,
>>> respectively.
>>>
>>> Fixes: 5a5efdaffda5 ("thermal: core: Resume thermal zones asynchronously")
>>> Reported-by: Mauricio Faria de Oliveira <mfo@igalia.com>
>>> Closes: https://lore.kernel.org/linux-pm/20260324-thermal-core-uaf-init_delayed_work-v1-1-6611ae76a8a1@igalia.com/ [1]
>>> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>> ---
>>>
>>> v1 -> v2: Return -ENOMEM from thermal_init() when the workqueue allocation
>>> fails (Sashiko)
>>>
>>> Lukasz, Daniel, I'm quite confident about this patch, but I would appreciate
>>> your feedback.
>>
>> My apologies for delay...
>>
>>>
>>> ---
>>> drivers/thermal/thermal_core.c | 31 ++++++++++++++++++++++++++-----
>>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>>
>>> --- a/drivers/thermal/thermal_core.c
>>> +++ b/drivers/thermal/thermal_core.c
>>> @@ -42,6 +42,8 @@ static struct thermal_governor *def_gove
>>>
>>> static bool thermal_pm_suspended;
>>>
>>> +static struct workqueue_struct *thermal_wq __ro_after_init;
>>> +
>>> /*
>>> * Governor section: set of functions to handle thermal governors
>>> *
>>> @@ -314,7 +316,7 @@ static void thermal_zone_device_set_poll
>>> if (delay > HZ)
>>> delay = round_jiffies_relative(delay);
>>>
>>> - mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, delay);
>>> + mod_delayed_work(thermal_wq, &tz->poll_queue, delay);
>>> }
>>>
>>> static void thermal_zone_recheck(struct thermal_zone_device *tz, int error)
>>> @@ -1795,6 +1797,10 @@ static void thermal_zone_device_resume(s
>>>
>>> guard(thermal_zone)(tz);
>>>
>>> + /* If the thermal zone is going away, there's nothing to do. */
>>> + if (tz->state & TZ_STATE_FLAG_EXIT)
>>> + return;
>>> +
>>> tz->state &= ~(TZ_STATE_FLAG_SUSPENDED | TZ_STATE_FLAG_RESUMING);
>>>
>>> thermal_debug_tz_resume(tz);
>>> @@ -1825,6 +1831,9 @@ static void thermal_zone_pm_prepare(stru
>>> }
>>>
>>> tz->state |= TZ_STATE_FLAG_SUSPENDED;
>>> +
>>> + /* Prevent new work from getting to the workqueue subsequently. */
>>> + cancel_delayed_work(&tz->poll_queue);
>>> }
>>>
>>> static void thermal_pm_notify_prepare(void)
>>> @@ -1843,8 +1852,6 @@ static void thermal_zone_pm_complete(str
>>> {
>>> guard(thermal_zone)(tz);
>>>
>>> - cancel_delayed_work(&tz->poll_queue);
>>> -
>>> reinit_completion(&tz->resume);
>>> tz->state |= TZ_STATE_FLAG_RESUMING;
>>>
>>> @@ -1854,7 +1861,7 @@ static void thermal_zone_pm_complete(str
>>> */
>>> INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_resume);
>>> /* Queue up the work without a delay. */
>>> - mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, 0);
>>> + mod_delayed_work(thermal_wq, &tz->poll_queue, 0);
>>> }
>>>
>>> static void thermal_pm_notify_complete(void)
>>> @@ -1877,6 +1884,11 @@ static int thermal_pm_notify(struct noti
>>> case PM_RESTORE_PREPARE:
>>> case PM_SUSPEND_PREPARE:
>>> thermal_pm_notify_prepare();
>>> + /*
>>> + * Allow any leftover thermal work items already on the
>>> + * worqueue to complete so they don't get in the way later.
>>> + */
>>> + flush_workqueue(thermal_wq);
>>> break;
>>> case PM_POST_HIBERNATION:
>>> case PM_POST_RESTORE:
>>> @@ -1909,9 +1921,16 @@ static int __init thermal_init(void)
>>> if (result)
>>> goto error;
>>>
>>> + thermal_wq = alloc_workqueue("thermal_events",
>>> + WQ_FREEZABLE | WQ_POWER_EFFICIENT | WQ_PERCPU, 0);
>>
>>
>> Why we need those workqueue instances per-cpu?
>
> That's to limit the changes in this fix to what's needed to address
> the problem at hand.
>
> The previously used workqueue was also per-CPU and freezable.
>
>> It isn't a concurrent work, only one CPU can manage the cpufreq domain.
>>
>> I would drop that flag and allow to have single instance and migrate
>> between cpus (to not wake up the one which queued the work).
>
> I have a separate patch for that on top of this one, will post it later.
>
> Let's avoid mixing fixes with changes that aren't directly related to them.
Thanks Rafael for clarification. With that in mind feel free to
add:
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
^ permalink raw reply
* Re: [PATCH RESEND 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor
From: Yaxiong Tian @ 2026-03-31 9:30 UTC (permalink / raw)
To: Jie Zhan, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <d6c69fc9-d504-4c62-8181-f531276c7443@hisilicon.com>
在 2026/3/31 16:53, Jie Zhan 写道:
>
> On 3/31/2026 4:02 PM, Yaxiong Tian wrote:
>> 在 2026/3/31 15:16, Jie Zhan 写道:
>>> On 3/19/2026 5:17 PM, Yaxiong Tian wrote:
>>>> Since devfreq_remove_governor() may clear the device's current governor
>>>> in certain situations, while governors actually exist independently
>>>> of the device, directly returning EINVAL in this case is inaccurate.
>>>>
>>>> To fix this issue, remove this check and add relevant logic for when
>>>> df->governor is NULL.
>>>>
>>>> Fixes: 483d557ee9a3 ("PM / devfreq: Clean up the devfreq instance name in sysfs attr")
>>>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>>>> ---
>>>> drivers/devfreq/devfreq.c | 15 ++++++++++++---
>>>> 1 file changed, 12 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>>> index 0bf320123e3a..4a312f3c2421 100644
>>>> --- a/drivers/devfreq/devfreq.c
>>>> +++ b/drivers/devfreq/devfreq.c
>>>> @@ -1425,9 +1425,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>>> char str_governor[DEVFREQ_NAME_LEN + 1];
>>>> const struct devfreq_governor *governor, *prev_governor;
>>>> - if (!df->governor)
>>>> - return -EINVAL;
>>>> -
>>>> ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>>>> if (ret != 1)
>>>> return -EINVAL;
>>>> @@ -1438,6 +1435,18 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>>> ret = PTR_ERR(governor);
>>>> goto out;
>>>> }
>>>> +
>>>> + if (!df->governor) {
>>>> + df->governor = governor;
>>>> + ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>>>> + if (ret) {
>>>> + dev_warn(dev, "%s: Governor %s not started(%d)\n",
>>>> + __func__, df->governor->name, ret);
>>>> + df->governor = NULL;
>>>> + }
>>>> + goto out;
>>>> + }
>>>> +
>>> The sequence that starts the governor, and stops, and then re-starts looks
>>> quite weird.
>>> Can you do a NULL pointer check before the IMMUTABLE flag check and
>>> stopping governor, rather than this?
>> This patch only addresses the issue raised in the commit message. As for the original
>>
>> start, stop, and then restart sequence, I haven't found any problems with it so far.
>>
> You just added the first 'start' here.
> Please see the other process in governor_store().
Could you explain what you mean?
Wouldn't it be correct to directly operate on the devices without a
governor first and then exit?
>>>> if (df->governor == governor) {
>>>> ret = 0;
>>>> goto out;
^ permalink raw reply
* Re: [PATCH RESEND 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor
From: Jie Zhan @ 2026-03-31 9:37 UTC (permalink / raw)
To: Yaxiong Tian, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <f954648e-33d0-4b07-977d-96af182fc2ef@kylinos.cn>
On 3/31/2026 5:30 PM, Yaxiong Tian wrote:
>
> 在 2026/3/31 16:53, Jie Zhan 写道:
>>
>> On 3/31/2026 4:02 PM, Yaxiong Tian wrote:
>>> 在 2026/3/31 15:16, Jie Zhan 写道:
>>>> On 3/19/2026 5:17 PM, Yaxiong Tian wrote:
>>>>> Since devfreq_remove_governor() may clear the device's current governor
>>>>> in certain situations, while governors actually exist independently
>>>>> of the device, directly returning EINVAL in this case is inaccurate.
>>>>>
>>>>> To fix this issue, remove this check and add relevant logic for when
>>>>> df->governor is NULL.
>>>>>
>>>>> Fixes: 483d557ee9a3 ("PM / devfreq: Clean up the devfreq instance name in sysfs attr")
>>>>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>>>>> ---
>>>>> drivers/devfreq/devfreq.c | 15 ++++++++++++---
>>>>> 1 file changed, 12 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>>>> index 0bf320123e3a..4a312f3c2421 100644
>>>>> --- a/drivers/devfreq/devfreq.c
>>>>> +++ b/drivers/devfreq/devfreq.c
>>>>> @@ -1425,9 +1425,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>>>> char str_governor[DEVFREQ_NAME_LEN + 1];
>>>>> const struct devfreq_governor *governor, *prev_governor;
>>>>> - if (!df->governor)
>>>>> - return -EINVAL;
>>>>> -
>>>>> ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>>>>> if (ret != 1)
>>>>> return -EINVAL;
>>>>> @@ -1438,6 +1435,18 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>>>> ret = PTR_ERR(governor);
>>>>> goto out;
>>>>> }
>>>>> +
>>>>> + if (!df->governor) {
>>>>> + df->governor = governor;
>>>>> + ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>>>>> + if (ret) {
>>>>> + dev_warn(dev, "%s: Governor %s not started(%d)\n",
>>>>> + __func__, df->governor->name, ret);
>>>>> + df->governor = NULL;
>>>>> + }
>>>>> + goto out;
>>>>> + }
>>>>> +
>>>> The sequence that starts the governor, and stops, and then re-starts looks
>>>> quite weird.
>>>> Can you do a NULL pointer check before the IMMUTABLE flag check and
>>>> stopping governor, rather than this?
>>> This patch only addresses the issue raised in the commit message. As for the original
>>>
>>> start, stop, and then restart sequence, I haven't found any problems with it so far.
>>>
>> You just added the first 'start' here.
>> Please see the other process in governor_store().
> Could you explain what you mean?
> Wouldn't it be correct to directly operate on the devices without a governor first and then exit?
Ok, the code here starts the governor and directly goes to 'out' that
unlocks mutex, so create_sysfs_files() is skipped.
For example, setting 'userspace' as the governor won't create its belonging
files.
Therefore, I'd suggest that doing a NULL pointer check before the IMMUTABLE
flag check and stopping governor, where df->governor is used, so the
existing logic is not changed.
>>>>> if (df->governor == governor) {
>>>>> ret = 0;
>>>>> goto out;
^ permalink raw reply
* Re: [PATCH RESEND 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor
From: Yaxiong Tian @ 2026-03-31 9:54 UTC (permalink / raw)
To: Jie Zhan, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <4d1d2077-a336-4914-b7b1-204cab5a60e0@hisilicon.com>
在 2026/3/31 17:37, Jie Zhan 写道:
---skip------
> Ok, the code here starts the governor and directly goes to 'out' that
> unlocks mutex, so create_sysfs_files() is skipped.
> For example, setting 'userspace' as the governor won't create its belonging
> files.
>
> Therefore, I'd suggest that doing a NULL pointer check before the IMMUTABLE
> flag check and stopping governor, where df->governor is used, so the
> existing logic is not changed.
Yes, I missed that. However, we still need to check df->governor later
and perform corresponding operations.
How about adding ret = sysfs_update_group(&df->dev.kobj,
&gov_attr_group) based on the original code (against the latest linux-next)?
^ permalink raw reply
* Re: [PATCH RESEND 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor
From: Yaxiong Tian @ 2026-03-31 10:12 UTC (permalink / raw)
To: Jie Zhan, myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel
In-Reply-To: <10e912b5-b7a9-4f4d-92fb-9de450e82c23@kylinos.cn>
在 2026/3/31 17:54, Yaxiong Tian 写道:
>
> 在 2026/3/31 17:37, Jie Zhan 写道:
> ---skip------
>> Ok, the code here starts the governor and directly goes to 'out' that
>> unlocks mutex, so create_sysfs_files() is skipped.
>> For example, setting 'userspace' as the governor won't create its
>> belonging
>> files.
>>
>> Therefore, I'd suggest that doing a NULL pointer check before the
>> IMMUTABLE
>> flag check and stopping governor, where df->governor is used, so the
>> existing logic is not changed.
>
> Yes, I missed that. However, we still need to check df->governor later
> and perform corresponding operations.
> How about adding ret = sysfs_update_group(&df->dev.kobj,
> &gov_attr_group) based on the original code (against the latest
> linux-next)?
>
Sorry, please disregard the earlier part for the time being.
The line sysfs_update_group(&df->dev.kobj, &gov_attr_group); may not be
needed, and I need to review it further.
^ permalink raw reply
* Re: [PATCH v4 1/9] dt-bindings: mfd: mt6397: Add MT6392 PMIC
From: Chen-Yu Tsai @ 2026-03-31 10:15 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: Krzysztof Kozlowski, linux-mediatek, Fabien Parent, Val Packett,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Liam Girdwood,
Mark Brown, Louis-Alexis Eyraud, Gary Bisson, Julien Massot,
Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-gpio
In-Reply-To: <CAORyz2+1bc9Z-opoNqyUU_WFzyXZKGQmR_Ur=4UonOC=AWtQ8w@mail.gmail.com>
On Tue, Mar 31, 2026 at 4:36 PM Luca Leonardo Scorcia
<l.scorcia@gmail.com> wrote:
>
> > > - required:
> > > - - compatible
> >
> > Not really, this affects existing ABI and might make the child schema
> > being applied. Basically regulators node can be anything now.
> >
> > This is definitely not a binding we want. The syntax for parent schema
> > when listing only compatibles is requiring this compatible. You cannot
> > have here whatever empty node.
>
> Hi, it felt quite strange to me too, but that's what I thought you
> meant with your previous suggestion [1].
> To keep the required attribute I would be happy to reintroduce the
> compatible here, in the regulator schema and the pmic dtsi.
>
> Before I do that and resubmit, could you please help me understand
> what you meant before?
I think the point is that compatibles for regulator sub-nodes on MFDs
is no longer accepted.
Instead if you want to have a separate binding for the regulator part,
you would need to reference the binding directly.
Say the binding is at bindings/regulator/mt6392.yaml, in this patch
you would have something after the "additionalProperties: false" like:
allOf:
- if:
properties:
"compatible":
contains:
const: mediatek,mt6392
then:
properties:
regulators:
$ref: /schemas/regulator/mt6392.yaml
else:
properties:
regulators:
required:
- compatible
And drop the "required: - compatible" part from the common regulator
node bits of the binding.
ChenYu
> Thank you!
>
> [1] https://lists.infradead.org/pipermail/linux-mediatek/2026-March/105060.html
> --
> Luca Leonardo Scorcia
> l.scorcia@gmail.com
>
^ permalink raw reply
* Re: [PATCH v5 09/11] mfd: bq257xx: Add BQ25792 support
From: Lee Jones @ 2026-03-31 10:27 UTC (permalink / raw)
To: Alexey Charkov
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chris Morgan,
Liam Girdwood, Mark Brown, Sebastian Reichel, devicetree,
linux-kernel, Sebastian Reichel, linux-pm
In-Reply-To: <20260324-bq25792-v5-9-0a2eb58cf11d@flipper.net>
On Tue, 24 Mar 2026, Alexey Charkov wrote:
> Add register definitions and a new 'type' enum to be passed via MFD
> private data to support the BQ25792, which is a newer variant of the
> BQ257xx family.
>
> BQ25792 shares similar logic of operation with the already supported
> BQ25703A but has a completely different register map and different
> electrical constraints.
>
> Tested-by: Chris Morgan <macromorgan@hotmail.com>
> Signed-off-by: Alexey Charkov <alchark@flipper.net>
> ---
> drivers/mfd/bq257xx.c | 54 +++++-
> include/linux/mfd/bq257xx.h | 412 ++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 463 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mfd/bq257xx.c b/drivers/mfd/bq257xx.c
> index e9d49dac0a16..31654925afa5 100644
> --- a/drivers/mfd/bq257xx.c
> +++ b/drivers/mfd/bq257xx.c
> @@ -39,6 +39,39 @@ static const struct regmap_config bq25703_regmap_config = {
> .val_format_endian = REGMAP_ENDIAN_LITTLE,
> };
>
> +static const struct regmap_range bq25792_writeable_reg_ranges[] = {
> + regmap_reg_range(BQ25792_REG00_MIN_SYS_VOLTAGE,
> + BQ25792_REG18_NTC_CONTROL_1),
> + regmap_reg_range(BQ25792_REG28_CHARGER_MASK_0,
> + BQ25792_REG30_ADC_FUNCTION_DISABLE_1),
> +};
> +
> +static const struct regmap_access_table bq25792_writeable_regs = {
> + .yes_ranges = bq25792_writeable_reg_ranges,
> + .n_yes_ranges = ARRAY_SIZE(bq25792_writeable_reg_ranges),
> +};
> +
> +static const struct regmap_range bq25792_volatile_reg_ranges[] = {
> + regmap_reg_range(BQ25792_REG19_ICO_CURRENT_LIMIT,
> + BQ25792_REG27_FAULT_FLAG_1),
> + regmap_reg_range(BQ25792_REG31_IBUS_ADC,
> + BQ25792_REG47_DPDM_DRIVER),
> +};
> +
> +static const struct regmap_access_table bq25792_volatile_regs = {
> + .yes_ranges = bq25792_volatile_reg_ranges,
> + .n_yes_ranges = ARRAY_SIZE(bq25792_volatile_reg_ranges),
> +};
> +
> +static const struct regmap_config bq25792_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = BQ25792_REG48_PART_INFORMATION,
> + .cache_type = REGCACHE_MAPLE,
> + .wr_table = &bq25792_writeable_regs,
> + .volatile_table = &bq25792_volatile_regs,
> +};
> +
> static const struct mfd_cell cells[] = {
> MFD_CELL_NAME("bq257xx-regulator"),
> MFD_CELL_NAME("bq257xx-charger"),
> @@ -46,6 +79,7 @@ static const struct mfd_cell cells[] = {
>
> static int bq257xx_probe(struct i2c_client *client)
> {
> + const struct regmap_config *rcfg;
> struct bq257xx_device *ddata;
> int ret;
>
> @@ -53,9 +87,21 @@ static int bq257xx_probe(struct i2c_client *client)
> if (!ddata)
> return -ENOMEM;
>
> + ddata->type = (uintptr_t)i2c_get_match_data(client);
> ddata->client = client;
>
> - ddata->regmap = devm_regmap_init_i2c(client, &bq25703_regmap_config);
> + switch (ddata->type) {
> + case BQ25703A:
> + rcfg = &bq25703_regmap_config;
> + break;
> + case BQ25792:
> + rcfg = &bq25792_regmap_config;
> + break;
> + default:
> + return dev_err_probe(&client->dev, -EINVAL, "Unsupported device type\n");
Nit: Shouldn't we be returning '-ENODEV' here for an unsupported device?
> + }
> +
> + ddata->regmap = devm_regmap_init_i2c(client, rcfg);
> if (IS_ERR(ddata->regmap)) {
> return dev_err_probe(&client->dev, PTR_ERR(ddata->regmap),
> "Failed to allocate register map\n");
> @@ -73,13 +119,15 @@ static int bq257xx_probe(struct i2c_client *client)
> }
>
> static const struct i2c_device_id bq257xx_i2c_ids[] = {
> - { "bq25703a" },
> + { "bq25703a", BQ25703A },
> + { "bq25792", BQ25792 },
> {}
> };
> MODULE_DEVICE_TABLE(i2c, bq257xx_i2c_ids);
>
> static const struct of_device_id bq257xx_of_match[] = {
> - { .compatible = "ti,bq25703a" },
> + { .compatible = "ti,bq25703a", .data = (void *)BQ25703A },
> + { .compatible = "ti,bq25792", .data = (void *)BQ25792 },
> {}
> };
> MODULE_DEVICE_TABLE(of, bq257xx_of_match);
> diff --git a/include/linux/mfd/bq257xx.h b/include/linux/mfd/bq257xx.h
> index 1d6ddc7fb09f..4ec72eb920f2 100644
> --- a/include/linux/mfd/bq257xx.h
> +++ b/include/linux/mfd/bq257xx.h
> @@ -98,7 +98,419 @@
>
> #define BQ25703_EN_OTG_MASK BIT(12)
>
> +#define BQ25792_REG00_MIN_SYS_VOLTAGE 0x00
> +#define BQ25792_REG01_CHARGE_VOLTAGE_LIMIT 0x01
> +#define BQ25792_REG03_CHARGE_CURRENT_LIMIT 0x03
> +#define BQ25792_REG05_INPUT_VOLTAGE_LIMIT 0x05
> +#define BQ25792_REG06_INPUT_CURRENT_LIMIT 0x06
> +#define BQ25792_REG08_PRECHARGE_CONTROL 0x08
> +#define BQ25792_REG09_TERMINATION_CONTROL 0x09
> +#define BQ25792_REG0A_RECHARGE_CONTROL 0x0a
> +#define BQ25792_REG0B_VOTG_REGULATION 0x0b
> +#define BQ25792_REG0D_IOTG_REGULATION 0x0d
> +#define BQ25792_REG0E_TIMER_CONTROL 0x0e
> +#define BQ25792_REG0F_CHARGER_CONTROL_0 0x0f
> +#define BQ25792_REG10_CHARGER_CONTROL_1 0x10
> +#define BQ25792_REG11_CHARGER_CONTROL_2 0x11
> +#define BQ25792_REG12_CHARGER_CONTROL_3 0x12
> +#define BQ25792_REG13_CHARGER_CONTROL_4 0x13
> +#define BQ25792_REG14_CHARGER_CONTROL_5 0x14
> +/* REG15 reserved */
> +#define BQ25792_REG16_TEMPERATURE_CONTROL 0x16
> +#define BQ25792_REG17_NTC_CONTROL_0 0x17
> +#define BQ25792_REG18_NTC_CONTROL_1 0x18
> +#define BQ25792_REG19_ICO_CURRENT_LIMIT 0x19
> +#define BQ25792_REG1B_CHARGER_STATUS_0 0x1b
> +#define BQ25792_REG1C_CHARGER_STATUS_1 0x1c
> +#define BQ25792_REG1D_CHARGER_STATUS_2 0x1d
> +#define BQ25792_REG1E_CHARGER_STATUS_3 0x1e
> +#define BQ25792_REG1F_CHARGER_STATUS_4 0x1f
> +#define BQ25792_REG20_FAULT_STATUS_0 0x20
> +#define BQ25792_REG21_FAULT_STATUS_1 0x21
> +#define BQ25792_REG22_CHARGER_FLAG_0 0x22
> +#define BQ25792_REG23_CHARGER_FLAG_1 0x23
> +#define BQ25792_REG24_CHARGER_FLAG_2 0x24
> +#define BQ25792_REG25_CHARGER_FLAG_3 0x25
> +#define BQ25792_REG26_FAULT_FLAG_0 0x26
> +#define BQ25792_REG27_FAULT_FLAG_1 0x27
> +#define BQ25792_REG28_CHARGER_MASK_0 0x28
> +#define BQ25792_REG29_CHARGER_MASK_1 0x29
> +#define BQ25792_REG2A_CHARGER_MASK_2 0x2a
> +#define BQ25792_REG2B_CHARGER_MASK_3 0x2b
> +#define BQ25792_REG2C_FAULT_MASK_0 0x2c
> +#define BQ25792_REG2D_FAULT_MASK_1 0x2d
> +#define BQ25792_REG2E_ADC_CONTROL 0x2e
> +#define BQ25792_REG2F_ADC_FUNCTION_DISABLE_0 0x2f
> +#define BQ25792_REG30_ADC_FUNCTION_DISABLE_1 0x30
> +#define BQ25792_REG31_IBUS_ADC 0x31
> +#define BQ25792_REG33_IBAT_ADC 0x33
> +#define BQ25792_REG35_VBUS_ADC 0x35
> +#define BQ25792_REG37_VAC1_ADC 0x37
> +#define BQ25792_REG39_VAC2_ADC 0x39
> +#define BQ25792_REG3B_VBAT_ADC 0x3b
> +#define BQ25792_REG3D_VSYS_ADC 0x3d
> +#define BQ25792_REG3F_TS_ADC 0x3f
> +#define BQ25792_REG41_TDIE_ADC 0x41
> +#define BQ25792_REG43_DP_ADC 0x43
> +#define BQ25792_REG45_DM_ADC 0x45
> +#define BQ25792_REG47_DPDM_DRIVER 0x47
> +#define BQ25792_REG48_PART_INFORMATION 0x48
> +
> +/* Minimal System Voltage */
> +#define BQ25792_REG00_VSYSMIN_MASK GENMASK(5, 0)
> +
> +#define BQ25792_MINVSYS_MIN_UV 2500000
> +#define BQ25792_MINVSYS_STEP_UV 250000
> +#define BQ25792_MINVSYS_MAX_UV 16000000
> +
> +/* Charge Voltage Limit */
> +#define BQ25792_REG01_VREG_MASK GENMASK(10, 0)
> +
> +#define BQ25792_VBATREG_MIN_UV 3000000
> +#define BQ25792_VBATREG_STEP_UV 10000
> +#define BQ25792_VBATREG_MAX_UV 18800000
> +
> +/* Charge Current Limit */
> +#define BQ25792_REG03_ICHG_MASK GENMASK(8, 0)
> +
> +#define BQ25792_ICHG_MIN_UA 50000
> +#define BQ25792_ICHG_STEP_UA 10000
> +#define BQ25792_ICHG_MAX_UA 5000000
> +
> +/* Input Voltage Limit */
> +#define BQ25792_REG05_VINDPM_MASK GENMASK(7, 0)
> +
> +/* Input Current Limit */
> +#define BQ25792_REG06_IINDPM_MASK GENMASK(8, 0)
> +#define BQ25792_IINDPM_DEFAULT_UA 3000000
> +#define BQ25792_IINDPM_STEP_UA 10000
> +#define BQ25792_IINDPM_MIN_UA 100000
> +#define BQ25792_IINDPM_MAX_UA 3300000
> +
> +/* Precharge Control */
> +#define BQ25792_REG08_VBAT_LOWV_MASK GENMASK(7, 6)
> +#define BQ25792_REG08_IPRECHG_MASK GENMASK(5, 0)
> +
> +/* Termination Control */
> +#define BQ25792_REG09_REG_RST BIT(6)
> +#define BQ25792_REG09_ITERM_MASK GENMASK(4, 0)
> +
> +/* Re-charge Control */
> +#define BQ25792_REG0A_CELL_MASK GENMASK(7, 6)
> +#define BQ25792_REG0A_TRECHG_MASK GENMASK(5, 4)
> +#define BQ25792_REG0A_VRECHG_MASK GENMASK(3, 0)
> +
> +/* VOTG regulation */
> +#define BQ25792_REG0B_VOTG_MASK GENMASK(10, 0)
> +
> +#define BQ25792_OTG_VOLT_MIN_UV 2800000
> +#define BQ25792_OTG_VOLT_STEP_UV 10000
> +#define BQ25792_OTG_VOLT_MAX_UV 22000000
> +#define BQ25792_OTG_VOLT_NUM_VOLT ((BQ25792_OTG_VOLT_MAX_UV \
> + - BQ25792_OTG_VOLT_MIN_UV) \
> + / BQ25792_OTG_VOLT_STEP_UV + 1)
> +
> +/* IOTG regulation */
> +#define BQ25792_REG0D_PRECHG_TMR BIT(7)
> +#define BQ25792_REG0D_IOTG_MASK GENMASK(6, 0)
> +
> +#define BQ25792_OTG_CUR_MIN_UA 120000
> +#define BQ25792_OTG_CUR_STEP_UA 40000
> +#define BQ25792_OTG_CUR_MAX_UA 3320000
> +
> +/* Timer Control */
> +#define BQ25792_REG0E_TOPOFF_TMR_MASK GENMASK(7, 6)
> +#define BQ25792_REG0E_EN_TRICHG_TMR BIT(5)
> +#define BQ25792_REG0E_EN_PRECHG_TMR BIT(4)
> +#define BQ25792_REG0E_EN_CHG_TMR BIT(3)
> +#define BQ25792_REG0E_CHG_TMR_MASK GENMASK(2, 1)
> +#define BQ25792_REG0E_TMR2X_EN BIT(0)
> +
> +/* Charger Control 0 */
> +#define BQ25792_REG0F_EN_AUTO_IBATDIS BIT(7)
> +#define BQ25792_REG0F_FORCE_IBATDIS BIT(6)
> +#define BQ25792_REG0F_EN_CHG BIT(5)
> +#define BQ25792_REG0F_EN_ICO BIT(4)
> +#define BQ25792_REG0F_FORCE_ICO BIT(3)
> +#define BQ25792_REG0F_EN_HIZ BIT(2)
> +#define BQ25792_REG0F_EN_TERM BIT(1)
> +/* bit0 reserved */
> +
> +/* Charger Control 1 */
> +#define BQ25792_REG10_VAC_OVP_MASK GENMASK(5, 4)
> +#define BQ25792_REG10_WD_RST BIT(3)
> +#define BQ25792_REG10_WATCHDOG_MASK GENMASK(2, 0)
> +
> +/* Charger Control 2 */
> +#define BQ25792_REG11_FORCE_INDET BIT(7)
> +#define BQ25792_REG11_AUTO_INDET_EN BIT(6)
> +#define BQ25792_REG11_EN_12V BIT(5)
> +#define BQ25792_REG11_EN_9V BIT(4)
> +#define BQ25792_REG11_HVDCP_EN BIT(3)
> +#define BQ25792_REG11_SDRV_CTRL_MASK GENMASK(2, 1)
> +#define BQ25792_REG11_SDRV_DLY BIT(0)
> +
> +/* Charger Control 3 */
> +#define BQ25792_REG12_DIS_ACDRV BIT(7)
> +#define BQ25792_REG12_EN_OTG BIT(6)
> +#define BQ25792_REG12_PFM_OTG_DIS BIT(5)
> +#define BQ25792_REG12_PFM_FWD_DIS BIT(4)
> +#define BQ25792_REG12_WKUP_DLY BIT(3)
> +#define BQ25792_REG12_DIS_LDO BIT(2)
> +#define BQ25792_REG12_DIS_OTG_OOA BIT(1)
> +#define BQ25792_REG12_DIS_FWD_OOA BIT(0)
> +
> +/* Charger Control 4 */
> +#define BQ25792_REG13_EN_ACDRV2 BIT(7)
> +#define BQ25792_REG13_EN_ACDRV1 BIT(6)
> +#define BQ25792_REG13_PWM_FREQ BIT(5)
> +#define BQ25792_REG13_DIS_STAT BIT(4)
> +#define BQ25792_REG13_DIS_VSYS_SHORT BIT(3)
> +#define BQ25792_REG13_DIS_VOTG_UVP BIT(2)
> +#define BQ25792_REG13_FORCE_VINDPM_DET BIT(1)
> +#define BQ25792_REG13_EN_IBUS_OCP BIT(0)
> +
> +/* Charger Control 5 */
> +#define BQ25792_REG14_SFET_PRESENT BIT(7)
> +/* bit6 reserved */
> +#define BQ25792_REG14_EN_IBAT BIT(5)
> +#define BQ25792_REG14_IBAT_REG_MASK GENMASK(4, 3)
> +#define BQ25792_REG14_EN_IINDPM BIT(2)
> +#define BQ25792_REG14_EN_EXTILIM BIT(1)
> +#define BQ25792_REG14_EN_BATOC BIT(0)
> +
> +#define BQ25792_IBAT_3A FIELD_PREP(BQ25792_REG14_IBAT_REG_MASK, 0)
> +#define BQ25792_IBAT_4A FIELD_PREP(BQ25792_REG14_IBAT_REG_MASK, 1)
> +#define BQ25792_IBAT_5A FIELD_PREP(BQ25792_REG14_IBAT_REG_MASK, 2)
> +#define BQ25792_IBAT_UNLIM FIELD_PREP(BQ25792_REG14_IBAT_REG_MASK, 3)
> +
> +/* Temperature Control */
> +#define BQ25792_REG16_TREG_MASK GENMASK(7, 6)
> +#define BQ25792_REG16_TSHUT_MASK GENMASK(5, 4)
> +#define BQ25792_REG16_VBUS_PD_EN BIT(3)
> +#define BQ25792_REG16_VAC1_PD_EN BIT(2)
> +#define BQ25792_REG16_VAC2_PD_EN BIT(1)
> +
> +/* NTC Control 0 */
> +#define BQ25792_REG17_JEITA_VSET_MASK GENMASK(7, 5)
> +#define BQ25792_REG17_JEITA_ISETH_MASK GENMASK(4, 3)
> +#define BQ25792_REG17_JEITA_ISETC_MASK GENMASK(2, 1)
> +
> +/* NTC Control 1 */
> +#define BQ25792_REG18_TS_COOL_MASK GENMASK(7, 6)
> +#define BQ25792_REG18_TS_WARM_MASK GENMASK(5, 4)
> +#define BQ25792_REG18_BHOT_MASK GENMASK(3, 2)
> +#define BQ25792_REG18_BCOLD BIT(1)
> +#define BQ25792_REG18_TS_IGNORE BIT(0)
> +
> +/* ICO Current Limit */
> +#define BQ25792_REG19_ICO_ILIM_MASK GENMASK(8, 0)
> +
> +/* Charger Status 0 */
> +#define BQ25792_REG1B_IINDPM_STAT BIT(7)
> +#define BQ25792_REG1B_VINDPM_STAT BIT(6)
> +#define BQ25792_REG1B_WD_STAT BIT(5)
> +#define BQ25792_REG1B_POORSRC_STAT BIT(4)
> +#define BQ25792_REG1B_PG_STAT BIT(3)
> +#define BQ25792_REG1B_AC2_PRESENT_STAT BIT(2)
> +#define BQ25792_REG1B_AC1_PRESENT_STAT BIT(1)
> +#define BQ25792_REG1B_VBUS_PRESENT_STAT BIT(0)
> +
> +/* Charger Status 1 */
> +#define BQ25792_REG1C_CHG_STAT_MASK GENMASK(7, 5)
> +#define BQ25792_REG1C_VBUS_STAT_MASK GENMASK(4, 1)
> +#define BQ25792_REG1C_BC12_DONE_STAT BIT(0)
> +
> +/* Charger Status 2 */
> +#define BQ25792_REG1D_ICO_STAT_MASK GENMASK(7, 6)
> +#define BQ25792_REG1D_TREG_STAT BIT(2)
> +#define BQ25792_REG1D_DPDM_STAT BIT(1)
> +#define BQ25792_REG1D_VBAT_PRESENT_STAT BIT(0)
> +
> +/* Charger Status 3 */
> +#define BQ25792_REG1E_ACRB2_STAT BIT(7)
> +#define BQ25792_REG1E_ACRB1_STAT BIT(6)
> +#define BQ25792_REG1E_ADC_DONE_STAT BIT(5)
> +#define BQ25792_REG1E_VSYS_STAT BIT(4)
> +#define BQ25792_REG1E_CHG_TMR_STAT BIT(3)
> +#define BQ25792_REG1E_TRICHG_TMR_STAT BIT(2)
> +#define BQ25792_REG1E_PRECHG_TMR_STAT BIT(1)
> +
> +/* Charger Status 4 */
> +#define BQ25792_REG1F_VBATOTG_LOW_STAT BIT(4)
> +#define BQ25792_REG1F_TS_COLD_STAT BIT(3)
> +#define BQ25792_REG1F_TS_COOL_STAT BIT(2)
> +#define BQ25792_REG1F_TS_WARM_STAT BIT(1)
> +#define BQ25792_REG1F_TS_HOT_STAT BIT(0)
> +
> +/* FAULT Status 0 */
> +#define BQ25792_REG20_IBAT_REG_STAT BIT(7)
> +#define BQ25792_REG20_VBUS_OVP_STAT BIT(6)
> +#define BQ25792_REG20_VBAT_OVP_STAT BIT(5)
> +#define BQ25792_REG20_IBUS_OCP_STAT BIT(4)
> +#define BQ25792_REG20_IBAT_OCP_STAT BIT(3)
> +#define BQ25792_REG20_CONV_OCP_STAT BIT(2)
> +#define BQ25792_REG20_VAC2_OVP_STAT BIT(1)
> +#define BQ25792_REG20_VAC1_OVP_STAT BIT(0)
> +
> +#define BQ25792_REG20_OVERVOLTAGE_MASK (BQ25792_REG20_VBAT_OVP_STAT | \
> + BQ25792_REG20_VAC2_OVP_STAT | \
> + BQ25792_REG20_VAC1_OVP_STAT)
> +#define BQ25792_REG20_OVERCURRENT_MASK (BQ25792_REG20_IBAT_OCP_STAT | \
> + BQ25792_REG20_CONV_OCP_STAT)
> +
> +/* FAULT Status 1 */
> +#define BQ25792_REG21_VSYS_SHORT_STAT BIT(7)
> +#define BQ25792_REG21_VSYS_OVP_STAT BIT(6)
> +#define BQ25792_REG21_OTG_OVP_STAT BIT(5)
> +#define BQ25792_REG21_OTG_UVP_STAT BIT(4)
> +#define BQ25792_REG21_TSHUT_STAT BIT(2)
> +
> +
> +/* Charger Flag 0 */
> +#define BQ25792_REG22_IINDPM_FLAG BIT(7)
> +#define BQ25792_REG22_VINDPM_FLAG BIT(6)
> +#define BQ25792_REG22_WD_FLAG BIT(5)
> +#define BQ25792_REG22_POORSRC_FLAG BIT(4)
> +#define BQ25792_REG22_PG_FLAG BIT(3)
> +#define BQ25792_REG22_AC2_PRESENT_FLAG BIT(2)
> +#define BQ25792_REG22_AC1_PRESENT_FLAG BIT(1)
> +#define BQ25792_REG22_VBUS_PRESENT_FLAG BIT(0)
> +
> +/* Charger Flag 1 */
> +#define BQ25792_REG23_CHG_FLAG BIT(7)
> +#define BQ25792_REG23_ICO_FLAG BIT(6)
> +#define BQ25792_REG23_VBUS_FLAG BIT(4)
> +#define BQ25792_REG23_TREG_FLAG BIT(2)
> +#define BQ25792_REG23_VBAT_PRESENT_FLAG BIT(1)
> +#define BQ25792_REG23_BC12_DONE_FLAG BIT(0)
> +
> +/* Charger Flag 2 */
> +#define BQ25792_REG24_DPDM_DONE_FLAG BIT(6)
> +#define BQ25792_REG24_ADC_DONE_FLAG BIT(5)
> +#define BQ25792_REG24_VSYS_FLAG BIT(4)
> +#define BQ25792_REG24_CHG_TMR_FLAG BIT(3)
> +#define BQ25792_REG24_TRICHG_TMR_FLAG BIT(2)
> +#define BQ25792_REG24_PRECHG_TMR_FLAG BIT(1)
> +#define BQ25792_REG24_TOPOFF_TMR_FLAG BIT(0)
> +
> +/* Charger Flag 3 */
> +#define BQ25792_REG25_VBATOTG_LOW_FLAG BIT(4)
> +#define BQ25792_REG25_TS_COLD_FLAG BIT(3)
> +#define BQ25792_REG25_TS_COOL_FLAG BIT(2)
> +#define BQ25792_REG25_TS_WARM_FLAG BIT(1)
> +#define BQ25792_REG25_TS_HOT_FLAG BIT(0)
> +
> +/* FAULT Flag 0 */
> +#define BQ25792_REG26_IBAT_REG_FLAG BIT(7)
> +#define BQ25792_REG26_VBUS_OVP_FLAG BIT(6)
> +#define BQ25792_REG26_VBAT_OVP_FLAG BIT(5)
> +#define BQ25792_REG26_IBUS_OCP_FLAG BIT(4)
> +#define BQ25792_REG26_IBAT_OCP_FLAG BIT(3)
> +#define BQ25792_REG26_CONV_OCP_FLAG BIT(2)
> +#define BQ25792_REG26_VAC2_OVP_FLAG BIT(1)
> +#define BQ25792_REG26_VAC1_OVP_FLAG BIT(0)
> +
> +/* FAULT Flag 1 */
> +#define BQ25792_REG27_VSYS_SHORT_FLAG BIT(7)
> +#define BQ25792_REG27_VSYS_OVP_FLAG BIT(6)
> +#define BQ25792_REG27_OTG_OVP_FLAG BIT(5)
> +#define BQ25792_REG27_OTG_UVP_FLAG BIT(4)
> +#define BQ25792_REG27_TSHUT_FLAG BIT(2)
> +
> +/* Charger Mask 0 */
> +#define BQ25792_REG28_IINDPM_MASK BIT(7)
> +#define BQ25792_REG28_VINDPM_MASK BIT(6)
> +#define BQ25792_REG28_WD_MASK BIT(5)
> +#define BQ25792_REG28_POORSRC_MASK BIT(4)
> +#define BQ25792_REG28_PG_MASK BIT(3)
> +#define BQ25792_REG28_AC2_PRESENT_MASK BIT(2)
> +#define BQ25792_REG28_AC1_PRESENT_MASK BIT(1)
> +#define BQ25792_REG28_VBUS_PRESENT_MASK BIT(0)
> +
> +/* Charger Mask 1 */
> +#define BQ25792_REG29_CHG_MASK BIT(7)
> +#define BQ25792_REG29_ICO_MASK BIT(6)
> +#define BQ25792_REG29_VBUS_MASK BIT(4)
> +#define BQ25792_REG29_TREG_MASK BIT(2)
> +#define BQ25792_REG29_VBAT_PRESENT_MASK BIT(1)
> +#define BQ25792_REG29_BC12_DONE_MASK BIT(0)
> +
> +/* Charger Mask 2 */
> +#define BQ25792_REG2A_DPDM_DONE_MASK BIT(6)
> +#define BQ25792_REG2A_ADC_DONE_MASK BIT(5)
> +#define BQ25792_REG2A_VSYS_MASK BIT(4)
> +#define BQ25792_REG2A_CHG_TMR_MASK BIT(3)
> +#define BQ25792_REG2A_TRICHG_TMR_MASK BIT(2)
> +#define BQ25792_REG2A_PRECHG_TMR_MASK BIT(1)
> +#define BQ25792_REG2A_TOPOFF_TMR_MASK BIT(0)
> +
> +/* Charger Mask 3 */
> +#define BQ25792_REG2B_VBATOTG_LOW_MASK BIT(4)
> +#define BQ25792_REG2B_TS_COLD_MASK BIT(3)
> +#define BQ25792_REG2B_TS_COOL_MASK BIT(2)
> +#define BQ25792_REG2B_TS_WARM_MASK BIT(1)
> +#define BQ25792_REG2B_TS_HOT_MASK BIT(0)
> +
> +/* FAULT Mask 0 */
> +#define BQ25792_REG2C_IBAT_REG_MASK BIT(7)
> +#define BQ25792_REG2C_VBUS_OVP_MASK BIT(6)
> +#define BQ25792_REG2C_VBAT_OVP_MASK BIT(5)
> +#define BQ25792_REG2C_IBUS_OCP_MASK BIT(4)
> +#define BQ25792_REG2C_IBAT_OCP_MASK BIT(3)
> +#define BQ25792_REG2C_CONV_OCP_MASK BIT(2)
> +#define BQ25792_REG2C_VAC2_OVP_MASK BIT(1)
> +#define BQ25792_REG2C_VAC1_OVP_MASK BIT(0)
> +
> +/* FAULT Mask 1 */
> +#define BQ25792_REG2D_VSYS_SHORT_MASK BIT(7)
> +#define BQ25792_REG2D_VSYS_OVP_MASK BIT(6)
> +#define BQ25792_REG2D_OTG_OVP_MASK BIT(5)
> +#define BQ25792_REG2D_OTG_UVP_MASK BIT(4)
> +#define BQ25792_REG2D_TSHUT_MASK BIT(2)
> +
> +/* ADC Control */
> +#define BQ25792_REG2E_ADC_EN BIT(7)
> +#define BQ25792_REG2E_ADC_RATE BIT(6)
> +#define BQ25792_REG2E_ADC_SAMPLE_MASK GENMASK(5, 4)
> +#define BQ25792_REG2E_ADC_AVG BIT(3)
> +#define BQ25792_REG2E_ADC_AVG_INIT BIT(2)
> +
> +/* ADC Function Disable 0 */
> +#define BQ25792_REG2F_IBUS_ADC_DIS BIT(7)
> +#define BQ25792_REG2F_IBAT_ADC_DIS BIT(6)
> +#define BQ25792_REG2F_VBUS_ADC_DIS BIT(5)
> +#define BQ25792_REG2F_VBAT_ADC_DIS BIT(4)
> +#define BQ25792_REG2F_VSYS_ADC_DIS BIT(3)
> +#define BQ25792_REG2F_TS_ADC_DIS BIT(2)
> +#define BQ25792_REG2F_TDIE_ADC_DIS BIT(1)
> +
> +/* ADC Function Disable 1 */
> +#define BQ25792_REG30_DP_ADC_DIS BIT(7)
> +#define BQ25792_REG30_DM_ADC_DIS BIT(6)
> +#define BQ25792_REG30_VAC2_ADC_DIS BIT(5)
> +#define BQ25792_REG30_VAC1_ADC_DIS BIT(4)
> +
> +/* 0x31-0x45: ADC result registers (16-bit, RO): single full-width field */
> +
> +#define BQ25792_ADCVSYSVBAT_STEP_UV 1000
> +#define BQ25792_ADCIBAT_STEP_UA 1000
> +
> +/* DPDM Driver */
> +#define BQ25792_REG47_DPLUS_DAC_MASK GENMASK(7, 5)
> +#define BQ25792_REG47_DMINUS_DAC_MASK GENMASK(4, 2)
> +
> +/* Part Information */
> +#define BQ25792_REG48_PN_MASK GENMASK(5, 3)
> +#define BQ25792_REG48_DEV_REV_MASK GENMASK(2, 0)
> +
> +enum bq257xx_type {
> + BQ25703A = 1,
> + BQ25792,
> +};
> +
> struct bq257xx_device {
> struct i2c_client *client;
> struct regmap *regmap;
> + enum bq257xx_type type;
> };
>
> --
> 2.52.0
>
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: [PATCH v5 2/5] media: iris: scale MMCX power domain on SM8250
From: Bryan O'Donoghue @ 2026-03-31 11:19 UTC (permalink / raw)
To: Dmitry Baryshkov, Bjorn Andersson, Michael Turquette,
Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Taniya Das, Jonathan Marek, Ulf Hansson, Rafael J. Wysocki,
Vikash Garodia, Dikshita Agarwal, Mauro Carvalho Chehab,
Stanimir Varbanov, Abhinav Kumar, Hans Verkuil, Stefan Schmidt,
Konrad Dybcio, Bryan O'Donoghue, Dikshita Agarwal
Cc: linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-pm,
linux-media, Mauro Carvalho Chehab
In-Reply-To: <20260209-iris-venus-fix-sm8250-v5-2-0a22365d3585@oss.qualcomm.com>
On 09/02/2026 01:32, Dmitry Baryshkov wrote:
> On SM8250 most of the video clocks are powered by the MMCX domain, while
> the PLL is powered on by the MX domain. Extend the driver to support
> scaling both power domains, while keeping compatibility with the
> existing DTs, which define only the MX domain.
>
> Fixes: 79865252acb6 ("media: iris: enable video driver probe of SM8250 SoC")
> Reviewed-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
> drivers/media/platform/qcom/iris/iris_platform_gen1.c | 2 +-
> drivers/media/platform/qcom/iris/iris_probe.c | 7 +++++++
> 2 files changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen1.c b/drivers/media/platform/qcom/iris/iris_platform_gen1.c
> index df8e6bf9430e..aa71f7f53ee3 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_gen1.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_gen1.c
> @@ -281,7 +281,7 @@ static const struct bw_info sm8250_bw_table_dec[] = {
>
> static const char * const sm8250_pmdomain_table[] = { "venus", "vcodec0" };
>
> -static const char * const sm8250_opp_pd_table[] = { "mx" };
> +static const char * const sm8250_opp_pd_table[] = { "mx", "mmcx" };
>
> static const struct platform_clk_data sm8250_clk_table[] = {
> {IRIS_AXI_CLK, "iface" },
> diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
> index 7b612ad37e4f..74ec81e3d622 100644
> --- a/drivers/media/platform/qcom/iris/iris_probe.c
> +++ b/drivers/media/platform/qcom/iris/iris_probe.c
> @@ -64,6 +64,13 @@ static int iris_init_power_domains(struct iris_core *core)
> return ret;
>
> ret = devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data, &core->opp_pmdomain_tbl);
> + /* backwards compatibility for incomplete ABI SM8250 */
> + if (ret == -ENODEV &&
> + of_device_is_compatible(core->dev->of_node, "qcom,sm8250-venus")) {
> + iris_opp_pd_data.num_pd_names--;
> + ret = devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data,
ci is choking on this.
=>
drivers/media/platform/qcom/venus/pm_helpers.c: In function
‘vcodec_domains_get’:
drivers/media/platform/qcom/venus/pm_helpers.c:910:41: error: decrement
of read-only member ‘num_pd_names’
910 | opp_pd_data.num_pd_names--;
| ^~
=>
include/linux/pm_domain.h
struct dev_pm_domain_attach_data {
const char * const *pd_names;
const u32 num_pd_names;
const u32 pd_flags;
};
=>
struct dev_pm_domain_attach_data opp_pd_data = {
.pd_names = res->opp_pmdomain,
.num_pd_names = res->opp_pmdomain_num,
.pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP,
};
---
bod
^ permalink raw reply
* Re: [PATCH v5 2/5] media: iris: scale MMCX power domain on SM8250
From: Ulf Hansson @ 2026-03-31 11:33 UTC (permalink / raw)
To: Dikshita Agarwal, Dmitry Baryshkov
Cc: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Taniya Das, Jonathan Marek,
Rafael J. Wysocki, Bryan O'Donoghue, Vikash Garodia,
Mauro Carvalho Chehab, Stanimir Varbanov, Abhinav Kumar,
Hans Verkuil, Stefan Schmidt, Konrad Dybcio, Bryan O'Donoghue,
Dikshita Agarwal, linux-arm-msm, linux-clk, devicetree,
linux-kernel, linux-pm, linux-media, Mauro Carvalho Chehab
In-Reply-To: <0b41ee7c-83fe-d604-b750-8a5a0bd62bf8@oss.qualcomm.com>
On Mon, 30 Mar 2026 at 15:06, Dikshita Agarwal
<dikshita.agarwal@oss.qualcomm.com> wrote:
>
>
>
> On 3/30/2026 4:45 PM, Dmitry Baryshkov wrote:
> > On Mon, Mar 30, 2026 at 10:55:02AM +0530, Dikshita Agarwal wrote:
> >>
> >>
> >> On 2/9/2026 7:02 AM, Dmitry Baryshkov wrote:
> >>> On SM8250 most of the video clocks are powered by the MMCX domain, while
> >>> the PLL is powered on by the MX domain. Extend the driver to support
> >>> scaling both power domains, while keeping compatibility with the
> >>> existing DTs, which define only the MX domain.
> >>>
> >>> Fixes: 79865252acb6 ("media: iris: enable video driver probe of SM8250 SoC")
> >>> Reviewed-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
> >>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> >>> ---
> >>> drivers/media/platform/qcom/iris/iris_platform_gen1.c | 2 +-
> >>> drivers/media/platform/qcom/iris/iris_probe.c | 7 +++++++
> >>> 2 files changed, 8 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen1.c b/drivers/media/platform/qcom/iris/iris_platform_gen1.c
> >>> index df8e6bf9430e..aa71f7f53ee3 100644
> >>> --- a/drivers/media/platform/qcom/iris/iris_platform_gen1.c
> >>> +++ b/drivers/media/platform/qcom/iris/iris_platform_gen1.c
> >>> @@ -281,7 +281,7 @@ static const struct bw_info sm8250_bw_table_dec[] = {
> >>>
> >>> static const char * const sm8250_pmdomain_table[] = { "venus", "vcodec0" };
> >>>
> >>> -static const char * const sm8250_opp_pd_table[] = { "mx" };
> >>> +static const char * const sm8250_opp_pd_table[] = { "mx", "mmcx" };
> >>>
> >>> static const struct platform_clk_data sm8250_clk_table[] = {
> >>> {IRIS_AXI_CLK, "iface" },
> >>> diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
> >>> index 7b612ad37e4f..74ec81e3d622 100644
> >>> --- a/drivers/media/platform/qcom/iris/iris_probe.c
> >>> +++ b/drivers/media/platform/qcom/iris/iris_probe.c
> >>> @@ -64,6 +64,13 @@ static int iris_init_power_domains(struct iris_core *core)
> >>> return ret;
> >>>
> >>> ret = devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data, &core->opp_pmdomain_tbl);
> >>> + /* backwards compatibility for incomplete ABI SM8250 */
> >>> + if (ret == -ENODEV &&
> >>> + of_device_is_compatible(core->dev->of_node, "qcom,sm8250-venus")) {
> >>> + iris_opp_pd_data.num_pd_names--;
> >>> + ret = devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data,
> >>> + &core->opp_pmdomain_tbl);
> >>> + }
> >>> if (ret < 0)
> >>> return ret;
> >>>
> >>>
> >>
> >> Hitting below compilation error on latest kernel
> >>
> >> drivers/media/platform/qcom/iris/iris_probe.c: In function
> >> ‘iris_init_power_domains’:
> >> drivers/media/platform/qcom/iris/iris_probe.c:71:46: error: decrement of
> >> read-only member ‘num_pd_names’
> >> 71 | iris_opp_pd_data.num_pd_names--;
> >
> > See commit 7ad7f43e568b ("pmdomain: de-constify fields struct
> > dev_pm_domain_attach_data")
The intent was for this patch to be part of v7.0-rc1, but I failed
with my pull-request to Linus.
Instead this will be part of v7.1-rc1, assuming everything goes as expected.
Is it possible to drop/defer these changes until v7.2?
Kind regards
Uffe
^ 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