* Re: [PATCH 07/10] HID: apple: Add support for DockChannel HID keyboards
From: Sasha Finkelstein @ 2026-06-30 13:41 UTC (permalink / raw)
To: michael.reeves077
Cc: Sven Peter, Janne Grunau, Neal Gompa, Jassi Brar, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Hector Martin,
Joerg Roedel (AMD), Will Deacon, Robin Murphy, Dmitry Torokhov,
Jiri Kosina, Benjamin Tissoires, asahi, linux-arm-kernel,
linux-kernel, devicetree, iommu, linux-input
In-Reply-To: <20260630-apple-mtp-keyboard-final-v1-7-506d936a1707@gmail.com>
> On Jun 30, 2026, at 14:54, Michael Reeves via B4 Relay <devnull+michael.reeves077.gmail.com@kernel.org> wrote:
>
> @@ -659,6 +669,7 @@ static void apple_battery_timer_tick(struct timer_list *t)
> /*
> * MacBook JIS keyboard has wrong logical maximum
> * Magic Keyboard JIS has wrong logical maximum
> + * Internal DockChannel keyboards can advertise oversized report sizes
> */
> static const __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
> unsigned int *rsize)
> @@ -699,6 +710,27 @@ static const __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
> rdesc[3] = 0x06;
> }
>
> + if (apple_is_dockchannel_keyboard(hdev) && *rsize >= 5) {
> + int i;
> +
> + for (i = 0; i <= *rsize - 5; i++) {
> + if (rdesc[i] == 0x76 && rdesc[i + 1] == 0x00 &&
> + rdesc[i + 2] == 0x40 && rdesc[i + 3] == 0x95) {
> + u8 count = rdesc[i + 4];
> +
> + if (count > 0 && count < 32) {
> + hid_info(hdev,
> + "fixing up DockChannel report size\n");
> + rdesc[i] = 0x75;
> + rdesc[i + 1] = 0x08;
> + rdesc[i + 2] = 0x96;
> + rdesc[i + 3] = 0x00;
> + rdesc[i + 4] = count * 8;
> + }
> + }
> + }
> + }
> +
> return rdesc;
> }
>
It looks like this section is duplicated in the following commit (8).
Is that correct?
^ permalink raw reply
* [PATCH v3 net-next 1/2] arm64: dts: ti: Add PLL1 refclk to J784S4 SoC SERDES node
From: Gokul Praveen @ 2026-06-30 13:43 UTC (permalink / raw)
To: conor+dt, devicetree, krzk+dt, linux-arm-kernel, linux-kernel,
linux-phy, neil.armstrong, nm, robh, sjakhade, kristo, vigneshr,
vkoul, yamonkar
In-Reply-To: <20260630134324.61085-1-g-praveen@ti.com>
Add PLL1 refclk to "clocks" and "clock-names" parameter of SERDES2 node
as "assigned clocks" parameter has PLL1 and serdes multilink configuration
fails without PLL1.
Signed-off-by: Gokul Praveen <g-praveen@ti.com>
---
arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
index 78fcd0c40abc..da8d582574d0 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
@@ -122,8 +122,9 @@ serdes2: serdes@5020000 {
resets = <&serdes_wiz2 0>;
reset-names = "torrent_reset";
clocks = <&serdes_wiz2 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz2 TI_WIZ_PLL1_REFCLK>,
<&serdes_wiz2 TI_WIZ_PHY_EN_REFCLK>;
- clock-names = "refclk", "phy_en_refclk";
+ clock-names = "refclk","pll1_refclk", "phy_en_refclk";
assigned-clocks = <&serdes_wiz2 TI_WIZ_PLL0_REFCLK>,
<&serdes_wiz2 TI_WIZ_PLL1_REFCLK>,
<&serdes_wiz2 TI_WIZ_REFCLK_DIG>;
--
2.34.1
^ permalink raw reply related
* [PATCH v3 net-next 0/2] Add support for dual port USXGMII+SGMII
From: Gokul Praveen @ 2026-06-30 13:43 UTC (permalink / raw)
To: conor+dt, devicetree, krzk+dt, linux-arm-kernel, linux-kernel,
linux-phy, neil.armstrong, nm, robh, sjakhade, kristo, vigneshr,
vkoul, yamonkar
This patch series enables dual port USXGMII and SGMII Ethernet mode
support on the TI J784S4 EVM platform using the CPSW9G Ethernet switch.
The CPSW9G instance supports both SGMII and USXGMII modes simultaneously
on MAC Ports 1 and 2, which connect to ENET Expansion 1 and ENET
Expansion 2 slots through the SERDES2 instance. The series includes:
Multilink SERDES configuration support added to the SERDES2 node by adding
the PLL1 refclk.
v2 <==> v1
===========
* Added modifications to the device tree bindings documentation.
v3 <=> v2
==========
* Added net-next suffix in the patch subject.
* Added a separate bindings patch and added appropriate subject
format expected for Bindings patches.
* Updated the cover letter description
Gokul Praveen (2):
arm64: dts: ti: Add PLL1 refclk to J784S4 SoC SERDES node
dt-bindings: phy: cadence-torrent: Update property values to support 3
clocks
.../devicetree/bindings/phy/phy-cadence-torrent.yaml | 4 ++--
arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi | 3 ++-
2 files changed, 4 insertions(+), 3 deletions(-)
--
2.34.1
^ permalink raw reply
* [PATCH v3 net-next 2/2] dt-bindings: phy: cadence-torrent: Update property values to support 3 clocks
From: Gokul Praveen @ 2026-06-30 13:43 UTC (permalink / raw)
To: conor+dt, devicetree, krzk+dt, linux-arm-kernel, linux-kernel,
linux-phy, neil.armstrong, nm, robh, sjakhade, kristo, vigneshr,
vkoul, yamonkar
In-Reply-To: <20260630134324.61085-1-g-praveen@ti.com>
Update maxItems value of "clocks" property to 3 as description of
this parameter already indicates 3 clocks(refclk,pll1_refclk(optional)
and phy_en_refclk(optional))
Update the "clock-names" property as well with the 3 clocks.
Signed-off-by: Gokul Praveen <g-praveen@ti.com>
---
.../devicetree/bindings/phy/phy-cadence-torrent.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml b/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml
index 9af39b33646a..54fe78da297a 100644
--- a/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml
+++ b/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml
@@ -34,7 +34,7 @@ properties:
clocks:
minItems: 1
- maxItems: 2
+ maxItems: 3
description:
PHY input reference clocks - refclk (for PLL0) & pll1_refclk (for PLL1).
pll1_refclk is optional and used for multi-protocol configurations requiring
@@ -47,7 +47,7 @@ properties:
minItems: 1
items:
- const: refclk
- - enum: [ pll1_refclk, phy_en_refclk ]
+ - enum: [refclk, pll1_refclk, phy_en_refclk ]
reg:
minItems: 1
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v3 3/5] arm64: dts: qcom: kaanapali: fix traceNoC probe issue
From: Jie Gan @ 2026-06-30 13:44 UTC (permalink / raw)
To: Konrad Dybcio, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Tingwei Zhang, Jingyi Wang,
Abel Vesa, Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Yuanfang Zhang, Abel Vesa, Alexander Shishkin
Cc: linux-arm-msm, devicetree, linux-kernel, coresight,
linux-arm-kernel
In-Reply-To: <a88201a7-0a00-48d8-97cd-300d6aa5fc88@oss.qualcomm.com>
On 6/30/2026 8:53 PM, Konrad Dybcio wrote:
> On 6/30/26 12:36 PM, Jie Gan wrote:
>> The traceNoC node used the "qcom,coresight-tnoc", "arm,primecell"
>> compatible, which places the device on the AMBA bus. The AMBA peripheral
>> ID probing fails on this platform, so the device never probes.
>
> An interested reader would immediately expect an answer to why that's
> the case
>
>> Switch the node to the standalone "qcom,coresight-agtnoc" compatible.
>> Dropping "arm,primecell" makes the device probe through the platform
>> driver instead of the AMBA bus, which resolves the probe failure while
>> keeping it an Aggregator TNOC that retains ATID functionality.
>
> This describes OS behavior. Move your message towards the other
> compatible not depending on reading that ID register.
Thanks for the suggestion, will rephrase the description.
Thanks,
Jie
>
> Konrad
^ permalink raw reply
* Re: [PATCH net-next v11 1/7] dt-bindings: phy: document the serdes PHY on sa8255p
From: Bartosz Golaszewski @ 2026-06-30 13:44 UTC (permalink / raw)
To: Vinod Koul
Cc: Geert Uytterhoeven, Bartosz Golaszewski, Bjorn Andersson,
Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Giuseppe Cavallaro, Chen-Yu Tsai, Jernej Skrabec, Neil Armstrong,
Kevin Hilman, Jerome Brunet, Shawn Guo, Fabio Estevam,
Jan Petrous, s32, Mohd Ayaan Anwar, Romain Gantois, Magnus Damm,
Maxime Ripard, Christophe Roullier, Radu Rendec, linux-arm-msm,
devicetree, linux-kernel, netdev, linux-stm32, linux-arm-kernel,
Drew Fustini, linux-sunxi, linux-amlogic, linux-mips, imx,
linux-renesas-soc, linux-rockchip, sophgo, linux-riscv,
Bartosz Golaszewski, Bartosz Golaszewski
In-Reply-To: <akOZFIowVvprnAMf@vaman>
On Tue, 30 Jun 2026 12:23:16 +0200, Vinod Koul <vkoul@kernel.org> said:
> On 29-06-26, 16:51, Geert Uytterhoeven wrote:
>> > Russell King asked me to put the PHY logic for SCMI pm domains into the PHY
>> > driver instead of the MAC driver where it was previously. Instead of cramming
>> > both HLOS and firmware handling into the same driver, I figured it makes more
>> > sense to have a dedicated, cleaner driver as the two share very little code (if
>> > any).
>>
>> I think you are mixing up DT bindings and driver implementation?
>
> Should the bindings change if we have different driver and firmware
> implementations? Isn't binding supposed to be agnostic of
> implementations..?
>
The way sa8255p implements SCMI is with SMC exclusively but - since even base
support is not yet upstream - maybe it would be possible to expose SCMI clocks
like some platforms do and reuse the same binding.
Would it make sense?
Bart
^ permalink raw reply
* Re: [PATCH 09/27] ASoC: codecs: idt821034: Use guard() for mutex locks
From: Bui Duc Phuc @ 2026-06-30 13:50 UTC (permalink / raw)
To: Mark Brown
Cc: Herve Codina, Takashi Iwai, Nick Li, Support Opensource,
Liam Girdwood, Jaroslav Kysela, Srinivas Kandagatla,
Charles Keepax, Richard Fitzgerald, Matthias Brugger,
AngeloGioacchino Del Regno, Shenghao Ding, Kevin Lu, Baojun Xu,
Sen Wang, Oder Chiou, Linus Walleij, Kuninori Morimoto,
u.kleine-koenig, Zhang Yi, Marco Crivellari, Kees Cook,
HyeongJun An, Arnd Bergmann, Qianfeng Rong, linux-sound,
linux-kernel, patches, linux-mediatek, linux-arm-msm,
linux-arm-kernel
In-Reply-To: <f5ab965a-9640-4df0-8108-7877f34b6950@sirena.org.uk>
On Tue, Jun 30, 2026 at 8:29 PM Mark Brown <broonie@kernel.org> wrote:
> Please delete unneeded context from mails when replying. Doing this
> makes it much easier to find your reply in the message, helping ensure
> it won't be missed by people scrolling through the irrelevant quoted
> material.
Got it. I'll make sure to trim the unneeded context in my future replies.
Thanks for the reminder!
Best regards,
Phuc
^ permalink raw reply
* [PATCH 00/10] Add support for Apple Silicon DockChannel internal keyboards
From: Michael Reeves via B4 Relay @ 2026-06-30 12:54 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Neal Gompa, Jassi Brar, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Hector Martin,
Joerg Roedel (AMD), Will Deacon, Robin Murphy, Dmitry Torokhov,
Jiri Kosina, Benjamin Tissoires
Cc: asahi, linux-arm-kernel, linux-kernel, devicetree, iommu,
linux-input, Michael Reeves, Sasha Finkelstein
This series introduces support for the internal keyboards on Apple
Silicon M2 and M3 MacBook models.
On these platforms, built-in input devices are managed by a dedicated
coprocessor running an RTKit-based operating system. Communication
between this coprocessor and the main processor is carried out over a
low-latency hardware byte FIFO interface called DockChannel.
To support this input path, the series introduces a few new components:
- An apple-dockchannel mailbox driver to handle the low-level
byte-stream FIFO.
- A DockChannel HID transport driver (apple-hid) that boots the
coprocessor using the RTKit framework and encapsulates the HID
protocol over the mailbox.
- Minor additions to the apple-rtkit and hid-apple drivers to support
the TraceKit endpoint and integrate the keyboards into the existing
input-quirks framework.
- Devicetree bindings and DTS updates to describe the nodes on M2 and
M3 laptops.
The transport driver is based on an original out-of-tree implementation
by Hector Martin, but it has been significantly rewritten for upstream
inclusion to use the standard Linux mailbox framework and align better
with upstream HID design patterns and reduce reliance on hacks.
While the coprocessor manages both the keyboard and the trackpad, this
series only enables keyboard support. The keyboard can be initialised
without loading external firmware, whereas the trackpad requires
firmware. Trackpad support will be submitted in a subsequent series
once these base transport layers are established.
Tested on: MacBook Air M3 (J613).
Signed-off-by: Michael Reeves <michael.reeves077@gmail.com>
---
Michael Reeves (9):
dt-bindings: mailbox: Add Apple t8122 ASC mailbox
dt-bindings: mailbox: apple: Add DockChannel mailbox
dt-bindings: iommu: apple,dart: Add t8122 compatible
dt-bindings: input: apple: Add DockChannel HID transport
mailbox: apple: Add DockChannel FIFO controller
HID: apple: Add support for DockChannel HID keyboards
HID: apple: Add DockChannel HID transport driver
arm64: dts: apple: Add MTP DockChannel HID nodes
arm64: dts: apple: Enable DockChannel HID on M2 and M3 laptops
Sasha Finkelstein (1):
soc: apple: rtkit: Add tracekit endpoint
.../bindings/input/apple,dockchannel-hid.yaml | 91 ++
.../devicetree/bindings/iommu/apple,dart.yaml | 4 +-
.../bindings/mailbox/apple,dockchannel.yaml | 75 ++
.../devicetree/bindings/mailbox/apple,mailbox.yaml | 1 +
MAINTAINERS | 5 +
arch/arm64/boot/dts/apple/t602x-die0.dtsi | 46 +
arch/arm64/boot/dts/apple/t602x-j414-j416.dtsi | 25 +
arch/arm64/boot/dts/apple/t8112-j413.dts | 20 +
arch/arm64/boot/dts/apple/t8112-j415.dts | 20 +
arch/arm64/boot/dts/apple/t8112-j493.dts | 22 +-
arch/arm64/boot/dts/apple/t8112.dtsi | 46 +
arch/arm64/boot/dts/apple/t8122-j504.dts | 22 +
arch/arm64/boot/dts/apple/t8122-j613.dts | 23 +
arch/arm64/boot/dts/apple/t8122-j615.dts | 23 +
arch/arm64/boot/dts/apple/t8122.dtsi | 47 +
drivers/hid/Kconfig | 2 +
drivers/hid/Makefile | 2 +
drivers/hid/dockchannel/Kconfig | 15 +
drivers/hid/dockchannel/Makefile | 3 +
drivers/hid/dockchannel/apple-hid.c | 1130 ++++++++++++++++++++
drivers/hid/hid-apple.c | 139 ++-
drivers/mailbox/Kconfig | 12 +
drivers/mailbox/Makefile | 2 +
drivers/mailbox/apple-dockchannel.c | 380 +++++++
drivers/soc/apple/rtkit.c | 2 +
include/linux/hid.h | 1 +
include/linux/mailbox/apple-dockchannel.h | 29 +
27 files changed, 2139 insertions(+), 48 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260629-apple-mtp-keyboard-final-91cb5a6ff4fc
Best regards,
--
Michael Reeves <michael.reeves077@gmail.com>
^ permalink raw reply
* Re: [PATCH 0/3] arm64: dts/net: stmmac: Add Agilex5 SoCDK TSN Config2 board support
From: Maxime Chevallier @ 2026-06-30 13:53 UTC (permalink / raw)
To: muhammad.nazim.amirul.nazle.asmade, dinguyen
Cc: rmk+kernel, krzk+dt, conor+dt, robh, davem, edumazet, kuba,
pabeni, andrew+netdev, devicetree, linux-arm-kernel, netdev,
linux-kernel
In-Reply-To: <20260630133108.27244-1-muhammad.nazim.amirul.nazle.asmade@altera.com>
Hi,
On 6/30/26 15:31, muhammad.nazim.amirul.nazle.asmade@altera.com wrote:
> From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
>
> The Intel SoCFPGA Agilex5 SoCDK TSN Config2 board uses a dual-port
> Ethernet setup where gmac1 (TSN port) operates with different MAC-side
> and PHY-side interface modes: GMII internally in the MAC, and RGMII
> towards the PHY.
There's the same behaviour on Gen5, e.g. CycloneV where we have the
"EMAC splitter". Based on wether or not we have that splitter in DT,
we override the INTF_SEL bits to set GMII as the MAC output, the splitter
converting that to RGMII/SGMII.
Is there something similar on this AgileX5 version by any chance, for
which we could reuse the logic ?
I know that on CycloneV you also need to adjust that GMII -> RGMII/SGMII
splitter whenever the speed changes, is that different on agileX5 ? have
you tested 10/100Mbps ?
Thanks,
Maxime
^ permalink raw reply
* Re: [PATCH v4 0/2] arm64: errata: NVIDIA Olympus device store/load ordering
From: Will Deacon @ 2026-06-30 13:53 UTC (permalink / raw)
To: Shanker Donthineni
Cc: Vladimir Murzin, Catalin Marinas, Jason Gunthorpe,
linux-arm-kernel, Mark Rutland, linux-kernel, linux-doc,
Vikram Sethi, Jason Sequeira
In-Reply-To: <ba15e106-9066-4e55-be2f-6767a32e123d@nvidia.com>
On Mon, Jun 29, 2026 at 06:08:37PM -0500, Shanker Donthineni wrote:
> On 6/29/2026 5:45 AM, Vladimir Murzin wrote:
> > That's interesting. With the way the patch set is structured, it
> > now looks like:
> >
> > 1. Fix the erratum, but cause a performance regression.
> > 2. Restore the performance regression and (re)apply the erratum
> > workaround.
> >
> > Would it make sense to avoid introducing the performance
> > regression in the first place by structuring the patch set
> > slightly differently?
> >
> > 1. (Re)introduce arm64 memset_io()/memcpy_toio().
> > 2. Fix the erratum once for all
> >
> > What do you reckon?
>
> Yes, that ordering makes sense.
>
> I can restructure v5 so that patch 1 introduces the arm64 memset_{to}io()
> implementations while preserving the existing behavior. Patch 2 will
> then add the complete erratum workaround, including the conditional
> trailing DMB for those block-write helpers. This avoids introducing
> the intermediate performance regression and keeps each commit
> independently usable.
>
> Will and Catalin, could you please share your thoughts on this approach?
tbh, I think I'm ok with the current ordering. The second patch is purely
a performance thing for affected CPUs, so doesn't strictly need to be
applied or backported for functional correctness afaict.
Will
^ permalink raw reply
* Re: [PATCH v7 1/4] dt-bindings: pci: Strictly distinguish C0 from C1-C5
From: Rob Herring (Arm) @ 2026-06-30 13:54 UTC (permalink / raw)
To: Thierry Reding
Cc: Krzysztof Wilczyński, linux-arm-kernel, Jonathan Hunter,
Thomas Petazzoni, linux-tegra, Pali Rohár, devicetree,
Karthikeyan Mitran, linux-kernel, linux-pci, Thierry Reding,
Manivannan Sadhasivam, Conor Dooley, Michal Simek, Bjorn Helgaas,
Aksh Garg, Krzysztof Kozlowski, Kevin Xie, Lorenzo Pieralisi,
Thierry Reding, Hou Zhiqiang
In-Reply-To: <20260617-tegra264-pcie-v7-1-eae7ae964629@nvidia.com>
On Wed, 17 Jun 2026 18:01:28 +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Instead of using the ECAM registers as the first entry, strictly make a
> distinction between C0 and C1-C5. This is needed because otherwise the
> unit address doesn't match the first "reg" entry. We also cannot change
> the ordering of these nodes to follow the ECAM addresses because that
> would put them outside of their "control bus" hierarchy since the ECAM
> address space is a global one outside of any of the control busses.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> Changes in v7:
> - undo changes suggested by Sashiko, should've trust the dedicated tool
> rather than the AI
>
> Changes in v6:
> - add maxItems as suggested by Sashiko
>
> Changes in v5:
> - rebase on top of v7.1-rc1, make it into a fix
>
> Changes in v4:
> - ECAM is outside of the controller's region, so it cannot be the first
> reg entry, otherwise we get warnings because it doesn't match the
> unit-address, so revert back to oneOf construct
>
> Changes in v2:
> - move ECAM region first and unify C0 vs. C1-C5
> - move unevaluatedProperties to right before the examples
> - add description to clarify the two types of controllers
> - add examples for C0 and C1-C5
> ---
> .../bindings/pci/nvidia,tegra264-pcie.yaml | 75 ++++++++++++++--------
> 1 file changed, 50 insertions(+), 25 deletions(-)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v4 5/6] mm/vmalloc: map contiguous pages in batches for vmap() if possible
From: Uladzislau Rezki @ 2026-06-30 13:54 UTC (permalink / raw)
To: Wen Jiang
Cc: linux-mm, linux-arm-kernel, catalin.marinas, will, akpm, urezki,
baohua, Xueyuan.chen21, dev.jain, rppt, david, ryan.roberts,
anshuman.khandual, ajd, linux-kernel, jiangwen6, shanghaoqiang
In-Reply-To: <20260618084726.1070022-6-jiangwen6@xiaomi.com>
On Thu, Jun 18, 2026 at 04:47:25PM +0800, Wen Jiang wrote:
> From: "Barry Song (Xiaomi)" <baohua@kernel.org>
>
> In many cases, the pages passed to vmap() may include high-order
> pages. For example, the systemheap often allocates pages in descending
> order: order 8, then 4, then 0. Currently, vmap() iterates over every
> page individually—even pages inside a high-order block are handled
> one by one.
>
> This patch detects physically contiguous pages (regardless of whether
> they are compound or non-compound) by scanning with
> num_pages_contiguous(), and maps them as a single contiguous block
> whenever possible. The mapping order is determined by taking the
> minimum of the contiguous page count and the pfn alignment, allowing
> graceful degradation when pfn alignment is less than the contiguous
> range.
>
> Pages with the same page_shift are coalesced and mapped via
> vmap_pages_range_noflush_walk() to avoid page table rewalk.
>
> As users typically allocate memory in descending orders (e.g.
> 8 → 4 → 0), once an order-0 page is encountered, we stop scanning
> for contiguous pages since subsequent pages are likely order-0 as well.
>
> Signed-off-by: Barry Song (Xiaomi) <baohua@kernel.org>
> Co-developed-by: Dev Jain <dev.jain@arm.com>
> Signed-off-by: Dev Jain <dev.jain@arm.com>
> Signed-off-by: Wen Jiang <jiangwen6@xiaomi.com>
> Tested-by: Xueyuan Chen <xueyuan.chen21@gmail.com>
> ---
> mm/vmalloc.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 85 insertions(+), 2 deletions(-)
>
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index 253e017130e09..fffb885cb2158 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -3545,6 +3545,89 @@ void vunmap(const void *addr)
> }
> EXPORT_SYMBOL(vunmap);
>
> +static inline unsigned int vm_shift(pgprot_t prot, unsigned long size)
> +{
> + if (arch_vmap_pmd_supported(prot) && size >= PMD_SIZE)
> + return PMD_SHIFT;
> +
> + return arch_vmap_pte_supported_shift(size);
> +}
> +
> +static inline int get_vmap_batch_order(struct page **pages,
> + pgprot_t prot, unsigned int max_steps, unsigned int idx)
> +{
> + unsigned int nr_contig;
> + int order;
> +
> + if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP))
> + return 0;
> +
> + nr_contig = num_pages_contiguous(&pages[idx], max_steps);
> + if (nr_contig < 2)
> + return 0;
> +
> + order = ilog2(nr_contig);
> +
> + /* Limit order by pfn alignment */
> + order = min_t(int, order, __ffs(page_to_pfn(pages[idx])));
> +
> + if (vm_shift(prot, PAGE_SIZE << order) == PAGE_SHIFT)
> + return 0;
> +
> + return order;
> +}
> +
> +static int vmap_batched(unsigned long addr, unsigned long end,
> + pgprot_t prot, struct page **pages)
> +{
> + unsigned int count = (end - addr) >> PAGE_SHIFT;
> + unsigned int prev_shift = 0, idx = 0;
> + unsigned long start = addr, map_addr = addr;
> + int err;
> +
> + err = kmsan_vmap_pages_range_noflush(addr, end, prot, pages,
> + PAGE_SHIFT, GFP_KERNEL);
> + if (err)
> + goto out;
> +
> + for (unsigned int i = 0; i < count; ) {
> + unsigned int shift = PAGE_SHIFT +
> + get_vmap_batch_order(pages, prot, count - i, i);
> +
> + if (!i)
> + prev_shift = shift;
> +
> + if (shift != prev_shift) {
> + err = vmap_pages_range_noflush_walk(map_addr, addr,
> + prot, pages + idx, prev_shift);
> + if (err)
> + goto out;
> + prev_shift = shift;
> + map_addr = addr;
> + idx = i;
> + }
> +
> + /*
> + * Once small pages are encountered, the remaining pages
> + * are likely small as well.
> + */
> + if (shift == PAGE_SHIFT)
> + break;
> +
> + addr += 1UL << shift;
> + i += 1U << (shift - PAGE_SHIFT);
> + }
> +
> + /* Remaining */
> + if (map_addr < end)
> + err = vmap_pages_range_noflush_walk(map_addr, end,
> + prot, pages + idx, prev_shift);
> +
> +out:
> + flush_cache_vmap(start, end);
> + return err;
> +}
> +
> /**
> * vmap - map an array of pages into virtually contiguous space
> * @pages: array of page pointers
> @@ -3588,8 +3671,8 @@ void *vmap(struct page **pages, unsigned int count,
> return NULL;
>
> addr = (unsigned long)area->addr;
> - if (vmap_pages_range(addr, addr + size, pgprot_nx(prot),
> - pages, PAGE_SHIFT) < 0) {
> + if (vmap_batched(addr, addr + size, pgprot_nx(prot),
> + pages) < 0) {
>
Better naming? vmap_pages_range_batched()?
--
Uladzislau Rezki
^ permalink raw reply
* Re: [PATCH 2/4] dt-bindings: raspberrypi,bcm2835-firmware: Include 'reboot-mode.yaml'
From: Gregor Herburger @ 2026-06-30 13:56 UTC (permalink / raw)
To: Conor Dooley
Cc: Florian Fainelli, Broadcom internal kernel review list, Ray Jui,
Scott Branden, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Eric Anholt, Stefan Wahren, linux-rpi-kernel, linux-arm-kernel,
linux-kernel, devicetree
In-Reply-To: <20260626-quaking-shove-fcc9d8057ae0@spud>
Hi Conor,
On Fri, Jun 26, 2026 at 04:57:35PM +0100, Conor Dooley wrote:
> On Fri, Jun 26, 2026 at 09:35:05AM +0200, Gregor Herburger wrote:
> > The Raspberry Pi firmware allows to set a reboot mode called tryboot
> > that allows to try booting from a different partition to allow updating
> > of the boot partition. Allow reboot mode properties by referencing the
> > reboot-mode schema.
> >
> > Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
> > ---
> > .../devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
> > index 983ea80eaec97..30b490e0d9fb3 100644
> > --- a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
> > +++ b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
> > @@ -133,11 +133,14 @@ properties:
> > required:
> > - compatible
> >
> > +allOf:
> > + - $ref: /schemas/power/reset/reboot-mode.yaml#
> > +
> > required:
> > - compatible
> > - mboxes
> >
> > -additionalProperties: false
> > +unevaluatedProperties: false
>
> I think you should keep additionalProperties: false and add
> mode-normal: true
> mode-tryboot: true
>
> (I don't know if the latter works though, you may need to have a $ref to
> uint32-array).
>
> What you've done permits freeform reboot modes, but I think only normal
> and tryboot are valid?
Ah yes good point. I do think it should be restricted to
'mode-{normal,tryboot}'.
Sashiko also suggested to set maxItems to 1 and I think that is a good idea as
well, because afaik the firmware only accepts a 32bit value for the reboot flag.
The $ref to uin32 is not needed that is already enforced by the
patternProperties "^mode-.*$": in reboot-mode.yaml.
Therefore I will add the following (and keep additionalProperties: false):
properties:
...
mode-normal:
maxItems: 1
mode-tryboot:
maxItems: 1
allOf:
- $ref: /schemas/power/reset/reboot-mode.yaml#
I will do some more testing and send a v2 later.
Regards
--
Gregor Herburger
Linutronix GmbH | Bahnhofstrasse 3 | D-88690 Uhldingen-Mühlhofen
Phone: +49 7556 25 999 35; Fax.: +49 7556 25 999 99
Hinweise zum Datenschutz finden Sie hier (Informations on data privacy
can be found here): https://linutronix.de/legal/data-protection.php
Linutronix GmbH | Firmensitz (Registered Office): Uhldingen-Mühlhofen |
Registergericht (Registration Court): Amtsgericht Freiburg i.Br., HRB700
806 | Geschäftsführer (Managing Directors): Dr. Wilfried Wessner,
Katharina Kopp, Alexander Gieringer
^ permalink raw reply
* Re: [PATCH v7 1/3] dt-bindings: imx6q-pcie: Add optional intr/aer/pme interrupts for i.MX95
From: Rob Herring (Arm) @ 2026-06-30 13:56 UTC (permalink / raw)
To: hongxing.zhu
Cc: linux-arm-kernel, kwilczynski, linux-kernel, Richard Zhu, mani,
l.stach, kernel, krzk+dt, bhelgaas, frank.li, s.hauer, linux-pci,
devicetree, imx, Frank Li, lpieralisi, festevam, conor+dt
In-Reply-To: <20260618092100.3669556-2-hongxing.zhu@oss.nxp.com>
On Thu, 18 Jun 2026 17:20:58 +0800, hongxing.zhu@oss.nxp.com wrote:
> From: Richard Zhu <hongxing.zhu@nxp.com>
>
> The i.MX95 PCIe controller introduces three additional dedicated hardware
> interrupt lines for specific events:
> - intr: general controller events
> - aer: Advanced Error Reporting events
> - pme: Power Management Events
>
> These interrupts are optional on i.MX95. PCIe basic functionality
> (enumeration, configuration, and data transfer) works correctly without
> them, as the controller can operate using only the existing msi interrupt.
>
> Earlier i.MX PCIe variants (imx6q, imx6sx, imx6qp, imx7d, imx8mm, imx8mp,
> imx8mq, imx8q) do not have these three dedicated interrupt lines.
>
> Update the binding to allow up to 5 interrupts for i.MX95, while
> restricting earlier variants to a maximum of 2 interrupts using
> conditional constraints (if/then schema). This ensures the schema
> accurately reflects the hardware capabilities of each SoC variant.
>
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> ---
> .../bindings/pci/fsl,imx6q-pcie.yaml | 25 +++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH] soc: imx8m: fix clock reference leak in imx8m_soc_prepare()
From: Felix Gu @ 2026-06-30 13:58 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Marco Felsch, Shawn Guo, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <MRWPR04MB12330BE6893CE9A0F6702ABD188E82@MRWPR04MB12330.eurprd04.prod.outlook.com>
Hi Peng,
On Mon, Jun 29, 2026 at 3:21 PM Peng Fan (OSS) <peng.fan@oss.nxp.com> wrote:
> > platform_device *pdev, const char *ocotp_com
> >
> > ret = clk_prepare_enable(drvdata->clk);
> > if (ret)
> > - goto err_clk;
> > + goto put_clk;
> >
> > return 0;
> >
> > +put_clk:
> > + clk_put(drvdata->clk);
> > err_clk:
>
> It should be safe to directly put "clk_put" here, no
> need extra label.
Passing an error_ptr to clk_put() could invoke WARN_ON_ONCE.
Best regards
Felix
>
> Regards
> Peng.
>
> > iounmap(drvdata->ocotp_base);
> > return ret;
> >
^ permalink raw reply
* Re: [PATCH 2/3] arm64: dts: socfpga: agilex5: Add SoCDK TSN Config2 board
From: Andrew Lunn @ 2026-06-30 13:58 UTC (permalink / raw)
To: muhammad.nazim.amirul.nazle.asmade
Cc: dinguyen, maxime.chevallier, rmk+kernel, krzk+dt, conor+dt, robh,
davem, edumazet, kuba, pabeni, andrew+netdev, devicetree,
linux-arm-kernel, netdev, linux-kernel
In-Reply-To: <20260630133108.27244-3-muhammad.nazim.amirul.nazle.asmade@altera.com>
> + * gmac1 is the TSN port. The MAC operates in GMII mode internally
> + * while the PHY-side interface is RGMII, so mac-mode and phy-mode differ.
> + */
> +&gmac1 {
> + status = "okay";
> + phy-mode = "rgmii"; /* TX/RX clock delays provided by Agilex5 I/O hardware */
Could you provide more details about this. I want to understand the
big picture.
Normally we talk about the PCB providing the delays. This sounds like
it is the FPGA? So i need convincing this is correct.
https://elixir.bootlin.com/linux/v6.15/source/Documentation/devicetree/bindings/net/ethernet-controller.yaml#L287
Andrew
^ permalink raw reply
* [PATCH 07/10] HID: apple: Add support for DockChannel HID keyboards
From: Michael Reeves via B4 Relay @ 2026-06-30 12:54 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Neal Gompa, Jassi Brar, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Hector Martin,
Joerg Roedel (AMD), Will Deacon, Robin Murphy, Dmitry Torokhov,
Jiri Kosina, Benjamin Tissoires
Cc: asahi, linux-arm-kernel, linux-kernel, devicetree, iommu,
linux-input, Michael Reeves
In-Reply-To: <20260630-apple-mtp-keyboard-final-v1-0-506d936a1707@gmail.com>
From: Michael Reeves <michael.reeves077@gmail.com>
DockChannel keyboards are registered as host-bus Apple HID devices
instead of USB or Bluetooth devices.
Match them in hid-apple, use the modern Magic Keyboard function-key
table, and fix up the oversized report-size descriptor pattern before
parsing.
Signed-off-by: Michael Reeves <michael.reeves077@gmail.com>
---
drivers/hid/hid-apple.c | 139 ++++++++++++++++++++++++++++++++----------------
include/linux/hid.h | 1 +
2 files changed, 94 insertions(+), 46 deletions(-)
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index bf7dd0fbf249..47c6ec09d5fa 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -390,6 +390,12 @@ static bool apple_is_omoton_kb066(struct hid_device *hdev)
strcmp(hdev->name, "Bluetooth Keyboard") == 0;
}
+static bool apple_is_dockchannel_keyboard(struct hid_device *hdev)
+{
+ return hdev->bus == BUS_HOST &&
+ hdev->group == HID_GROUP_APPLE_DOCKCHANNEL;
+}
+
static inline void apple_setup_key_translation(struct input_dev *input,
const struct apple_key_translation *table)
{
@@ -477,53 +483,57 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
asc->fn_on = !!value;
if (real_fnmode) {
- switch (hid->product) {
- case USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI:
- case USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO:
- case USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS:
- case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI:
- case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO:
- case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS:
- case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI:
- case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO:
- case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS:
- table = magic_keyboard_alu_fn_keys;
- break;
- case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015:
- case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015:
- table = magic_keyboard_2015_fn_keys;
- break;
- case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021:
- case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021:
- case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021:
- case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024:
- case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2024:
- case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2024:
+ if (apple_is_dockchannel_keyboard(hid)) {
table = magic_keyboard_2021_and_2024_fn_keys;
- break;
- case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
- case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
- case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
- case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
- table = macbookpro_no_esc_fn_keys;
- break;
- case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
- case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
- case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
- table = macbookpro_dedicated_esc_fn_keys;
- break;
- case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
- case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
- table = apple_fn_keys;
- break;
- default:
- if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
- hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
- table = macbookair_fn_keys;
- else if (hid->product < 0x21d || hid->product >= 0x300)
- table = powerbook_fn_keys;
- else
+ } else {
+ switch (hid->product) {
+ case USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI:
+ case USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO:
+ case USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS:
+ case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI:
+ case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO:
+ case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS:
+ case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI:
+ case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO:
+ case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS:
+ table = magic_keyboard_alu_fn_keys;
+ break;
+ case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015:
+ case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015:
+ table = magic_keyboard_2015_fn_keys;
+ break;
+ case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021:
+ case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021:
+ case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021:
+ case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024:
+ case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2024:
+ case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2024:
+ table = magic_keyboard_2021_and_2024_fn_keys;
+ break;
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
+ table = macbookpro_no_esc_fn_keys;
+ break;
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
+ table = macbookpro_dedicated_esc_fn_keys;
+ break;
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
table = apple_fn_keys;
+ break;
+ default:
+ if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
+ hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
+ table = macbookair_fn_keys;
+ else if (hid->product < 0x21d || hid->product >= 0x300)
+ table = powerbook_fn_keys;
+ else
+ table = apple_fn_keys;
+ }
}
trans = apple_find_translation(table, code);
@@ -659,6 +669,7 @@ static void apple_battery_timer_tick(struct timer_list *t)
/*
* MacBook JIS keyboard has wrong logical maximum
* Magic Keyboard JIS has wrong logical maximum
+ * Internal DockChannel keyboards can advertise oversized report sizes
*/
static const __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
@@ -699,6 +710,27 @@ static const __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
rdesc[3] = 0x06;
}
+ if (apple_is_dockchannel_keyboard(hdev) && *rsize >= 5) {
+ int i;
+
+ for (i = 0; i <= *rsize - 5; i++) {
+ if (rdesc[i] == 0x76 && rdesc[i + 1] == 0x00 &&
+ rdesc[i + 2] == 0x40 && rdesc[i + 3] == 0x95) {
+ u8 count = rdesc[i + 4];
+
+ if (count > 0 && count < 32) {
+ hid_info(hdev,
+ "fixing up DockChannel report size\n");
+ rdesc[i] = 0x75;
+ rdesc[i + 1] = 0x08;
+ rdesc[i + 2] = 0x96;
+ rdesc[i + 3] = 0x00;
+ rdesc[i + 4] = count * 8;
+ }
+ }
+ }
+ }
+
return rdesc;
}
@@ -763,7 +795,7 @@ static int apple_input_configured(struct hid_device *hdev,
struct apple_sc *asc = hid_get_drvdata(hdev);
if (((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) || apple_is_omoton_kb066(hdev)) {
- hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n");
+ hid_info(hdev, "Disabling function quirk for device without function key\n");
asc->quirks &= ~APPLE_HAS_FN;
}
@@ -1003,6 +1035,17 @@ static void apple_remove(struct hid_device *hdev)
hid_hw_stop(hdev);
}
+static bool apple_match(struct hid_device *hdev, bool ignore_special_driver)
+{
+ if (ignore_special_driver)
+ return false;
+
+ if (hdev->group == HID_GROUP_APPLE_DOCKCHANNEL)
+ return apple_is_dockchannel_keyboard(hdev);
+
+ return true;
+}
+
static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
@@ -1224,6 +1267,9 @@ static const struct hid_device_id apple_devices[] = {
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT),
.driver_data = APPLE_MAGIC_BACKLIGHT },
+ { HID_DEVICE(BUS_HOST, HID_GROUP_APPLE_DOCKCHANNEL,
+ HID_ANY_ID, HID_ANY_ID),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ }
};
@@ -1232,6 +1278,7 @@ MODULE_DEVICE_TABLE(hid, apple_devices);
static struct hid_driver apple_driver = {
.name = "apple",
.id_table = apple_devices,
+ .match = apple_match,
.report_fixup = apple_report_fixup,
.probe = apple_probe,
.remove = apple_remove,
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 47dc0bc89fa4..0d40deec6295 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -441,6 +441,7 @@ struct hid_item {
#define HID_GROUP_STEAM 0x0103
#define HID_GROUP_LOGITECH_27MHZ_DEVICE 0x0104
#define HID_GROUP_VIVALDI 0x0105
+#define HID_GROUP_APPLE_DOCKCHANNEL 0x0106
/*
* HID protocol status
--
2.51.2
^ permalink raw reply related
* [PATCH 08/10] HID: apple: Add DockChannel HID transport driver
From: Michael Reeves via B4 Relay @ 2026-06-30 12:54 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Neal Gompa, Jassi Brar, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Hector Martin,
Joerg Roedel (AMD), Will Deacon, Robin Murphy, Dmitry Torokhov,
Jiri Kosina, Benjamin Tissoires
Cc: asahi, linux-arm-kernel, linux-kernel, devicetree, iommu,
linux-input, Michael Reeves
In-Reply-To: <20260630-apple-mtp-keyboard-final-v1-0-506d936a1707@gmail.com>
From: Michael Reeves <michael.reeves077@gmail.com>
Apple MTP exposes internal keyboard and trackpad interfaces over a HID
transport carried by DockChannel.
Add a transport driver that boots the MTP RTKit coprocessor, exchanges
HID packets through the DockChannel mailbox, and registers child HID
interfaces from devicetree.
Co-developed-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Michael Reeves <michael.reeves077@gmail.com>
---
MAINTAINERS | 1 +
drivers/hid/Kconfig | 2 +
drivers/hid/Makefile | 2 +
drivers/hid/dockchannel/Kconfig | 15 +
drivers/hid/dockchannel/Makefile | 3 +
drivers/hid/dockchannel/apple-hid.c | 1130 +++++++++++++++++++++++++++++++++++
6 files changed, 1153 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index ed68452c0ad6..0063276f0349 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2620,6 +2620,7 @@ F: drivers/clk/clk-apple-nco.c
F: drivers/cpufreq/apple-soc-cpufreq.c
F: drivers/dma/apple-admac.c
F: drivers/gpio/gpio-macsmc.c
+F: drivers/hid/dockchannel/
F: drivers/hwmon/macsmc-hwmon.c
F: drivers/pmdomain/apple/
F: drivers/i2c/busses/i2c-pasemi-core.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index f9bcaeb66385..f27cda601ede 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1488,6 +1488,8 @@ source "drivers/hid/surface-hid/Kconfig"
source "drivers/hid/intel-thc-hid/Kconfig"
+source "drivers/hid/dockchannel/Kconfig"
+
endif # HID
# USB support may be used with HID disabled
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 23e6e3dd0c56..c9b4b1aff247 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -182,3 +182,5 @@ obj-$(CONFIG_AMD_SFH_HID) += amd-sfh-hid/
obj-$(CONFIG_SURFACE_HID_CORE) += surface-hid/
obj-$(CONFIG_INTEL_THC_HID) += intel-thc-hid/
+
+obj-$(CONFIG_APPLE_DOCKCHANNEL_HID) += dockchannel/
diff --git a/drivers/hid/dockchannel/Kconfig b/drivers/hid/dockchannel/Kconfig
new file mode 100644
index 000000000000..fca09ef74403
--- /dev/null
+++ b/drivers/hid/dockchannel/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-only OR MIT
+
+config APPLE_DOCKCHANNEL_HID
+ tristate "HID over Apple DockChannel"
+ depends on APPLE_DOCKCHANNEL
+ depends on APPLE_RTKIT
+ depends on HID
+ depends on INPUT
+ depends on OF
+ help
+ This provides a HID transport layer over the Apple DockChannel
+ mailbox interface. It is required to support the internal keyboard
+ and trackpad on M2 and later MacBook models.
+
+ Say Y here if you have an M2 or later Apple MacBook.
diff --git a/drivers/hid/dockchannel/Makefile b/drivers/hid/dockchannel/Makefile
new file mode 100644
index 000000000000..d1a82aa57a69
--- /dev/null
+++ b/drivers/hid/dockchannel/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only OR MIT
+
+obj-$(CONFIG_APPLE_DOCKCHANNEL_HID) += apple-hid.o
diff --git a/drivers/hid/dockchannel/apple-hid.c b/drivers/hid/dockchannel/apple-hid.c
new file mode 100644
index 000000000000..162fcfb5ab1c
--- /dev/null
+++ b/drivers/hid/dockchannel/apple-hid.c
@@ -0,0 +1,1130 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Apple DockChannel HID transport driver
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <linux/bitfield.h>
+#include <linux/completion.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/hid.h>
+#include <linux/mailbox/apple-dockchannel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/soc/apple/rtkit.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/unaligned.h>
+#include <linux/workqueue.h>
+
+#define APPLE_ASC_CPU_CONTROL 0x44
+#define APPLE_ASC_CPU_CONTROL_RUN BIT(4)
+
+#define COMMAND_TIMEOUT_MS 1000
+#define START_TIMEOUT_MS 2000
+
+#define MAX_INTERFACES 16
+
+#define DCHID_MAX_PAYLOAD 0xffff
+#define DCHID_CHECKSUM_LEN 4
+#define DCHID_RX_BUF_SIZE (sizeof(struct dchid_hdr) + DCHID_MAX_PAYLOAD + \
+ DCHID_CHECKSUM_LEN)
+
+#define DCHID_CHANNEL_CMD 0x11
+#define DCHID_CHANNEL_REPORT 0x12
+#define DCHID_CHECKSUM_SEED 0xffffffff
+
+struct dchid_hdr {
+ u8 hdr_len;
+ u8 channel;
+ __le16 length;
+ u8 seq;
+ u8 iface;
+ __le16 pad;
+} __packed;
+
+#define IFACE_COMM 0
+
+#define FLAGS_GROUP GENMASK(7, 6)
+#define FLAGS_REQ GENMASK(5, 0)
+
+#define REQ_SET_REPORT 0
+#define REQ_GET_REPORT 1
+
+struct dchid_subhdr {
+ u8 flags;
+ u8 unk;
+ __le16 length;
+ __le32 retcode;
+} __packed;
+
+#define EVENT_INIT 0xf0
+#define EVENT_READY 0xf1
+
+struct dchid_init_hdr {
+ u8 type;
+ u8 unk1;
+ u8 unk2;
+ u8 iface;
+ char name[16];
+ u8 more_packets;
+ u8 unkpad;
+} __packed;
+
+#define INIT_HID_DESCRIPTOR 0
+#define INIT_TERMINATOR 2
+#define INIT_PRODUCT_NAME 7
+
+#define CMD_RESET_INTERFACE 0x40
+#define CMD_RESET_INTERFACE_SUB 1
+#define CMD_ENABLE_INTERFACE 0xb4
+
+struct dchid_init_block_hdr {
+ __le16 type;
+ __le16 length;
+} __packed;
+
+#define STM_REPORT_ID 0x10
+#define STM_REPORT_SERIAL 0x11
+
+struct dchid_stm_id {
+ u8 unk;
+ __le16 vendor_id;
+ __le16 product_id;
+ __le16 version_number;
+ u8 unk2;
+ u8 unk3;
+ u8 keyboard_type;
+ u8 serial_length;
+ /* Serial follows, but we grab it with a different report. */
+} __packed;
+
+struct dchid_work {
+ struct work_struct work;
+ struct dchid_iface *iface;
+
+ struct dchid_hdr hdr;
+ u8 data[];
+};
+
+struct dchid_iface {
+ struct dchid_dev *dchid;
+ struct hid_device *hid;
+ struct workqueue_struct *wq;
+
+ bool creating;
+ struct work_struct create_work;
+
+ int index;
+ const char *name;
+ struct fwnode_handle *fwnode;
+
+ u8 tx_seq;
+ bool deferred;
+ bool starting;
+ bool open;
+ struct completion ready;
+
+ void *hid_desc;
+ size_t hid_desc_len;
+
+ /* Lock for command submission state below */
+ spinlock_t out_lock;
+ u32 out_flags;
+ int out_report;
+ u32 retcode;
+ void *resp_buf;
+ size_t resp_size;
+ struct completion out_complete;
+};
+
+struct dchid_dev {
+ struct device *dev;
+ struct mbox_client dc_mbox_client;
+ struct mbox_chan *dc_mbox;
+
+ struct apple_rtkit *rtk;
+ void __iomem *asc_base;
+ void __iomem *sram_base;
+ struct resource sram_res;
+
+ bool id_ready;
+ struct dchid_stm_id device_id;
+ char serial[64];
+
+ u8 *rx_buf;
+ size_t rx_len;
+
+ struct dchid_iface *comm;
+ struct mutex ifaces_lock; /* protects ifaces array */
+ struct dchid_iface *ifaces[MAX_INTERFACES];
+
+ /* Workqueue to asynchronously create HID devices */
+ struct workqueue_struct *new_iface_wq;
+};
+
+static void dchid_destroy_wq(void *data)
+{
+ struct workqueue_struct *wq = data;
+
+ destroy_workqueue(wq);
+}
+
+static void dchid_fwnode_release(void *data)
+{
+ fwnode_handle_put(data);
+}
+
+static void dchid_free_mbox(void *data)
+{
+ mbox_free_channel(data);
+}
+
+static u32 dchid_checksum(const void *data, size_t len)
+{
+ const u8 *p = data;
+ u32 sum = 0;
+ int i;
+
+ while (len >= sizeof(u32)) {
+ sum += get_unaligned_le32(p);
+ p += sizeof(u32);
+ len -= sizeof(u32);
+ }
+
+ if (len) {
+ u32 tmp = 0;
+
+ for (i = 0; i < len; i++)
+ tmp |= p[i] << (i * 8);
+ sum += tmp;
+ }
+
+ return sum;
+}
+
+static struct dchid_iface *
+dchid_get_interface(struct dchid_dev *dchid, int index, const char *name)
+{
+ struct dchid_iface *iface;
+ struct fwnode_handle *fwnode;
+ int ret;
+
+ if (index >= MAX_INTERFACES) {
+ dev_err(dchid->dev, "interface index %d out of range\n", index);
+ return NULL;
+ }
+
+ mutex_lock(&dchid->ifaces_lock);
+ if (dchid->ifaces[index]) {
+ iface = dchid->ifaces[index];
+ mutex_unlock(&dchid->ifaces_lock);
+ return iface;
+ }
+
+ iface = devm_kzalloc(dchid->dev, sizeof(*iface), GFP_KERNEL);
+ if (!iface) {
+ mutex_unlock(&dchid->ifaces_lock);
+ return NULL;
+ }
+
+ iface->index = index;
+ iface->name = devm_kstrdup(dchid->dev, name, GFP_KERNEL);
+ if (!iface->name) {
+ mutex_unlock(&dchid->ifaces_lock);
+ return NULL;
+ }
+
+ iface->dchid = dchid;
+ iface->out_report = -1;
+ init_completion(&iface->out_complete);
+ init_completion(&iface->ready);
+ spin_lock_init(&iface->out_lock);
+
+ iface->wq = alloc_ordered_workqueue("dchid-%s", 0, iface->name);
+ if (!iface->wq) {
+ mutex_unlock(&dchid->ifaces_lock);
+ return NULL;
+ }
+
+ ret = devm_add_action_or_reset(dchid->dev, dchid_destroy_wq, iface->wq);
+ if (ret) {
+ mutex_unlock(&dchid->ifaces_lock);
+ return NULL;
+ }
+
+ if (!strcmp(name, "comm")) {
+ /* Comm is not a HID subdevice */
+ dchid->ifaces[index] = iface;
+ mutex_unlock(&dchid->ifaces_lock);
+ return iface;
+ }
+
+ fwnode = device_get_named_child_node(dchid->dev, name);
+ if (fwnode) {
+ iface->fwnode = fwnode;
+ ret = devm_add_action_or_reset(dchid->dev, dchid_fwnode_release,
+ iface->fwnode);
+ if (ret) {
+ mutex_unlock(&dchid->ifaces_lock);
+ return NULL;
+ }
+ } else {
+ iface->fwnode = dev_fwnode(dchid->dev);
+ }
+
+ dchid->ifaces[index] = iface;
+ mutex_unlock(&dchid->ifaces_lock);
+ return iface;
+}
+
+static int dchid_send(struct dchid_iface *iface, u32 flags, const void *msg,
+ size_t size)
+{
+ struct dchid_dev *dchid = iface->dchid;
+ size_t payload_padded = round_up(size, sizeof(u32));
+ size_t total_len = sizeof(struct dchid_hdr) + sizeof(struct dchid_subhdr) +
+ payload_padded + DCHID_CHECKSUM_LEN;
+ struct apple_dockchannel_msg dc_msg;
+ struct dchid_hdr *hdr;
+ struct dchid_subhdr *sub;
+ u32 *checksum_ptr;
+ u8 *buf;
+ int ret;
+
+ if (total_len > DCHID_RX_BUF_SIZE)
+ return -EINVAL;
+
+ buf = kzalloc(total_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ hdr = (struct dchid_hdr *)buf;
+ sub = (struct dchid_subhdr *)(buf + sizeof(*hdr));
+ checksum_ptr = (u32 *)(buf + total_len - DCHID_CHECKSUM_LEN);
+
+ hdr->hdr_len = sizeof(*hdr);
+ hdr->channel = DCHID_CHANNEL_CMD;
+ hdr->length = cpu_to_le16(payload_padded + sizeof(*sub));
+ hdr->seq = iface->tx_seq;
+ hdr->iface = iface->index;
+
+ sub->flags = (u8)flags;
+ sub->length = cpu_to_le16(size);
+
+ memcpy(buf + sizeof(*hdr) + sizeof(*sub), msg, size);
+
+ *checksum_ptr = 0xffffffff - dchid_checksum(buf, total_len - DCHID_CHECKSUM_LEN);
+
+ dc_msg.data = buf;
+ dc_msg.len = total_len;
+ ret = mbox_send_message(dchid->dc_mbox, &dc_msg);
+ kfree(buf);
+
+ return ret < 0 ? ret : 0;
+}
+
+static int dchid_cmd(struct dchid_iface *iface, u32 type, u32 req,
+ void *data, size_t size, void *resp_buf, size_t resp_size)
+{
+ unsigned long flags;
+ int ret;
+ int report_id;
+ bool timed_out = false;
+ u32 out_flags;
+
+ if (size < 1)
+ return -EINVAL;
+
+ report_id = *(u8 *)data;
+ out_flags = FIELD_PREP(FLAGS_GROUP, type) | FIELD_PREP(FLAGS_REQ, req);
+
+ spin_lock_irqsave(&iface->out_lock, flags);
+
+ /* Only one command can be in flight per interface */
+ if (WARN_ON(iface->out_report != -1)) {
+ spin_unlock_irqrestore(&iface->out_lock, flags);
+ return -EBUSY;
+ }
+
+ iface->out_report = report_id;
+ iface->out_flags = out_flags;
+ iface->retcode = 0;
+ iface->resp_buf = resp_buf;
+ iface->resp_size = resp_size;
+ reinit_completion(&iface->out_complete);
+
+ spin_unlock_irqrestore(&iface->out_lock, flags);
+
+ ret = dchid_send(iface, out_flags, data, size);
+ if (ret < 0) {
+ spin_lock_irqsave(&iface->out_lock, flags);
+ iface->out_report = -1;
+ iface->resp_buf = NULL;
+ iface->resp_size = 0;
+ spin_unlock_irqrestore(&iface->out_lock, flags);
+ return ret;
+ }
+
+ if (!wait_for_completion_timeout(&iface->out_complete,
+ msecs_to_jiffies(COMMAND_TIMEOUT_MS))) {
+ dev_err(iface->dchid->dev, "command 0x%x to iface %d (%s) timed out\n",
+ report_id, iface->index, iface->name);
+ timed_out = true;
+ }
+
+ spin_lock_irqsave(&iface->out_lock, flags);
+
+ if (timed_out && iface->out_report == report_id) {
+ ret = -ETIMEDOUT;
+ } else if (iface->retcode) {
+ dev_err(iface->dchid->dev,
+ "command 0x%x to iface %d (%s) failed with err 0x%x\n",
+ report_id, iface->index, iface->name, iface->retcode);
+ ret = -EIO;
+ } else {
+ ret = iface->resp_size;
+ }
+
+ iface->tx_seq++;
+ iface->out_report = -1;
+ iface->resp_buf = NULL;
+ iface->resp_size = 0;
+ spin_unlock_irqrestore(&iface->out_lock, flags);
+
+ return ret;
+}
+
+static int dchid_comm_cmd(struct dchid_dev *dchid, void *cmd, size_t size)
+{
+ return dchid_cmd(dchid->comm, HID_FEATURE_REPORT, REQ_SET_REPORT,
+ cmd, size, NULL, 0);
+}
+
+static int dchid_enable_interface(struct dchid_iface *iface)
+{
+ u8 cmd[] = { CMD_ENABLE_INTERFACE, iface->index };
+
+ return dchid_comm_cmd(iface->dchid, cmd, sizeof(cmd));
+}
+
+static int dchid_reset_interface(struct dchid_iface *iface, int state)
+{
+ u8 cmd[] = { CMD_RESET_INTERFACE, CMD_RESET_INTERFACE_SUB, iface->index,
+ (u8)state };
+
+ return dchid_comm_cmd(iface->dchid, cmd, sizeof(cmd));
+}
+
+static int dchid_start_interface(struct dchid_iface *iface)
+{
+ if (iface->starting)
+ return -EINPROGRESS;
+
+ dev_dbg(iface->dchid->dev, "starting interface %s\n", iface->name);
+
+ iface->starting = true;
+ dchid_reset_interface(iface, 0);
+ dchid_reset_interface(iface, 2);
+
+ return 0;
+}
+
+static int dchid_start(struct hid_device *hdev)
+{
+ return 0;
+}
+
+static int dchid_open(struct hid_device *hdev)
+{
+ struct dchid_iface *iface = hdev->driver_data;
+ int ret;
+
+ if (!completion_done(&iface->ready)) {
+ ret = dchid_start_interface(iface);
+ if (ret < 0)
+ return ret;
+
+ if (!wait_for_completion_timeout(&iface->ready,
+ msecs_to_jiffies(START_TIMEOUT_MS))) {
+ dev_err(iface->dchid->dev, "iface %s start timed out\n",
+ iface->name);
+ return -ETIMEDOUT;
+ }
+ }
+
+ iface->open = true;
+ return 0;
+}
+
+static void dchid_close(struct hid_device *hdev)
+{
+ struct dchid_iface *iface = hdev->driver_data;
+
+ iface->open = false;
+}
+
+static int dchid_parse(struct hid_device *hdev)
+{
+ struct dchid_iface *iface = hdev->driver_data;
+
+ return hid_parse_report(hdev, iface->hid_desc, iface->hid_desc_len);
+}
+
+/* Note: buf excludes report number. */
+static int dchid_get_report_cmd(struct dchid_iface *iface, u8 reportnum,
+ void *buf, size_t len)
+{
+ int ret;
+
+ ret = dchid_cmd(iface, HID_FEATURE_REPORT, REQ_GET_REPORT, &reportnum, 1,
+ buf, len);
+
+ return ret <= 0 ? ret : ret - 1;
+}
+
+/* Note: buf includes report number. */
+static int dchid_set_report(struct dchid_iface *iface, void *buf, size_t len)
+{
+ return dchid_cmd(iface, HID_OUTPUT_REPORT, REQ_SET_REPORT, buf, len,
+ NULL, 0);
+}
+
+static int dchid_raw_request(struct hid_device *hdev, unsigned char reportnum,
+ __u8 *buf, size_t len, unsigned char rtype,
+ int reqtype)
+{
+ struct dchid_iface *iface = hdev->driver_data;
+
+ switch (reqtype) {
+ case HID_REQ_GET_REPORT:
+ if (len < 1)
+ return -EINVAL;
+
+ buf[0] = reportnum;
+ return dchid_cmd(iface, rtype, REQ_GET_REPORT, &reportnum, 1,
+ buf + 1, len - 1);
+ case HID_REQ_SET_REPORT:
+ return dchid_set_report(iface, buf, len);
+ default:
+ return -EIO;
+ }
+}
+
+static const struct hid_ll_driver dchid_ll = {
+ .start = dchid_start,
+ .open = dchid_open,
+ .close = dchid_close,
+ .parse = dchid_parse,
+ .raw_request = dchid_raw_request,
+};
+
+static void dchid_create_interface_work(struct work_struct *ws)
+{
+ struct dchid_iface *iface = container_of(ws, struct dchid_iface, create_work);
+ struct dchid_dev *dchid = iface->dchid;
+ struct hid_device *hid;
+ char cap_name[16];
+ int ret;
+
+ if (iface->hid) {
+ dev_warn(dchid->dev, "interface %s already created\n", iface->name);
+ goto done;
+ }
+
+ ret = dchid_enable_interface(iface);
+ if (ret < 0) {
+ dev_warn(dchid->dev, "failed to enable %s: %d\n", iface->name, ret);
+ goto done;
+ }
+
+ iface->deferred = false;
+
+ hid = hid_allocate_device();
+ if (IS_ERR(hid))
+ goto done;
+
+ strscpy(cap_name, iface->name, sizeof(cap_name));
+ if (cap_name[0])
+ cap_name[0] = toupper(cap_name[0]);
+ snprintf(hid->name, sizeof(hid->name), "Apple DockChannel %s", cap_name);
+
+ snprintf(hid->phys, sizeof(hid->phys), "%s.%d", dev_name(dchid->dev),
+ iface->index);
+ strscpy(hid->uniq, dchid->serial, sizeof(hid->uniq));
+
+ hid->ll_driver = &dchid_ll;
+ hid->bus = BUS_HOST;
+ hid->vendor = le16_to_cpu(dchid->device_id.vendor_id);
+ hid->product = le16_to_cpu(dchid->device_id.product_id);
+ hid->version = le16_to_cpu(dchid->device_id.version_number);
+ hid->type = HID_TYPE_OTHER;
+ if (!strcmp(iface->name, "keyboard")) {
+ u32 country_code;
+
+ hid->group = HID_GROUP_APPLE_DOCKCHANNEL;
+
+ /*
+ * The device provides no reliable way to get the keyboard
+ * country code, so board devicetrees provide it instead,
+ * filled by the bootloader.
+ */
+ if (!fwnode_property_read_u32(iface->fwnode, "hid-country-code",
+ &country_code))
+ hid->country = country_code;
+ }
+
+ hid->dev.parent = iface->dchid->dev;
+ hid->driver_data = iface;
+ iface->hid = hid;
+
+ ret = hid_add_device(hid);
+ if (ret < 0) {
+ iface->hid = NULL;
+ hid_destroy_device(hid);
+ dev_warn(iface->dchid->dev, "failed to register HID device %s\n",
+ iface->name);
+ }
+
+done:
+ iface->creating = false;
+}
+
+static int dchid_create_interface(struct dchid_iface *iface)
+{
+ if (iface->creating)
+ return -EBUSY;
+
+ iface->creating = true;
+ INIT_WORK(&iface->create_work, dchid_create_interface_work);
+ return queue_work(iface->dchid->new_iface_wq, &iface->create_work);
+}
+
+static void dchid_handle_descriptor(struct dchid_iface *iface, void *hid_desc,
+ size_t desc_len)
+{
+ u8 *rdesc;
+ int i;
+
+ if (iface->hid)
+ return;
+
+ rdesc = devm_kmemdup(iface->dchid->dev, hid_desc, desc_len,
+ GFP_KERNEL);
+ if (!rdesc)
+ return;
+
+ /* Fix up oversized report sizes in DockChannel report descriptors */
+ if (desc_len >= 5) {
+ for (i = 0; i <= (int)desc_len - 5; i++) {
+ if (rdesc[i] == 0x76 && rdesc[i + 1] == 0x00 &&
+ rdesc[i + 2] == 0x40 && rdesc[i + 3] == 0x95) {
+ u8 count = rdesc[i + 4];
+
+ if (count > 0 && count < 32) {
+ dev_info(iface->dchid->dev,
+ "fixing up interface %s (%d) report size\n",
+ iface->name, iface->index);
+ rdesc[i] = 0x75;
+ rdesc[i + 1] = 0x08;
+ rdesc[i + 2] = 0x96;
+ rdesc[i + 3] = 0x00;
+ rdesc[i + 4] = count * 8;
+ }
+ }
+ }
+ }
+
+ iface->hid_desc = rdesc;
+ iface->hid_desc_len = desc_len;
+}
+
+static void dchid_handle_ready(struct dchid_dev *dchid, void *data, size_t length)
+{
+ struct dchid_iface *iface;
+ u8 *pkt = data;
+ u8 index;
+ int i;
+ int ret;
+
+ if (length < 2)
+ return;
+
+ index = pkt[1];
+ if (index >= MAX_INTERFACES)
+ return;
+
+ iface = dchid->ifaces[index];
+ if (!iface)
+ return;
+
+ dev_dbg(dchid->dev, "interface %s is now ready\n", iface->name);
+ complete_all(&iface->ready);
+
+ /* When STM is ready, grab global device info */
+ if (!strcmp(iface->name, "stm")) {
+ ret = dchid_get_report_cmd(iface, STM_REPORT_ID, &dchid->device_id,
+ sizeof(dchid->device_id));
+ if (ret < (int)sizeof(dchid->device_id)) {
+ dev_warn(iface->dchid->dev, "failed to get device ID from STM\n");
+ /* Fake it and keep going. Things might still work. */
+ memset(&dchid->device_id, 0, sizeof(dchid->device_id));
+ }
+
+ ret = dchid_get_report_cmd(iface, STM_REPORT_SERIAL, dchid->serial,
+ sizeof(dchid->serial) - 1);
+ if (ret < 0) {
+ dev_warn(iface->dchid->dev, "failed to get serial from STM\n");
+ dchid->serial[0] = 0;
+ }
+
+ dchid->id_ready = true;
+ for (i = 0; i < MAX_INTERFACES; i++) {
+ if (!dchid->ifaces[i] || !dchid->ifaces[i]->deferred)
+ continue;
+ dchid_create_interface(dchid->ifaces[i]);
+ }
+ }
+}
+
+static void dchid_handle_init(struct dchid_dev *dchid, void *data, size_t length)
+{
+ struct dchid_init_hdr *hdr = data;
+ struct dchid_init_block_hdr *blk;
+ struct dchid_iface *iface;
+ u8 *p = data;
+
+ if (length < sizeof(*hdr))
+ return;
+
+ iface = dchid_get_interface(dchid, hdr->iface, hdr->name);
+ if (!iface)
+ return;
+
+ p += sizeof(*hdr);
+ length -= sizeof(*hdr);
+
+ while (length >= sizeof(*blk)) {
+ u16 blk_len;
+
+ blk = (struct dchid_init_block_hdr *)p;
+ p += sizeof(*blk);
+ length -= sizeof(*blk);
+
+ blk_len = le16_to_cpu(blk->length);
+ if (blk_len > length)
+ break;
+
+ switch (le16_to_cpu(blk->type)) {
+ case INIT_HID_DESCRIPTOR:
+ dchid_handle_descriptor(iface, p, blk_len);
+ break;
+ case INIT_PRODUCT_NAME:
+ if (blk_len > 0 && p[blk_len - 1] != 0)
+ dev_warn(dchid->dev, "unterminated product name for %s\n",
+ iface->name);
+ break;
+ }
+
+ p += blk_len;
+ length -= blk_len;
+
+ if (le16_to_cpu(blk->type) == INIT_TERMINATOR)
+ break;
+ }
+
+ if (hdr->more_packets)
+ return;
+
+ /*
+ * Prefer to enable STM first, since it provides device IDs. Some
+ * firmware versions do not expose STM, so let the keyboard start
+ * without it.
+ */
+ if (iface->dchid->id_ready || !strcmp(iface->name, "stm") ||
+ !strcmp(iface->name, "keyboard"))
+ dchid_create_interface(iface);
+ else
+ iface->deferred = true;
+}
+
+static void dchid_handle_event(struct dchid_dev *dchid, void *data, size_t length)
+{
+ u8 *p = data;
+
+ if (!length)
+ return;
+
+ switch (*p) {
+ case EVENT_INIT:
+ dchid_handle_init(dchid, data, length);
+ break;
+ case EVENT_READY:
+ dchid_handle_ready(dchid, data, length);
+ break;
+ }
+}
+
+static void dchid_handle_report(struct dchid_iface *iface, void *data, size_t length)
+{
+ if (!iface->hid || !iface->open)
+ return;
+
+ hid_input_report(iface->hid, HID_INPUT_REPORT, data, length, 1);
+}
+
+static void dchid_packet_work(struct work_struct *ws)
+{
+ struct dchid_work *work = container_of(ws, struct dchid_work, work);
+ struct dchid_subhdr *shdr = (void *)work->data;
+ struct dchid_dev *dchid = work->iface->dchid;
+ u16 hdr_len = le16_to_cpu(work->hdr.length);
+ u16 sub_len;
+ int type;
+ u8 *payload;
+
+ if (hdr_len < sizeof(*shdr)) {
+ dev_err(dchid->dev, "bad subheader length\n");
+ goto done;
+ }
+
+ sub_len = le16_to_cpu(shdr->length);
+ if (sub_len > hdr_len - sizeof(*shdr)) {
+ dev_err(dchid->dev, "bad subheader length\n");
+ goto done;
+ }
+
+ type = FIELD_GET(FLAGS_GROUP, shdr->flags);
+ payload = work->data + sizeof(*shdr);
+
+ switch (type) {
+ case HID_INPUT_REPORT:
+ if (work->hdr.iface == IFACE_COMM)
+ dchid_handle_event(dchid, payload, sub_len);
+ else
+ dchid_handle_report(work->iface, payload, sub_len);
+ break;
+ }
+
+done:
+ kfree(work);
+}
+
+static void dchid_handle_ack(struct dchid_iface *iface, struct dchid_hdr *hdr,
+ void *data)
+{
+ struct dchid_subhdr *shdr = data;
+ u8 *payload = data + sizeof(*shdr);
+ u16 hdr_len = le16_to_cpu(hdr->length);
+ u16 sub_len = le16_to_cpu(shdr->length);
+ unsigned long flags;
+ bool complete_cmd = false;
+
+ if (hdr_len < sizeof(*shdr) || sub_len > hdr_len - sizeof(*shdr) ||
+ sub_len < 1)
+ return;
+
+ spin_lock_irqsave(&iface->out_lock, flags);
+
+ if (shdr->flags == iface->out_flags && iface->tx_seq == hdr->seq &&
+ iface->out_report == payload[0]) {
+ if (iface->resp_buf && iface->resp_size)
+ memcpy(iface->resp_buf, payload + 1,
+ min_t(size_t, sub_len - 1, iface->resp_size));
+
+ iface->resp_size = sub_len;
+ iface->out_report = -1;
+ iface->retcode = le32_to_cpu(shdr->retcode);
+ complete_cmd = true;
+ }
+
+ spin_unlock_irqrestore(&iface->out_lock, flags);
+
+ if (complete_cmd)
+ complete(&iface->out_complete);
+}
+
+static void dchid_process_packet(struct dchid_dev *dchid, struct dchid_hdr *hdr,
+ u8 *payload, size_t payload_len, u8 *packet,
+ size_t packet_len)
+{
+ struct dchid_work *work;
+
+ if (dchid_checksum(packet, packet_len) != DCHID_CHECKSUM_SEED) {
+ dev_err_ratelimited(dchid->dev, "checksum error\n");
+ return;
+ }
+
+ if (payload_len < sizeof(struct dchid_subhdr))
+ return;
+
+ if (hdr->iface >= MAX_INTERFACES || !dchid->ifaces[hdr->iface])
+ return;
+
+ if (hdr->channel == DCHID_CHANNEL_CMD) {
+ dchid_handle_ack(dchid->ifaces[hdr->iface], hdr, payload);
+ return;
+ }
+
+ if (hdr->channel != DCHID_CHANNEL_REPORT)
+ return;
+
+ work = kzalloc(sizeof(*work) + payload_len, GFP_ATOMIC);
+ if (!work)
+ return;
+
+ work->hdr = *hdr;
+ work->iface = dchid->ifaces[hdr->iface];
+ memcpy(work->data, payload, payload_len);
+ INIT_WORK(&work->work, dchid_packet_work);
+
+ queue_work(work->iface->wq, &work->work);
+}
+
+static void dchid_consume_rx(struct dchid_dev *dchid)
+{
+ while (dchid->rx_len >= sizeof(struct dchid_hdr)) {
+ struct dchid_hdr *hdr = (struct dchid_hdr *)dchid->rx_buf;
+ size_t payload_len;
+ size_t packet_len;
+
+ if (hdr->hdr_len != sizeof(*hdr)) {
+ dev_err_ratelimited(dchid->dev, "bad header length %u\n",
+ hdr->hdr_len);
+ dchid->rx_len = 0;
+ return;
+ }
+
+ payload_len = le16_to_cpu(hdr->length);
+ packet_len = sizeof(*hdr) + payload_len + DCHID_CHECKSUM_LEN;
+ if (packet_len > DCHID_RX_BUF_SIZE) {
+ dev_err_ratelimited(dchid->dev, "oversized packet %zu\n",
+ packet_len);
+ dchid->rx_len = 0;
+ return;
+ }
+
+ if (dchid->rx_len < packet_len)
+ return;
+
+ dchid_process_packet(dchid, hdr, dchid->rx_buf + sizeof(*hdr),
+ payload_len, dchid->rx_buf, packet_len);
+
+ dchid->rx_len -= packet_len;
+ memmove(dchid->rx_buf, dchid->rx_buf + packet_len, dchid->rx_len);
+ }
+}
+
+static void dchid_rx_callback(struct mbox_client *cl, void *mssg)
+{
+ struct dchid_dev *dchid = container_of(cl, struct dchid_dev, dc_mbox_client);
+ struct apple_dockchannel_msg *msg = mssg;
+
+ if (!msg || !msg->data || !msg->len)
+ return;
+
+ if (msg->len > DCHID_RX_BUF_SIZE - dchid->rx_len) {
+ dev_err_ratelimited(dchid->dev, "RX buffer overflow\n");
+ dchid->rx_len = 0;
+ return;
+ }
+
+ memcpy(dchid->rx_buf + dchid->rx_len, msg->data, msg->len);
+ dchid->rx_len += msg->len;
+
+ dchid_consume_rx(dchid);
+}
+
+static int dchid_rtkit_shmem_setup(void *cookie, struct apple_rtkit_shmem *bfr)
+{
+ struct dchid_dev *dchid = cookie;
+ struct resource res = {
+ .start = bfr->iova,
+ .end = bfr->iova + bfr->size - 1,
+ .name = "rtkit_map",
+ };
+
+ if (!bfr->iova) {
+ bfr->buffer = dma_alloc_coherent(dchid->dev, bfr->size,
+ &bfr->iova, GFP_KERNEL);
+ if (!bfr->buffer)
+ return -ENOMEM;
+ return 0;
+ }
+
+ if (!dchid->sram_res.start)
+ return -EFAULT;
+
+ res.flags = dchid->sram_res.flags;
+ if (res.end < res.start || !resource_contains(&dchid->sram_res, &res))
+ return -EFAULT;
+
+ bfr->iomem = dchid->sram_base + (res.start - dchid->sram_res.start);
+ bfr->is_mapped = true;
+
+ return 0;
+}
+
+static void dchid_rtkit_shmem_destroy(void *cookie, struct apple_rtkit_shmem *bfr)
+{
+ struct dchid_dev *dchid = cookie;
+
+ if (bfr->buffer)
+ dma_free_coherent(dchid->dev, bfr->size, bfr->buffer, bfr->iova);
+}
+
+static const struct apple_rtkit_ops dchid_rtkit_ops = {
+ .shmem_setup = dchid_rtkit_shmem_setup,
+ .shmem_destroy = dchid_rtkit_shmem_destroy,
+};
+
+static int dchid_map_helper_cpu(struct platform_device *pdev, struct dchid_dev *dchid)
+{
+ struct resource *res;
+
+ dchid->asc_base = devm_platform_ioremap_resource_byname(pdev, "coproc-asc");
+ if (IS_ERR(dchid->asc_base))
+ return PTR_ERR(dchid->asc_base);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "coproc-sram");
+ if (!res)
+ return -EINVAL;
+
+ dchid->sram_res = *res;
+
+ dchid->sram_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dchid->sram_base))
+ return PTR_ERR(dchid->sram_base);
+
+ return 0;
+}
+
+static int dchid_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct dchid_dev *dchid;
+ int ret;
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(44));
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to set DMA mask\n");
+
+ dchid = devm_kzalloc(dev, sizeof(*dchid), GFP_KERNEL);
+ if (!dchid)
+ return -ENOMEM;
+
+ dchid->rx_buf = devm_kmalloc(dev, DCHID_RX_BUF_SIZE, GFP_KERNEL);
+ if (!dchid->rx_buf)
+ return -ENOMEM;
+
+ dchid->dev = dev;
+ mutex_init(&dchid->ifaces_lock);
+ platform_set_drvdata(pdev, dchid);
+
+ ret = dchid_map_helper_cpu(pdev, dchid);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to map helper CPU\n");
+
+ dchid->dc_mbox_client.dev = dev;
+ dchid->dc_mbox_client.tx_block = true;
+ dchid->dc_mbox_client.rx_callback = dchid_rx_callback;
+
+ dchid->dc_mbox = mbox_request_channel_byname(&dchid->dc_mbox_client,
+ "dockchannel");
+ if (IS_ERR(dchid->dc_mbox))
+ return dev_err_probe(dev, PTR_ERR(dchid->dc_mbox),
+ "failed to request DockChannel mailbox\n");
+
+ ret = devm_add_action_or_reset(dev, dchid_free_mbox, dchid->dc_mbox);
+ if (ret)
+ return ret;
+
+ dchid->rtk = devm_apple_rtkit_init(dev, dchid, "asc", 0, &dchid_rtkit_ops);
+ if (IS_ERR(dchid->rtk))
+ return dev_err_probe(dev, PTR_ERR(dchid->rtk), "failed to init RTKit\n");
+
+ writel_relaxed(APPLE_ASC_CPU_CONTROL_RUN,
+ dchid->asc_base + APPLE_ASC_CPU_CONTROL);
+
+ ret = apple_rtkit_wake(dchid->rtk);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to wake coprocessor\n");
+
+ dchid->new_iface_wq = alloc_ordered_workqueue("dchid-new", 0);
+ if (!dchid->new_iface_wq)
+ return dev_err_probe(dev, -ENOMEM, "failed to allocate workqueue\n");
+
+ ret = devm_add_action_or_reset(dev, dchid_destroy_wq, dchid->new_iface_wq);
+ if (ret)
+ return ret;
+
+ dchid->comm = dchid_get_interface(dchid, IFACE_COMM, "comm");
+ if (!dchid->comm)
+ return dev_err_probe(dev, -EIO, "failed to init comm interface\n");
+
+ return 0;
+}
+
+static void dchid_remove(struct platform_device *pdev)
+{
+ struct dchid_dev *dchid = platform_get_drvdata(pdev);
+ int i;
+
+ if (dchid->dc_mbox) {
+ devm_release_action(&pdev->dev, dchid_free_mbox, dchid->dc_mbox);
+ dchid->dc_mbox = NULL;
+ }
+
+ if (dchid->rtk && apple_rtkit_is_running(dchid->rtk))
+ apple_rtkit_quiesce(dchid->rtk);
+
+ if (dchid->asc_base)
+ writel_relaxed(0, dchid->asc_base + APPLE_ASC_CPU_CONTROL);
+
+ for (i = 0; i < MAX_INTERFACES; i++) {
+ struct dchid_iface *iface = dchid->ifaces[i];
+
+ if (!iface)
+ continue;
+
+ cancel_work_sync(&iface->create_work);
+ flush_workqueue(iface->wq);
+
+ if (iface->hid)
+ hid_destroy_device(iface->hid);
+ }
+
+ if (dchid->new_iface_wq)
+ flush_workqueue(dchid->new_iface_wq);
+}
+
+static const struct of_device_id dchid_of_match[] = {
+ { .compatible = "apple,t8122-dockchannel-hid" },
+ { .compatible = "apple,t8112-dockchannel-hid" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, dchid_of_match);
+
+static struct platform_driver dchid_platform_driver = {
+ .driver = {
+ .name = "dockchannel-hid",
+ .of_match_table = dchid_of_match,
+ },
+ .probe = dchid_probe,
+ .remove = dchid_remove,
+};
+module_platform_driver(dchid_platform_driver);
+
+MODULE_DESCRIPTION("Apple DockChannel HID transport driver");
+MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
+MODULE_AUTHOR("Michael Reeves <michael.reeves077@gmail.com>");
+MODULE_LICENSE("Dual MIT/GPL");
--
2.51.2
^ permalink raw reply related
* Re: [PATCH 3/3] net: stmmac: dwmac-socfpga: Add mac-mode DT property support
From: Andrew Lunn @ 2026-06-30 14:02 UTC (permalink / raw)
To: muhammad.nazim.amirul.nazle.asmade
Cc: dinguyen, maxime.chevallier, rmk+kernel, krzk+dt, conor+dt, robh,
davem, edumazet, kuba, pabeni, andrew+netdev, devicetree,
linux-arm-kernel, netdev, linux-kernel
In-Reply-To: <20260630133108.27244-4-muhammad.nazim.amirul.nazle.asmade@altera.com>
On Tue, Jun 30, 2026 at 06:31:08AM -0700, muhammad.nazim.amirul.nazle.asmade@altera.com wrote:
> From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
>
> Russell King's commit de696c63c1dc ("net: stmmac: socfpga: convert to
> use phy_interface") replaced mac_interface with phy_interface in
> socfpga_get_plat_phymode(), noting that no upstream DTS files set the
> "mac-mode" property, making the two values identical.
>
> The Agilex5 SoCDK TSN Config2 board is an exception: its gmac1 TSN
> port uses GMII internally in the MAC while the PHY-side interface is
> RGMII, so mac-mode and phy-mode differ.
Maybe you need to represent the hardware block which magically
converts GMII to RGMII in DT?
Andrew
^ permalink raw reply
* [PATCH v4 0/3] regulator: Rework i2c_device_id initialisation
From: Uwe Kleine-König (The Capable Hub) @ 2026-06-30 14:01 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Woodrow Douglass, Michael Hennerich,
Support Opensource, Laurent Pinchart, Ivaylo Ivanov,
Claudiu Beznea, Andrei Simion, Saravanan Sekar, Matthias Brugger,
AngeloGioacchino Del Regno, Jagan Teki, Icenowy Zheng,
Alexis Czezar Torreno
Cc: linux-kernel, linux-arm-kernel, linux-mediatek
Hello,
changes since v2
(https://lore.kernel.org/lkml/cover.1781888370.git.u.kleine-koenig@baylibre.com):
- rebase to next/master
This fixes a merge conflict and also shifts a bit which drivers are
adapted in the different patches
- patch #3 is new
Best regards
Uwe
Uwe Kleine-König (The Capable Hub) (3):
regulator: Drop unused i2c driver data
regulator: Use named initializers for arrays of i2c_device_data
regulator: Improve style of i2c_device_id arrays
drivers/regulator/88pg86x.c | 4 ++--
drivers/regulator/act8865-regulator.c | 2 +-
drivers/regulator/ad5398.c | 4 ++--
drivers/regulator/adp5055-regulator.c | 4 ++--
drivers/regulator/aw37503-regulator.c | 4 ++--
drivers/regulator/da9121-regulator.c | 20 ++++++++++----------
drivers/regulator/da9210-regulator.c | 4 ++--
drivers/regulator/da9211-regulator.c | 18 +++++++++---------
drivers/regulator/fan53880.c | 4 ++--
drivers/regulator/isl6271a-regulator.c | 2 +-
drivers/regulator/isl9305.c | 4 ++--
drivers/regulator/lp3971.c | 2 +-
drivers/regulator/lp3972.c | 2 +-
drivers/regulator/lp872x.c | 4 ++--
drivers/regulator/lp8755.c | 4 ++--
drivers/regulator/ltc3589.c | 6 +++---
drivers/regulator/ltc3676.c | 2 +-
drivers/regulator/max1586.c | 2 +-
drivers/regulator/max20086-regulator.c | 8 ++++----
drivers/regulator/max20411-regulator.c | 2 +-
drivers/regulator/max77503-regulator.c | 2 +-
drivers/regulator/max77675-regulator.c | 2 +-
drivers/regulator/max77826-regulator.c | 2 +-
drivers/regulator/max77838-regulator.c | 2 +-
drivers/regulator/max77857-regulator.c | 8 ++++----
drivers/regulator/max8649.c | 2 +-
drivers/regulator/max8893.c | 2 +-
drivers/regulator/max8952.c | 2 +-
drivers/regulator/max8973-regulator.c | 6 +++---
drivers/regulator/mcp16502.c | 2 +-
drivers/regulator/mp5416.c | 6 +++---
drivers/regulator/mp8859.c | 4 ++--
drivers/regulator/mp886x.c | 6 +++---
drivers/regulator/mpq7920.c | 4 ++--
drivers/regulator/mt6311-regulator.c | 4 ++--
drivers/regulator/pf530x-regulator.c | 8 ++++----
drivers/regulator/pf8x00-regulator.c | 8 ++++----
drivers/regulator/pv88060-regulator.c | 4 ++--
drivers/regulator/pv88080-regulator.c | 8 ++++----
drivers/regulator/pv88090-regulator.c | 4 ++--
drivers/regulator/sgm3804-regulator.c | 2 +-
drivers/regulator/slg51000-regulator.c | 4 ++--
drivers/regulator/sy8106a-regulator.c | 2 +-
drivers/regulator/sy8824x.c | 8 ++++----
drivers/regulator/sy8827n.c | 4 ++--
drivers/regulator/tps51632-regulator.c | 4 ++--
drivers/regulator/tps62360-regulator.c | 10 +++++-----
drivers/regulator/tps6286x-regulator.c | 10 +++++-----
drivers/regulator/tps6287x-regulator.c | 10 +++++-----
drivers/regulator/tps65023-regulator.c | 6 +++---
drivers/regulator/tps65132-regulator.c | 4 ++--
51 files changed, 126 insertions(+), 126 deletions(-)
base-commit: 7de6ae9e12207ec146f2f3f1e58d1a99317e88bc
--
2.47.3
^ permalink raw reply
* Re: (subset) [PATCH v3 0/2] gpio: fix sleeping-in-atomic in shared-proxy; restore meson non-sleeping
From: Bartosz Golaszewski @ 2026-06-30 14:03 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Viacheslav Bocharov
Cc: Bartosz Golaszewski, Neil Armstrong, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Marek Szyprowski, Robin Murphy,
Diederik de Haas, linux-gpio, linux-arm-kernel, linux-amlogic,
linux-kernel
In-Reply-To: <20260630101545.800625-1-v@baodeep.com>
On Tue, 30 Jun 2026 13:15:43 +0300, Viacheslav Bocharov wrote:
> gpio-shared-proxy chooses its descriptor lock (mutex vs spinlock) from
> the underlying chip's can_sleep, but under that lock it calls config and
> direction ops that reach sleeping pinctrl paths. On a controller with
> non-sleeping MMIO value ops the lock is a spinlock, so a sleeping call
> runs from atomic context:
>
> BUG: sleeping function called from invalid context
> ... pinctrl_gpio_set_config <- gpiochip_generic_config
> <- gpio_shared_proxy_set_config (voting spinlock held)
> <- ... <- mmc_pwrseq_simple_probe
>
> [...]
There are no build-time dependencies between this and 2/2 so let me queue this
for fixes on its own and Linus W can take 2/2.
[1/2] gpio: shared-proxy: always serialize with a sleeping mutex
https://git.kernel.org/brgl/c/efecde8a254d1f207b75c5ebcfba2c51f4c771d9
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* [PATCH v4 2/3] regulator: Use named initializers for arrays of i2c_device_data
From: Uwe Kleine-König (The Capable Hub) @ 2026-06-30 14:01 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Michael Hennerich, Support Opensource,
Laurent Pinchart, Ivaylo Ivanov, Claudiu Beznea, Andrei Simion,
Saravanan Sekar, Matthias Brugger, AngeloGioacchino Del Regno,
Jagan Teki, Icenowy Zheng
Cc: linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1782827697.git.u.kleine-koenig@baylibre.com>
While being less compact, using named initializers allows to more easily
see which members of the structs are assigned which value without having
to lookup the declaration of the struct. And it's also more robust
against changes to the struct definition.
The mentioned robustness is relevant for a planned change to struct
i2c_device_id that replaces .driver_data by an anonymous union.
While touching all these arrays, unify usage of whitespace and commas.
This patch doesn't modify the compiled arrays, only their representation
in source form benefits. The former was confirmed with x86 and arm64
builds.
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
---
drivers/regulator/88pg86x.c | 4 ++--
drivers/regulator/ad5398.c | 4 ++--
drivers/regulator/da9121-regulator.c | 20 ++++++++++----------
drivers/regulator/da9210-regulator.c | 4 ++--
drivers/regulator/da9211-regulator.c | 18 +++++++++---------
drivers/regulator/fan53880.c | 4 ++--
drivers/regulator/isl9305.c | 4 ++--
drivers/regulator/lp3971.c | 2 +-
drivers/regulator/lp3972.c | 2 +-
drivers/regulator/lp872x.c | 4 ++--
drivers/regulator/lp8755.c | 4 ++--
drivers/regulator/ltc3589.c | 6 +++---
drivers/regulator/ltc3676.c | 2 +-
drivers/regulator/max1586.c | 2 +-
drivers/regulator/max20086-regulator.c | 8 ++++----
drivers/regulator/max20411-regulator.c | 2 +-
drivers/regulator/max77503-regulator.c | 2 +-
drivers/regulator/max77826-regulator.c | 2 +-
drivers/regulator/max77838-regulator.c | 2 +-
drivers/regulator/max77857-regulator.c | 8 ++++----
drivers/regulator/max8649.c | 2 +-
drivers/regulator/max8893.c | 2 +-
drivers/regulator/max8952.c | 2 +-
drivers/regulator/mcp16502.c | 2 +-
drivers/regulator/mp5416.c | 6 +++---
drivers/regulator/mp8859.c | 4 ++--
drivers/regulator/mp886x.c | 6 +++---
drivers/regulator/mpq7920.c | 4 ++--
drivers/regulator/mt6311-regulator.c | 4 ++--
drivers/regulator/pf8x00-regulator.c | 8 ++++----
drivers/regulator/pv88060-regulator.c | 4 ++--
drivers/regulator/pv88080-regulator.c | 8 ++++----
drivers/regulator/pv88090-regulator.c | 4 ++--
drivers/regulator/sgm3804-regulator.c | 2 +-
drivers/regulator/slg51000-regulator.c | 4 ++--
drivers/regulator/sy8106a-regulator.c | 2 +-
drivers/regulator/sy8824x.c | 8 ++++----
drivers/regulator/sy8827n.c | 4 ++--
drivers/regulator/tps6286x-regulator.c | 10 +++++-----
drivers/regulator/tps6287x-regulator.c | 10 +++++-----
40 files changed, 100 insertions(+), 100 deletions(-)
diff --git a/drivers/regulator/88pg86x.c b/drivers/regulator/88pg86x.c
index e6598e74ec94..8c25a1db412f 100644
--- a/drivers/regulator/88pg86x.c
+++ b/drivers/regulator/88pg86x.c
@@ -92,8 +92,8 @@ static const struct of_device_id __maybe_unused pg86x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pg86x_dt_ids);
static const struct i2c_device_id pg86x_i2c_id[] = {
- { "88pg867", },
- { "88pg868", },
+ { .name = "88pg867" },
+ { .name = "88pg868" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pg86x_i2c_id);
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index eb2a666a45cb..0123ca8157a8 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -207,8 +207,8 @@ struct ad5398_current_data_format {
static const struct ad5398_current_data_format df_10_4_120 = {10, 4, 0, 120000};
static const struct i2c_device_id ad5398_id[] = {
- { "ad5398", (kernel_ulong_t)&df_10_4_120 },
- { "ad5821", (kernel_ulong_t)&df_10_4_120 },
+ { .name = "ad5398", .driver_data = (kernel_ulong_t)&df_10_4_120 },
+ { .name = "ad5821", .driver_data = (kernel_ulong_t)&df_10_4_120 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ad5398_id);
diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c
index 36a52f707602..f501cf8152c2 100644
--- a/drivers/regulator/da9121-regulator.c
+++ b/drivers/regulator/da9121-regulator.c
@@ -1195,16 +1195,16 @@ static void da9121_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id da9121_i2c_id[] = {
- {"da9121", DA9121_SUBTYPE_DA9121},
- {"da9130", DA9121_SUBTYPE_DA9130},
- {"da9217", DA9121_SUBTYPE_DA9217},
- {"da9122", DA9121_SUBTYPE_DA9122},
- {"da9131", DA9121_SUBTYPE_DA9131},
- {"da9220", DA9121_SUBTYPE_DA9220},
- {"da9132", DA9121_SUBTYPE_DA9132},
- {"da9141", DA9121_SUBTYPE_DA9141},
- {"da9142", DA9121_SUBTYPE_DA9142},
- {},
+ { .name = "da9121", .driver_data = DA9121_SUBTYPE_DA9121 },
+ { .name = "da9130", .driver_data = DA9121_SUBTYPE_DA9130 },
+ { .name = "da9217", .driver_data = DA9121_SUBTYPE_DA9217 },
+ { .name = "da9122", .driver_data = DA9121_SUBTYPE_DA9122 },
+ { .name = "da9131", .driver_data = DA9121_SUBTYPE_DA9131 },
+ { .name = "da9220", .driver_data = DA9121_SUBTYPE_DA9220 },
+ { .name = "da9132", .driver_data = DA9121_SUBTYPE_DA9132 },
+ { .name = "da9141", .driver_data = DA9121_SUBTYPE_DA9141 },
+ { .name = "da9142", .driver_data = DA9121_SUBTYPE_DA9142 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, da9121_i2c_id);
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index 39ade0dba40f..9154e32bd745 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -202,8 +202,8 @@ static int da9210_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id da9210_i2c_id[] = {
- { "da9210" },
- {}
+ { .name = "da9210" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, da9210_i2c_id);
diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
index d4f14d7ea8cf..9cf713755636 100644
--- a/drivers/regulator/da9211-regulator.c
+++ b/drivers/regulator/da9211-regulator.c
@@ -522,15 +522,15 @@ static int da9211_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id da9211_i2c_id[] = {
- {"da9211", DA9211},
- {"da9212", DA9212},
- {"da9213", DA9213},
- {"da9223", DA9223},
- {"da9214", DA9214},
- {"da9224", DA9224},
- {"da9215", DA9215},
- {"da9225", DA9225},
- {},
+ { .name = "da9211", .driver_data = DA9211 },
+ { .name = "da9212", .driver_data = DA9212 },
+ { .name = "da9213", .driver_data = DA9213 },
+ { .name = "da9223", .driver_data = DA9223 },
+ { .name = "da9214", .driver_data = DA9214 },
+ { .name = "da9224", .driver_data = DA9224 },
+ { .name = "da9215", .driver_data = DA9215 },
+ { .name = "da9225", .driver_data = DA9225 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, da9211_i2c_id);
diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c
index 6cb5656845f9..79ba705ec324 100644
--- a/drivers/regulator/fan53880.c
+++ b/drivers/regulator/fan53880.c
@@ -164,8 +164,8 @@ static const struct of_device_id fan53880_dt_ids[] = {
MODULE_DEVICE_TABLE(of, fan53880_dt_ids);
static const struct i2c_device_id fan53880_i2c_id[] = {
- { "fan53880", },
- {}
+ { .name = "fan53880" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, fan53880_i2c_id);
diff --git a/drivers/regulator/isl9305.c b/drivers/regulator/isl9305.c
index 5a234f25e6bb..ec6bd6bb9721 100644
--- a/drivers/regulator/isl9305.c
+++ b/drivers/regulator/isl9305.c
@@ -186,8 +186,8 @@ MODULE_DEVICE_TABLE(of, isl9305_dt_ids);
#endif
static const struct i2c_device_id isl9305_i2c_id[] = {
- { "isl9305", },
- { "isl9305h", },
+ { .name = "isl9305" },
+ { .name = "isl9305h" },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl9305_i2c_id);
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index d4dab86fe385..6f830ae1bb61 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -439,7 +439,7 @@ static int lp3971_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id lp3971_i2c_id[] = {
- { "lp3971" },
+ { .name = "lp3971" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index 1b918fb72134..235c640ba57f 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -537,7 +537,7 @@ static int lp3972_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id lp3972_i2c_id[] = {
- { "lp3972" },
+ { .name = "lp3972" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp3972_i2c_id);
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 942f37082cb1..5b2faddd8110 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -935,8 +935,8 @@ static const struct of_device_id lp872x_dt_ids[] __maybe_unused = {
MODULE_DEVICE_TABLE(of, lp872x_dt_ids);
static const struct i2c_device_id lp872x_ids[] = {
- {"lp8720", LP8720},
- {"lp8725", LP8725},
+ { .name = "lp8720", .driver_data = LP8720 },
+ { .name = "lp8725", .driver_data = LP8725 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp872x_ids);
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index 5509bee49bda..632320ba1800 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -430,8 +430,8 @@ static void lp8755_remove(struct i2c_client *client)
}
static const struct i2c_device_id lp8755_id[] = {
- { LP8755_NAME },
- {}
+ { .name = LP8755_NAME },
+ { }
};
MODULE_DEVICE_TABLE(i2c, lp8755_id);
diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c
index 3f70c2225dba..8bae5d8aeaf4 100644
--- a/drivers/regulator/ltc3589.c
+++ b/drivers/regulator/ltc3589.c
@@ -445,9 +445,9 @@ static const struct ltc3589_info ltc3589_12_info = {
};
static const struct i2c_device_id ltc3589_i2c_id[] = {
- { "ltc3589", (kernel_ulong_t)<c3589_info },
- { "ltc3589-1", (kernel_ulong_t)<c3589_12_info },
- { "ltc3589-2", (kernel_ulong_t)<c3589_12_info },
+ { .name = "ltc3589", .driver_data = (kernel_ulong_t)<c3589_info },
+ { .name = "ltc3589-1", .driver_data = (kernel_ulong_t)<c3589_12_info },
+ { .name = "ltc3589-2", .driver_data = (kernel_ulong_t)<c3589_12_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc3589_i2c_id);
diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c
index 73d511eb1c1d..597d20a200d7 100644
--- a/drivers/regulator/ltc3676.c
+++ b/drivers/regulator/ltc3676.c
@@ -357,7 +357,7 @@ static int ltc3676_regulator_probe(struct i2c_client *client)
}
static const struct i2c_device_id ltc3676_i2c_id[] = {
- { "ltc3676" },
+ { .name = "ltc3676" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc3676_i2c_id);
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 4242fbb7b147..e5cbc09c2d39 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -276,7 +276,7 @@ static int max1586_pmic_probe(struct i2c_client *client)
}
static const struct i2c_device_id max1586_id[] = {
- { "max1586" },
+ { .name = "max1586" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max1586_id);
diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c
index fcdd2d0317a5..92594b2915f3 100644
--- a/drivers/regulator/max20086-regulator.c
+++ b/drivers/regulator/max20086-regulator.c
@@ -301,10 +301,10 @@ static const struct max20086_chip_info max20089_chip_info = {
};
static const struct i2c_device_id max20086_i2c_id[] = {
- { "max20086", (kernel_ulong_t)&max20086_chip_info },
- { "max20087", (kernel_ulong_t)&max20087_chip_info },
- { "max20088", (kernel_ulong_t)&max20088_chip_info },
- { "max20089", (kernel_ulong_t)&max20089_chip_info },
+ { .name = "max20086", .driver_data = (kernel_ulong_t)&max20086_chip_info },
+ { .name = "max20087", .driver_data = (kernel_ulong_t)&max20087_chip_info },
+ { .name = "max20088", .driver_data = (kernel_ulong_t)&max20088_chip_info },
+ { .name = "max20089", .driver_data = (kernel_ulong_t)&max20089_chip_info },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max20086_i2c_id);
diff --git a/drivers/regulator/max20411-regulator.c b/drivers/regulator/max20411-regulator.c
index 6c0ebb970e90..ac7a9aa014aa 100644
--- a/drivers/regulator/max20411-regulator.c
+++ b/drivers/regulator/max20411-regulator.c
@@ -145,7 +145,7 @@ static const struct of_device_id of_max20411_match_tbl[] = {
MODULE_DEVICE_TABLE(of, of_max20411_match_tbl);
static const struct i2c_device_id max20411_id[] = {
- { "max20411" },
+ { .name = "max20411" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max20411_id);
diff --git a/drivers/regulator/max77503-regulator.c b/drivers/regulator/max77503-regulator.c
index c7c94e868fc1..1cae846f96d0 100644
--- a/drivers/regulator/max77503-regulator.c
+++ b/drivers/regulator/max77503-regulator.c
@@ -107,7 +107,7 @@ static const struct of_device_id of_max77503_match_tbl[] = {
MODULE_DEVICE_TABLE(of, of_max77503_match_tbl);
static const struct i2c_device_id max77503_regulator_id[] = {
- {"max77503"},
+ { .name = "max77503" },
{ }
};
diff --git a/drivers/regulator/max77826-regulator.c b/drivers/regulator/max77826-regulator.c
index 310bc8ee7af8..8b60a9fcab44 100644
--- a/drivers/regulator/max77826-regulator.c
+++ b/drivers/regulator/max77826-regulator.c
@@ -278,7 +278,7 @@ static const struct of_device_id __maybe_unused max77826_of_match[] = {
MODULE_DEVICE_TABLE(of, max77826_of_match);
static const struct i2c_device_id max77826_id[] = {
- { "max77826-regulator" },
+ { .name = "max77826-regulator" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max77826_id);
diff --git a/drivers/regulator/max77838-regulator.c b/drivers/regulator/max77838-regulator.c
index 9faddbfd25fd..765756fdcf6e 100644
--- a/drivers/regulator/max77838-regulator.c
+++ b/drivers/regulator/max77838-regulator.c
@@ -200,7 +200,7 @@ static const struct of_device_id __maybe_unused max77838_of_match[] = {
MODULE_DEVICE_TABLE(of, max77838_of_match);
static const struct i2c_device_id max77838_id[] = {
- { "max77838-regulator" },
+ { .name = "max77838-regulator" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max77838_id);
diff --git a/drivers/regulator/max77857-regulator.c b/drivers/regulator/max77857-regulator.c
index 1216cc3a6f72..f1410f845653 100644
--- a/drivers/regulator/max77857-regulator.c
+++ b/drivers/regulator/max77857-regulator.c
@@ -428,10 +428,10 @@ static int max77857_probe(struct i2c_client *client)
}
static const struct i2c_device_id max77857_id[] = {
- { "max77831", ID_MAX77831 },
- { "max77857", ID_MAX77857 },
- { "max77859", ID_MAX77859 },
- { "max77859a", ID_MAX77859A },
+ { .name = "max77831", .driver_data = ID_MAX77831 },
+ { .name = "max77857", .driver_data = ID_MAX77857 },
+ { .name = "max77859", .driver_data = ID_MAX77859 },
+ { .name = "max77859a", .driver_data = ID_MAX77859A },
{ }
};
MODULE_DEVICE_TABLE(i2c, max77857_id);
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index f57c588bcf28..2d17405242e7 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -240,7 +240,7 @@ static int max8649_regulator_probe(struct i2c_client *client)
}
static const struct i2c_device_id max8649_id[] = {
- { "max8649" },
+ { .name = "max8649" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max8649_id);
diff --git a/drivers/regulator/max8893.c b/drivers/regulator/max8893.c
index 5a90633d8536..7a0e44a16d49 100644
--- a/drivers/regulator/max8893.c
+++ b/drivers/regulator/max8893.c
@@ -162,7 +162,7 @@ MODULE_DEVICE_TABLE(of, max8893_dt_match);
#endif
static const struct i2c_device_id max8893_ids[] = {
- { "max8893" },
+ { .name = "max8893" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max8893_ids);
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 1f94315bfb02..f8b91a5701f3 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -307,7 +307,7 @@ static int max8952_pmic_probe(struct i2c_client *client)
}
static const struct i2c_device_id max8952_ids[] = {
- { "max8952" },
+ { .name = "max8952" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max8952_ids);
diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c
index b34ae0bbba6f..89fd79d446f7 100644
--- a/drivers/regulator/mcp16502.c
+++ b/drivers/regulator/mcp16502.c
@@ -578,7 +578,7 @@ static const struct dev_pm_ops mcp16502_pm_ops = {
};
#endif
static const struct i2c_device_id mcp16502_i2c_id[] = {
- { "mcp16502" },
+ { .name = "mcp16502" },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcp16502_i2c_id);
diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c
index e6794190cb68..2948635b1b9f 100644
--- a/drivers/regulator/mp5416.c
+++ b/drivers/regulator/mp5416.c
@@ -228,9 +228,9 @@ static const struct of_device_id mp5416_of_match[] = {
MODULE_DEVICE_TABLE(of, mp5416_of_match);
static const struct i2c_device_id mp5416_id[] = {
- { "mp5416", (kernel_ulong_t)&mp5416_regulators_desc },
- { "mp5496", (kernel_ulong_t)&mp5496_regulators_desc },
- {}
+ { .name = "mp5416", .driver_data = (kernel_ulong_t)&mp5416_regulators_desc },
+ { .name = "mp5496", .driver_data = (kernel_ulong_t)&mp5496_regulators_desc },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mp5416_id);
diff --git a/drivers/regulator/mp8859.c b/drivers/regulator/mp8859.c
index ab105ffd6a2e..9a708e826d93 100644
--- a/drivers/regulator/mp8859.c
+++ b/drivers/regulator/mp8859.c
@@ -386,8 +386,8 @@ static const struct of_device_id mp8859_dt_id[] __maybe_unused = {
MODULE_DEVICE_TABLE(of, mp8859_dt_id);
static const struct i2c_device_id mp8859_i2c_id[] = {
- { "mp8859", },
- { },
+ { .name = "mp8859" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mp8859_i2c_id);
diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c
index 9ad16b04c913..e0b62bc02a1e 100644
--- a/drivers/regulator/mp886x.c
+++ b/drivers/regulator/mp886x.c
@@ -348,9 +348,9 @@ static const struct of_device_id mp886x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, mp886x_dt_ids);
static const struct i2c_device_id mp886x_id[] = {
- { "mp8867", (kernel_ulong_t)&mp8867_ci },
- { "mp8869", (kernel_ulong_t)&mp8869_ci },
- { },
+ { .name = "mp8867", .driver_data = (kernel_ulong_t)&mp8867_ci },
+ { .name = "mp8869", .driver_data = (kernel_ulong_t)&mp8869_ci },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mp886x_id);
diff --git a/drivers/regulator/mpq7920.c b/drivers/regulator/mpq7920.c
index a670e09891e7..0cbc17deb1d1 100644
--- a/drivers/regulator/mpq7920.c
+++ b/drivers/regulator/mpq7920.c
@@ -309,8 +309,8 @@ static const struct of_device_id mpq7920_of_match[] = {
MODULE_DEVICE_TABLE(of, mpq7920_of_match);
static const struct i2c_device_id mpq7920_id[] = {
- { "mpq7920", },
- { },
+ { .name = "mpq7920" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mpq7920_id);
diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c
index 2ebc1c0b5e6f..1d457d1fdf23 100644
--- a/drivers/regulator/mt6311-regulator.c
+++ b/drivers/regulator/mt6311-regulator.c
@@ -133,8 +133,8 @@ static int mt6311_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id mt6311_i2c_id[] = {
- { "mt6311" },
- {}
+ { .name = "mt6311" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mt6311_i2c_id);
diff --git a/drivers/regulator/pf8x00-regulator.c b/drivers/regulator/pf8x00-regulator.c
index ea3611de42b4..c938b4632ef1 100644
--- a/drivers/regulator/pf8x00-regulator.c
+++ b/drivers/regulator/pf8x00-regulator.c
@@ -596,10 +596,10 @@ static const struct of_device_id pf8x00_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pf8x00_dt_ids);
static const struct i2c_device_id pf8x00_i2c_id[] = {
- { "pf8100" },
- { "pf8121a" },
- { "pf8200" },
- {}
+ { .name = "pf8100" },
+ { .name = "pf8121a" },
+ { .name = "pf8200" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pf8x00_i2c_id);
diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c
index ae1c4b9daaa1..375d9e759c47 100644
--- a/drivers/regulator/pv88060-regulator.c
+++ b/drivers/regulator/pv88060-regulator.c
@@ -360,8 +360,8 @@ static int pv88060_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id pv88060_i2c_id[] = {
- { "pv88060" },
- {}
+ { .name = "pv88060" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pv88060_i2c_id);
diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c
index 112eb1c73647..b96afbf11ff3 100644
--- a/drivers/regulator/pv88080-regulator.c
+++ b/drivers/regulator/pv88080-regulator.c
@@ -522,10 +522,10 @@ static const struct of_device_id pv88080_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pv88080_dt_ids);
static const struct i2c_device_id pv88080_i2c_id[] = {
- { "pv88080", (kernel_ulong_t)&pv88080_aa_regs },
- { "pv88080-aa", (kernel_ulong_t)&pv88080_aa_regs },
- { "pv88080-ba", (kernel_ulong_t)&pv88080_ba_regs },
- {}
+ { .name = "pv88080", .driver_data = (kernel_ulong_t)&pv88080_aa_regs },
+ { .name = "pv88080-aa", .driver_data = (kernel_ulong_t)&pv88080_aa_regs },
+ { .name = "pv88080-ba", .driver_data = (kernel_ulong_t)&pv88080_ba_regs },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id);
diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c
index 3c48757bbbda..ca5eeb5dfe62 100644
--- a/drivers/regulator/pv88090-regulator.c
+++ b/drivers/regulator/pv88090-regulator.c
@@ -381,8 +381,8 @@ static int pv88090_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id pv88090_i2c_id[] = {
- { "pv88090" },
- {}
+ { .name = "pv88090" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pv88090_i2c_id);
diff --git a/drivers/regulator/sgm3804-regulator.c b/drivers/regulator/sgm3804-regulator.c
index c3406cfb73d0..a34c9418b275 100644
--- a/drivers/regulator/sgm3804-regulator.c
+++ b/drivers/regulator/sgm3804-regulator.c
@@ -285,7 +285,7 @@ static int sgm3804_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id sgm3804_id[] = {
- { "sgm3804" },
+ { .name = "sgm3804" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sgm3804_id);
diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c
index 3bbd4a29e6d3..d682764cdbf8 100644
--- a/drivers/regulator/slg51000-regulator.c
+++ b/drivers/regulator/slg51000-regulator.c
@@ -497,8 +497,8 @@ static int slg51000_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id slg51000_i2c_id[] = {
- { "slg51000" },
- {}
+ { .name = "slg51000" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, slg51000_i2c_id);
diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c
index d79a4cc25a0d..b2b835c60262 100644
--- a/drivers/regulator/sy8106a-regulator.c
+++ b/drivers/regulator/sy8106a-regulator.c
@@ -130,7 +130,7 @@ static const struct of_device_id sy8106a_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, sy8106a_i2c_of_match);
static const struct i2c_device_id sy8106a_i2c_id[] = {
- { "sy8106a" },
+ { .name = "sy8106a" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sy8106a_i2c_id);
diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c
index 5bec84db25f1..3f07e7da90cb 100644
--- a/drivers/regulator/sy8824x.c
+++ b/drivers/regulator/sy8824x.c
@@ -213,10 +213,10 @@ static const struct of_device_id sy8824_dt_ids[] = {
MODULE_DEVICE_TABLE(of, sy8824_dt_ids);
static const struct i2c_device_id sy8824_id[] = {
- { "sy8824c", (kernel_ulong_t)&sy8824c_cfg },
- { "sy8824e", (kernel_ulong_t)&sy8824e_cfg },
- { "sy20276", (kernel_ulong_t)&sy20276_cfg },
- { "sy20278", (kernel_ulong_t)&sy20278_cfg },
+ { .name = "sy8824c", .driver_data = (kernel_ulong_t)&sy8824c_cfg },
+ { .name = "sy8824e", .driver_data = (kernel_ulong_t)&sy8824e_cfg },
+ { .name = "sy20276", .driver_data = (kernel_ulong_t)&sy20276_cfg },
+ { .name = "sy20278", .driver_data = (kernel_ulong_t)&sy20278_cfg },
{ }
};
MODULE_DEVICE_TABLE(i2c, sy8824_id);
diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c
index 0b811514782f..a1cac8cc3d96 100644
--- a/drivers/regulator/sy8827n.c
+++ b/drivers/regulator/sy8827n.c
@@ -180,8 +180,8 @@ static const struct of_device_id sy8827n_dt_ids[] = {
MODULE_DEVICE_TABLE(of, sy8827n_dt_ids);
static const struct i2c_device_id sy8827n_id[] = {
- { "sy8827n", },
- { },
+ { .name = "sy8827n" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, sy8827n_id);
diff --git a/drivers/regulator/tps6286x-regulator.c b/drivers/regulator/tps6286x-regulator.c
index e29aab06bf79..1ab53bee9f6e 100644
--- a/drivers/regulator/tps6286x-regulator.c
+++ b/drivers/regulator/tps6286x-regulator.c
@@ -145,11 +145,11 @@ static int tps6286x_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tps6286x_i2c_id[] = {
- { "tps62864" },
- { "tps62866" },
- { "tps62868" },
- { "tps62869" },
- {}
+ { .name = "tps62864" },
+ { .name = "tps62866" },
+ { .name = "tps62868" },
+ { .name = "tps62869" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, tps6286x_i2c_id);
diff --git a/drivers/regulator/tps6287x-regulator.c b/drivers/regulator/tps6287x-regulator.c
index 9df104cb6bd2..e6403398facc 100644
--- a/drivers/regulator/tps6287x-regulator.c
+++ b/drivers/regulator/tps6287x-regulator.c
@@ -228,11 +228,11 @@ static const struct of_device_id tps6287x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, tps6287x_dt_ids);
static const struct i2c_device_id tps6287x_i2c_id[] = {
- { "tps62870" },
- { "tps62871" },
- { "tps62872" },
- { "tps62873" },
- {}
+ { .name = "tps62870" },
+ { .name = "tps62871" },
+ { .name = "tps62872" },
+ { .name = "tps62873" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id);
--
2.47.3
^ permalink raw reply related
* Re: [PATCH 3/3] net: stmmac: dwmac-socfpga: Add mac-mode DT property support
From: Maxime Chevallier @ 2026-06-30 14:04 UTC (permalink / raw)
To: Andrew Lunn, muhammad.nazim.amirul.nazle.asmade
Cc: dinguyen, rmk+kernel, krzk+dt, conor+dt, robh, davem, edumazet,
kuba, pabeni, andrew+netdev, devicetree, linux-arm-kernel, netdev,
linux-kernel
In-Reply-To: <4c285993-978c-4d9e-a8c5-c3b36baa6840@lunn.ch>
On 6/30/26 16:02, Andrew Lunn wrote:
> On Tue, Jun 30, 2026 at 06:31:08AM -0700, muhammad.nazim.amirul.nazle.asmade@altera.com wrote:
>> From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
>>
>> Russell King's commit de696c63c1dc ("net: stmmac: socfpga: convert to
>> use phy_interface") replaced mac_interface with phy_interface in
>> socfpga_get_plat_phymode(), noting that no upstream DTS files set the
>> "mac-mode" property, making the two values identical.
>>
>> The Agilex5 SoCDK TSN Config2 board is an exception: its gmac1 TSN
>> port uses GMII internally in the MAC while the PHY-side interface is
>> RGMII, so mac-mode and phy-mode differ.
>
> Maybe you need to represent the hardware block which magically
> converts GMII to RGMII in DT?
Yeah that's what we have on CycloneV, and we force the INTF_SEL to GMII if that
HW block is present. I wonder if there's the same on agileX5 ?
>
> Andrew
^ permalink raw reply
* Re: [PATCH v6 7/7] arm64: dts: qcom: eliza: Add support for MM clock controllers
From: Konrad Dybcio @ 2026-06-30 14:09 UTC (permalink / raw)
To: Taniya Das, Bjorn Andersson, Michael Turquette, Stephen Boyd,
Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Luca Weiss, Konrad Dybcio, Maxime Coquelin, Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Dmitry Baryshkov
In-Reply-To: <20260609-b4-eliza_mm_cc_v6-v6-7-17df09e5940c@oss.qualcomm.com>
On 6/9/26 5:02 PM, Taniya Das wrote:
> Add the device nodes for the multimedia clock controllers (cambistmclkcc,
> camcc, videocc, gpucc) for Qualcomm Eliza SoC.
>
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
> ---
Almost all of these nodes lack power-domains, meaning the
aggregated performance state requests will not be translated
into RPMH requests
Konrad
^ permalink raw reply
* Re: [PATCH v4 2/2] arm64: io: apply the device store-release workaround once per block write
From: Will Deacon @ 2026-06-30 14:17 UTC (permalink / raw)
To: Shanker Donthineni
Cc: Vladimir Murzin, Catalin Marinas, Jason Gunthorpe,
linux-arm-kernel, Mark Rutland, linux-kernel, linux-doc,
Vikram Sethi, Jason Sequeira
In-Reply-To: <d75592c9-5292-4704-b024-6450ea0e8278@nvidia.com>
On Mon, Jun 29, 2026 at 06:09:11PM -0500, Shanker Donthineni wrote:
> On 6/29/2026 5:48 AM, Vladimir Murzin wrote:
> > > + : "memory");
> > > + src += sizeof(u64);
> > > + dst += sizeof(u64);
> > > + count -= sizeof(u64);
> > > + }
> > > + while (count) {
> > > + asm volatile("strb %w0, [%1]"
> > > + : : "rZ"(*(const u8 *)src), "r"(dst) : "memory");
> > > + src++;
> > > + dst++;
> > > + count--;
> > > + }
> > > +
> > > + iomem_block_store_barrier();
> > It is perhaps a matter of taste, but having the inline assembly
> > here (and in memset_io()) might make the code clearer. To a
> > casual reader, it would be obvious that the barrier is not
> > guaranteed and is only applicable to ARM64_WORKAROUND_DEVICE_STORE_RELEASE,
> > without having to jump back and forth through the code.
> >
> > Obliviously maintainers might have different preference ;)
Oblivious maintainer here :)
> Regarding the barrier, iomem_block_store_barrier() is declared
> static __always_inline, so it does not add a function call. The nop/dmb
> osh alternative is emitted directly in each caller. I used the helper to
> avoid duplicating the alternative sequence.
>
> I understand that placing the assembly directly in both functions could
> make its conditional nature more obvious. I do not have a strong preference
> and am happy to follow Will’s and Catalin’s preference here.
I agree with Vladimir that it would be clearer to inline the conditional
barrier.
It would be even better if we could avoid having to duplicate this code
to start with, but I can't immediately think of a better alternative.
Will
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox