* [PATCH v8 0/9] Add support for MT6392 PMIC
From: Luca Leonardo Scorcia @ 2026-06-20 19:56 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,
Linus Walleij, Louis-Alexis Eyraud, Val Packett, Julien Massot,
Fabien Parent, Akari Tsuyukusa, Chen Zhong, linux-input,
devicetree, linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
The MediaTek MT6392 PMIC is usually found on devices powered by
the MT8516/MT8167 SoC and is yet another MT6323/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.
These patches enable four functions: keys, regulator, pinctrl and RTC.
Mono speaker amp will follow later as I need to work further on the
audio codec.
I added a handful of device tree improvements to fix some dtbs_check
errors, added support for the pinctrl device and addressed the comments
from last year's reviews.
Please note that patch 0006 and 0008 depend on patch 0005 as they need the
registers.h file, but belong to different driver areas. I'm not sure if
I'm supposed to squash them even if they belong to different driver
areas of if it's fine like this. Any advice is welcome.
Patch 0009 also depends on patch 0003 because of mt6392-regulator.h.
The series has been tested on Xiaomi Mi Smart Clock X04G and on the
Lenovo Smart Clock 2 CD-24502F.
Changes in v8:
From reviewers:
- Added example code to the MFD device binding, removed it from the
regulators docs.
- Added minItems/maxItems constraints on the regulator mode definitions,
improved the mode constants.
- Fixed formatting issues in the regulator binding.
- Import the mt6392.dtsi file in pumpkin-common.dtsi, as it was originally
meant in [8].
From sashiko:
- Added more explicit constraints on the regulator modes definitions.
- Use the appropriate modeget register for LDO regulators, Buck registers
don't have the corresponding register according to the data sheet.
- Added the missing of_map_mode function.
- Removed some debugging code that had no use and masked error codes.
Changes in v7 [7]:
- Removed patch 0008 dependency on patch 0003.
- Reintroduced the regulator driver. In earlier revisions of this series,
it was proposed to remove the dedicated compatible for the regulator
device [3]. The driver does not use actually it, but it is not possible
at this time to remove it from the bindings since it's a required
property.
Making the regulator-required property conditional was NACKed in [5],
with the suggestion to create a separate binding altogether for devices
that do not require the compatible property. I tried implementing this,
but since the parent device needs to be declared as compatible with
mt6323, it leads to a warning in dt_binding_check since mt6323 would
be declared as a compatible in both mt6392 and mt6397.
In the end the only regulator driver from the mt6397 documentation that
still declares an of_match is mt6397-regulator and it does not seem
to be necessary, so it should be possible to remove it and make the
regulator compatible optional for all regulators, but that change would
probably deserve its own separate patch series.
Changes in v6 [6]:
- Dropped the regulators driver for the moment
- Explained the FCHR key name origin in the commit message
- Introduced the MFD_CELL_* macro in the sub-devices definitions.
A separate, independent commit introduced MFD_CELL_* to all the
subdevices in the mt6397-core.c file for consistency
- Replaced of_device_get_match_data with device_get_match_data
- Removed the mfd_match_data enum in favor of the preexisting
chip_id enum
- Adjusted the error message if the device is unsupported
Changes in v5 [5]:
- Double checked regulator driver with data sheet and Android sources.
The data sheet I have misses a lot of register descriptions, but
Android sources have been helpful to fill the gaps
- Reintroduced the required attribute for the regulator compatible
in the bindings
- Fixed the missing reference to the MT6392 schema
- Fixed casts/unused vars reported by kernel test robot
- Removed Reviewed-by tags from the regulator patches as they have been
modified in this version
Changes in v4 [4]:
- Dropped usage of the regulator compatible
- Fixed commit messages text to properly reference the target subsystem
- Added supply rails to the regulator
- Reworked the regulator schema and PMIC dtsi. Now all supplies are
documented and the schema no longer includes voltage information
- Removed redundant ldo- / buck- prefixes
- Renamed the pinfunc header to mediatek,mt6392-pinfunc.h
- Modified the MFD driver to use a simple identifier in the of_match
data properties
Changes in v3 [3]:
- Added pinctrl device
- Changed mt6397-rtc fallback to mt6323-rtc
- Added schema for regulators
- Fixed checkpatch issues
Changes in v2 [2]:
- Replaced explicit compatibles with fallbacks
Initial version: [1]
[1] https://lore.kernel.org/linux-mediatek/cover.1771865014.git.l.scorcia@gmail.com/
[2] https://lore.kernel.org/linux-mediatek/20260306120521.163654-1-l.scorcia@gmail.com/
[3] https://lore.kernel.org/linux-mediatek/20260317184507.523060-1-l.scorcia@gmail.com/
[4] https://lore.kernel.org/linux-mediatek/20260330083429.359819-1-l.scorcia@gmail.com/
[5] https://lore.kernel.org/linux-mediatek/20260420213529.1645560-1-l.scorcia@gmail.com/
[6] https://lore.kernel.org/linux-mediatek/20260612200717.361018-1-l.scorcia@gmail.com/
[7] https://lore.kernel.org/linux-mediatek/20260615071836.362883-1-l.scorcia@gmail.com/
[8] https://lore.kernel.org/linux-mediatek/20190323211612.860-25-fparent@baylibre.com/
Fabien Parent (3):
dt-bindings: input: mtk-pmic-keys: Add MT6392 PMIC keys
mfd: mt6397: Add support for MT6392 PMIC
regulator: Add MediaTek MT6392 regulator
Luca Leonardo Scorcia (4):
dt-bindings: mfd: mt6397: Add MT6392 PMIC
regulator: dt-bindings: Add MediaTek MT6392 PMIC
mfd: mt6397: Use MFD_CELL_* to describe sub-devices
pinctrl: mediatek: mt6397: Add MediaTek MT6392
Val Packett (2):
input: keyboard: mtk-pmic-keys: Add MT6392 support
arm64: dts: mediatek: Add MediaTek MT6392 PMIC dtsi
.../bindings/input/mediatek,pmic-keys.yaml | 1 +
.../bindings/mfd/mediatek,mt6397.yaml | 74 ++
.../regulator/mediatek,mt6392-regulator.yaml | 118 +++
arch/arm64/boot/dts/mediatek/mt6392.dtsi | 148 ++++
.../boot/dts/mediatek/pumpkin-common.dtsi | 2 +
drivers/input/keyboard/mtk-pmic-keys.c | 17 +
drivers/mfd/mt6397-core.c | 295 ++++---
drivers/mfd/mt6397-irq.c | 8 +
drivers/pinctrl/mediatek/pinctrl-mt6397.c | 37 +-
drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h | 64 ++
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mt6392-regulator.c | 764 ++++++++++++++++++
.../regulator/mediatek,mt6392-regulator.h | 23 +
include/linux/mfd/mt6392/core.h | 43 +
include/linux/mfd/mt6392/registers.h | 488 +++++++++++
include/linux/mfd/mt6397/core.h | 1 +
include/linux/regulator/mt6392-regulator.h | 42 +
18 files changed, 1973 insertions(+), 162 deletions(-)
create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6392-regulator.yaml
create mode 100644 arch/arm64/boot/dts/mediatek/mt6392.dtsi
create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt6392.h
create mode 100644 drivers/regulator/mt6392-regulator.c
create mode 100644 include/dt-bindings/regulator/mediatek,mt6392-regulator.h
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
* Re: [PATCH RFC v4 01/12] dt-bindings: clk: zte: Add zx297520v3 top clock and reset bindings
From: Stefan Dösinger @ 2026-06-20 17:28 UTC (permalink / raw)
To: Conor Dooley
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Brian Masney, linux-clk, devicetree,
linux-kernel, linux-arm-kernel
In-Reply-To: <20260618-fantasy-estimate-6c52edbc6890@spud>
[-- Attachment #1: Type: text/plain, Size: 2446 bytes --]
Hi Conor,
Am Donnerstag, 18. Juni 2026, 22:54:53 Ostafrikanische Zeit schrieb Conor
Dooley:
I think I get the gist of your suggestions. I have a few follow-up questions
to make sure I understand things right:
> I think aux bus makes perfect sense when you have a clock/reset
> controller, but once you start expanding past that and you have reboot
> or hwmon or hwspinlock then mfd starts to make sense.
At what point does it make sense to move the bindings from bindings/clock to
bindings/mfd? The controllers are still very clock-heavy. allwinner,*-
prcm.yaml look like clock, reset, misc controllers in mfd/ whereas
ingenic,cgu.yaml, sprd,sc9863a-clk.yaml and da8xx-cfgchip.txt are clock + misc
drivers in clock/.
Likewise for the node names: syscon@ or clock-controller@?
> You'd then have topclock that is a syscon + simple-mfd, matrixclk that is
> a syscon and lsp that's using the aux bus. The topclock and matrixclock
> would have dedicated and trivial drivers somewhere that have the mfd_cells
> and call mfd_add_devices().
Do I even need simple-mfd? It seems I can add the syscon-reboot node via
mfd_cells too by setting .of_compatible. It seems once it has a driver (even a
very short one) simple-mfd is misplaced.
What about syscon? Topclk needs it for syscon-reboot and the watchdog
controls. For the other two I only want a regmap. Afaiu device_node_to_regmap
works without a "syscon" compatible. There's also regmap_init_mmio, but afaics
I only want this when my driver is the only one using the regmap.
> Probably the compatibles you've chosen start to make less sense at this
> point though, but probably "topclk" and "matrixclk" are not what the
> documentation for this device calls these register regions?
Yeah I'll rename them top topcrm / matrixcrm / lspcrm. I just stuck to the old
names for this email.
> I think the priority is having something that reflects the hardware
> accurately, I wouldn't compromise on that just to have the same design
> for all three drivers.
As far as I can see the primary difference between mfd_add_devices and simple-
mfd + child nodes is that the latter makes the MFD composition visible in the
device tree and the former keeps it a driver implementation detail. My sense
is that the latter is preferred unless a subcomponent of the MFD might be
reused in other components - e.g. an ADC is used in PMIC-abc and PMIC-xyz and
thus the driver can be reused as well.
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 870 bytes --]
^ permalink raw reply
* Re: [PATCH] PCI: meson: Fix PERST# timing by asserting reset before LTSSM enable
From: Ronald Claveau @ 2026-06-20 16:40 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Gowtham Kudupudi, robh, bhelgaas, neil.armstrong, khilman,
jbrunet, martin.blumenstingl, linux-pci, linux-amlogic,
linux-arm-kernel, linux-kernel, yue.wang, lpieralisi, kwilczynski
In-Reply-To: <qq4dum3xqs2stcrd6ula75snrxy34elhodrtp3gftjgzqhs3ir@ykl54gvrfwxs>
On 6/20/26 5:11 PM, Manivannan Sadhasivam wrote:
> On Mon, Jun 15, 2026 at 12:34:11PM +0200, Ronald Claveau wrote:
>> On 6/14/26 3:56 AM, Gowtham Kudupudi wrote:
>>> On warm reboot, the PCIe controller's LTSSM starts link training
>>> immediately if PERST# is already deasserted from the previous boot.
>>> The driver then pulses PERST# for only 500us, which is too short to
>>> properly reset the endpoint device that has already started training.
>>>
>>> Fix by moving the PERST# assert/deassert pulse BEFORE enabling LTSSM,
>>> so the endpoint gets a clean reset cycle before link training begins.
>>>
>>> This was found on Amlogic G12B (A311D) with NVMe on an M.2 slot.
>>> Cold boot worked because POR held PERST# low; warm reboot did not.
>>> The fix was confirmed on a Banana Pi CM4 with Waveshare IO base board.
>>>
>>> Signed-off-by: Gowtham Kudupudi <gowtham@ferryfair.com>
>>> ---
>>> drivers/pci/controller/dwc/pci-meson.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
>>> index 5f8e2f4b3c12..3a7e9f1d5b8c 100644
>>> --- a/drivers/pci/controller/dwc/pci-meson.c
>>> +++ b/drivers/pci/controller/dwc/pci-meson.c
>>> @@ -310,8 +310,8 @@ static int meson_pcie_start_link(struct dw_pcie *pci)
>>> {
>>> struct meson_pcie *mp = to_meson_pcie(pci);
>>>
>>> + meson_pcie_assert_reset(mp);
>>> meson_pcie_ltssm_enable(mp);
>>> - meson_pcie_assert_reset(mp);
>
> meson_pcie_assert_reset() itself is wrong as it toggles PERST#. You'd just need:
>
> msleep(PCIE_T_PERST_CLK_US);
> gpiod_set_value_cansleep(mp->reset_gpio, GPIOD_OUT_LOW)
>
> but in probe(), after meson_pcie_probe_clocks() as that's when both power and
> REFCLK becomes stable.
>
>>>
>>> return 0;
>>> }
>>
>> Hi Gowtham,
>>
>> I have a patch [1] that I haven't submitted yet.
>> This might be related to your issue, what do you think ?
>>
>> [1] https://github.com/rclaveau-tech/linux-khadas/commit/bee0a02d9756
>>
>
> This patch is also needed as it correctly fixes the PERST# polarity when
> requesting the GPIO. Since the devicetree is defining the PERST# GPIO as
> ACIVE_LOW, the driver should request it as GPIOD_OUT_HIGH to make sure that
> PERST# is asserted.
>
> So please submit the referenced patch.
>
> - Mani
>
Hi Mani,
I sent it here:
https://lore.kernel.org/all/20260616-fix-meson-pcie-reset-gpio-v1-1-fca404b4c8be@aliel.fr/
--
Best regards,
Ronald
^ permalink raw reply
* [PATCH] wifi: mt76: mt7915: guard HE capability lookups
From: Ruoyu Wang @ 2026-06-20 15:53 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
Ruoyu Wang
mt7915_mcu_bss_he_tlv() and mt7915_mcu_sta_bfer_tlv() both run after
checking HE support, then dereference the HE PHY capability returned by
mt76_connac_get_he_phy_cap(). That helper can return NULL when no
capability entry matches the vif type.
Fetch the capability before appending the TLV and skip the HE-specific
setup when no matching capability is available.
Fixes: e6d557a78b60 ("mt76: mt7915: rely on mt76_connac_get_phy utilities")
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
---
.../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 318c38149463..391c91675130 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -595,6 +595,8 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct tlv *tlv;
cap = mt76_connac_get_he_phy_cap(phy->mt76, vif);
+ if (!cap)
+ return;
tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he));
@@ -1177,13 +1179,12 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy,
}
static void
-mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
- struct mt7915_phy *phy, struct sta_rec_bf *bf)
+mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta,
+ const struct ieee80211_sta_he_cap *vc,
+ struct sta_rec_bf *bf)
{
struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap;
struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;
- const struct ieee80211_sta_he_cap *vc =
- mt76_connac_get_he_phy_cap(phy->mt76, vif);
const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem;
u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80);
u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);
@@ -1242,6 +1243,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt7915_phy *phy = mvif->phy;
+ const struct ieee80211_sta_he_cap *vc = NULL;
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
struct sta_rec_bf *bf;
struct tlv *tlv;
@@ -1260,6 +1262,12 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
if (!ebf && !dev->ibf)
return;
+ if (sta->deflink.he_cap.has_he && ebf) {
+ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif);
+ if (!vc)
+ return;
+ }
+
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf));
bf = (struct sta_rec_bf *)tlv;
@@ -1268,7 +1276,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
* ht: iBF only, since mac80211 lacks of eBF support
*/
if (sta->deflink.he_cap.has_he && ebf)
- mt7915_mcu_sta_bfer_he(sta, vif, phy, bf);
+ mt7915_mcu_sta_bfer_he(sta, vc, bf);
else if (sta->deflink.vht_cap.vht_supported)
mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf);
else if (sta->deflink.ht_cap.ht_supported)
^ permalink raw reply related
* Re: [PATCH] PCI: meson: Fix PERST# timing by asserting reset before LTSSM enable
From: Manivannan Sadhasivam @ 2026-06-20 15:11 UTC (permalink / raw)
To: Ronald Claveau
Cc: Gowtham Kudupudi, robh, bhelgaas, neil.armstrong, khilman,
jbrunet, martin.blumenstingl, linux-pci, linux-amlogic,
linux-arm-kernel, linux-kernel, yue.wang, lpieralisi, kwilczynski
In-Reply-To: <84cc8b0c-da06-4d01-a076-9743c29c91f6@aliel.fr>
On Mon, Jun 15, 2026 at 12:34:11PM +0200, Ronald Claveau wrote:
> On 6/14/26 3:56 AM, Gowtham Kudupudi wrote:
> > On warm reboot, the PCIe controller's LTSSM starts link training
> > immediately if PERST# is already deasserted from the previous boot.
> > The driver then pulses PERST# for only 500us, which is too short to
> > properly reset the endpoint device that has already started training.
> >
> > Fix by moving the PERST# assert/deassert pulse BEFORE enabling LTSSM,
> > so the endpoint gets a clean reset cycle before link training begins.
> >
> > This was found on Amlogic G12B (A311D) with NVMe on an M.2 slot.
> > Cold boot worked because POR held PERST# low; warm reboot did not.
> > The fix was confirmed on a Banana Pi CM4 with Waveshare IO base board.
> >
> > Signed-off-by: Gowtham Kudupudi <gowtham@ferryfair.com>
> > ---
> > drivers/pci/controller/dwc/pci-meson.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
> > index 5f8e2f4b3c12..3a7e9f1d5b8c 100644
> > --- a/drivers/pci/controller/dwc/pci-meson.c
> > +++ b/drivers/pci/controller/dwc/pci-meson.c
> > @@ -310,8 +310,8 @@ static int meson_pcie_start_link(struct dw_pcie *pci)
> > {
> > struct meson_pcie *mp = to_meson_pcie(pci);
> >
> > + meson_pcie_assert_reset(mp);
> > meson_pcie_ltssm_enable(mp);
> > - meson_pcie_assert_reset(mp);
meson_pcie_assert_reset() itself is wrong as it toggles PERST#. You'd just need:
msleep(PCIE_T_PERST_CLK_US);
gpiod_set_value_cansleep(mp->reset_gpio, GPIOD_OUT_LOW)
but in probe(), after meson_pcie_probe_clocks() as that's when both power and
REFCLK becomes stable.
> >
> > return 0;
> > }
>
> Hi Gowtham,
>
> I have a patch [1] that I haven't submitted yet.
> This might be related to your issue, what do you think ?
>
> [1] https://github.com/rclaveau-tech/linux-khadas/commit/bee0a02d9756
>
This patch is also needed as it correctly fixes the PERST# polarity when
requesting the GPIO. Since the devicetree is defining the PERST# GPIO as
ACIVE_LOW, the driver should request it as GPIOD_OUT_HIGH to make sure that
PERST# is asserted.
So please submit the referenced patch.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* [PATCH net v3] net: airoha: fix BQL underflow in shared QDMA TX ring
From: Lorenzo Bianconi @ 2026-06-20 15:04 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Lorenzo Bianconi
Cc: Wayen Yan, linux-arm-kernel, linux-mediatek, netdev
When multiple netdevs share a QDMA TX ring and one device is stopped,
netdev_tx_reset_subqueue() zeroes that device's BQL counters while its
pending skbs remain in the shared HW TX ring. When NAPI later completes
those skbs via netdev_tx_completed_queue(), the already-zeroed
dql->num_queued counter underflows.
Fix the issue:
- Remove netdev_tx_reset_subqueue() from airoha_dev_stop() so pending
skbs are completed naturally by NAPI with proper BQL accounting.
- Rework airoha_qdma_tx_cleanup() to disable TX DMA, flush BQL
counters, DMA-unmap and free all pending skbs while skb->dev
references are still valid. Use a per-queue flushing flag checked
under q->lock in airoha_dev_xmit() to prevent races between teardown
and transmit. Call airoha_qdma_stop_napi() before
airoha_qdma_tx_cleanup() at the call sites.
- Move DMA engine start into probe. Split DMA teardown so TX DMA is
disabled in airoha_qdma_tx_cleanup() and RX DMA in
airoha_qdma_cleanup().
- Remove qdma->users counter since DMA lifetime is now tied to
probe/cleanup rather than per-netdev open/stop.
Fixes: a9c2ca61fec7 ("net: airoha: Support multiple net_devices for a single FE GDM port")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes in v3:
- Remove airoha_qdma users counter.
- Drop DEV_STATE_FLUSH bit and add per-queue flushing bool to avoid any
race between airoha_qdma_tx_flush() and airoha_dev_xmit().
- Refactor airoha_qdma_cleanup_tx_queue().
- Rename airoha_qdma_cleanup_tx_queue() in airoha_qdma_tx_cleanup().
- Link to v2: https://lore.kernel.org/r/20260619-airoha-bql-fixes-v2-1-4351d6a24484@kernel.org
Changes in v2:
- Introduce airoha_qdma_tx_flush() to account BQL in airoha_remove() or
airoha_probe() error path.
- Fix possible NULL pointer dereference in airoha_qdma_cleanup().
- Introduce DEV_STATE_FLUSH().
- Move back airoha_hw_cleanup().
- Set proper Fixes tag.
- Link to v1: https://lore.kernel.org/r/20260618-airoha-bql-fixes-v1-1-ffd2c2089518@kernel.org
---
drivers/net/ethernet/airoha/airoha_eth.c | 166 +++++++++++++++++--------------
drivers/net/ethernet/airoha/airoha_eth.h | 3 +-
2 files changed, 93 insertions(+), 76 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 64dde6464f3f..8b81e932d535 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1004,6 +1004,7 @@ static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
e = &q->entry[index];
skb = e->skb;
+ e->skb = NULL;
dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
DMA_TO_DEVICE);
@@ -1147,55 +1148,76 @@ static int airoha_qdma_init_tx(struct airoha_qdma *qdma)
return 0;
}
-static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
+static void airoha_qdma_tx_cleanup(struct airoha_qdma *qdma)
{
- struct airoha_qdma *qdma = q->qdma;
- struct airoha_eth *eth = qdma->eth;
- int i, qid = q - &qdma->q_tx[0];
- u16 index = 0;
+ u32 status;
+ int i;
- spin_lock_bh(&q->lock);
- for (i = 0; i < q->ndesc; i++) {
- struct airoha_queue_entry *e = &q->entry[i];
- struct airoha_qdma_desc *desc = &q->desc[i];
+ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
+ GLOBAL_CFG_TX_DMA_EN_MASK);
+ if (read_poll_timeout(airoha_qdma_rr, status,
+ !(status & GLOBAL_CFG_TX_DMA_BUSY_MASK),
+ USEC_PER_MSEC, 50 * USEC_PER_MSEC, true,
+ qdma, REG_QDMA_GLOBAL_CFG))
+ dev_warn(qdma->eth->dev, "QDMA TX DMA busy timeout\n");
- if (!e->dma_addr)
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
+ struct airoha_queue *q = &qdma->q_tx[i];
+ u16 index = 0;
+ int j;
+
+ if (!q->ndesc)
continue;
- dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
- DMA_TO_DEVICE);
- dev_kfree_skb_any(e->skb);
- e->dma_addr = 0;
- e->skb = NULL;
- list_add_tail(&e->list, &q->tx_list);
+ spin_lock_bh(&q->lock);
- /* Reset DMA descriptor */
- WRITE_ONCE(desc->ctrl, 0);
- WRITE_ONCE(desc->addr, 0);
- WRITE_ONCE(desc->data, 0);
- WRITE_ONCE(desc->msg0, 0);
- WRITE_ONCE(desc->msg1, 0);
- WRITE_ONCE(desc->msg2, 0);
+ q->flushing = true;
+ for (j = 0; j < q->ndesc; j++) {
+ struct airoha_queue_entry *e = &q->entry[j];
+ struct airoha_qdma_desc *desc = &q->desc[j];
+ struct sk_buff *skb = e->skb;
- q->queued--;
- }
+ if (!e->dma_addr)
+ continue;
- if (!list_empty(&q->tx_list)) {
- struct airoha_queue_entry *e;
+ dma_unmap_single(qdma->eth->dev, e->dma_addr,
+ e->dma_len, DMA_TO_DEVICE);
+ e->dma_addr = 0;
+ list_add_tail(&e->list, &q->tx_list);
+
+ WRITE_ONCE(desc->ctrl, 0);
+ WRITE_ONCE(desc->addr, 0);
+ WRITE_ONCE(desc->data, 0);
+ WRITE_ONCE(desc->msg0, 0);
+ WRITE_ONCE(desc->msg1, 0);
+ WRITE_ONCE(desc->msg2, 0);
+
+ if (skb) {
+ struct netdev_queue *txq;
+
+ txq = skb_get_tx_queue(skb->dev, skb);
+ netdev_tx_completed_queue(txq, 1, skb->len);
+ dev_kfree_skb_any(skb);
+ e->skb = NULL;
+ }
- e = list_first_entry(&q->tx_list, struct airoha_queue_entry,
- list);
- index = e - q->entry;
- }
- /* Set TX_DMA_IDX to TX_CPU_IDX to notify the hw the QDMA TX ring is
- * empty.
- */
- airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
- FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
- airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK,
- FIELD_PREP(TX_RING_DMA_IDX_MASK, index));
+ q->queued--;
+ }
- spin_unlock_bh(&q->lock);
+ if (!list_empty(&q->tx_list)) {
+ struct airoha_queue_entry *e;
+
+ e = list_first_entry(&q->tx_list,
+ struct airoha_queue_entry, list);
+ index = e - q->entry;
+ }
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(i), TX_RING_CPU_IDX_MASK,
+ FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
+ airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(i), TX_RING_DMA_IDX_MASK,
+ FIELD_PREP(TX_RING_DMA_IDX_MASK, index));
+
+ spin_unlock_bh(&q->lock);
+ }
}
static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma)
@@ -1523,10 +1545,23 @@ static int airoha_qdma_init(struct platform_device *pdev,
return airoha_qdma_hw_init(qdma);
}
-static void airoha_qdma_cleanup(struct airoha_qdma *qdma)
+static void airoha_qdma_cleanup(struct airoha_eth *eth,
+ struct airoha_qdma *qdma)
{
int i;
+ if (test_bit(DEV_STATE_INITIALIZED, ð->state)) {
+ u32 status;
+
+ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
+ GLOBAL_CFG_RX_DMA_EN_MASK);
+ if (read_poll_timeout(airoha_qdma_rr, status,
+ !(status & GLOBAL_CFG_RX_DMA_BUSY_MASK),
+ USEC_PER_MSEC, 50 * USEC_PER_MSEC, true,
+ qdma, REG_QDMA_GLOBAL_CFG))
+ dev_warn(eth->dev, "QDMA RX DMA busy timeout\n");
+ }
+
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
if (!qdma->q_rx[i].ndesc)
continue;
@@ -1546,12 +1581,6 @@ static void airoha_qdma_cleanup(struct airoha_qdma *qdma)
netif_napi_del(&qdma->q_tx_irq[i].napi);
}
- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
- if (!qdma->q_tx[i].ndesc)
- continue;
-
- airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
- }
}
static int airoha_hw_init(struct platform_device *pdev,
@@ -1593,7 +1622,7 @@ static int airoha_hw_init(struct platform_device *pdev,
return 0;
error:
for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
- airoha_qdma_cleanup(ð->qdma[i]);
+ airoha_qdma_cleanup(eth, ð->qdma[i]);
return err;
}
@@ -1603,7 +1632,7 @@ static void airoha_hw_cleanup(struct airoha_eth *eth)
int i;
for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
- airoha_qdma_cleanup(ð->qdma[i]);
+ airoha_qdma_cleanup(eth, ð->qdma[i]);
airoha_ppe_deinit(eth);
}
@@ -1837,11 +1866,6 @@ static int airoha_dev_open(struct net_device *netdev)
}
port->users++;
- airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG,
- GLOBAL_CFG_TX_DMA_EN_MASK |
- GLOBAL_CFG_RX_DMA_EN_MASK);
- qdma->users++;
-
if (!airoha_is_lan_gdm_dev(dev) &&
airoha_ppe_is_enabled(qdma->eth, 1))
pse_port = FE_PSE_PORT_PPE2;
@@ -1880,12 +1904,9 @@ static int airoha_dev_stop(struct net_device *netdev)
struct airoha_gdm_dev *dev = netdev_priv(netdev);
struct airoha_gdm_port *port = dev->port;
struct airoha_qdma *qdma = dev->qdma;
- int i;
netif_tx_disable(netdev);
airoha_set_vip_for_gdm_port(dev, false);
- for (i = 0; i < netdev->num_tx_queues; i++)
- netdev_tx_reset_subqueue(netdev, i);
if (--port->users)
airoha_set_port_mtu(dev->eth, port);
@@ -1893,20 +1914,6 @@ static int airoha_dev_stop(struct net_device *netdev)
airoha_set_gdm_port_fwd_cfg(qdma->eth,
REG_GDM_FWD_CFG(port->id),
FE_PSE_PORT_DROP);
-
- if (!--qdma->users) {
- airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
- GLOBAL_CFG_TX_DMA_EN_MASK |
- GLOBAL_CFG_RX_DMA_EN_MASK);
-
- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
- if (!qdma->q_tx[i].ndesc)
- continue;
-
- airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
- }
- }
-
return 0;
}
@@ -2229,6 +2236,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
spin_lock_bh(&q->lock);
+ if (q->flushing)
+ goto error_unlock;
+
txq = skb_get_tx_queue(netdev, skb);
nr_frags = 1 + skb_shinfo(skb)->nr_frags;
@@ -2309,7 +2319,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
e->dma_addr = 0;
}
list_splice(&tx_list, &q->tx_list);
-
+error_unlock:
spin_unlock_bh(&q->lock);
error:
dev_kfree_skb_any(skb);
@@ -3413,8 +3423,12 @@ static int airoha_probe(struct platform_device *pdev)
if (err)
goto error_netdev_free;
- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
airoha_qdma_start_napi(ð->qdma[i]);
+ airoha_qdma_set(ð->qdma[i], REG_QDMA_GLOBAL_CFG,
+ GLOBAL_CFG_TX_DMA_EN_MASK |
+ GLOBAL_CFG_RX_DMA_EN_MASK);
+ }
for_each_child_of_node(pdev->dev.of_node, np) {
if (!of_device_is_compatible(np, "airoha,eth-mac"))
@@ -3437,8 +3451,10 @@ static int airoha_probe(struct platform_device *pdev)
return 0;
error_napi_stop:
- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
airoha_qdma_stop_napi(ð->qdma[i]);
+ airoha_qdma_tx_cleanup(ð->qdma[i]);
+ }
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
@@ -3474,8 +3490,10 @@ static void airoha_remove(struct platform_device *pdev)
struct airoha_eth *eth = platform_get_drvdata(pdev);
int i;
- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
airoha_qdma_stop_napi(ð->qdma[i]);
+ airoha_qdma_tx_cleanup(ð->qdma[i]);
+ }
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index 41d2e7a1f9fb..d7ff8c5200e2 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -197,6 +197,7 @@ struct airoha_queue {
int free_thr;
int buf_size;
bool txq_stopped;
+ bool flushing;
struct napi_struct napi;
struct page_pool *page_pool;
@@ -524,8 +525,6 @@ struct airoha_qdma {
struct airoha_eth *eth;
void __iomem *regs;
- int users;
-
struct airoha_irq_bank irq_banks[AIROHA_MAX_NUM_IRQ_BANKS];
struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
---
base-commit: a887f2c7da66a805a55fd8706d45faec85f646db
change-id: 20260618-airoha-bql-fixes-f57b2d108573
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* Re: [PATCH 15/78] ASoC: codecs: cs42l43: Use guard() for mutex locks
From: Bui Duc Phuc @ 2026-06-20 14:31 UTC (permalink / raw)
To: Takashi Iwai
Cc: Charles Keepax, David Laight, Mark Brown, Liam Girdwood,
Jaroslav Kysela, Takashi Iwai, Cheng-Yi Chiang, Tzung-Bi Shih,
Guenter Roeck, Benson Leung, David Rhodes, Richard Fitzgerald,
povik+lin, Support Opensource, Nick Li, Herve Codina,
Srinivas Kandagatla, Matthias Brugger, AngeloGioacchino Del Regno,
Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, Oder Chiou,
Lars-Peter Clausen, nuno.sa, Steven Eckhoff, patches,
chrome-platform, asahi, linux-arm-msm, linux-sound, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <871pe2kcif.wl-tiwai@suse.de>
On Fri, Jun 19, 2026 at 6:14 PM Takashi Iwai <tiwai@suse.de> wrote:
>
> On Fri, 19 Jun 2026 12:57:57 +0200,
> Bui Duc Phuc wrote:
> >
> > Hi Charles, David,
> >
> >
> >
> > > > > > > I believe you have to use scoped_guard here, as there is a return
> > > > > > > from the function above, if memory serves it attempts to release
> > > > > > > the mutex on that path despite it being above the guard.
> > > > > >
> > > > > > Indeed.
> > > > > > I believe clang will complain.
> > > > > > That makes these mechanical conversions of existing code dangerous churn.
> > > > > >
> > > > > > While using guard() (etc) can make it easier to ensure the lock is released
> > > > > > when functions have multiple error exits, I'm not convinced it makes the
> > > > > > code any easier to read (other people may disagree).
> > > > >
> > > > > I built the code with both GCC and Clang and didn't see any warnings.
> > > > >
> > > > > My understanding was that the early return exits the function before
> > > > > the guard is instantiated, so it should not affect the guard's cleanup
> > > > > handling.
> > > >
> > > > When a variable is defined (and initialised) part way down a block the
> > > > compiler moves the definition to the top of the block but doesn't initialise
> > > > it at all, the first assignment happens where the code contains the
> > > > definition.
> > > >
> > > > However the destructor is always called at the end of the block.
> > > > So if you return from a function before the definition the destructor
> > > > is called with an uninitialised argument.
> > >
> > > My understanding was exactly as your David, but it seems that isn't
> > > the whole story and indeed I had to fix a bug in our SDCA code
> > > that hit this. However testing this out, results in some things I
> > > find very hard to explain.
> > >
> > > It seems as far as I have managed to test, the code below works
> > > fine as Phuc suggests. It does not appear to run the mutex_unlock
> > > on the error path.
> > >
> > > int function()
> > > {
> > > if (error)
> > > return;
> > >
> > > guard(mutex)(&mutex);
> > >
> > > stuff();
> > >
> > > return;
> > > }
> > >
> >
> > Thanks both for the clarification.
> >
> > > The situation I hit this in before that doesn't work was actually
> > > this:
> > >
> > > int function()
> > > {
> > > if (error)
> > > goto error_label;
> > >
> > > guard(mutex)(&mutex);
> > >
> > > stuff();
> > >
> > > error_label;
> > > return;
> > > }
> > >
> > > Which in this case it does run the mutex_unlock and NULL pointer.
> > > Will try to find sometime to look at the generated assembly, but
> > > this basically totally blows my mind. Very unclear as to if this
> > > is supposed to work this way or just does by pure luck.
> > >
> >
> > As stated in cleanup.h, mixing goto-based cleanup and scope-based
> > cleanup helpers in the same function is not expected, so I think
> > we should keep a consistent approach here.
>
> Right, and IIRC, clang would complain the mixed goto case at least
> with W=1.
>
>
> Takashi
Thank you all.
In fact, I have only been using GCC for building and testing. It was
only after David mentioned Clang that I decided to give it a try, and
this is actually the first time I have used it.
Also, thanks to Takashi-san for adding the W=1 build option. It helped
me catch and address warnings more easily.
I will send a v2 to address a few remaining goto cases that slipped through.
In addition, I will switch to using guards for PM runtime to reduce
indentation and improve code readability.
Best regards,
Phuc
^ permalink raw reply
* Re: [PATCH 4/4] spi: nxp-fspi: disable runtime PM on probe failures
From: Frank Li @ 2026-06-20 14:09 UTC (permalink / raw)
To: Jiawen Liu
Cc: broonie, cl634, william.zhang, kursad.oney, jonas.gorski,
bcm-kernel-feedback-list, anand.gore, f.fainelli, rafal, olteanv,
han.xu, haibo.chen, yogeshgaur.83, linux-spi, linux-kernel,
linux-arm-kernel, imx
In-Reply-To: <tencent_8FC0B8DFAF4AE67AEBA20548045D53A77707@qq.com>
On Sat, Jun 20, 2026 at 12:39:31PM +0400, Jiawen Liu wrote:
> [You don't often get email from 1298662399@qq.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> nxp_fspi_probe() enables runtime PM and autosuspend before
> several operations that can fail.
>
> Some failure paths returned directly before the devm cleanup
> action was installed, leaving runtime PM enabled.
>
> Route those failures through a common runtime PM cleanup path.
> Use pm_runtime_resume_and_get() for the initial clock enable.
>
> Signed-off-by: Jiawen Liu <1298662399@qq.com>
> ---
> drivers/spi/spi-nxp-fspi.c | 31 ++++++++++++++++++++++---------
> 1 file changed, 22 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index 1e36ae084dd8..d94a2a7b98d4 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -1350,9 +1350,11 @@ static int nxp_fspi_probe(struct platform_device *pdev)
> pm_runtime_use_autosuspend(dev);
>
> /* enable clock */
> - ret = pm_runtime_get_sync(f->dev);
> - if (ret < 0)
> - return dev_err_probe(dev, ret, "Failed to enable clock");
> + ret = pm_runtime_resume_and_get(f->dev);
> + if (ret < 0) {
> + ret = dev_err_probe(dev, ret, "Failed to enable clock");
> + goto err_disable_pm;
> + }
Use PM_RUNTIME_ACQUIRE help macro to avoid all goto
Frank
>
> /* Clear potential interrupts */
> reg = fspi_readl(f, f->iobase + FSPI_INTR);
> @@ -1362,18 +1364,24 @@ static int nxp_fspi_probe(struct platform_device *pdev)
> nxp_fspi_default_setup(f);
>
> ret = pm_runtime_put_sync(dev);
> - if (ret < 0)
> - return dev_err_probe(dev, ret, "Failed to disable clock");
> + if (ret < 0) {
> + ret = dev_err_probe(dev, ret, "Failed to disable clock");
> + goto err_disable_pm;
> + }
>
> init_completion(&f->c);
> ret = devm_request_irq(dev, irq,
> nxp_fspi_irq_handler, 0, pdev->name, f);
> - if (ret)
> - return dev_err_probe(dev, ret, "Failed to request irq\n");
> + if (ret) {
> + ret = dev_err_probe(dev, ret, "Failed to request irq\n");
> + goto err_disable_pm;
> + }
>
> ret = devm_mutex_init(dev, &f->lock);
> - if (ret)
> - return dev_err_probe(dev, ret, "Failed to initialize lock\n");
> + if (ret) {
> + ret = dev_err_probe(dev, ret, "Failed to initialize lock\n");
> + goto err_disable_pm;
> + }
>
> ctlr->bus_num = -1;
> ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT;
> @@ -1389,6 +1397,11 @@ static int nxp_fspi_probe(struct platform_device *pdev)
> return ret;
>
> return devm_spi_register_controller(&pdev->dev, ctlr);
> +
> +err_disable_pm:
> + pm_runtime_dont_use_autosuspend(dev);
> + pm_runtime_disable(dev);
> + return ret;
> }
>
> static int nxp_fspi_runtime_suspend(struct device *dev)
> --
> 2.34.1
>
>
^ permalink raw reply
* Re: [PATCH v6] soc: aspeed: lpc-snoop: Fix usercopy overflow in snoop_file_read
From: Karthikeyan KS @ 2026-06-20 13:11 UTC (permalink / raw)
To: andrew
Cc: joel, andrew, Kees Cook, linux-arm-kernel, linux-aspeed,
linux-kernel, linux-hardening
In-Reply-To: <033f2657ae6a94ad13d22f717a2900afb75d892d.camel@codeconstruct.com.au>
On Wed, 2026-06-17 at 13:10 +0000, Andrew Jeffery wrote:
> Can you confirm you have tested on hardware a backport of this
> patch to your BSP kernel?
Not until yesterday, done now. Backported the fix to
the BSP kernel (5.4.x) on the AST2600 BMC where the original failure
was observed. Tested under continuous host reboot cycles with concurrent
userspace reads on /dev/aspeed-lpc-snoop0. no panic, no usercopy
splat. Same workload on the unpatched BSP reproduced reliably.
Thanks,
Karthikeyan
^ permalink raw reply
* Re: [PATCH v2] media: meson: vdec: fix use-after-free of decode work in stop/close path
From: Anand Moon @ 2026-06-20 13:45 UTC (permalink / raw)
To: Doruk Tan Ozturk
Cc: neil.armstrong, mchehab, gregkh, hverkuil, jbrunet,
martin.blumenstingl, linux-media, linux-amlogic, linux-staging,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260617074123.32464-1-doruk@0sec.ai>
Hi Doruk,
On Wed, 17 Jun 2026 at 13:11, Doruk Tan Ozturk <doruk@0sec.ai> wrote:
>
> Please drop v1 and v2 -- both are wrong, and the sashiko review was right
> about the deadlock.
>
> The underlying bug is real: vdec_close() does kfree(sess) (and
> v4l2_m2m_ctx_release() frees sess->m2m_ctx) without cancelling
> sess->esparser_queue_work, whose worker dereferences sess->lock and
> sess->m2m_ctx -> UAF if it is pending/running at teardown.
>
> But cancelling on the streamoff/poweroff path can't work:
>
> 1) Deadlock. The worker takes sess->lock. For an m2m fh the ioctl core
> takes m2m_ctx->q_lock (== sess->lock) for VIDIOC_STREAMOFF and holds it
> across the handler, so vdec_stop_streaming() -> vdec_poweroff() already
> runs under sess->lock; cancel_work_sync() there waits on a worker blocked
> on that same lock.
>
> 2) Use-after-power-down. v2 also cancelled after vdec_ops->stop(), which
> power-gates VDEC1 (__vdec_1_stop()), while the worker still reads a VDEC1
> register (vdec_1_vififo_level() -> VLD_MEM_VIFIFO_LEVEL).
>
> The only deadlock-free point I see is vdec_close() (the ->release fop, not
> under sess->lock), cancelling before v4l2_m2m_ctx_release() -- but that
> still leaves the threaded VDEC ISR (amvdec_dst_buf_done() ->
> schedule_work()) able to re-arm the worker, and there are adjacent teardown
> issues (esparser_isr() vs the dos_parser_clk disable;
> vdec_decoder_cmd()/esparser_queue_eos() without sess->lock).
>
> I don't have Meson hardware to validate a corrected fix. Is a
> vdec_close()-only cancel (plus quiescing the VDEC IRQ outside sess->lock)
> the direction you'd want, or would you rather take it given the HW testing
> and the surrounding teardown concerns?
>
Actually, I've been working on this issue for a while and have made a few
changes. I really like your approach, so I'd like to integrate
it alongside my cleanup changes. It should solve this issue.
diff --git a/drivers/staging/media/meson/vdec/esparser.c
b/drivers/staging/media/meson/vdec/esparser.c
index 4632346f04a9..c5b909c6a2b7 100644
--- a/drivers/staging/media/meson/vdec/esparser.c
+++ b/drivers/staging/media/meson/vdec/esparser.c
@@ -375,6 +375,9 @@ void esparser_queue_all_src(struct work_struct *work)
struct amvdec_session *sess =
container_of(work, struct amvdec_session, esparser_queue_work);
+ if (READ_ONCE(sess->should_stop))
+ return;
+
mutex_lock(&sess->lock);
v4l2_m2m_for_each_src_buf_safe(sess->m2m_ctx, buf, n) {
if (sess->should_stop)
diff --git a/drivers/staging/media/meson/vdec/vdec.c
b/drivers/staging/media/meson/vdec/vdec.c
index 51ea7beef811..de3a660d22b1 100644
--- a/drivers/staging/media/meson/vdec/vdec.c
+++ b/drivers/staging/media/meson/vdec/vdec.c
@@ -448,6 +448,9 @@ static void vdec_stop_streaming(struct vb2_queue *q)
enum amvdec_status old_status;
bool full_cleanup = false;
+ sess->should_stop = 1;
+ cancel_work_sync(&sess->esparser_queue_work);
+
/*
* Secure the hardware lock for the ENTIRE state evaluation
* sequence to block concurrent start_streaming() callers.
@@ -1000,6 +1003,9 @@ static int vdec_close(struct file *file)
{
struct amvdec_session *sess = file_to_amvdec_session(file);
+ sess->should_stop = 1;
+ cancel_work_sync(&sess->esparser_queue_work);
+
if (!IS_ERR_OR_NULL(sess->recycle_thread)) {
kthread_stop(sess->recycle_thread);
sess->recycle_thread = NULL;
> Doruk
>
Thanks
-Anand
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply related
* Re: [PATCH] PCI: meson: Fix PERST# timing by asserting reset before LTSSM enable
From: Ronald Claveau @ 2026-06-20 8:59 UTC (permalink / raw)
To: gowtham
Cc: robh, bhelgaas, khilman, jbrunet, martin.blumenstingl, linux-pci,
linux-amlogic, linux-arm-kernel, linux-kernel, yue.wang,
lpieralisi, kwilczynski, mani, neil.armstrong
In-Reply-To: <20260618020025.2739cb96@slick.ferryfair.com>
On 6/17/26 10:30 PM, gowtham wrote:
> Hi Ronald,
> I see you submitted the patch. Last couple of days I've been fixing the
> etherenet of my BPiCM4+Waveshare-io-base-b due to which I couldn't test
> your patch any sooner. Now I got my ethernet working but now I couldn't
> reproduce the issue *without* either of our patches!!!
>
> Anyway it's proper to initialize PCIe with RESET Active but I think
> meson_pcie_assert_reset(mp) will give sufficient time to PCIe devices
> to complete the reset cycle.
>
Hi Gowtham,
No worries and no rush to me.
I think it's due to how uboot set the gpio before the linux boot for my
issue, and that does not seem to be relevant for yours.
Thank you for testing the patch.
> ---
> drivers/pci/controller/dwc/pci-meson.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/dwc/pci-meson.c
> b/drivers/pci/controller/dwc/pci-meson.c index 0694084f612..c28ab40c9ff
> 100644 --- a/drivers/pci/controller/dwc/pci-meson.c
> +++ b/drivers/pci/controller/dwc/pci-meson.c
> @@ -308,8 +308,8 @@ static int meson_pcie_start_link(struct dw_pcie
> *pci) {
> struct meson_pcie *mp = to_meson_pcie(pci);
>
> - meson_pcie_ltssm_enable(mp);
> meson_pcie_assert_reset(mp);
> + meson_pcie_ltssm_enable(mp);
>
> return 0;
> }
--
Best regards,
Ronald
^ permalink raw reply
* Re: [PATCH v1] irqchip/gic-v3-its: Fix OF node reference leak
From: Marc Zyngier @ 2026-06-20 8:59 UTC (permalink / raw)
To: Yuho Choi; +Cc: Thomas Gleixner, linux-arm-kernel, linux-kernel
In-Reply-To: <20260619185808.1090575-1-dbgh9129@gmail.com>
On Fri, 19 Jun 2026 19:58:08 +0100,
Yuho Choi <dbgh9129@gmail.com> wrote:
>
> of_get_cpu_node() returns a referenced device node. In
> its_cpu_init_collection(), the node is only used to get the CPU NUMA
> node for the Cavium 23144 workaround, but the reference is never
> dropped.
>
> Store the NUMA node locally and call of_node_put() before either
> continuing with collection setup or returning early for a NUMA mismatch.
>
> Fixes: 920181ce8469 ("irqchip/gic-v3-its: Add ability to resend MAPC on resume")
> Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
> ---
> drivers/irqchip/irq-gic-v3-its.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index b57d81ad33a0..f82035eb77e5 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -3291,10 +3291,14 @@ static void its_cpu_init_collection(struct its_node *its)
> /* avoid cross node collections and its mapping */
> if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
> struct device_node *cpu_node;
> + int cpu_nid;
>
> cpu_node = of_get_cpu_node(cpu, NULL);
> + cpu_nid = of_node_to_nid(cpu_node);
> + of_node_put(cpu_node);
> +
> if (its->numa_node != NUMA_NO_NODE &&
> - its->numa_node != of_node_to_nid(cpu_node))
> + its->numa_node != cpu_nid)
> return;
> }
>
Please consider using the cleanup infrastructure instead, something
like the untested hack below.
Thanks,
M.
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 291d7668cc8da..947a15bb42012 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3290,11 +3290,10 @@ static void its_cpu_init_collection(struct its_node *its)
/* avoid cross node collections and its mapping */
if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
- struct device_node *cpu_node;
+ struct device_node *cpu_node __free(device_node) = of_get_cpu_node(cpu, NULL);
- cpu_node = of_get_cpu_node(cpu, NULL);
if (its->numa_node != NUMA_NO_NODE &&
- its->numa_node != of_node_to_nid(cpu_node))
+ its->numa_node != of_node_to_nid(cpu_node))
return;
}
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply related
* [PATCH net v5] net: airoha: Fix skb->priority underflow in airoha_dev_select_queue()
From: Wayen Yan @ 2026-06-20 8:17 UTC (permalink / raw)
To: netdev
Cc: lorenzo, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek, Joe Damato
In airoha_dev_select_queue(), the expression:
queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES;
implicitly converts to unsigned arithmetic: when skb->priority is 0
(the default for unclassified traffic), (0u - 1u) wraps to UINT_MAX,
and UINT_MAX % 8 = 7, routing default best-effort packets to the
highest-priority QoS queue. This causes QoS inversion where the
majority of traffic on a PON gateway starves actual high-priority
flows (VoIP, gaming, etc.).
The "- 1" offset was a leftover from the ETS offload implementation
that has since been removed. The correct mapping is a direct modulo:
queue = skb->priority % AIROHA_NUM_QOS_QUEUES;
This maps priority 0 → queue 0 (lowest), priority 7 → queue 7
(highest), with higher priorities wrapping around. This is the
standard Linux sk_prio → HW queue mapping used by other drivers.
Fixes: 2b288b81560b ("net: airoha: Introduce ndo_select_queue callback")
Link: https://lore.kernel.org/netdev/178185573207.2378135.3729126358670287878@gmail.com/
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Joe Damato <joe@dama.to>
---
Changes in v5:
- Rebase on net/main (previous version was incorrectly based on
net-next/origin/master, causing Patchwork CI apply failure).
Signed-off-by: Wayen Yan <win847@gmail.com>
---
drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 64dde6464f3f..3370c3df7c10 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2110,7 +2110,7 @@ static u16 airoha_dev_select_queue(struct net_device *netdev,
*/
channel = netdev_uses_dsa(netdev) ? skb_get_queue_mapping(skb) : port->id;
channel = channel % AIROHA_NUM_QOS_CHANNELS;
- queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */
+ queue = skb->priority % AIROHA_NUM_QOS_QUEUES;
queue = channel * AIROHA_NUM_QOS_QUEUES + queue;
return queue < netdev->num_tx_queues ? queue : 0;
--
2.51.0
^ permalink raw reply related
* Re: [PATCH] arm64: dts: broadcom: bcm2712: Remove non-functional EL2 virtual timer
From: Marc Zyngier @ 2026-06-20 8:49 UTC (permalink / raw)
To: Daniel Drake
Cc: robh, krzk+dt, conor+dt, florian.fainelli,
bcm-kernel-feedback-list, devicetree, linux-rpi-kernel,
linux-arm-kernel, m.szyprowski, andrea.porta
In-Reply-To: <20260619204832.586079-1-dan@reactivated.net>
Hi Daniel,
Thanks for posting this.
On Fri, 19 Jun 2026 21:48:32 +0100,
Daniel Drake <dan@reactivated.net> wrote:
>
> Commit d87773de9efe1 ("clocksource/drivers/arm_arch_timer: Default to
> EL2 virtual timer when running VHE") causes boot to hang on
> Raspberry Pi 5. The newly-selected EL2 virtual timer does not generate
> any interrupts, even though the GIC_DIST_ENABLE_SET flag has been
> confirmed set via readback.
>
> The reasons for this failure are unknown, however it is likely that
> this timer was never tested. Raspberry Pi's original devicetree did
The timer is part of the CPU, and there are enough A76 implementations
around to prove that it actually works. The same can be said for the
GIC400 this is (supposedly) attached to.
> not include this timer interrupt; it was only introduced via a
> suggestion[1] made in code review as part of the upstreaming process.
> (Current RPi firmware versions do include this timer, but only because
> they rebased on top of the upstreamed devicetree starting with
> Linux 6.12)
>
> Until more is known about this non-firing timer interrupt, remove
> the devicetree entry to enable RPi5 devices to boot.
I'd like to understand the reason why the timer interrupt isn't being
delivered *before* we paper over it, and not the other way
around. Each of the CPUs definitely have an EL2 virtual timer, the GIC
has a per-CPU interrupt, but somehow the two don't seem to be linked.
Since DT is supposed to describe the HW, I'd expect someone from
Broadcom or RPi to shine a light on this issue. Integration mistakes
happen, and we work around them (see the handful of Samsung SoCs where
the timer interrupt was simply not wired). But we absolutely need to
know what we are dealing with beforehand.
Finally, just hacking the DT is not enough. Assuming that the timer is
indeed unusable, we need to cope with the fact that there are DTs
describing it in the wild, as nobody should be forced to upgrade their
DT in lockstep with the kernel. For that, you'd also need something
like the patch below (untested, and in need of a proper commit
message, which I expect the SoC vendor to provide).
Thanks,
M.
From 9de354b472e28112d73fdb63be986f68fb3c91a9 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <maz@kernel.org>
Date: Sat, 20 Jun 2026 09:32:09 +0100
Subject: [PATCH] clocksource/drivers/arm_arch_timer: Workaround RPi5 broken
EL2 virtual timer
Insert $REASON here.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
drivers/clocksource/arm_arch_timer.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 4adf756423de9..de9007a30a923 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1090,6 +1090,16 @@ static int __init arch_timer_common_init(void)
return arch_timer_arch_init();
}
+static bool __init has_broken_el2_vtimer(void)
+{
+ static const char * const broken_el2_vtimer[] __initconst = {
+ "brcm,bcm2712",
+ NULL
+ };
+
+ return of_machine_compatible_match(broken_el2_vtimer);
+}
+
/**
* arch_timer_select_ppi() - Select suitable PPI for the current system.
*
@@ -1115,7 +1125,8 @@ static int __init arch_timer_common_init(void)
static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void)
{
if (is_kernel_in_hyp_mode()) {
- if (arch_timer_ppi[ARCH_TIMER_HYP_VIRT_PPI])
+ if (arch_timer_ppi[ARCH_TIMER_HYP_VIRT_PPI] &&
+ !has_broken_el2_vtimer())
return ARCH_TIMER_HYP_VIRT_PPI;
pr_warn_once(FW_BUG "VHE-capable CPU without EL2 virtual timer interrupt\n");
--
2.47.3
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply related
* [PATCH 3/4] spi: fsl-dspi: clean up after failed suspend and resume
From: Jiawen Liu @ 2026-06-20 8:39 UTC (permalink / raw)
To: broonie
Cc: cl634, william.zhang, kursad.oney, jonas.gorski,
bcm-kernel-feedback-list, anand.gore, f.fainelli, rafal, olteanv,
han.xu, haibo.chen, yogeshgaur.83, linux-spi, linux-kernel,
linux-arm-kernel, imx, Jiawen Liu
In-Reply-To: <20260620083931.1120616-1-1298662399@qq.com>
dspi_suspend() disabled the IRQ before spi_controller_suspend(),
but ignored a suspend failure and kept tearing the device down.
Restore the IRQ and return the error if suspend fails.
dspi_resume() also left the clock prepared if controller resume or
hardware init failed. Route those failures through clock cleanup.
Signed-off-by: Jiawen Liu <1298662399@qq.com>
---
drivers/spi/spi-fsl-dspi.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 019d05cdefe6..c2d283876ef8 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1464,10 +1464,18 @@ static int dspi_init(struct fsl_dspi *dspi)
static int dspi_suspend(struct device *dev)
{
struct fsl_dspi *dspi = dev_get_drvdata(dev);
+ int ret;
if (dspi->irq)
disable_irq(dspi->irq);
- spi_controller_suspend(dspi->ctlr);
+
+ ret = spi_controller_suspend(dspi->ctlr);
+ if (ret) {
+ if (dspi->irq)
+ enable_irq(dspi->irq);
+ return ret;
+ }
+
clk_disable_unprepare(dspi->clk);
pinctrl_pm_select_sleep_state(dev);
@@ -1485,12 +1493,15 @@ static int dspi_resume(struct device *dev)
ret = clk_prepare_enable(dspi->clk);
if (ret)
return ret;
- spi_controller_resume(dspi->ctlr);
+
+ ret = spi_controller_resume(dspi->ctlr);
+ if (ret)
+ goto disable_clk;
ret = dspi_init(dspi);
if (ret) {
dev_err(dev, "failed to initialize dspi during resume\n");
- return ret;
+ goto disable_clk;
}
dspi_set_mtf(dspi);
@@ -1499,6 +1510,10 @@ static int dspi_resume(struct device *dev)
enable_irq(dspi->irq);
return 0;
+
+disable_clk:
+ clk_disable_unprepare(dspi->clk);
+ return ret;
}
#endif /* CONFIG_PM_SLEEP */
--
2.34.1
^ permalink raw reply related
* [PATCH 4/4] spi: nxp-fspi: disable runtime PM on probe failures
From: Jiawen Liu @ 2026-06-20 8:39 UTC (permalink / raw)
To: broonie
Cc: cl634, william.zhang, kursad.oney, jonas.gorski,
bcm-kernel-feedback-list, anand.gore, f.fainelli, rafal, olteanv,
han.xu, haibo.chen, yogeshgaur.83, linux-spi, linux-kernel,
linux-arm-kernel, imx, Jiawen Liu
In-Reply-To: <20260620083931.1120616-1-1298662399@qq.com>
nxp_fspi_probe() enables runtime PM and autosuspend before
several operations that can fail.
Some failure paths returned directly before the devm cleanup
action was installed, leaving runtime PM enabled.
Route those failures through a common runtime PM cleanup path.
Use pm_runtime_resume_and_get() for the initial clock enable.
Signed-off-by: Jiawen Liu <1298662399@qq.com>
---
drivers/spi/spi-nxp-fspi.c | 31 ++++++++++++++++++++++---------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 1e36ae084dd8..d94a2a7b98d4 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -1350,9 +1350,11 @@ static int nxp_fspi_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
/* enable clock */
- ret = pm_runtime_get_sync(f->dev);
- if (ret < 0)
- return dev_err_probe(dev, ret, "Failed to enable clock");
+ ret = pm_runtime_resume_and_get(f->dev);
+ if (ret < 0) {
+ ret = dev_err_probe(dev, ret, "Failed to enable clock");
+ goto err_disable_pm;
+ }
/* Clear potential interrupts */
reg = fspi_readl(f, f->iobase + FSPI_INTR);
@@ -1362,18 +1364,24 @@ static int nxp_fspi_probe(struct platform_device *pdev)
nxp_fspi_default_setup(f);
ret = pm_runtime_put_sync(dev);
- if (ret < 0)
- return dev_err_probe(dev, ret, "Failed to disable clock");
+ if (ret < 0) {
+ ret = dev_err_probe(dev, ret, "Failed to disable clock");
+ goto err_disable_pm;
+ }
init_completion(&f->c);
ret = devm_request_irq(dev, irq,
nxp_fspi_irq_handler, 0, pdev->name, f);
- if (ret)
- return dev_err_probe(dev, ret, "Failed to request irq\n");
+ if (ret) {
+ ret = dev_err_probe(dev, ret, "Failed to request irq\n");
+ goto err_disable_pm;
+ }
ret = devm_mutex_init(dev, &f->lock);
- if (ret)
- return dev_err_probe(dev, ret, "Failed to initialize lock\n");
+ if (ret) {
+ ret = dev_err_probe(dev, ret, "Failed to initialize lock\n");
+ goto err_disable_pm;
+ }
ctlr->bus_num = -1;
ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT;
@@ -1389,6 +1397,11 @@ static int nxp_fspi_probe(struct platform_device *pdev)
return ret;
return devm_spi_register_controller(&pdev->dev, ctlr);
+
+err_disable_pm:
+ pm_runtime_dont_use_autosuspend(dev);
+ pm_runtime_disable(dev);
+ return ret;
}
static int nxp_fspi_runtime_suspend(struct device *dev)
--
2.34.1
^ permalink raw reply related
* [PATCH 2/4] spi: bcmbca-hsspi: return error from failed controller suspend
From: Jiawen Liu @ 2026-06-20 8:39 UTC (permalink / raw)
To: broonie
Cc: cl634, william.zhang, kursad.oney, jonas.gorski,
bcm-kernel-feedback-list, anand.gore, f.fainelli, rafal, olteanv,
han.xu, haibo.chen, yogeshgaur.83, linux-spi, linux-kernel,
linux-arm-kernel, imx, Jiawen Liu
In-Reply-To: <20260620083931.1120616-1-1298662399@qq.com>
spi_controller_suspend() can fail if pending transfers cannot stop.
bcmbca_hsspi_suspend() ignored the error and still disabled the
PLL and core clocks.
Return the error before disabling the clocks.
Signed-off-by: Jiawen Liu <1298662399@qq.com>
---
drivers/spi/spi-bcmbca-hsspi.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c
index 09c1472ae4fa..af88ce04948b 100644
--- a/drivers/spi/spi-bcmbca-hsspi.c
+++ b/drivers/spi/spi-bcmbca-hsspi.c
@@ -568,8 +568,12 @@ static int bcmbca_hsspi_suspend(struct device *dev)
{
struct spi_controller *host = dev_get_drvdata(dev);
struct bcmbca_hsspi *bs = spi_controller_get_devdata(host);
+ int ret;
+
+ ret = spi_controller_suspend(host);
+ if (ret)
+ return ret;
- spi_controller_suspend(host);
clk_disable_unprepare(bs->pll_clk);
clk_disable_unprepare(bs->clk);
--
2.34.1
^ permalink raw reply related
* [PATCH 1/4] spi: atcspi200: return error from failed controller suspend
From: Jiawen Liu @ 2026-06-20 8:39 UTC (permalink / raw)
To: broonie
Cc: cl634, william.zhang, kursad.oney, jonas.gorski,
bcm-kernel-feedback-list, anand.gore, f.fainelli, rafal, olteanv,
han.xu, haibo.chen, yogeshgaur.83, linux-spi, linux-kernel,
linux-arm-kernel, imx, Jiawen Liu
In-Reply-To: <20260620083931.1120616-1-1298662399@qq.com>
spi_controller_suspend() can fail when the SPI core cannot stop the
controller. atcspi_suspend() ignored that error and disabled the
controller clock anyway.
Return the error before disabling the clock.
Signed-off-by: Jiawen Liu <1298662399@qq.com>
---
drivers/spi/spi-atcspi200.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi-atcspi200.c b/drivers/spi/spi-atcspi200.c
index 6d4b6aeb3f5b..e0fd101a62bc 100644
--- a/drivers/spi/spi-atcspi200.c
+++ b/drivers/spi/spi-atcspi200.c
@@ -599,8 +599,11 @@ static int atcspi_suspend(struct device *dev)
{
struct spi_controller *host = dev_get_drvdata(dev);
struct atcspi_dev *spi = spi_controller_get_devdata(host);
+ int ret;
- spi_controller_suspend(host);
+ ret = spi_controller_suspend(host);
+ if (ret)
+ return ret;
clk_disable_unprepare(spi->clk);
--
2.34.1
^ permalink raw reply related
* [PATCH 0/4] spi: fix PM error handling in several drivers
From: Jiawen Liu @ 2026-06-20 8:39 UTC (permalink / raw)
To: broonie
Cc: cl634, william.zhang, kursad.oney, jonas.gorski,
bcm-kernel-feedback-list, anand.gore, f.fainelli, rafal, olteanv,
han.xu, haibo.chen, yogeshgaur.83, linux-spi, linux-kernel,
linux-arm-kernel, imx, Jiawen Liu
This series fixes several SPI PM error paths where drivers continued
tearing down or reported success after a controller suspend or runtime PM
operation failed.
The patches are independent and only touch the local error paths in each
driver.
Jiawen Liu (4):
spi: atcspi200: return error from failed controller suspend
spi: bcmbca-hsspi: return error from failed controller suspend
spi: fsl-dspi: clean up after failed suspend and resume
spi: nxp-fspi: disable runtime PM on probe failures
drivers/spi/spi-atcspi200.c | 5 ++++-
drivers/spi/spi-bcmbca-hsspi.c | 6 +++++-
drivers/spi/spi-fsl-dspi.c | 21 ++++++++++++++++++---
drivers/spi/spi-nxp-fspi.c | 31 ++++++++++++++++++++++---------
4 files changed, 49 insertions(+), 14 deletions(-)
base-commit: 9e7e6633458362db72427b48effad8d759131c35
--
2.34.1
^ permalink raw reply
* Re: [PATCH v7 0/2] arm64: dts: rockchip: add Vicharak Axon board support
From: Hrushiraj Gandhi @ 2026-06-20 5:37 UTC (permalink / raw)
To: heiko
Cc: krzk+dt, robh, conor+dt, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel
In-Reply-To: <20260608060940.52549-1-hrushirajg23@gmail.com>
Hi Heiko,
Just a friendly ping on this series.
The binding patch has received an Acked-by from Krzysztof and the
requested review comments from previous revisions have been addressed.
Could you please take a look when you have a chance? Any additional
feedback on either the binding or DTS patch would be greatly appreciated.
Thanks for your time.
Best regards,
Hrushiraj
^ permalink raw reply
* [STATUS] arm64/for-kernelci - 92e3f6ef4ffb1f65e7774f4611c27fb764b3bc14
From: KernelCI bot @ 2026-06-20 2:30 UTC (permalink / raw)
To: kernelci-results; +Cc: will, linux-arm-kernel
Hello,
Status summary for arm64/for-kernelci
Dashboard:
https://d.kernelci.org/c/arm64/for-kernelci/92e3f6ef4ffb1f65e7774f4611c27fb764b3bc14/
giturl: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
branch: for-kernelci
commit hash: 92e3f6ef4ffb1f65e7774f4611c27fb764b3bc14
origin: maestro
test start time: 2026-06-19 17:25:47.988000+00:00
Builds: 8 ✅ 0 ❌ 0 ⚠️
Boots: 24 ✅ 0 ❌ 1 ⚠️
Tests: 10579 ✅ 84 ❌ 93 ⚠️
### POSSIBLE REGRESSIONS
No possible regressions observed.
### FIXED REGRESSIONS
No fixed regressions observed.
### UNSTABLE TESTS
Hardware: bcm2711-rpi-4-b
> Config: defconfig+lab-setup+kselftest
- Architecture/compiler: arm64/gcc-14
- boot
last run: https://d.kernelci.org/test/maestro:6a3587e0ec8c023893a36461
history: > ✅ > ✅ > ⚠️ > ✅ > ✅
Sent every day if there were changes in the past 24 hours.
Legend: ✅ PASS ❌ FAIL ⚠️ INCONCLUSIVE
--
This is an experimental report format. Please send feedback in!
Talk to us at kernelci@lists.linux.dev
Made with love by the KernelCI team - https://kernelci.org
^ permalink raw reply
* Re: [PATCH v3 2/7] gpio: regmap: add gpio_regmap_get_gpiochip() accessor
From: Linus Walleij @ 2026-06-19 21:08 UTC (permalink / raw)
To: Michael Walle
Cc: Bartosz Golaszewski, Andy Shevchenko, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, afaerber@suse.com,
wbg@kernel.org, mathieu.dubois-briand@bootlin.com,
lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org,
nuno.sa@analog.com, andy@kernel.org, dlechner@baylibre.com,
TY_Chang[張子逸], linux-gpio@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-realtek-soc@lists.infradead.org, linux-iio@vger.kernel.org,
CY_Huang[黃鉦晏],
Stanley Chang[昌育德],
James Tai [戴志峰],
Yu-Chun Lin [林祐君]
In-Reply-To: <DJ3QVMZ6XLW9.1M9W541O92QWJ@kernel.org>
On Mon, Jun 8, 2026 at 4:41 PM Michael Walle <mwalle@kernel.org> wrote:
> >>> Without an accessor like gpio_regmap_get_gpiochip(), we cannot retrieve the
> >>> gpio_chip instantiated inside gpio-regmap.c to fulfill these requirements in our
> >>> map() function.
>
> Why is gpiochip_irq_reqres() called in the first place? Isn't that
> only called if the irq handling is set up via gc->irq.chip and not
> via gpiochip_irqchip_add_domain() like in gpio-regmap?
Not really, the gpiochip_irq_reqres() is called to mark that a
GPIO line is used for IRQ, so the gpiolib cannot turn this
GPIO into an output line, gpiod_direction_out() will fail
on lines used for IRQ. So it's a failsafe.
You can live without it of course, but then you don't get
this failsafe.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH] arm64: dts: broadcom: bcm2712: Remove non-functional EL2 virtual timer
From: Marek Szyprowski @ 2026-06-19 21:04 UTC (permalink / raw)
To: Daniel Drake, maz, robh, krzk+dt, conor+dt, florian.fainelli,
bcm-kernel-feedback-list
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, andrea.porta
In-Reply-To: <20260619204832.586079-1-dan@reactivated.net>
On 19.06.2026 22:48, Daniel Drake wrote:
> Commit d87773de9efe1 ("clocksource/drivers/arm_arch_timer: Default to
> EL2 virtual timer when running VHE") causes boot to hang on
> Raspberry Pi 5. The newly-selected EL2 virtual timer does not generate
> any interrupts, even though the GIC_DIST_ENABLE_SET flag has been
> confirmed set via readback.
>
> The reasons for this failure are unknown, however it is likely that
> this timer was never tested. Raspberry Pi's original devicetree did
> not include this timer interrupt; it was only introduced via a
> suggestion[1] made in code review as part of the upstreaming process.
> (Current RPi firmware versions do include this timer, but only because
> they rebased on top of the upstreamed devicetree starting with
> Linux 6.12)
>
> Until more is known about this non-firing timer interrupt, remove
> the devicetree entry to enable RPi5 devices to boot.
>
> [1] https://lore.kernel.org/all/12363be5b11c752b7155cc0c416fdfd2@kernel.org/
>
> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Closes: https://lore.kernel.org/all/ea15cce1-b393-43f6-8d58-3d6f90f0c0cd@samsung.com/
> Signed-off-by: Daniel Drake <dan@reactivated.net>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
> arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> index 761c59d90ffc..09ff5e9959d3 100644
> --- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> +++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> @@ -678,8 +678,6 @@ IRQ_TYPE_LEVEL_LOW)>,
> <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
> IRQ_TYPE_LEVEL_LOW)>,
> <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
> - IRQ_TYPE_LEVEL_LOW)>,
> - <GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
> IRQ_TYPE_LEVEL_LOW)>;
> };
>
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* [PATCH] arm64: dts: broadcom: bcm2712: Remove non-functional EL2 virtual timer
From: Daniel Drake @ 2026-06-19 20:48 UTC (permalink / raw)
To: maz, robh, krzk+dt, conor+dt, florian.fainelli,
bcm-kernel-feedback-list
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, m.szyprowski,
andrea.porta, Daniel Drake
Commit d87773de9efe1 ("clocksource/drivers/arm_arch_timer: Default to
EL2 virtual timer when running VHE") causes boot to hang on
Raspberry Pi 5. The newly-selected EL2 virtual timer does not generate
any interrupts, even though the GIC_DIST_ENABLE_SET flag has been
confirmed set via readback.
The reasons for this failure are unknown, however it is likely that
this timer was never tested. Raspberry Pi's original devicetree did
not include this timer interrupt; it was only introduced via a
suggestion[1] made in code review as part of the upstreaming process.
(Current RPi firmware versions do include this timer, but only because
they rebased on top of the upstreamed devicetree starting with
Linux 6.12)
Until more is known about this non-firing timer interrupt, remove
the devicetree entry to enable RPi5 devices to boot.
[1] https://lore.kernel.org/all/12363be5b11c752b7155cc0c416fdfd2@kernel.org/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Closes: https://lore.kernel.org/all/ea15cce1-b393-43f6-8d58-3d6f90f0c0cd@samsung.com/
Signed-off-by: Daniel Drake <dan@reactivated.net>
---
arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
index 761c59d90ffc..09ff5e9959d3 100644
--- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
@@ -678,8 +678,6 @@ IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
- IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>;
};
--
2.54.0
^ permalink raw reply related
* [PATCH] mfd: db8500-prcmu: Fold dbx500 header into db8500
From: Linus Walleij @ 2026-06-19 20:27 UTC (permalink / raw)
To: Russell King, Ulf Hansson, Michael Turquette, Stephen Boyd,
Brian Masney, Rafael J. Wysocki, Daniel Lezcano, Christian Loehle,
Lee Jones, Liam Girdwood, Mark Brown, Zhang Rui, Lukasz Luba,
Wim Van Sebroeck, Guenter Roeck, Jaroslav Kysela, Takashi Iwai
Cc: linux-arm-kernel, linux-clk, linux-pm, linux-watchdog,
linux-sound, kernel test robot, Linus Walleij
Move the DBx500 PRCMU definitions into the DB8500 PRCMU
header and delete the wrapper header.
Convert users of simple PRCMU wrappers to call the DB8500 helpers
directly.
The dbx500-prcmu.h header was the result of an earlier attempt to
abstract several DBx5x SoC PRCMU units to use the same abstract
header. They are deleted from the kernel and this is not just
causing maintenance burden and build errors.
The stub code is using -ENOSYS in a way checkpatch complains about
so replace these with -EINVAL while we're at it.
Assisted-by: Codex:gpt-5-5
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202606180825.vUSQntkJ-lkp@intel.com/
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
| 6 +-
| 20 +-
| 2 +-
| 6 +-
| 2 +-
| 6 +-
| 12 +-
| 10 +-
| 22 +-
| 252 ++++++++++++++++-
| 575 ---------------------------------------
| 2 +-
12 files changed, 294 insertions(+), 621 deletions(-)
--git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index b1a70f203372..0d7530fb6ad0 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -12,7 +12,7 @@
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/platform_data/arm-ux500-pm.h>
#include <linux/platform_device.h>
#include <linux/io.h>
@@ -81,7 +81,7 @@ static void __init ux500_init_irq(void)
struct resource r;
irqchip_init();
- prcmu_early_init();
+ db8500_prcmu_early_init();
np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu");
of_address_to_resource(np, 0, &r);
of_node_put(np);
@@ -101,7 +101,7 @@ static void ux500_restart(enum reboot_mode mode, const char *cmd)
local_irq_disable();
local_fiq_disable();
- prcmu_system_reset(0);
+ db8500_prcmu_system_reset(0);
}
static const struct of_device_id u8500_local_bus_nodes[] = {
--git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index ddc86551bf57..ac96c46bd1bb 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -7,7 +7,7 @@
*/
#include <linux/clk-provider.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/err.h>
@@ -35,13 +35,13 @@ static int clk_prcmu_prepare(struct clk_hw *hw)
{
struct clk_prcmu *clk = to_clk_prcmu(hw);
- return prcmu_request_clock(clk->cg_sel, true);
+ return db8500_prcmu_request_clock(clk->cg_sel, true);
}
static void clk_prcmu_unprepare(struct clk_hw *hw)
{
struct clk_prcmu *clk = to_clk_prcmu(hw);
- if (prcmu_request_clock(clk->cg_sel, false))
+ if (db8500_prcmu_request_clock(clk->cg_sel, false))
pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
clk_hw_get_name(hw));
}
@@ -86,7 +86,7 @@ static int clk_prcmu_opp_prepare(struct clk_hw *hw)
clk->opp_requested = 1;
}
- err = prcmu_request_clock(clk->cg_sel, true);
+ err = db8500_prcmu_request_clock(clk->cg_sel, true);
if (err) {
prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
(char *)clk_hw_get_name(hw));
@@ -101,7 +101,7 @@ static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
{
struct clk_prcmu *clk = to_clk_prcmu(hw);
- if (prcmu_request_clock(clk->cg_sel, false)) {
+ if (db8500_prcmu_request_clock(clk->cg_sel, false)) {
pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
clk_hw_get_name(hw));
return;
@@ -120,7 +120,7 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
struct clk_prcmu *clk = to_clk_prcmu(hw);
if (!clk->opp_requested) {
- err = prcmu_request_ape_opp_100_voltage(true);
+ err = db8500_prcmu_request_ape_opp_100_voltage(true);
if (err) {
pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
__func__, clk_hw_get_name(hw));
@@ -129,9 +129,9 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
clk->opp_requested = 1;
}
- err = prcmu_request_clock(clk->cg_sel, true);
+ err = db8500_prcmu_request_clock(clk->cg_sel, true);
if (err) {
- prcmu_request_ape_opp_100_voltage(false);
+ db8500_prcmu_request_ape_opp_100_voltage(false);
clk->opp_requested = 0;
return err;
}
@@ -143,14 +143,14 @@ static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
{
struct clk_prcmu *clk = to_clk_prcmu(hw);
- if (prcmu_request_clock(clk->cg_sel, false)) {
+ if (db8500_prcmu_request_clock(clk->cg_sel, false)) {
pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
clk_hw_get_name(hw));
return;
}
if (clk->opp_requested) {
- prcmu_request_ape_opp_100_voltage(false);
+ db8500_prcmu_request_ape_opp_100_voltage(false);
clk->opp_requested = 0;
}
}
--git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c
index 6f78808387b1..d2499815226f 100644
--- a/drivers/clk/ux500/u8500_of_clk.c
+++ b/drivers/clk/ux500/u8500_of_clk.c
@@ -9,7 +9,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/clk-provider.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include "clk.h"
#include "prcc.h"
--git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c
index f7d778580e9b..6d6c52c0bcc2 100644
--- a/drivers/cpuidle/cpuidle-ux500.c
+++ b/drivers/cpuidle/cpuidle-ux500.c
@@ -11,7 +11,7 @@
#include <linux/spinlock.h>
#include <linux/atomic.h>
#include <linux/smp.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/platform_data/arm-ux500-pm.h>
#include <linux/platform_device.h>
@@ -66,7 +66,7 @@ static inline int ux500_enter_idle(struct cpuidle_device *dev,
/* Go to the retention state, the prcmu will wait for the
* cpu to go WFI and this is what happens after exiting this
* 'master' critical section */
- if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true))
+ if (db8500_prcmu_set_power_state(PRCMU_AP_IDLE, true, true))
goto out;
/* When we switch to retention, the prcmu is in charge
@@ -109,7 +109,7 @@ static struct cpuidle_driver ux500_idle_driver = {
static int dbx500_cpuidle_probe(struct platform_device *pdev)
{
/* Configure wake up reasons */
- prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
+ db8500_prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
PRCMU_WAKEUP(ABB));
return cpuidle_register(&ux500_idle_driver, NULL);
--git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index f0bc0b5a6f4a..86fa99022cb3 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -19,7 +19,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/of.h>
/*
--git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 21e68a382b11..6672c55f2ebc 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -32,7 +32,7 @@
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/mfd/core.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/regulator/db8500-prcmu.h>
#include <linux/regulator/machine.h>
@@ -2285,7 +2285,7 @@ void db8500_prcmu_system_reset(u16 reset_code)
/**
* db8500_prcmu_get_reset_code - Retrieve SW reset reason code
*
- * Retrieves the reset reason code stored by prcmu_system_reset() before
+ * Retrieves the reset reason code stored by db8500_prcmu_system_reset() before
* last restart.
*/
u16 db8500_prcmu_get_reset_code(void)
@@ -3041,7 +3041,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
db8500_irq_init(np);
- prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
+ db8500_prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
err = mfd_add_devices(&pdev->dev, 0, common_prcmu_devs,
ARRAY_SIZE(common_prcmu_devs), NULL, 0, db8500_irq_domain);
--git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
index 1ec2e1348891..751fe36580fa 100644
--- a/drivers/regulator/db8500-prcmu.c
+++ b/drivers/regulator/db8500-prcmu.c
@@ -13,7 +13,7 @@
#include <linux/err.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/db8500-prcmu.h>
@@ -93,13 +93,13 @@ static int enable_epod(u16 epod_id, bool ramret)
if (ramret) {
if (!epod_on[epod_id]) {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
if (ret < 0)
return ret;
}
epod_ramret[epod_id] = true;
} else {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_ON);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_ON);
if (ret < 0)
return ret;
epod_on[epod_id] = true;
@@ -114,18 +114,18 @@ static int disable_epod(u16 epod_id, bool ramret)
if (ramret) {
if (!epod_on[epod_id]) {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
if (ret < 0)
return ret;
}
epod_ramret[epod_id] = false;
} else {
if (epod_ramret[epod_id]) {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
if (ret < 0)
return ret;
} else {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
if (ret < 0)
return ret;
}
--git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
index 576f88b6a1b3..cf1706569e6d 100644
--- a/drivers/thermal/db8500_thermal.c
+++ b/drivers/thermal/db8500_thermal.c
@@ -10,7 +10,7 @@
#include <linux/cpu_cooling.h>
#include <linux/interrupt.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -82,7 +82,7 @@ static void db8500_thermal_update_config(struct db8500_thermal_zone *th,
unsigned long next_low,
unsigned long next_high)
{
- prcmu_stop_temp_sense();
+ db8500_prcmu_stop_temp_sense();
th->cur_index = idx;
th->interpolated_temp = (next_low + next_high)/2;
@@ -91,8 +91,8 @@ static void db8500_thermal_update_config(struct db8500_thermal_zone *th,
* The PRCMU accept absolute temperatures in celsius so divide
* down the millicelsius with 1000
*/
- prcmu_config_hotmon((u8)(next_low/1000), (u8)(next_high/1000));
- prcmu_start_temp_sense(PRCMU_DEFAULT_MEASURE_TIME);
+ db8500_prcmu_config_hotmon((u8)(next_low / 1000), (u8)(next_high / 1000));
+ db8500_prcmu_start_temp_sense(PRCMU_DEFAULT_MEASURE_TIME);
}
static irqreturn_t prcmu_low_irq_handler(int irq, void *irq_data)
@@ -204,7 +204,7 @@ static int db8500_thermal_probe(struct platform_device *pdev)
static int db8500_thermal_suspend(struct platform_device *pdev,
pm_message_t state)
{
- prcmu_stop_temp_sense();
+ db8500_prcmu_stop_temp_sense();
return 0;
}
--git a/drivers/watchdog/db8500_wdt.c b/drivers/watchdog/db8500_wdt.c
index 97148ac0aa54..70ccea13288d 100644
--- a/drivers/watchdog/db8500_wdt.c
+++ b/drivers/watchdog/db8500_wdt.c
@@ -16,7 +16,7 @@
#include <linux/watchdog.h>
#include <linux/platform_device.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#define WATCHDOG_TIMEOUT 600 /* 10 minutes */
@@ -37,24 +37,24 @@ MODULE_PARM_DESC(nowayout,
static int db8500_wdt_start(struct watchdog_device *wdd)
{
- return prcmu_enable_a9wdog(PRCMU_WDOG_ALL);
+ return db8500_prcmu_enable_a9wdog(PRCMU_WDOG_ALL);
}
static int db8500_wdt_stop(struct watchdog_device *wdd)
{
- return prcmu_disable_a9wdog(PRCMU_WDOG_ALL);
+ return db8500_prcmu_disable_a9wdog(PRCMU_WDOG_ALL);
}
static int db8500_wdt_keepalive(struct watchdog_device *wdd)
{
- return prcmu_kick_a9wdog(PRCMU_WDOG_ALL);
+ return db8500_prcmu_kick_a9wdog(PRCMU_WDOG_ALL);
}
static int db8500_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
{
db8500_wdt_stop(wdd);
- prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+ db8500_prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
db8500_wdt_start(wdd);
return 0;
@@ -91,10 +91,10 @@ static int db8500_wdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(&db8500_wdt, nowayout);
/* disable auto off on sleep */
- prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
+ db8500_prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
/* set HW initial value */
- prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+ db8500_prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
ret = devm_watchdog_register_device(dev, &db8500_wdt);
if (ret)
@@ -110,9 +110,9 @@ static int db8500_wdt_suspend(struct platform_device *pdev,
{
if (watchdog_active(&db8500_wdt)) {
db8500_wdt_stop(&db8500_wdt);
- prcmu_config_a9wdog(PRCMU_WDOG_CPU1, true);
+ db8500_prcmu_config_a9wdog(PRCMU_WDOG_CPU1, true);
- prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+ db8500_prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
db8500_wdt_start(&db8500_wdt);
}
return 0;
@@ -122,9 +122,9 @@ static int db8500_wdt_resume(struct platform_device *pdev)
{
if (watchdog_active(&db8500_wdt)) {
db8500_wdt_stop(&db8500_wdt);
- prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
+ db8500_prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
- prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+ db8500_prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
db8500_wdt_start(&db8500_wdt);
}
return 0;
--git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h
index a62de3d155ed..c939c9a1170a 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -12,6 +12,9 @@
#include <linux/interrupt.h>
#include <linux/bitops.h>
+#include <linux/err.h>
+
+#include <dt-bindings/mfd/dbx500-prcmu.h> /* For clock identifiers */
/*
* Registers
@@ -24,6 +27,38 @@
#define DB8500_PRCM_DSI_SW_RESET_DSI1_SW_RESETN BIT(1)
#define DB8500_PRCM_DSI_SW_RESET_DSI2_SW_RESETN BIT(2)
+/* Offset for the firmware version within the TCPM */
+#define DB8500_PRCMU_FW_VERSION_OFFSET 0xA4
+
+#define DB8500_PRCMU_LEGACY_OFFSET 0xDD4
+
+/*
+ * CLKOUT sources
+ */
+#define PRCMU_CLKSRC_CLK38M 0x00
+#define PRCMU_CLKSRC_ACLK 0x01
+#define PRCMU_CLKSRC_SYSCLK 0x02
+#define PRCMU_CLKSRC_LCDCLK 0x03
+#define PRCMU_CLKSRC_SDMMCCLK 0x04
+#define PRCMU_CLKSRC_TVCLK 0x05
+#define PRCMU_CLKSRC_TIMCLK 0x06
+#define PRCMU_CLKSRC_CLK009 0x07
+/* These are only valid for CLKOUT1: */
+#define PRCMU_CLKSRC_SIAMMDSPCLK 0x40
+#define PRCMU_CLKSRC_I2CCLK 0x41
+#define PRCMU_CLKSRC_MSP02CLK 0x42
+#define PRCMU_CLKSRC_ARMPLL_OBSCLK 0x43
+#define PRCMU_CLKSRC_HSIRXCLK 0x44
+#define PRCMU_CLKSRC_HSITXCLK 0x45
+#define PRCMU_CLKSRC_ARMCLKFIX 0x46
+#define PRCMU_CLKSRC_HDMICLK 0x47
+
+/*
+ * Definitions for controlling ESRAM0 in deep sleep.
+ */
+#define ESRAM0_DEEP_SLEEP_STATE_OFF 1
+#define ESRAM0_DEEP_SLEEP_STATE_RET 2
+
/* This portion previously known as <mach/prcmu-fw-defs_v1.h> */
/**
@@ -451,10 +486,173 @@ enum prcmu_power_status {
PRCMU_ARMPENDINGIT_ER = 0x93,
};
+/* PRCMU Wakeup defines */
+enum prcmu_wakeup_index {
+ PRCMU_WAKEUP_INDEX_RTC,
+ PRCMU_WAKEUP_INDEX_RTT0,
+ PRCMU_WAKEUP_INDEX_RTT1,
+ PRCMU_WAKEUP_INDEX_HSI0,
+ PRCMU_WAKEUP_INDEX_HSI1,
+ PRCMU_WAKEUP_INDEX_USB,
+ PRCMU_WAKEUP_INDEX_ABB,
+ PRCMU_WAKEUP_INDEX_ABB_FIFO,
+ PRCMU_WAKEUP_INDEX_ARM,
+ PRCMU_WAKEUP_INDEX_CD_IRQ,
+ NUM_PRCMU_WAKEUP_INDICES
+};
+
+#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name))
+
+/**
+ * enum prcmu_wdog_id - PRCMU watchdog IDs
+ * @PRCMU_WDOG_ALL: use all timers
+ * @PRCMU_WDOG_CPU1: use first CPU timer only
+ * @PRCMU_WDOG_CPU2: use second CPU timer conly
+ */
+enum prcmu_wdog_id {
+ PRCMU_WDOG_ALL = 0x00,
+ PRCMU_WDOG_CPU1 = 0x01,
+ PRCMU_WDOG_CPU2 = 0x02,
+};
+
+/**
+ * enum ape_opp - APE OPP states definition
+ * @APE_OPP_INIT:
+ * @APE_NO_CHANGE: The APE operating point is unchanged
+ * @APE_100_OPP: The new APE operating point is ape100opp
+ * @APE_50_OPP: 50%
+ * @APE_50_PARTLY_25_OPP: 50%, except some clocks at 25%.
+ */
+enum ape_opp {
+ APE_OPP_INIT = 0x00,
+ APE_NO_CHANGE = 0x01,
+ APE_100_OPP = 0x02,
+ APE_50_OPP = 0x03,
+ APE_50_PARTLY_25_OPP = 0xFF,
+};
+
+/**
+ * enum arm_opp - ARM OPP states definition
+ * @ARM_OPP_INIT:
+ * @ARM_NO_CHANGE: The ARM operating point is unchanged
+ * @ARM_100_OPP: The new ARM operating point is arm100opp
+ * @ARM_50_OPP: The new ARM operating point is arm50opp
+ * @ARM_MAX_OPP: Operating point is "max" (more than 100)
+ * @ARM_MAX_FREQ100OPP: Set max opp if available, else 100
+ * @ARM_EXTCLK: The new ARM operating point is armExtClk
+ */
+enum arm_opp {
+ ARM_OPP_INIT = 0x00,
+ ARM_NO_CHANGE = 0x01,
+ ARM_100_OPP = 0x02,
+ ARM_50_OPP = 0x03,
+ ARM_MAX_OPP = 0x04,
+ ARM_MAX_FREQ100OPP = 0x05,
+ ARM_EXTCLK = 0x07
+};
+
+/**
+ * enum ddr_opp - DDR OPP states definition
+ * @DDR_100_OPP: The new DDR operating point is ddr100opp
+ * @DDR_50_OPP: The new DDR operating point is ddr50opp
+ * @DDR_25_OPP: The new DDR operating point is ddr25opp
+ */
+enum ddr_opp {
+ DDR_100_OPP = 0x00,
+ DDR_50_OPP = 0x01,
+ DDR_25_OPP = 0x02,
+};
+
+/**
+ * enum ddr_pwrst - DDR power states definition
+ * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged
+ * @DDR_PWR_STATE_ON:
+ * @DDR_PWR_STATE_OFFLOWLAT:
+ * @DDR_PWR_STATE_OFFHIGHLAT:
+ */
+enum ddr_pwrst {
+ DDR_PWR_STATE_UNCHANGED = 0x00,
+ DDR_PWR_STATE_ON = 0x01,
+ DDR_PWR_STATE_OFFLOWLAT = 0x02,
+ DDR_PWR_STATE_OFFHIGHLAT = 0x03
+};
+
/*
* Definitions for autonomous power management configuration.
*/
+/* EPOD (power domain) IDs */
+
+/*
+ * DB8500 EPODs
+ * - EPOD_ID_SVAMMDSP: power domain for SVA MMDSP
+ * - EPOD_ID_SVAPIPE: power domain for SVA pipe
+ * - EPOD_ID_SIAMMDSP: power domain for SIA MMDSP
+ * - EPOD_ID_SIAPIPE: power domain for SIA pipe
+ * - EPOD_ID_SGA: power domain for SGA
+ * - EPOD_ID_B2R2_MCDE: power domain for B2R2 and MCDE
+ * - EPOD_ID_ESRAM12: power domain for ESRAM 1 and 2
+ * - EPOD_ID_ESRAM34: power domain for ESRAM 3 and 4
+ * - NUM_EPOD_ID: number of power domains
+ *
+ * TODO: These should be prefixed.
+ */
+#define EPOD_ID_SVAMMDSP 0
+#define EPOD_ID_SVAPIPE 1
+#define EPOD_ID_SIAMMDSP 2
+#define EPOD_ID_SIAPIPE 3
+#define EPOD_ID_SGA 4
+#define EPOD_ID_B2R2_MCDE 5
+#define EPOD_ID_ESRAM12 6
+#define EPOD_ID_ESRAM34 7
+#define NUM_EPOD_ID 8
+
+/*
+ * state definition for EPOD (power domain)
+ * - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged
+ * - EPOD_STATE_OFF: The EPOD is switched off
+ * - EPOD_STATE_RAMRET: The EPOD is switched off with its internal RAM in
+ * retention
+ * - EPOD_STATE_ON_CLK_OFF: The EPOD is switched on, clock is still off
+ * - EPOD_STATE_ON: Same as above, but with clock enabled
+ */
+#define EPOD_STATE_NO_CHANGE 0x00
+#define EPOD_STATE_OFF 0x01
+#define EPOD_STATE_RAMRET 0x02
+#define EPOD_STATE_ON_CLK_OFF 0x03
+#define EPOD_STATE_ON 0x04
+
+#define PRCMU_FW_PROJECT_U8500 2
+#define PRCMU_FW_PROJECT_U8400 3
+#define PRCMU_FW_PROJECT_U9500 4 /* Customer specific */
+#define PRCMU_FW_PROJECT_U8500_MBB 5
+#define PRCMU_FW_PROJECT_U8500_C1 6
+#define PRCMU_FW_PROJECT_U8500_C2 7
+#define PRCMU_FW_PROJECT_U8500_C3 8
+#define PRCMU_FW_PROJECT_U8500_C4 9
+#define PRCMU_FW_PROJECT_U9500_MBL 10
+#define PRCMU_FW_PROJECT_U8500_SSG1 11 /* Samsung specific */
+#define PRCMU_FW_PROJECT_U8500_MBL2 12 /* Customer specific */
+#define PRCMU_FW_PROJECT_U8520 13
+#define PRCMU_FW_PROJECT_U8420 14
+#define PRCMU_FW_PROJECT_U8500_SSG2 15 /* Samsung specific */
+#define PRCMU_FW_PROJECT_U8420_SYSCLK 17
+#define PRCMU_FW_PROJECT_A9420 20
+/* [32..63] 9540 and derivatives */
+#define PRCMU_FW_PROJECT_U9540 32
+/* [64..95] 8540 and derivatives */
+#define PRCMU_FW_PROJECT_L8540 64
+/* [96..126] 8580 and derivatives */
+#define PRCMU_FW_PROJECT_L8580 96
+
+#define PRCMU_FW_PROJECT_NAME_LEN 20
+
+/* PRCMU QoS APE OPP class */
+#define PRCMU_QOS_APE_OPP 1
+#define PRCMU_QOS_DDR_OPP 2
+#define PRCMU_QOS_ARM_OPP 3
+#define PRCMU_QOS_DEFAULT_VALUE -1
+
#define PRCMU_AUTO_PM_OFF 0
#define PRCMU_AUTO_PM_ON 1
@@ -469,6 +667,14 @@ enum prcmu_auto_pm_policy {
PRCMU_AUTO_PM_POLICY_DSP_CLK_OFF_HWP_CLK_OFF,
};
+struct prcmu_fw_version {
+ u32 project; /* Notice, project shifted with 8 on ux540 */
+ u8 api_version;
+ u8 func_version;
+ u8 errata;
+ char project_name[PRCMU_FW_PROJECT_NAME_LEN];
+};
+
/**
* struct prcmu_auto_pm_config - Autonomous power management configuration.
* @sia_auto_pm_enable: SIA autonomous pm enable. (PRCMU_AUTO_PM_{OFF,ON})
@@ -501,6 +707,9 @@ void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
bool prcmu_is_auto_pm_enabled(void);
int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
+unsigned long prcmu_clock_rate(u8 clock);
+long prcmu_round_clock_rate(u8 clock, unsigned long rate);
+int prcmu_set_clock_rate(u8 clock, unsigned long rate);
int prcmu_set_clock_divider(u8 clock, u8 divider);
int db8500_prcmu_config_hotdog(u8 threshold);
int db8500_prcmu_config_hotmon(u8 low, u8 high);
@@ -508,6 +717,8 @@ int db8500_prcmu_start_temp_sense(u16 cycles32k);
int db8500_prcmu_stop_temp_sense(void);
int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value,
+ u8 *mask, u8 size);
int prcmu_ac_wake_req(void);
void prcmu_ac_sleep_req(void);
@@ -610,6 +821,21 @@ static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
return 0;
}
+static inline unsigned long prcmu_clock_rate(u8 clock)
+{
+ return 0;
+}
+
+static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate)
+{
+ return 0;
+}
+
+static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate)
+{
+ return 0;
+}
+
static inline int prcmu_set_clock_divider(u8 clock, u8 divider)
{
return 0;
@@ -637,12 +863,18 @@ static inline int db8500_prcmu_stop_temp_sense(void)
static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
{
- return -ENOSYS;
+ return -EINVAL;
}
static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
{
- return -ENOSYS;
+ return -EINVAL;
+}
+
+static inline int prcmu_abb_write_masked(u8 slave, u8 reg,
+ u8 *value, u8 *mask, u8 size)
+{
+ return -EINVAL;
}
static inline int prcmu_ac_wake_req(void)
@@ -745,4 +977,20 @@ static inline void db8500_prcmu_write_masked(unsigned int reg, u32 mask,
#endif /* !CONFIG_MFD_DB8500_PRCMU */
+static inline int prcmu_qos_add_requirement(int prcmu_qos_class,
+ char *name, s32 value)
+{
+ return 0;
+}
+
+static inline int prcmu_qos_update_requirement(int prcmu_qos_class,
+ char *name, s32 new_value)
+{
+ return 0;
+}
+
+static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name)
+{
+}
+
#endif /* __MFD_DB8500_PRCMU_H */
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
deleted file mode 100644
index 828362b7860c..000000000000
--- a/include/linux/mfd/dbx500-prcmu.h
+++ /dev/null
@@ -1,575 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) ST Ericsson SA 2011
- *
- * STE Ux500 PRCMU API
- */
-#ifndef __MACH_PRCMU_H
-#define __MACH_PRCMU_H
-
-#include <linux/interrupt.h>
-#include <linux/notifier.h>
-#include <linux/err.h>
-
-#include <dt-bindings/mfd/dbx500-prcmu.h> /* For clock identifiers */
-
-/* Offset for the firmware version within the TCPM */
-#define DB8500_PRCMU_FW_VERSION_OFFSET 0xA4
-#define DBX540_PRCMU_FW_VERSION_OFFSET 0xA8
-
-/* PRCMU Wakeup defines */
-enum prcmu_wakeup_index {
- PRCMU_WAKEUP_INDEX_RTC,
- PRCMU_WAKEUP_INDEX_RTT0,
- PRCMU_WAKEUP_INDEX_RTT1,
- PRCMU_WAKEUP_INDEX_HSI0,
- PRCMU_WAKEUP_INDEX_HSI1,
- PRCMU_WAKEUP_INDEX_USB,
- PRCMU_WAKEUP_INDEX_ABB,
- PRCMU_WAKEUP_INDEX_ABB_FIFO,
- PRCMU_WAKEUP_INDEX_ARM,
- PRCMU_WAKEUP_INDEX_CD_IRQ,
- NUM_PRCMU_WAKEUP_INDICES
-};
-#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name))
-
-/* EPOD (power domain) IDs */
-
-/*
- * DB8500 EPODs
- * - EPOD_ID_SVAMMDSP: power domain for SVA MMDSP
- * - EPOD_ID_SVAPIPE: power domain for SVA pipe
- * - EPOD_ID_SIAMMDSP: power domain for SIA MMDSP
- * - EPOD_ID_SIAPIPE: power domain for SIA pipe
- * - EPOD_ID_SGA: power domain for SGA
- * - EPOD_ID_B2R2_MCDE: power domain for B2R2 and MCDE
- * - EPOD_ID_ESRAM12: power domain for ESRAM 1 and 2
- * - EPOD_ID_ESRAM34: power domain for ESRAM 3 and 4
- * - NUM_EPOD_ID: number of power domains
- *
- * TODO: These should be prefixed.
- */
-#define EPOD_ID_SVAMMDSP 0
-#define EPOD_ID_SVAPIPE 1
-#define EPOD_ID_SIAMMDSP 2
-#define EPOD_ID_SIAPIPE 3
-#define EPOD_ID_SGA 4
-#define EPOD_ID_B2R2_MCDE 5
-#define EPOD_ID_ESRAM12 6
-#define EPOD_ID_ESRAM34 7
-#define NUM_EPOD_ID 8
-
-/*
- * state definition for EPOD (power domain)
- * - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged
- * - EPOD_STATE_OFF: The EPOD is switched off
- * - EPOD_STATE_RAMRET: The EPOD is switched off with its internal RAM in
- * retention
- * - EPOD_STATE_ON_CLK_OFF: The EPOD is switched on, clock is still off
- * - EPOD_STATE_ON: Same as above, but with clock enabled
- */
-#define EPOD_STATE_NO_CHANGE 0x00
-#define EPOD_STATE_OFF 0x01
-#define EPOD_STATE_RAMRET 0x02
-#define EPOD_STATE_ON_CLK_OFF 0x03
-#define EPOD_STATE_ON 0x04
-
-/*
- * CLKOUT sources
- */
-#define PRCMU_CLKSRC_CLK38M 0x00
-#define PRCMU_CLKSRC_ACLK 0x01
-#define PRCMU_CLKSRC_SYSCLK 0x02
-#define PRCMU_CLKSRC_LCDCLK 0x03
-#define PRCMU_CLKSRC_SDMMCCLK 0x04
-#define PRCMU_CLKSRC_TVCLK 0x05
-#define PRCMU_CLKSRC_TIMCLK 0x06
-#define PRCMU_CLKSRC_CLK009 0x07
-/* These are only valid for CLKOUT1: */
-#define PRCMU_CLKSRC_SIAMMDSPCLK 0x40
-#define PRCMU_CLKSRC_I2CCLK 0x41
-#define PRCMU_CLKSRC_MSP02CLK 0x42
-#define PRCMU_CLKSRC_ARMPLL_OBSCLK 0x43
-#define PRCMU_CLKSRC_HSIRXCLK 0x44
-#define PRCMU_CLKSRC_HSITXCLK 0x45
-#define PRCMU_CLKSRC_ARMCLKFIX 0x46
-#define PRCMU_CLKSRC_HDMICLK 0x47
-
-/**
- * enum prcmu_wdog_id - PRCMU watchdog IDs
- * @PRCMU_WDOG_ALL: use all timers
- * @PRCMU_WDOG_CPU1: use first CPU timer only
- * @PRCMU_WDOG_CPU2: use second CPU timer conly
- */
-enum prcmu_wdog_id {
- PRCMU_WDOG_ALL = 0x00,
- PRCMU_WDOG_CPU1 = 0x01,
- PRCMU_WDOG_CPU2 = 0x02,
-};
-
-/**
- * enum ape_opp - APE OPP states definition
- * @APE_OPP_INIT:
- * @APE_NO_CHANGE: The APE operating point is unchanged
- * @APE_100_OPP: The new APE operating point is ape100opp
- * @APE_50_OPP: 50%
- * @APE_50_PARTLY_25_OPP: 50%, except some clocks at 25%.
- */
-enum ape_opp {
- APE_OPP_INIT = 0x00,
- APE_NO_CHANGE = 0x01,
- APE_100_OPP = 0x02,
- APE_50_OPP = 0x03,
- APE_50_PARTLY_25_OPP = 0xFF,
-};
-
-/**
- * enum arm_opp - ARM OPP states definition
- * @ARM_OPP_INIT:
- * @ARM_NO_CHANGE: The ARM operating point is unchanged
- * @ARM_100_OPP: The new ARM operating point is arm100opp
- * @ARM_50_OPP: The new ARM operating point is arm50opp
- * @ARM_MAX_OPP: Operating point is "max" (more than 100)
- * @ARM_MAX_FREQ100OPP: Set max opp if available, else 100
- * @ARM_EXTCLK: The new ARM operating point is armExtClk
- */
-enum arm_opp {
- ARM_OPP_INIT = 0x00,
- ARM_NO_CHANGE = 0x01,
- ARM_100_OPP = 0x02,
- ARM_50_OPP = 0x03,
- ARM_MAX_OPP = 0x04,
- ARM_MAX_FREQ100OPP = 0x05,
- ARM_EXTCLK = 0x07
-};
-
-/**
- * enum ddr_opp - DDR OPP states definition
- * @DDR_100_OPP: The new DDR operating point is ddr100opp
- * @DDR_50_OPP: The new DDR operating point is ddr50opp
- * @DDR_25_OPP: The new DDR operating point is ddr25opp
- */
-enum ddr_opp {
- DDR_100_OPP = 0x00,
- DDR_50_OPP = 0x01,
- DDR_25_OPP = 0x02,
-};
-
-/*
- * Definitions for controlling ESRAM0 in deep sleep.
- */
-#define ESRAM0_DEEP_SLEEP_STATE_OFF 1
-#define ESRAM0_DEEP_SLEEP_STATE_RET 2
-
-/**
- * enum ddr_pwrst - DDR power states definition
- * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged
- * @DDR_PWR_STATE_ON:
- * @DDR_PWR_STATE_OFFLOWLAT:
- * @DDR_PWR_STATE_OFFHIGHLAT:
- */
-enum ddr_pwrst {
- DDR_PWR_STATE_UNCHANGED = 0x00,
- DDR_PWR_STATE_ON = 0x01,
- DDR_PWR_STATE_OFFLOWLAT = 0x02,
- DDR_PWR_STATE_OFFHIGHLAT = 0x03
-};
-
-#define DB8500_PRCMU_LEGACY_OFFSET 0xDD4
-
-#define PRCMU_FW_PROJECT_U8500 2
-#define PRCMU_FW_PROJECT_U8400 3
-#define PRCMU_FW_PROJECT_U9500 4 /* Customer specific */
-#define PRCMU_FW_PROJECT_U8500_MBB 5
-#define PRCMU_FW_PROJECT_U8500_C1 6
-#define PRCMU_FW_PROJECT_U8500_C2 7
-#define PRCMU_FW_PROJECT_U8500_C3 8
-#define PRCMU_FW_PROJECT_U8500_C4 9
-#define PRCMU_FW_PROJECT_U9500_MBL 10
-#define PRCMU_FW_PROJECT_U8500_SSG1 11 /* Samsung specific */
-#define PRCMU_FW_PROJECT_U8500_MBL2 12 /* Customer specific */
-#define PRCMU_FW_PROJECT_U8520 13
-#define PRCMU_FW_PROJECT_U8420 14
-#define PRCMU_FW_PROJECT_U8500_SSG2 15 /* Samsung specific */
-#define PRCMU_FW_PROJECT_U8420_SYSCLK 17
-#define PRCMU_FW_PROJECT_A9420 20
-/* [32..63] 9540 and derivatives */
-#define PRCMU_FW_PROJECT_U9540 32
-/* [64..95] 8540 and derivatives */
-#define PRCMU_FW_PROJECT_L8540 64
-/* [96..126] 8580 and derivatives */
-#define PRCMU_FW_PROJECT_L8580 96
-
-#define PRCMU_FW_PROJECT_NAME_LEN 20
-struct prcmu_fw_version {
- u32 project; /* Notice, project shifted with 8 on ux540 */
- u8 api_version;
- u8 func_version;
- u8 errata;
- char project_name[PRCMU_FW_PROJECT_NAME_LEN];
-};
-
-#include <linux/mfd/db8500-prcmu.h>
-
-#if defined(CONFIG_UX500_SOC_DB8500)
-
-static inline void __init prcmu_early_init(void)
-{
- db8500_prcmu_early_init();
-}
-
-static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
- bool keep_ap_pll)
-{
- return db8500_prcmu_set_power_state(state, keep_ulp_clk,
- keep_ap_pll);
-}
-
-static inline u8 prcmu_get_power_state_result(void)
-{
- return db8500_prcmu_get_power_state_result();
-}
-
-static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
-{
- return db8500_prcmu_set_epod(epod_id, epod_state);
-}
-
-static inline void prcmu_enable_wakeups(u32 wakeups)
-{
- db8500_prcmu_enable_wakeups(wakeups);
-}
-
-static inline void prcmu_disable_wakeups(void)
-{
- prcmu_enable_wakeups(0);
-}
-
-static inline void prcmu_config_abb_event_readout(u32 abb_events)
-{
- db8500_prcmu_config_abb_event_readout(abb_events);
-}
-
-static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
-{
- db8500_prcmu_get_abb_event_buffer(buf);
-}
-
-int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
-int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
-int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size);
-
-int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
-
-static inline int prcmu_request_clock(u8 clock, bool enable)
-{
- return db8500_prcmu_request_clock(clock, enable);
-}
-
-unsigned long prcmu_clock_rate(u8 clock);
-long prcmu_round_clock_rate(u8 clock, unsigned long rate);
-int prcmu_set_clock_rate(u8 clock, unsigned long rate);
-
-static inline int prcmu_get_ddr_opp(void)
-{
- return db8500_prcmu_get_ddr_opp();
-}
-
-static inline int prcmu_set_arm_opp(u8 opp)
-{
- return db8500_prcmu_set_arm_opp(opp);
-}
-
-static inline int prcmu_get_arm_opp(void)
-{
- return db8500_prcmu_get_arm_opp();
-}
-
-static inline int prcmu_set_ape_opp(u8 opp)
-{
- return db8500_prcmu_set_ape_opp(opp);
-}
-
-static inline int prcmu_get_ape_opp(void)
-{
- return db8500_prcmu_get_ape_opp();
-}
-
-static inline int prcmu_request_ape_opp_100_voltage(bool enable)
-{
- return db8500_prcmu_request_ape_opp_100_voltage(enable);
-}
-
-static inline void prcmu_system_reset(u16 reset_code)
-{
- db8500_prcmu_system_reset(reset_code);
-}
-
-static inline u16 prcmu_get_reset_code(void)
-{
- return db8500_prcmu_get_reset_code();
-}
-
-int prcmu_ac_wake_req(void);
-void prcmu_ac_sleep_req(void);
-static inline void prcmu_modem_reset(void)
-{
- db8500_prcmu_modem_reset();
-}
-
-static inline bool prcmu_is_ac_wake_requested(void)
-{
- return db8500_prcmu_is_ac_wake_requested();
-}
-
-static inline int prcmu_config_esram0_deep_sleep(u8 state)
-{
- return db8500_prcmu_config_esram0_deep_sleep(state);
-}
-
-static inline int prcmu_config_hotdog(u8 threshold)
-{
- return db8500_prcmu_config_hotdog(threshold);
-}
-
-static inline int prcmu_config_hotmon(u8 low, u8 high)
-{
- return db8500_prcmu_config_hotmon(low, high);
-}
-
-static inline int prcmu_start_temp_sense(u16 cycles32k)
-{
- return db8500_prcmu_start_temp_sense(cycles32k);
-}
-
-static inline int prcmu_stop_temp_sense(void)
-{
- return db8500_prcmu_stop_temp_sense();
-}
-
-static inline u32 prcmu_read(unsigned int reg)
-{
- return db8500_prcmu_read(reg);
-}
-
-static inline void prcmu_write(unsigned int reg, u32 value)
-{
- db8500_prcmu_write(reg, value);
-}
-
-static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
-{
- db8500_prcmu_write_masked(reg, mask, value);
-}
-
-static inline int prcmu_enable_a9wdog(u8 id)
-{
- return db8500_prcmu_enable_a9wdog(id);
-}
-
-static inline int prcmu_disable_a9wdog(u8 id)
-{
- return db8500_prcmu_disable_a9wdog(id);
-}
-
-static inline int prcmu_kick_a9wdog(u8 id)
-{
- return db8500_prcmu_kick_a9wdog(id);
-}
-
-static inline int prcmu_load_a9wdog(u8 id, u32 timeout)
-{
- return db8500_prcmu_load_a9wdog(id, timeout);
-}
-
-static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
-{
- return db8500_prcmu_config_a9wdog(num, sleep_auto_off);
-}
-#else
-
-static inline void prcmu_early_init(void) {}
-
-static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
- bool keep_ap_pll)
-{
- return 0;
-}
-
-static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
-{
- return 0;
-}
-
-static inline void prcmu_enable_wakeups(u32 wakeups) {}
-
-static inline void prcmu_disable_wakeups(void) {}
-
-static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
- u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
-{
- return 0;
-}
-
-static inline int prcmu_request_clock(u8 clock, bool enable)
-{
- return 0;
-}
-
-static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate)
-{
- return 0;
-}
-
-static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate)
-{
- return 0;
-}
-
-static inline unsigned long prcmu_clock_rate(u8 clock)
-{
- return 0;
-}
-
-static inline int prcmu_set_ape_opp(u8 opp)
-{
- return 0;
-}
-
-static inline int prcmu_get_ape_opp(void)
-{
- return APE_100_OPP;
-}
-
-static inline int prcmu_request_ape_opp_100_voltage(bool enable)
-{
- return 0;
-}
-
-static inline int prcmu_set_arm_opp(u8 opp)
-{
- return 0;
-}
-
-static inline int prcmu_get_arm_opp(void)
-{
- return ARM_100_OPP;
-}
-
-static inline int prcmu_get_ddr_opp(void)
-{
- return DDR_100_OPP;
-}
-
-static inline void prcmu_system_reset(u16 reset_code) {}
-
-static inline u16 prcmu_get_reset_code(void)
-{
- return 0;
-}
-
-static inline int prcmu_ac_wake_req(void)
-{
- return 0;
-}
-
-static inline void prcmu_ac_sleep_req(void) {}
-
-static inline void prcmu_modem_reset(void) {}
-
-static inline bool prcmu_is_ac_wake_requested(void)
-{
- return false;
-}
-
-static inline int prcmu_config_esram0_deep_sleep(u8 state)
-{
- return 0;
-}
-
-static inline void prcmu_config_abb_event_readout(u32 abb_events) {}
-
-static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
-{
- *buf = NULL;
-}
-
-static inline int prcmu_config_hotdog(u8 threshold)
-{
- return 0;
-}
-
-static inline int prcmu_config_hotmon(u8 low, u8 high)
-{
- return 0;
-}
-
-static inline int prcmu_start_temp_sense(u16 cycles32k)
-{
- return 0;
-}
-
-static inline int prcmu_stop_temp_sense(void)
-{
- return 0;
-}
-
-static inline u32 prcmu_read(unsigned int reg)
-{
- return 0;
-}
-
-static inline void prcmu_write(unsigned int reg, u32 value) {}
-
-static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
-
-#endif
-
-static inline void prcmu_set(unsigned int reg, u32 bits)
-{
- prcmu_write_masked(reg, bits, bits);
-}
-
-static inline void prcmu_clear(unsigned int reg, u32 bits)
-{
- prcmu_write_masked(reg, bits, 0);
-}
-
-/* PRCMU QoS APE OPP class */
-#define PRCMU_QOS_APE_OPP 1
-#define PRCMU_QOS_DDR_OPP 2
-#define PRCMU_QOS_ARM_OPP 3
-#define PRCMU_QOS_DEFAULT_VALUE -1
-
-static inline int prcmu_qos_add_requirement(int prcmu_qos_class,
- char *name, s32 value)
-{
- return 0;
-}
-
-static inline int prcmu_qos_update_requirement(int prcmu_qos_class,
- char *name, s32 new_value)
-{
- return 0;
-}
-
-static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name)
-{
-}
-
-#endif /* __MACH_PRCMU_H */
--git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index 7798957c6504..499e826d7120 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -14,7 +14,7 @@
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
---
base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
change-id: 20260619-mfd-prcmu-merge-headers-bc84905195b4
Best regards,
--
Linus Walleij <linusw@kernel.org>
^ permalink raw reply related
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