* [PATCH v3 0/7] BCMBCA PMB power, clock, reset and hardware monitoring support
@ 2026-11-06 8:26 Linus Walleij
2026-11-06 8:26 ` [PATCH v3 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
` (6 more replies)
0 siblings, 7 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-06 8:26 UTC (permalink / raw)
To: Linus Walleij, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, William Zhang, Anand Gore, Kursad Oney,
Florian Fainelli, Rafał Miłecki,
Broadcom internal kernel review list, Stephen Boyd, Brian Masney,
Jerome Brunet, Guenter Roeck, Philipp Zabel, Jonathan Corbet,
Randy Dunlap, Ulf Hansson, Benjamin Larsson
Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon,
linux-pm
This is another of these big upfront design binding and driver hoards
that is the consequence of adding new SoC support.
My stake is to be able to boot and test a full featured Cortex-A7
system and the BCM6846 XG6846B is one such system on my desk.
It's been cooking for a while in various prototype forms.
IMPLEMENTATION:
The PMC contains various stuff so this needs to be a simple MFD node
so more things can be added into it later.
Inside the PMC is the PMB, the processor monitor bus. This bridges
to several individual peripherals which are very clearly distinct
devices on that bus.
Handle the PMB with an MFD driver with power domain, clock, reset and hwmon
providers.
Expose the standard BPCM peripheral, memory, USB and PCIe domains and
a combined XRDP domain covering XRDP, the three Runners and WAN. Keep
the peripheral and memory domains always on. The power domain provider
now owns zone transitions, leaving the reset provider to pulse resets.
The CPU and PLL blocks use different register layouts and are excluded.
This new power domain integration has not been tested on hardware.
The BCM6846 XRDP reset sequence enabled full-MTU traffic on all four LAN
ports and copper WAN and has been tested on that series. The zone
power-up sequence also passed direct CFE flash boot in the Linux 6.18
OpenWrt port; this folded v7.3-rc1 revision still needs hardware testing.
MERGE STRATEGY:
Through an MFD immutable branch once everyone ACKs the subdrivers,
it will take time I guess. Queue the bindings and drivers in MFD.
Updates to peripheral schemas and device trees to accommodate the power
domains will be submitted separately.
The patches were authored with the assistance of an LLM.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Changes in v3:
- Add a PMB power domain subdriver and binding with a combined XRDP domain.
- Move XRDP, Runner and WAN power sequencing out of the reset driver.
- Register the power domain MFD child.
- MFD transport: simplify cell registration, drop unused state and
property.h, and add the bcmbca-pmb subject prefix.
- Power domains: default to MFD_BCMBCA_PMB.
- MFD transport and reset: use mutex guards; reset: use
str_assert_deassert().
- Clock: use the reference clock as parent, limit CLK_GET_RATE_NOCACHE to
PLL outputs, drop CLK_IGNORE_UNUSED and simplify Runner registration.
- Clock and reset: suppress manual bind/unbind.
- MFD transport, clock, reset and hwmon: drop redundant mod_devicetable.h;
clock: drop slab.h.
- Power domain, clock, reset and hwmon drivers and PMC/PMB bindings: drop
vendor-source references from comments.
- Link to v2: https://patch.msgid.link/20261101-xg6846b-bcmbca-xrdp-reset-v2-0-455fe9eed5ee@kernel.org
Changes in v2:
- Use a shared PMB regmap in all child drivers, keeping keyhole semaphore
handling and timeout recovery inside the MFD provider.
- Drop PCIe reset IDs and sequences pending proper power and lane
configuration handling.
- Power up the XRDP, Runner and WAN zones before the XRDP reset pulse,
preserving the sequence tested with direct CFE flash boot in OpenWrt.
- Describe clock, reset and PVTMON PMB child nodes with separate
compatibles.
- Move the PMB transport and accessor header under MFD and register
clock, reset and PVTMON MFD cells matched to their child DT nodes.
Select reset variants through OF match data.
- Add PMB clock support and PVTMON clock and reset bindings.
- Add PVTMON hwmon support for temperature and all seven voltage inputs,
retaining the zero-cell thermal sensor through the hwmon bridge.
- Drop the unnecessary literal block marker from the PMC description.
- Use the BCM6846-specific "brcm,bcm6846-pmc" compatible.
- Expand PMC as "Power Management Controller" throughout.
- Move the LLM assistance disclosure from trailers to the cover letter.
- Drop the RFC prefix.
- Link to v1: https://patch.msgid.link/20261014-xg6846b-bcmbca-xrdp-reset-v1-0-daf5d177e113@kernel.org
---
Linus Walleij (7):
dt-bindings: mfd: Describe the BCM6846 PMC complex
dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus
mfd: bcmbca-pmb: Add a shared BCMBCA PMC3 PMB transport
pmdomain: bcm: Add BCMBCA PMB power domains
reset: Add BCMBCA block resets through the PMB
clk: bcm: Add BCMBCA PMB clocks
hwmon: Add Broadcom PMB PVTMON monitoring
.../bindings/clock/brcm,bcm6846-pmb-clock.yaml | 39 +++
.../bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml | 42 +++
.../devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml | 87 +++++
.../bindings/power/brcm,bcm6846-pmb-power.yaml | 44 +++
.../bindings/reset/brcm,bcm6846-pmb-reset.yaml | 31 ++
.../bindings/soc/bcm/brcm,bcm6846-pmb.yaml | 90 +++++
Documentation/hwmon/bcm_pmb_pvtmon.rst | 53 +++
Documentation/hwmon/index.rst | 1 +
MAINTAINERS | 20 ++
drivers/clk/bcm/Kconfig | 11 +
drivers/clk/bcm/Makefile | 1 +
drivers/clk/bcm/clk-bcmbca-pmb.c | 388 +++++++++++++++++++++
drivers/hwmon/Kconfig | 18 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/bcm_pmb_pvtmon.c | 231 ++++++++++++
drivers/mfd/Kconfig | 11 +
drivers/mfd/Makefile | 1 +
drivers/mfd/bcmbca_pmc3_pmb.c | 286 +++++++++++++++
drivers/pmdomain/bcm/Kconfig | 10 +
drivers/pmdomain/bcm/Makefile | 1 +
drivers/pmdomain/bcm/bcmbca-pmb.c | 279 +++++++++++++++
drivers/reset/Kconfig | 13 +
drivers/reset/Makefile | 1 +
drivers/reset/reset-bcmbca-pmb.c | 243 +++++++++++++
include/dt-bindings/clock/brcm,bcm6846-pmb.h | 42 +++
include/dt-bindings/power/brcm,bcm6846-pmb.h | 12 +
include/dt-bindings/reset/brcm,bcm6846-pmb.h | 11 +
include/linux/mfd/bcmbca-pmb.h | 11 +
28 files changed, 1978 insertions(+)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261013-xg6846b-bcmbca-xrdp-reset-de71b80c25a4
Best regards,
--
Linus Walleij <linusw@kernel.org>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v3 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex
2026-11-06 8:26 [PATCH v3 0/7] BCMBCA PMB power, clock, reset and hardware monitoring support Linus Walleij
@ 2026-11-06 8:26 ` Linus Walleij
2026-11-06 8:36 ` sashiko-bot
2026-11-06 12:57 ` Rob Herring (Arm)
2026-11-06 8:26 ` [PATCH v3 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus Linus Walleij
` (5 subsequent siblings)
6 siblings, 2 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-06 8:26 UTC (permalink / raw)
To: Linus Walleij, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, William Zhang, Anand Gore, Kursad Oney,
Florian Fainelli, Rafał Miłecki,
Broadcom internal kernel review list, Stephen Boyd, Brian Masney,
Jerome Brunet, Guenter Roeck, Philipp Zabel, Jonathan Corbet,
Randy Dunlap, Ulf Hansson, Benjamin Larsson
Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon,
linux-pm
The third generation Power Management Controller (PMC3) has
different subdevices.
Identify the parent with the BCM6846-specific "brcm,bcm6846-pmc"
compatible.
Describe the complex as a simple-mfd with a PMB bus child owning its
register resource. Include the PMB clock and reset controllers and
PVTMON, with its acquisition clock and reset resources.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
.../devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml | 82 ++++++++++++++++++++++
MAINTAINERS | 5 ++
2 files changed, 87 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
new file mode 100644
index 000000000000..d4c927cabb3f
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/brcm,bcm6846-pmc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM6846 Power Management Controller
+
+maintainers:
+ - Linus Walleij <linusw@kernel.org>
+
+description:
+ The third generation Power Management Controller (PMC3) contains several
+ register banks. This binding describes the Processor Monitor Bus (PMB)
+ interface within Procmon. The PMB child owns its register bank. The parent
+ provides address translation and does not own a register bank.
+
+properties:
+ compatible:
+ items:
+ - const: brcm,bcm6846-pmc
+ - const: simple-mfd
+
+ ranges:
+ maxItems: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+patternProperties:
+ '^bus@[0-9a-f]+$':
+ $ref: /schemas/soc/bcm/brcm,bcm6846-pmb.yaml#
+ description: PMB configuration, keyhole and address mapping registers
+
+required:
+ - compatible
+ - ranges
+ - '#address-cells'
+ - '#size-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/brcm,bcm6846-pmb.h>
+ #include <dt-bindings/reset/brcm,bcm6846-pmb.h>
+
+ system-controller@ffb00000 {
+ /* Broadcom BCM6846 Power Management Controller complex */
+ compatible = "brcm,bcm6846-pmc", "simple-mfd";
+ ranges = <0x0 0xffb00000 0x21000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Processor Monitor Bus */
+ bus@20100 {
+ compatible = "brcm,bcm6846-pmb";
+ reg = <0x20100 0x200>;
+
+ pmb_clk: clock-controller {
+ compatible = "brcm,bcm6846-pmb-clock";
+ clocks = <&osc50m>;
+ clock-names = "ref";
+ #clock-cells = <1>;
+ };
+
+ pmb_reset: reset-controller {
+ compatible = "brcm,bcm6846-pmb-reset";
+ #reset-cells = <1>;
+ };
+
+ hwmon {
+ compatible = "brcm,bcm6846-pmb-pvtmon";
+ clocks = <&pmb_clk BCM6846_CLK_PVTMON>;
+ resets = <&pmb_reset BCM6846_RESET_PVTMON>;
+ #thermal-sensor-cells = <0>;
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 93abbb315065..f14f9910911c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5444,6 +5444,11 @@ N: bcm[9]?6856
N: bcm[9]?6858
N: bcm[9]?6878
+BROADCOM BCMBCA PMC3 PMB DRIVER
+M: Linus Walleij <linusw@kernel.org>
+S: Maintained
+F: Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
+
BROADCOM BDC DRIVER
M: Justin Chen <justin.chen@broadcom.com>
M: Al Cooper <alcooperx@gmail.com>
--
2.56.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus
2026-11-06 8:26 [PATCH v3 0/7] BCMBCA PMB power, clock, reset and hardware monitoring support Linus Walleij
2026-11-06 8:26 ` [PATCH v3 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
@ 2026-11-06 8:26 ` Linus Walleij
2026-11-06 8:43 ` sashiko-bot
2026-11-06 17:03 ` William Zhang
2026-11-06 8:26 ` [PATCH v3 3/7] mfd: bcmbca-pmb: Add a shared BCMBCA PMC3 PMB transport Linus Walleij
` (4 subsequent siblings)
6 siblings, 2 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-06 8:26 UTC (permalink / raw)
To: Linus Walleij, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, William Zhang, Anand Gore, Kursad Oney,
Florian Fainelli, Rafał Miłecki,
Broadcom internal kernel review list, Stephen Boyd, Brian Masney,
Jerome Brunet, Guenter Roeck, Philipp Zabel, Jonathan Corbet,
Randy Dunlap, Ulf Hansson, Benjamin Larsson
Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon,
linux-pm
The third generation Power Management Controller (PMC3) accesses SoC
block control and reset registers through the Processor Monitor Bus
(PMB). Describe the BCM6846 PMC and PMB.
Describe the power controller child and all supported power domain IDs,
including the combined XRDP, Runner and WAN domain.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
I considered even just using the PMB but the PMC has more stuff and
it seems natural to let it live in a simple-mfd node.
---
.../bindings/clock/brcm,bcm6846-pmb-clock.yaml | 39 ++++++++++
.../bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml | 42 ++++++++++
.../devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml | 5 ++
.../bindings/power/brcm,bcm6846-pmb-power.yaml | 44 +++++++++++
.../bindings/reset/brcm,bcm6846-pmb-reset.yaml | 31 ++++++++
.../bindings/soc/bcm/brcm,bcm6846-pmb.yaml | 90 ++++++++++++++++++++++
MAINTAINERS | 8 ++
include/dt-bindings/clock/brcm,bcm6846-pmb.h | 42 ++++++++++
include/dt-bindings/power/brcm,bcm6846-pmb.h | 12 +++
include/dt-bindings/reset/brcm,bcm6846-pmb.h | 11 +++
10 files changed, 324 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm6846-pmb-clock.yaml b/Documentation/devicetree/bindings/clock/brcm,bcm6846-pmb-clock.yaml
new file mode 100644
index 000000000000..519606522c8b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/brcm,bcm6846-pmb-clock.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/brcm,bcm6846-pmb-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM6846 PMB clocks
+
+maintainers:
+ - Linus Walleij <linusw@kernel.org>
+
+description:
+ The Processor Monitor Bus (PMB) provides access to the RDP and BIU PLL
+ outputs, the Runner clock, the crystal output, the PVTMON acquisition
+ clock and the clock gates in block power-control zones. Clock indices
+ are defined in dt-bindings/clock/brcm,bcm6846-pmb.h.
+ The PLLs and crystal output use a 50 MHz reference clock.
+ Zone clocks require their associated blocks to be powered.
+
+properties:
+ compatible:
+ const: brcm,bcm6846-pmb-clock
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: ref
+
+ '#clock-cells':
+ const: 1
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - '#clock-cells'
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml b/Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
new file mode 100644
index 000000000000..9bf52cf097a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/brcm,bcm6846-pmb-pvtmon.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM6846 PMB process, voltage and temperature monitor
+
+maintainers:
+ - Linus Walleij <linusw@kernel.org>
+
+description:
+ The process, voltage and temperature monitor (PVTMON) is a child of
+ the Processor Monitor Bus (PMB) controller and uses its indirect
+ register interface. It measures die temperature and seven voltages,
+ including a diagnostic test input.
+
+allOf:
+ - $ref: /schemas/thermal/thermal-sensor.yaml#
+
+properties:
+ compatible:
+ const: brcm,bcm6846-pmb-pvtmon
+
+ clocks:
+ maxItems: 1
+ description: PVTMON acquisition clock
+
+ resets:
+ maxItems: 1
+ description: PVTMON analog-acquisition reset
+
+ '#thermal-sensor-cells':
+ const: 0
+
+required:
+ - compatible
+ - clocks
+ - resets
+ - '#thermal-sensor-cells'
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
index d4c927cabb3f..77fbf92926ab 100644
--- a/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
+++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
@@ -60,6 +60,11 @@ examples:
compatible = "brcm,bcm6846-pmb";
reg = <0x20100 0x200>;
+ pmb_power: power-controller {
+ compatible = "brcm,bcm6846-pmb-power";
+ #power-domain-cells = <1>;
+ };
+
pmb_clk: clock-controller {
compatible = "brcm,bcm6846-pmb-clock";
clocks = <&osc50m>;
diff --git a/Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml b/Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
new file mode 100644
index 000000000000..891eb0f347e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/brcm,bcm6846-pmb-power.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM6846 Processor Monitor Bus power controller
+
+maintainers:
+ - Linus Walleij <linusw@kernel.org>
+
+description: |
+ The power controller is a child of the Processor Monitor Bus (PMB)
+ controller and accesses BPCM power zones through the parent regmap.
+ A domain includes all power zones of a block. The XRDP domain groups
+ XRDP, its three Runner cores and WAN, matching the vendor power sequence.
+
+ Domain IDs are defined in dt-bindings/power/brcm,bcm6846-pmb.h:
+ BCM6846_PD_PERIPH: peripheral block (bus 0, device 0, four zones)
+ BCM6846_PD_MEMC: memory controller (bus 1, device 8, one zone)
+ BCM6846_PD_USB20: USB 2.0 (bus 1, device 10, four zones)
+ BCM6846_PD_XRDP: XRDP (bus 1, device 12, three zones), Runner cores
+ (bus 1, devices 14, 15 and 16, one zone each) and WAN
+ (bus 1, device 11, three zones)
+ BCM6846_PD_PCIE0: PCIe 0 (bus 0, device 18, one zone)
+ BCM6846_PD_PCIE1: PCIe 1 (bus 0, device 19, one zone)
+
+ Peripheral and memory domains remain powered because they provide
+ resources required for system operation. CPU and PLL blocks use different
+ register layouts and are outside the scope of this provider.
+
+properties:
+ compatible:
+ const: brcm,bcm6846-pmb-power
+
+ '#power-domain-cells':
+ const: 1
+ description: Power domain ID from dt-bindings/power/brcm,bcm6846-pmb.h
+
+required:
+ - compatible
+ - '#power-domain-cells'
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml b/Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
new file mode 100644
index 000000000000..d2a85266e36a
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/brcm,bcm6846-pmb-reset.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM6846 Processor Monitor Bus reset controller
+
+maintainers:
+ - Linus Walleij <linusw@kernel.org>
+
+description:
+ The reset controller is a child of the Processor Monitor Bus (PMB)
+ controller and uses its indirect register interface.
+
+ Each reset specifier identifies a logical reset group, which may span
+ several blocks that must be reset together.
+
+properties:
+ compatible:
+ const: brcm,bcm6846-pmb-reset
+
+ '#reset-cells':
+ const: 1
+ description: Reset group ID from dt-bindings/reset/brcm,bcm6846-pmb.h
+
+required:
+ - compatible
+ - '#reset-cells'
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
new file mode 100644
index 000000000000..134a8a676dbd
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/bcm/brcm,bcm6846-pmb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM6846 Processor Monitor Bus
+
+maintainers:
+ - Linus Walleij <linusw@kernel.org>
+
+description:
+ The Processor Monitor Bus (PMB) connects the third generation Power
+ Management Controller (PMC3) to the control registers of miscellaneous
+ independent hardware blocks.
+
+ The controller provides configuration, arbitration and four keyhole
+ interfaces for indirect register access.
+
+ Child nodes describe independent hardware blocks accessed over the PMB.
+ These provide global resources and even resources for each other.
+
+properties:
+ compatible:
+ const: brcm,bcm6846-pmb
+
+ reg:
+ maxItems: 1
+ description: PMB configuration, keyhole and address mapping registers
+
+ power-controller:
+ type: object
+ $ref: /schemas/power/brcm,bcm6846-pmb-power.yaml#
+
+ clock-controller:
+ type: object
+ $ref: /schemas/clock/brcm,bcm6846-pmb-clock.yaml#
+
+ reset-controller:
+ type: object
+ $ref: /schemas/reset/brcm,bcm6846-pmb-reset.yaml#
+
+ hwmon:
+ type: object
+ $ref: /schemas/hwmon/brcm,bcm6846-pmb-pvtmon.yaml#
+
+required:
+ - compatible
+ - reg
+ - power-controller
+ - clock-controller
+ - reset-controller
+ - hwmon
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/brcm,bcm6846-pmb.h>
+ #include <dt-bindings/reset/brcm,bcm6846-pmb.h>
+
+ /* Processor Monitor Bus */
+ bus@ffb20100 {
+ compatible = "brcm,bcm6846-pmb";
+ reg = <0xffb20100 0x200>;
+
+ pmb_power: power-controller {
+ compatible = "brcm,bcm6846-pmb-power";
+ #power-domain-cells = <1>;
+ };
+
+ pmb_clk: clock-controller {
+ compatible = "brcm,bcm6846-pmb-clock";
+ clocks = <&osc50m>;
+ clock-names = "ref";
+ #clock-cells = <1>;
+ };
+
+ pmb_reset: reset-controller {
+ compatible = "brcm,bcm6846-pmb-reset";
+ #reset-cells = <1>;
+ };
+
+ hwmon {
+ compatible = "brcm,bcm6846-pmb-pvtmon";
+ clocks = <&pmb_clk BCM6846_CLK_PVTMON>;
+ resets = <&pmb_reset BCM6846_RESET_PVTMON>;
+ #thermal-sensor-cells = <0>;
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index f14f9910911c..e11fc5064dc5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5447,7 +5447,15 @@ N: bcm[9]?6878
BROADCOM BCMBCA PMC3 PMB DRIVER
M: Linus Walleij <linusw@kernel.org>
S: Maintained
+F: Documentation/devicetree/bindings/clock/brcm,bcm6846-pmb-clock.yaml
+F: Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
F: Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
+F: Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
+F: Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
+F: Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
+F: include/dt-bindings/clock/brcm,bcm6846-pmb.h
+F: include/dt-bindings/power/brcm,bcm6846-pmb.h
+F: include/dt-bindings/reset/brcm,bcm6846-pmb.h
BROADCOM BDC DRIVER
M: Justin Chen <justin.chen@broadcom.com>
diff --git a/include/dt-bindings/clock/brcm,bcm6846-pmb.h b/include/dt-bindings/clock/brcm,bcm6846-pmb.h
new file mode 100644
index 000000000000..548a18ed7959
--- /dev/null
+++ b/include/dt-bindings/clock/brcm,bcm6846-pmb.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+#ifndef _DT_BINDINGS_CLOCK_BRCM_BCM6846_PMB_H
+#define _DT_BINDINGS_CLOCK_BRCM_BCM6846_PMB_H
+
+#define BCM6846_CLK_RDPPLL_CH0 0
+#define BCM6846_CLK_RDPPLL_CH1 1
+#define BCM6846_CLK_RDPPLL_CH2 2
+#define BCM6846_CLK_RDPPLL_CH3 3
+#define BCM6846_CLK_RDPPLL_CH4 4
+#define BCM6846_CLK_RDPPLL_CH5 5
+#define BCM6846_CLK_BIUPLL_CH0 6
+#define BCM6846_CLK_BIUPLL_CH1 7
+#define BCM6846_CLK_BIUPLL_CH2 8
+#define BCM6846_CLK_BIUPLL_CH3 9
+#define BCM6846_CLK_BIUPLL_CH4 10
+#define BCM6846_CLK_BIUPLL_CH5 11
+#define BCM6846_CLK_RUNNER 12
+#define BCM6846_CLK_XTAL_OUT 13
+#define BCM6846_CLK_PVTMON 14
+#define BCM6846_CLK_PERIPH_ZONE0 15
+#define BCM6846_CLK_PERIPH_ZONE1 16
+#define BCM6846_CLK_PERIPH_ZONE2 17
+#define BCM6846_CLK_PERIPH_ZONE3 18
+#define BCM6846_CLK_MEMC 19
+#define BCM6846_CLK_USB_ZONE0 20
+#define BCM6846_CLK_USB_ZONE1 21
+#define BCM6846_CLK_USB_ZONE2 22
+#define BCM6846_CLK_USB_ZONE3 23
+#define BCM6846_CLK_WAN_ZONE0 24
+#define BCM6846_CLK_WAN_ZONE1 25
+#define BCM6846_CLK_WAN_ZONE2 26
+#define BCM6846_CLK_XRDP_ZONE0 27
+#define BCM6846_CLK_XRDP_ZONE1 28
+#define BCM6846_CLK_XRDP_ZONE2 29
+#define BCM6846_CLK_RUNNER0 30
+#define BCM6846_CLK_RUNNER1 31
+#define BCM6846_CLK_RUNNER2 32
+#define BCM6846_CLK_PCIE0 33
+#define BCM6846_CLK_PCIE1 34
+#define BCM6846_CLK_BIU 35
+
+#endif
diff --git a/include/dt-bindings/power/brcm,bcm6846-pmb.h b/include/dt-bindings/power/brcm,bcm6846-pmb.h
new file mode 100644
index 000000000000..abdd01c94bc5
--- /dev/null
+++ b/include/dt-bindings/power/brcm,bcm6846-pmb.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+#ifndef _DT_BINDINGS_POWER_BCM6846_PMB_H
+#define _DT_BINDINGS_POWER_BCM6846_PMB_H
+
+#define BCM6846_PD_PERIPH 0
+#define BCM6846_PD_MEMC 1
+#define BCM6846_PD_USB20 2
+#define BCM6846_PD_XRDP 3
+#define BCM6846_PD_PCIE0 4
+#define BCM6846_PD_PCIE1 5
+
+#endif
diff --git a/include/dt-bindings/reset/brcm,bcm6846-pmb.h b/include/dt-bindings/reset/brcm,bcm6846-pmb.h
new file mode 100644
index 000000000000..ce68adb10108
--- /dev/null
+++ b/include/dt-bindings/reset/brcm,bcm6846-pmb.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+#ifndef _DT_BINDINGS_RESET_BRCM_BCM6846_PMB_H
+#define _DT_BINDINGS_RESET_BRCM_BCM6846_PMB_H
+
+/* XRDP packet engine and its three Runner cores. */
+#define BCM6846_RESET_XRDP 0
+
+/* Process, voltage and temperature monitor analog acquisition reset. */
+#define BCM6846_RESET_PVTMON 1
+
+#endif
--
2.56.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 3/7] mfd: bcmbca-pmb: Add a shared BCMBCA PMC3 PMB transport
2026-11-06 8:26 [PATCH v3 0/7] BCMBCA PMB power, clock, reset and hardware monitoring support Linus Walleij
2026-11-06 8:26 ` [PATCH v3 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
2026-11-06 8:26 ` [PATCH v3 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus Linus Walleij
@ 2026-11-06 8:26 ` Linus Walleij
2026-11-06 8:39 ` sashiko-bot
2026-11-06 8:26 ` [PATCH v3 4/7] pmdomain: bcm: Add BCMBCA PMB power domains Linus Walleij
` (3 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Linus Walleij @ 2026-11-06 8:26 UTC (permalink / raw)
To: Linus Walleij, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, William Zhang, Anand Gore, Kursad Oney,
Florian Fainelli, Rafał Miłecki,
Broadcom internal kernel review list, Stephen Boyd, Brian Masney,
Jerome Brunet, Guenter Roeck, Philipp Zabel, Jonathan Corbet,
Randy Dunlap, Ulf Hansson, Benjamin Larsson
Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon,
linux-pm
Add an MFD driver for shared access to the Processor Monitor Bus (PMB)
of the third generation Power Management Controller (PMC3), initially
for BCM6846.
Expose an uncached regmap to all children, encoding the bus, device and
word offset in each register address. Keep keyhole semaphore acquisition
and transaction recovery inside the MFD driver.
A software timeout does not abort a transaction. If the keyhole is still
busy, retain its hardware lock and reject new callers until delayed work
observes completion and releases it.
The keyhole register layout differs from older Broadcom PMB controllers.
Match only BCM6846 for now.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
MAINTAINERS | 2 +
drivers/mfd/Kconfig | 11 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/bcmbca_pmc3_pmb.c | 286 +++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/bcmbca-pmb.h | 11 ++
5 files changed, 311 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index e11fc5064dc5..9c9ef7eddb10 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5453,9 +5453,11 @@ F: Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
F: Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
F: Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
F: Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
+F: drivers/mfd/bcmbca_pmc3_pmb.c
F: include/dt-bindings/clock/brcm,bcm6846-pmb.h
F: include/dt-bindings/power/brcm,bcm6846-pmb.h
F: include/dt-bindings/reset/brcm,bcm6846-pmb.h
+F: include/linux/mfd/bcmbca-pmb.h
BROADCOM BDC DRIVER
M: Justin Chen <justin.chen@broadcom.com>
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 87ed55c155f0..5207c9505c91 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -173,6 +173,17 @@ config MFD_ATMEL_SMC
bool
select MFD_SYSCON
+config MFD_BCMBCA_PMB
+ bool "Broadcom BCMBCA Processor Monitor Bus"
+ depends on ARCH_BCMBCA || COMPILE_TEST
+ depends on OF
+ select MFD_CORE
+ select REGMAP
+ help
+ Provide shared Processor Monitor Bus (PMB) access through the third
+ generation Power Management Controller (PMC3), initially on
+ BCM6846.
+
config MFD_BCM590XX
tristate "Broadcom BCM590xx PMUs"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f8101d2a9ce9..f00f5caabe04 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_MFD_88PM886_PMIC) += 88pm886.o
obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
+obj-$(CONFIG_MFD_BCMBCA_PMB) += bcmbca_pmc3_pmb.o
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
obj-$(CONFIG_MFD_BQ257XX) += bq257xx.o
diff --git a/drivers/mfd/bcmbca_pmc3_pmb.c b/drivers/mfd/bcmbca_pmc3_pmb.c
new file mode 100644
index 000000000000..8ebcbc26a502
--- /dev/null
+++ b/drivers/mfd/bcmbca_pmc3_pmb.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Broadcom BCMBCA Processor Monitor Bus (PMB) transport for the third
+ * generation Power Management Controller (PMC3).
+ *
+ * Children access keyhole 0 through a shared regmap.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/log2.h>
+#include <linux/mfd/bcmbca-pmb.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/workqueue.h>
+
+#define PMB_CONFIG 0x00
+#define PMB_REGS_PER_DEVICE GENMASK(29, 20)
+#define PMB_CONTROL 0x10
+#define PMB_WRITE_DATA 0x14
+#define PMB_MUTEX 0x18
+#define PMB_READ_DATA 0x1c
+#define PMB_START BIT(31)
+#define PMB_TIMEOUT BIT(30)
+#define PMB_SLAVE_ERROR BIT(29)
+#define PMB_BUSY BIT(28)
+#define PMB_WRITE BIT(24)
+#define PMB_BUS GENMASK(21, 20)
+#define PMB_LOCKED BIT(0)
+
+struct bcmbca_pmb {
+ struct device *dev;
+ void __iomem *base;
+ /* Serializes regmap operations and recovery state. */
+ struct mutex lock;
+ struct delayed_work recovery;
+ u32 regs_per_device;
+ bool keyhole_acquired;
+ bool recovering;
+ bool stopping;
+};
+
+static void bcmbca_pmb_recover(struct work_struct *work)
+{
+ struct bcmbca_pmb *pmb = container_of(to_delayed_work(work),
+ struct bcmbca_pmb, recovery);
+
+ guard(mutex)(&pmb->lock);
+ if (!pmb->stopping) {
+ if (readl(pmb->base + PMB_CONTROL) & PMB_BUSY) {
+ queue_delayed_work(system_dfl_wq, &pmb->recovery,
+ msecs_to_jiffies(100));
+ } else {
+ writel(PMB_LOCKED, pmb->base + PMB_MUTEX);
+ pmb->recovering = false;
+ }
+ }
+}
+
+static int bcmbca_pmb_acquire(struct bcmbca_pmb *pmb)
+{
+ u32 value;
+ int ret;
+
+ lockdep_assert_held(&pmb->lock);
+ if (pmb->stopping)
+ return -ENODEV;
+ if (pmb->recovering)
+ return -EBUSY;
+ if (pmb->keyhole_acquired)
+ return 0;
+
+ /* Reading bit 0 acquires the hardware lock; writing 1 releases it. */
+ ret = readl_poll_timeout(pmb->base + PMB_MUTEX, value,
+ value & PMB_LOCKED, 1, 1000);
+ if (!ret)
+ pmb->keyhole_acquired = true;
+ return ret;
+}
+
+static int bcmbca_pmb_op(struct bcmbca_pmb *pmb, u8 bus, u8 device,
+ u16 offset, u32 *value, bool write)
+{
+ u32 status, command;
+ int ret;
+
+ lockdep_assert_held(&pmb->lock);
+ if (bus > FIELD_MAX(PMB_BUS) || offset >= pmb->regs_per_device)
+ return -EINVAL;
+
+ ret = readl_poll_timeout(pmb->base + PMB_CONTROL, status,
+ !(status & PMB_BUSY), 1, 1000);
+ if (ret)
+ return ret;
+ command = PMB_START | FIELD_PREP(PMB_BUS, bus) |
+ (device * pmb->regs_per_device) | offset;
+ if (write) {
+ writel(*value, pmb->base + PMB_WRITE_DATA);
+ command |= PMB_WRITE;
+ }
+ writel(command, pmb->base + PMB_CONTROL);
+ ret = readl_poll_timeout(pmb->base + PMB_CONTROL, status,
+ !(status & PMB_BUSY), 1, 1000);
+ if (ret || status & PMB_TIMEOUT)
+ return -ETIMEDOUT;
+ if (status & PMB_SLAVE_ERROR)
+ return -EIO;
+ if (!write)
+ *value = readl(pmb->base + PMB_READ_DATA);
+ return 0;
+}
+
+static void bcmbca_pmb_regmap_lock(void *arg)
+{
+ struct bcmbca_pmb *pmb = arg;
+
+ mutex_lock(&pmb->lock);
+}
+
+static void bcmbca_pmb_regmap_unlock(void *arg)
+{
+ struct bcmbca_pmb *pmb = arg;
+
+ if (pmb->keyhole_acquired) {
+ if (readl(pmb->base + PMB_CONTROL) & PMB_BUSY) {
+ pmb->recovering = true;
+ dev_err(pmb->dev, "PMB keyhole still busy; deferring unlock\n");
+ queue_delayed_work(system_dfl_wq, &pmb->recovery,
+ msecs_to_jiffies(100));
+ } else {
+ writel(PMB_LOCKED, pmb->base + PMB_MUTEX);
+ }
+ pmb->keyhole_acquired = false;
+ }
+ mutex_unlock(&pmb->lock);
+}
+
+/* Acquire lazily so semaphore errors reach the caller of the regmap API. */
+static int bcmbca_pmb_reg_read(void *context, unsigned int reg, unsigned int *value)
+{
+ struct bcmbca_pmb *pmb = context;
+ int ret;
+
+ ret = bcmbca_pmb_acquire(pmb);
+ if (ret)
+ return ret;
+ return bcmbca_pmb_op(pmb, reg >> 24, (reg >> 16) & 0xff,
+ reg & 0xffff, value, false);
+}
+
+static int bcmbca_pmb_reg_write(void *context, unsigned int reg, unsigned int value)
+{
+ struct bcmbca_pmb *pmb = context;
+ int ret;
+
+ ret = bcmbca_pmb_acquire(pmb);
+ if (ret)
+ return ret;
+ return bcmbca_pmb_op(pmb, reg >> 24, (reg >> 16) & 0xff,
+ reg & 0xffff, &value, true);
+}
+
+static bool bcmbca_pmb_precious_reg(struct device *dev, unsigned int reg)
+{
+ /* Do not let debugfs probe unimplemented or firmware-owned registers. */
+ return true;
+}
+
+static struct regmap *bcmbca_pmb_regmap_init(struct bcmbca_pmb *pmb)
+{
+ const struct regmap_config config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 1,
+ .max_register = BCMBCA_PMB_REG(3, 255, 65535),
+ .cache_type = REGCACHE_NONE,
+ .precious_reg = bcmbca_pmb_precious_reg,
+ .reg_read = bcmbca_pmb_reg_read,
+ .reg_write = bcmbca_pmb_reg_write,
+ .lock = bcmbca_pmb_regmap_lock,
+ .unlock = bcmbca_pmb_regmap_unlock,
+ .can_sleep = true,
+ .lock_arg = pmb,
+ };
+
+ return devm_regmap_init(pmb->dev, NULL, pmb, &config);
+}
+
+/* Children are removed before this action, while MMIO is still mapped. */
+static void bcmbca_pmb_stop(void *data)
+{
+ struct bcmbca_pmb *pmb = data;
+
+ scoped_guard(mutex, &pmb->lock)
+ pmb->stopping = true;
+ cancel_delayed_work_sync(&pmb->recovery);
+
+ if (pmb->recovering) {
+ if (readl(pmb->base + PMB_CONTROL) & PMB_BUSY)
+ dev_err(pmb->dev, "PMB keyhole remains busy; hardware reset required\n");
+ else
+ writel(PMB_LOCKED, pmb->base + PMB_MUTEX);
+ }
+}
+
+static const struct mfd_cell bcm6846_pmb_cells[] = {
+ {
+ .name = "bcm6846-pmb-power",
+ .of_compatible = "brcm,bcm6846-pmb-power",
+ },
+ {
+ .name = "bcm6846-pmb-clock",
+ .of_compatible = "brcm,bcm6846-pmb-clock",
+ },
+ {
+ .name = "bcm6846-pmb-reset",
+ .of_compatible = "brcm,bcm6846-pmb-reset",
+ },
+ {
+ .name = "bcm6846-pmb-pvtmon",
+ .of_compatible = "brcm,bcm6846-pmb-pvtmon",
+ },
+};
+
+static int bcmbca_pmb_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct bcmbca_pmb *pmb;
+ struct regmap *regmap;
+ struct resource *res;
+ int ret;
+
+ pmb = devm_kzalloc(dev, sizeof(*pmb), GFP_KERNEL);
+ if (!pmb)
+ return -ENOMEM;
+ pmb->dev = dev;
+ pmb->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(pmb->base))
+ return PTR_ERR(pmb->base);
+ if (resource_size(res) < PMB_READ_DATA + sizeof(u32))
+ return dev_err_probe(dev, -EINVAL, "PMB register range is too small\n");
+ pmb->regs_per_device = FIELD_GET(PMB_REGS_PER_DEVICE,
+ readl(pmb->base + PMB_CONFIG));
+ if (!is_power_of_2(pmb->regs_per_device))
+ return dev_err_probe(dev, -EINVAL, "invalid PMB register stride\n");
+ mutex_init(&pmb->lock);
+ INIT_DELAYED_WORK(&pmb->recovery, bcmbca_pmb_recover);
+ ret = devm_add_action_or_reset(dev, bcmbca_pmb_stop, pmb);
+ if (ret)
+ return ret;
+ regmap = bcmbca_pmb_regmap_init(pmb);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap), "failed to register PMB regmap\n");
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, bcm6846_pmb_cells,
+ ARRAY_SIZE(bcm6846_pmb_cells), NULL, 0, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to register PMB functions\n");
+
+ return 0;
+}
+
+static const struct of_device_id bcmbca_pmb_match[] = {
+ { .compatible = "brcm,bcm6846-pmb" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bcmbca_pmb_match);
+
+static struct platform_driver bcmbca_pmb_driver = {
+ .probe = bcmbca_pmb_probe,
+ .driver = {
+ .name = "bcmbca-pmb",
+ .of_match_table = bcmbca_pmb_match,
+ .suppress_bind_attrs = true,
+ },
+};
+builtin_platform_driver(bcmbca_pmb_driver);
+
+MODULE_DESCRIPTION("Broadcom BCMBCA Processor Monitor Bus transport for PMC3");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/bcmbca-pmb.h b/include/linux/mfd/bcmbca-pmb.h
new file mode 100644
index 000000000000..36e2b42bf053
--- /dev/null
+++ b/include/linux/mfd/bcmbca-pmb.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __LINUX_MFD_BCMBCA_PMB_H
+#define __LINUX_MFD_BCMBCA_PMB_H
+
+#include <linux/types.h>
+
+/* Logical regmap addresses: 8-bit bus, 8-bit device, 16-bit word offset. */
+#define BCMBCA_PMB_REG(bus, device, offset) \
+ (((u32)(bus) << 24) | ((u32)(device) << 16) | (offset))
+
+#endif
--
2.56.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 4/7] pmdomain: bcm: Add BCMBCA PMB power domains
2026-11-06 8:26 [PATCH v3 0/7] BCMBCA PMB power, clock, reset and hardware monitoring support Linus Walleij
` (2 preceding siblings ...)
2026-11-06 8:26 ` [PATCH v3 3/7] mfd: bcmbca-pmb: Add a shared BCMBCA PMC3 PMB transport Linus Walleij
@ 2026-11-06 8:26 ` Linus Walleij
2026-11-06 8:26 ` [PATCH v3 5/7] reset: Add BCMBCA block resets through the PMB Linus Walleij
` (2 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-06 8:26 UTC (permalink / raw)
To: Linus Walleij, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, William Zhang, Anand Gore, Kursad Oney,
Florian Fainelli, Rafał Miłecki,
Broadcom internal kernel review list, Stephen Boyd, Brian Masney,
Jerome Brunet, Guenter Roeck, Philipp Zabel, Jonathan Corbet,
Randy Dunlap, Ulf Hansson, Benjamin Larsson
Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon,
linux-pm
Implement BCM6846 BPCM power domains.
Group XRDP, its three Runner cores and WAN in vendor xrdp_pmb[] order,
so consumers can power the complete packet engine before resetting it.
Also expose peripheral, memory, USB and PCIe domains. Keep the peripheral
and memory domains always on; exclude CPU and PLL blocks with different
register layouts.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
MAINTAINERS | 1 +
drivers/pmdomain/bcm/Kconfig | 10 ++
drivers/pmdomain/bcm/Makefile | 1 +
drivers/pmdomain/bcm/bcmbca-pmb.c | 279 ++++++++++++++++++++++++++++++++++++++
4 files changed, 291 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 9c9ef7eddb10..6702e9c447ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5454,6 +5454,7 @@ F: Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
F: Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
F: Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
F: drivers/mfd/bcmbca_pmc3_pmb.c
+F: drivers/pmdomain/bcm/bcmbca-pmb.c
F: include/dt-bindings/clock/brcm,bcm6846-pmb.h
F: include/dt-bindings/power/brcm,bcm6846-pmb.h
F: include/dt-bindings/reset/brcm,bcm6846-pmb.h
diff --git a/drivers/pmdomain/bcm/Kconfig b/drivers/pmdomain/bcm/Kconfig
index b28c9f6d256b..ed085f29d927 100644
--- a/drivers/pmdomain/bcm/Kconfig
+++ b/drivers/pmdomain/bcm/Kconfig
@@ -31,6 +31,16 @@ config BCM_PMB
This enables support for the Broadcom's PMB (Power Management Bus) that
is used for disabling and enabling SoC devices.
+config BCMBCA_PMB_POWER
+ bool "Broadcom BCMBCA PMB power domains"
+ depends on MFD_BCMBCA_PMB
+ depends on PM
+ default MFD_BCMBCA_PMB
+ select PM_GENERIC_DOMAINS
+ help
+ Provide power domains for BCM6846 blocks through the shared PMC3
+ Processor Monitor Bus regmap, including the XRDP packet processor.
+
config BCM63XX_POWER
bool "BCM63xx power domain driver"
depends on BMIPS_GENERIC || (COMPILE_TEST && OF)
diff --git a/drivers/pmdomain/bcm/Makefile b/drivers/pmdomain/bcm/Makefile
index 6bfbe4e4db13..ed8a1d3d4c10 100644
--- a/drivers/pmdomain/bcm/Makefile
+++ b/drivers/pmdomain/bcm/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_BCM_PMB) += bcm-pmb.o
obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o
obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
+obj-$(CONFIG_BCMBCA_PMB_POWER) += bcmbca-pmb.o
diff --git a/drivers/pmdomain/bcm/bcmbca-pmb.c b/drivers/pmdomain/bcm/bcmbca-pmb.c
new file mode 100644
index 000000000000..9a631b7b0360
--- /dev/null
+++ b/drivers/pmdomain/bcm/bcmbca-pmb.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Broadcom BCM6846 BPCM power zones, accessed through the PMC3 PMB regmap. */
+
+#include <linux/bits.h>
+#include <linux/mfd/bcmbca-pmb.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/power/brcm,bcm6846-pmb.h>
+
+/* BCM6846 BPCM zone control, in PMB words, with eight words per zone. */
+#define BCM6846_ZONE_CONTROL(zone) (32 + (zone) * 8)
+#define BCM6846_ZONE_DPG_EN BIT(8)
+#define BCM6846_ZONE_POWER_DOWN BIT(9)
+#define BCM6846_ZONE_POWER_UP BIT(10)
+#define BCM6846_ZONE_MEM_POWER BIT(11)
+#define BCM6846_ZONE_RESET BIT(12)
+#define BCM6846_ZONE_POWER_OFF BIT(25)
+#define BCM6846_ZONE_POWER_ON BIT(26)
+
+struct bcmbca_pmb_power_block {
+ u8 bus;
+ u8 device;
+ u8 zones;
+};
+
+struct bcmbca_pmb_power_data {
+ const char *name;
+ const struct bcmbca_pmb_power_block *blocks;
+ unsigned int num_blocks;
+ unsigned int flags;
+};
+
+struct bcmbca_pmb_power_domain {
+ struct generic_pm_domain genpd;
+ struct device *dev;
+ struct regmap *regmap;
+ const struct bcmbca_pmb_power_data *data;
+};
+
+static const struct bcmbca_pmb_power_block bcm6846_periph[] = { { 0, 0, 4 } };
+static const struct bcmbca_pmb_power_block bcm6846_memc[] = { { 1, 8, 1 } };
+static const struct bcmbca_pmb_power_block bcm6846_usb20[] = { { 1, 10, 4 } };
+static const struct bcmbca_pmb_power_block bcm6846_pcie0[] = { { 0, 18, 1 } };
+static const struct bcmbca_pmb_power_block bcm6846_pcie1[] = { { 0, 19, 1 } };
+
+/* Power up XRDP, three Runners, then WAN. */
+static const struct bcmbca_pmb_power_block bcm6846_xrdp[] = {
+ { 1, 12, 3 }, { 1, 14, 1 }, { 1, 15, 1 }, { 1, 16, 1 }, { 1, 11, 3 },
+};
+
+static const struct bcmbca_pmb_power_data bcm6846_domains[] = {
+ [BCM6846_PD_PERIPH] = {
+ .name = "periph",
+ .blocks = bcm6846_periph,
+ .num_blocks = ARRAY_SIZE(bcm6846_periph),
+ .flags = GENPD_FLAG_ALWAYS_ON,
+ },
+ [BCM6846_PD_MEMC] = {
+ .name = "memc",
+ .blocks = bcm6846_memc,
+ .num_blocks = ARRAY_SIZE(bcm6846_memc),
+ .flags = GENPD_FLAG_ALWAYS_ON,
+ },
+ [BCM6846_PD_USB20] = {
+ .name = "usb20",
+ .blocks = bcm6846_usb20,
+ .num_blocks = ARRAY_SIZE(bcm6846_usb20),
+ },
+ [BCM6846_PD_XRDP] = {
+ .name = "xrdp",
+ .blocks = bcm6846_xrdp,
+ .num_blocks = ARRAY_SIZE(bcm6846_xrdp),
+ },
+ [BCM6846_PD_PCIE0] = {
+ .name = "pcie0",
+ .blocks = bcm6846_pcie0,
+ .num_blocks = ARRAY_SIZE(bcm6846_pcie0),
+ },
+ [BCM6846_PD_PCIE1] = {
+ .name = "pcie1",
+ .blocks = bcm6846_pcie1,
+ .num_blocks = ARRAY_SIZE(bcm6846_pcie1),
+ },
+};
+
+static unsigned int bcmbca_pmb_zone_reg(const struct bcmbca_pmb_power_block *block,
+ unsigned int zone)
+{
+ return BCMBCA_PMB_REG(block->bus, block->device, BCM6846_ZONE_CONTROL(zone));
+}
+
+static int bcmbca_pmb_zone_off(struct bcmbca_pmb_power_domain *pd,
+ const struct bcmbca_pmb_power_block *block, unsigned int zone)
+{
+ unsigned int reg = bcmbca_pmb_zone_reg(block, zone);
+ unsigned int value;
+ int ret;
+
+ /* Request power-down and cancel power-up. */
+ ret = regmap_write_bits(pd->regmap, reg,
+ BCM6846_ZONE_POWER_DOWN | BCM6846_ZONE_POWER_UP,
+ BCM6846_ZONE_POWER_DOWN);
+ if (ret)
+ return ret;
+
+ return regmap_read_poll_timeout(pd->regmap, reg, value,
+ value & BCM6846_ZONE_POWER_OFF, 10, 10000);
+}
+
+static int bcmbca_pmb_power_on(struct generic_pm_domain *genpd)
+{
+ struct bcmbca_pmb_power_domain *pd = container_of(genpd, typeof(*pd), genpd);
+ const struct bcmbca_pmb_power_data *data = pd->data;
+ /* One bit per zone, tracking only zones changed by this attempt. */
+ u32 changed[ARRAY_SIZE(bcm6846_xrdp)] = {};
+ const struct bcmbca_pmb_power_block *block;
+ unsigned int i, zone, reg, value, mask;
+ int ret;
+
+ for (i = 0; i < data->num_blocks; i++) {
+ block = &data->blocks[i];
+ for (zone = 0; zone < block->zones; zone++) {
+ reg = bcmbca_pmb_zone_reg(block, zone);
+ ret = regmap_read(pd->regmap, reg, &value);
+ if (ret)
+ goto rollback;
+ if ((value & BCM6846_ZONE_POWER_ON) &&
+ !(value & BCM6846_ZONE_POWER_DOWN))
+ continue;
+
+ changed[i] |= BIT(zone);
+ /* Enable dynamic gating, memory power control and block reset. */
+ mask = BCM6846_ZONE_POWER_DOWN | BCM6846_ZONE_DPG_EN |
+ BCM6846_ZONE_POWER_UP | BCM6846_ZONE_MEM_POWER |
+ BCM6846_ZONE_RESET;
+ ret = regmap_write_bits(pd->regmap, reg, mask,
+ mask & ~BCM6846_ZONE_POWER_DOWN);
+ if (ret)
+ goto rollback;
+ ret = regmap_read_poll_timeout(pd->regmap, reg, value,
+ value & BCM6846_ZONE_POWER_ON, 10, 10000);
+ if (ret)
+ goto rollback;
+ }
+ }
+ return 0;
+
+rollback:
+ dev_err(pd->dev, "%s power-up failed at bus %u device %u zone %u: %d\n",
+ data->name, block->bus, block->device, zone, ret);
+ /* Preserve zones left powered by firmware or an earlier attempt. */
+ for (i = data->num_blocks; i-- > 0;) {
+ block = &data->blocks[i];
+ for (zone = block->zones; zone-- > 0;)
+ if ((changed[i] & BIT(zone)) && bcmbca_pmb_zone_off(pd, block, zone))
+ dev_err(pd->dev, "%s power-up rollback failed\n", data->name);
+ }
+ return ret;
+}
+
+static int bcmbca_pmb_power_off(struct generic_pm_domain *genpd)
+{
+ struct bcmbca_pmb_power_domain *pd = container_of(genpd, typeof(*pd), genpd);
+ const struct bcmbca_pmb_power_data *data = pd->data;
+ unsigned int i;
+ int ret;
+
+ /* Powering down zone zero powers down the whole block. */
+ for (i = data->num_blocks; i-- > 0;) {
+ ret = bcmbca_pmb_zone_off(pd, &data->blocks[i], 0);
+ if (ret) {
+ /* genpd keeps the domain logically on when power-off fails. */
+ if (bcmbca_pmb_power_on(genpd))
+ dev_err(pd->dev, "%s power-off recovery failed\n", data->name);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int bcmbca_pmb_power_is_off(struct bcmbca_pmb_power_domain *pd, bool *off)
+{
+ const struct bcmbca_pmb_power_data *data = pd->data;
+ unsigned int i, zone, value;
+ int ret;
+
+ *off = false;
+ for (i = 0; i < data->num_blocks; i++) {
+ for (zone = 0; zone < data->blocks[i].zones; zone++) {
+ ret = regmap_read(pd->regmap, bcmbca_pmb_zone_reg(&data->blocks[i], zone),
+ &value);
+ if (ret)
+ return ret;
+ if (!(value & BCM6846_ZONE_POWER_ON) || (value & BCM6846_ZONE_POWER_DOWN))
+ *off = true;
+ }
+ }
+ return 0;
+}
+
+static int bcmbca_pmb_power_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap = dev_get_regmap(dev->parent, NULL);
+ struct bcmbca_pmb_power_domain *domains;
+ struct genpd_onecell_data *onecell;
+ unsigned int i;
+ bool off;
+ int ret;
+
+ if (!regmap)
+ return -ENODEV;
+
+ onecell = devm_kzalloc(dev, sizeof(*onecell), GFP_KERNEL);
+ if (!onecell)
+ return -ENOMEM;
+ onecell->num_domains = ARRAY_SIZE(bcm6846_domains);
+ onecell->domains = devm_kcalloc(dev, onecell->num_domains,
+ sizeof(*onecell->domains), GFP_KERNEL);
+ domains = devm_kcalloc(dev, onecell->num_domains, sizeof(*domains), GFP_KERNEL);
+ if (!onecell->domains || !domains)
+ return -ENOMEM;
+
+ for (i = 0; i < onecell->num_domains; i++) {
+ struct bcmbca_pmb_power_domain *pd = &domains[i];
+
+ pd->dev = dev;
+ pd->regmap = regmap;
+ pd->data = &bcm6846_domains[i];
+ pd->genpd.name = pd->data->name;
+ pd->genpd.flags = pd->data->flags;
+ pd->genpd.power_on = bcmbca_pmb_power_on;
+ pd->genpd.power_off = bcmbca_pmb_power_off;
+ ret = bcmbca_pmb_power_is_off(pd, &off);
+ if (ret)
+ goto remove_domains;
+ /* Always-on domains must be fully powered before genpd initialization. */
+ if (off && (pd->data->flags & GENPD_FLAG_ALWAYS_ON)) {
+ ret = bcmbca_pmb_power_on(&pd->genpd);
+ if (ret)
+ goto remove_domains;
+ off = false;
+ }
+ ret = pm_genpd_init(&pd->genpd, NULL, off);
+ if (ret)
+ goto remove_domains;
+ onecell->domains[i] = &pd->genpd;
+ }
+ ret = of_genpd_add_provider_onecell(dev->of_node, onecell);
+ if (!ret)
+ return 0;
+
+remove_domains:
+ while (i-- > 0)
+ pm_genpd_remove(onecell->domains[i]);
+ return dev_err_probe(dev, ret, "failed to register PMB power domains\n");
+}
+
+static const struct of_device_id bcmbca_pmb_power_of_match[] = {
+ { .compatible = "brcm,bcm6846-pmb-power" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bcmbca_pmb_power_of_match);
+
+static struct platform_driver bcmbca_pmb_power_driver = {
+ .probe = bcmbca_pmb_power_probe,
+ .driver = {
+ .name = "bcmbca-pmb-power",
+ .of_match_table = bcmbca_pmb_power_of_match,
+ .suppress_bind_attrs = true,
+ },
+};
+builtin_platform_driver(bcmbca_pmb_power_driver);
+
+MODULE_DESCRIPTION("Broadcom BCMBCA PMB power domains");
+MODULE_LICENSE("GPL");
--
2.56.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 5/7] reset: Add BCMBCA block resets through the PMB
2026-11-06 8:26 [PATCH v3 0/7] BCMBCA PMB power, clock, reset and hardware monitoring support Linus Walleij
` (3 preceding siblings ...)
2026-11-06 8:26 ` [PATCH v3 4/7] pmdomain: bcm: Add BCMBCA PMB power domains Linus Walleij
@ 2026-11-06 8:26 ` Linus Walleij
2026-11-06 8:35 ` sashiko-bot
2026-11-06 11:59 ` Philipp Zabel
2026-11-06 8:26 ` [PATCH v3 6/7] clk: bcm: Add BCMBCA PMB clocks Linus Walleij
2026-11-06 8:26 ` [PATCH v3 7/7] hwmon: Add Broadcom PMB PVTMON monitoring Linus Walleij
6 siblings, 2 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-06 8:26 UTC (permalink / raw)
To: Linus Walleij, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, William Zhang, Anand Gore, Kursad Oney,
Florian Fainelli, Rafał Miłecki,
Broadcom internal kernel review list, Stephen Boyd, Brian Masney,
Jerome Brunet, Guenter Roeck, Philipp Zabel, Jonathan Corbet,
Randy Dunlap, Ulf Hansson, Benjamin Larsson
Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon,
linux-pm
Implement the BCM6846 XRDP reset group through the shared PMB regmap.
Assert all blocks before releasing any of them, preserving the vendor
reset masks and ordering. Provide the independent PVTMON acquisition
reset as well. Serialize complete sequences and hold blocks in reset
on failure.
Power domain consumers must enable their domains before requesting a
reset. Zone transitions belong to the PMB power domain subdriver.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
MAINTAINERS | 1 +
drivers/reset/Kconfig | 13 +++
drivers/reset/Makefile | 1 +
drivers/reset/reset-bcmbca-pmb.c | 243 +++++++++++++++++++++++++++++++++++++++
4 files changed, 258 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6702e9c447ae..1b7247b8c717 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5455,6 +5455,7 @@ F: Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
F: Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
F: drivers/mfd/bcmbca_pmc3_pmb.c
F: drivers/pmdomain/bcm/bcmbca-pmb.c
+F: drivers/reset/reset-bcmbca-pmb.c
F: include/dt-bindings/clock/brcm,bcm6846-pmb.h
F: include/dt-bindings/power/brcm,bcm6846-pmb.h
F: include/dt-bindings/reset/brcm,bcm6846-pmb.h
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index eda9c698a95f..56f7aee6cf1f 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -49,6 +49,19 @@ config RESET_BCM6345
help
This enables the reset controller driver for BCM6345 SoCs.
+config RESET_BCMBCA_PMB
+ tristate "Broadcom BCMBCA PMB reset controller"
+ depends on ARCH_BCMBCA || COMPILE_TEST
+ depends on OF && HAS_IOMEM
+ depends on MFD_BCMBCA_PMB
+ select REGMAP
+ default MFD_BCMBCA_PMB
+ help
+ Reset BCMBCA blocks through the Processor Monitor Bus (PMB) of
+ the third generation Power Management Controller (PMC3).
+
+ The module will be called reset-bcmbca-pmb.
+
config RESET_BERLIN
tristate "Berlin Reset Driver"
depends on ARCH_BERLIN || COMPILE_TEST
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 489fafd6bbe3..26c8a73f774f 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_RESET_ASPEED) += reset-aspeed.o
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
+obj-$(CONFIG_RESET_BCMBCA_PMB) += reset-bcmbca-pmb.o
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
diff --git a/drivers/reset/reset-bcmbca-pmb.c b/drivers/reset/reset-bcmbca-pmb.c
new file mode 100644
index 000000000000..e8e079c9ccb5
--- /dev/null
+++ b/drivers/reset/reset-bcmbca-pmb.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * BCMBCA block resets through the Processor Monitor Bus (PMB) of the
+ * third generation Power Management Controller (PMC3).
+ */
+
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/delay.h>
+#include <linux/mfd/bcmbca-pmb.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/string_choices.h>
+
+#include <dt-bindings/reset/brcm,bcm6846-pmb.h>
+
+struct bcmbca_pmb_reset_block {
+ u8 bus;
+ u8 device;
+ u16 offset; /* PMB word offset of the reset register. */
+ u32 mask;
+ u32 assert_value;
+ u32 deassert_value;
+};
+
+struct bcmbca_pmb_reset;
+
+struct bcmbca_pmb_reset_group {
+ const char *name;
+ int (*reset)(struct bcmbca_pmb_reset *rst,
+ const struct bcmbca_pmb_reset_group *group);
+ const struct bcmbca_pmb_reset_block *blocks;
+ unsigned int num_blocks;
+ /* Minimum reset assertion hold time in microseconds. */
+ unsigned int assert_hold_us;
+};
+
+struct bcmbca_pmb_reset_variant {
+ const struct bcmbca_pmb_reset_group *groups;
+ unsigned int num_groups;
+};
+
+struct bcmbca_pmb_reset {
+ struct reset_controller_dev rcdev;
+ const struct bcmbca_pmb_reset_variant *variant;
+ struct regmap *regmap;
+ /* Serialize complete reset pulses and failure cleanup. */
+ struct mutex lock;
+};
+
+static int bcmbca_pmb_reset_sequence(struct bcmbca_pmb_reset *rst,
+ const struct bcmbca_pmb_reset_group *group);
+
+static const struct bcmbca_pmb_reset_block bcm6846_xrdp_resets[] = {
+ {
+ .bus = 1,
+ .device = 12,
+ .offset = 5,
+ .mask = GENMASK(27, 0),
+ /* Keep bits 0–2 deasserted. */
+ .assert_value = GENMASK(2, 0),
+ .deassert_value = GENMASK(27, 0),
+ },
+ {
+ .bus = 1,
+ .device = 14,
+ .offset = 5,
+ .mask = GENMASK(27, 0),
+ .deassert_value = GENMASK(27, 0),
+ },
+ {
+ .bus = 1,
+ .device = 15,
+ .offset = 5,
+ .mask = GENMASK(27, 0),
+ .deassert_value = GENMASK(27, 0),
+ },
+ {
+ .bus = 1,
+ .device = 16,
+ .offset = 5,
+ .mask = GENMASK(27, 0),
+ .deassert_value = GENMASK(27, 0),
+ },
+};
+
+/* Analog acquisition reset, independent of clock and power configuration. */
+static const struct bcmbca_pmb_reset_block bcm6846_pvtmon_reset = {
+ .bus = 1,
+ .device = 6,
+ .offset = 17,
+ .mask = BIT(0),
+ .deassert_value = BIT(0),
+};
+
+static const struct bcmbca_pmb_reset_group bcm6846_pmb_reset_groups[] = {
+ [BCM6846_RESET_XRDP] = {
+ .name = "XRDP",
+ .reset = bcmbca_pmb_reset_sequence,
+ .blocks = bcm6846_xrdp_resets,
+ .num_blocks = ARRAY_SIZE(bcm6846_xrdp_resets),
+ .assert_hold_us = 10,
+ },
+ [BCM6846_RESET_PVTMON] = {
+ .name = "PVTMON",
+ .reset = bcmbca_pmb_reset_sequence,
+ .blocks = &bcm6846_pvtmon_reset,
+ .num_blocks = 1,
+ .assert_hold_us = 1000,
+ },
+};
+
+static const struct bcmbca_pmb_reset_variant bcm6846_pmb_variant = {
+ .groups = bcm6846_pmb_reset_groups,
+ .num_groups = ARRAY_SIZE(bcm6846_pmb_reset_groups),
+};
+
+/* Best effort: never restart a partially reset group. */
+static void bcmbca_pmb_reset_cleanup(struct bcmbca_pmb_reset *rst,
+ const struct bcmbca_pmb_reset_group *group)
+{
+ const struct bcmbca_pmb_reset_block *block;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < group->num_blocks; i++) {
+ block = &group->blocks[i];
+ ret = regmap_update_bits(rst->regmap,
+ BCMBCA_PMB_REG(block->bus, block->device, block->offset),
+ block->mask, block->assert_value);
+ if (ret)
+ dev_err(rst->rcdev.dev,
+ "failed to hold PMB bus %u device %u in reset: %d\n",
+ block->bus, block->device, ret);
+ }
+}
+
+static int bcmbca_pmb_reset_sequence(struct bcmbca_pmb_reset *rst,
+ const struct bcmbca_pmb_reset_group *group)
+{
+ const struct bcmbca_pmb_reset_block *block;
+ enum {
+ PASS_ASSERT,
+ PASS_DEASSERT,
+ } pass;
+ unsigned int i;
+ int ret;
+
+ if (!group->num_blocks)
+ return -EINVAL;
+
+ /* Assert every block before releasing any of them. */
+ for (pass = PASS_ASSERT; pass <= PASS_DEASSERT; pass++) {
+ for (i = 0; i < group->num_blocks; i++) {
+ block = &group->blocks[i];
+ ret = regmap_update_bits(rst->regmap,
+ BCMBCA_PMB_REG(block->bus, block->device,
+ block->offset), block->mask,
+ pass == PASS_DEASSERT ? block->deassert_value :
+ block->assert_value);
+ if (ret)
+ goto cleanup;
+ }
+ if (pass == PASS_ASSERT && group->assert_hold_us)
+ usleep_range(group->assert_hold_us, group->assert_hold_us * 2);
+ }
+cleanup:
+ if (ret) {
+ dev_err(rst->rcdev.dev, "%s %s failed at PMB bus %u device %u: %d\n",
+ group->name, str_assert_deassert(pass == PASS_ASSERT),
+ block->bus, block->device, ret);
+ bcmbca_pmb_reset_cleanup(rst, group);
+ }
+ return ret;
+}
+
+static int bcmbca_pmb_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ struct bcmbca_pmb_reset *rst = container_of(rcdev, struct bcmbca_pmb_reset, rcdev);
+ const struct bcmbca_pmb_reset_group *group;
+
+ if (id >= rst->variant->num_groups)
+ return -EINVAL;
+ group = &rst->variant->groups[id];
+ if (!group->reset)
+ return -EINVAL;
+
+ guard(mutex)(&rst->lock);
+ return group->reset(rst, group);
+}
+
+static const struct reset_control_ops bcmbca_pmb_reset_ops = {
+ .reset = bcmbca_pmb_reset,
+};
+
+static int bcmbca_pmb_reset_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap = dev_get_regmap(dev->parent, NULL);
+ struct bcmbca_pmb_reset *rst;
+
+ if (!regmap)
+ return -ENODEV;
+
+ rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
+ if (!rst)
+ return -ENOMEM;
+ rst->variant = device_get_match_data(dev);
+ if (!rst->variant)
+ return -ENODEV;
+ rst->regmap = regmap;
+ mutex_init(&rst->lock);
+ rst->rcdev.owner = THIS_MODULE;
+ rst->rcdev.dev = dev;
+ rst->rcdev.ops = &bcmbca_pmb_reset_ops;
+ rst->rcdev.of_node = dev->of_node;
+ rst->rcdev.of_reset_n_cells = 1;
+ rst->rcdev.nr_resets = rst->variant->num_groups;
+ return devm_reset_controller_register(dev, &rst->rcdev);
+}
+
+static const struct of_device_id bcmbca_pmb_reset_of_match[] = {
+ { .compatible = "brcm,bcm6846-pmb-reset", .data = &bcm6846_pmb_variant },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bcmbca_pmb_reset_of_match);
+
+static struct platform_driver bcmbca_pmb_reset_driver = {
+ .probe = bcmbca_pmb_reset_probe,
+ .driver = {
+ .name = "brcm-pmb-reset",
+ .of_match_table = bcmbca_pmb_reset_of_match,
+ .suppress_bind_attrs = true,
+ },
+};
+module_platform_driver(bcmbca_pmb_reset_driver);
+
+MODULE_DESCRIPTION("Broadcom BCMBCA PMB reset controller");
+MODULE_LICENSE("GPL");
--
2.56.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 6/7] clk: bcm: Add BCMBCA PMB clocks
2026-11-06 8:26 [PATCH v3 0/7] BCMBCA PMB power, clock, reset and hardware monitoring support Linus Walleij
` (4 preceding siblings ...)
2026-11-06 8:26 ` [PATCH v3 5/7] reset: Add BCMBCA block resets through the PMB Linus Walleij
@ 2026-11-06 8:26 ` Linus Walleij
2026-11-06 8:26 ` [PATCH v3 7/7] hwmon: Add Broadcom PMB PVTMON monitoring Linus Walleij
6 siblings, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-06 8:26 UTC (permalink / raw)
To: Linus Walleij, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, William Zhang, Anand Gore, Kursad Oney,
Florian Fainelli, Rafał Miłecki,
Broadcom internal kernel review list, Stephen Boyd, Brian Masney,
Jerome Brunet, Guenter Roeck, Philipp Zabel, Jonathan Corbet,
Randy Dunlap, Ulf Hansson, Benjamin Larsson
Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon,
linux-pm
Add a BCM6846 clock provider for the Processor Monitor Bus (PMB) MFD
cell. Expose six outputs from each of the RDP and BIU PLLs, the Runner
clock divided from RDP PLL channel 1, the crystal output, PVTMON and
block-zone clock gates.
PVTMON and zone clocks provide gate control only.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
MAINTAINERS | 1 +
drivers/clk/bcm/Kconfig | 11 ++
drivers/clk/bcm/Makefile | 1 +
drivers/clk/bcm/clk-bcmbca-pmb.c | 388 +++++++++++++++++++++++++++++++++++++++
4 files changed, 401 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 1b7247b8c717..2a280ca7d162 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5453,6 +5453,7 @@ F: Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
F: Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
F: Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
F: Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
+F: drivers/clk/bcm/clk-bcmbca-pmb.c
F: drivers/mfd/bcmbca_pmc3_pmb.c
F: drivers/pmdomain/bcm/bcmbca-pmb.c
F: drivers/reset/reset-bcmbca-pmb.c
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig
index a972d763eb77..db17eadde7aa 100644
--- a/drivers/clk/bcm/Kconfig
+++ b/drivers/clk/bcm/Kconfig
@@ -1,5 +1,16 @@
# SPDX-License-Identifier: GPL-2.0-only
+config CLK_BCMBCA_PMB
+ tristate "Broadcom BCMBCA PMB clocks"
+ depends on MFD_BCMBCA_PMB
+ select REGMAP
+ default MFD_BCMBCA_PMB
+ help
+ Provide BCM6846 PLL output, Runner, crystal, PVTMON and block-zone
+ clocks through the Processor Monitor Bus.
+
+ The module will be called clk-bcmbca-pmb.
+
config CLK_BCM2711_DVP
tristate "Broadcom BCM2711 DVP support"
depends on ARCH_BCM2835 ||COMPILE_TEST
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index d0b6f4b1fb08..7123eefff138 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_CLK_BCMBCA_PMB) += clk-bcmbca-pmb.o
obj-$(CONFIG_CLK_BCM_63XX) += clk-bcm63xx.o
obj-$(CONFIG_CLK_BCM_63XX_GATE) += clk-bcm63xx-gate.o
obj-$(CONFIG_CLK_BCM63268_TIMER) += clk-bcm63268-timer.o
diff --git a/drivers/clk/bcm/clk-bcmbca-pmb.c b/drivers/clk/bcm/clk-bcmbca-pmb.c
new file mode 100644
index 000000000000..70552a23c3ef
--- /dev/null
+++ b/drivers/clk/bcm/clk-bcmbca-pmb.c
@@ -0,0 +1,388 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Broadcom BCM6846 Processor Monitor Bus (PMB) clocks.
+ *
+ * PMB transactions sleep, so gating uses the prepare callbacks. Firmware
+ * also uses these clocks: leave prepared clocks running and retain PLL
+ * rates.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/math64.h>
+#include <linux/mfd/bcmbca-pmb.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/brcm,bcm6846-pmb.h>
+
+/* PMB register offsets are in 32-bit words. */
+#define PLL_CHANNEL_DISABLE BIT(8)
+#define PLL_CHANNEL_HOLD BIT(9)
+#define PLL_MDIV_OVERRIDE BIT(15)
+#define PLL_LOCK BIT(31)
+#define PLL_NDIV_INT GENMASK(9, 0)
+#define PLL_NDIV_FRAC GENMASK(31, 12)
+#define PLL_PDIV GENMASK(3, 0)
+
+#define XTAL_CONTROL 14
+#define XTAL_DRIVER_POWER_DOWN BIT(17)
+
+#define PVTMON_CONFIG 17
+#define PVTMON_CLOCK_ENABLE BIT(2)
+#define PVTMON_CLOCK_DIVIDER GENMASK(12, 8)
+
+#define ZONE_CLOCK_ENABLE BIT(0)
+#define ZONE_MANUAL_CONTROL BIT(7)
+#define ZONE_POWER_DOWN_REQUEST BIT(9)
+#define ZONE_POWER_ON BIT(26)
+
+enum bcmbca_pmb_clock_type {
+ PMB_PLL_CHANNEL,
+ PMB_RUNNER,
+ PMB_XTAL,
+ PMB_PVTMON,
+ PMB_ZONE,
+};
+
+struct bcmbca_pmb_pll_layout {
+ u16 ch01;
+ u16 status;
+ u16 ndiv;
+ u16 pdiv;
+ u16 ch25;
+};
+
+struct bcmbca_pmb_clock_desc {
+ const char *name;
+ enum bcmbca_pmb_clock_type type;
+ u8 bus;
+ u8 device;
+ u8 channel;
+ u16 reg;
+ const struct bcmbca_pmb_pll_layout *pll;
+};
+
+struct bcmbca_pmb_clock {
+ struct clk_hw hw;
+ struct device *dev;
+ struct regmap *regmap;
+ const struct bcmbca_pmb_clock_desc *desc;
+};
+
+#define to_pmb_clock(_hw) container_of(_hw, struct bcmbca_pmb_clock, hw)
+
+static int bcmbca_pmb_clock_prepare(struct clk_hw *hw)
+{
+ struct bcmbca_pmb_clock *clock = to_pmb_clock(hw);
+ const struct bcmbca_pmb_clock_desc *desc = clock->desc;
+ unsigned int shift = (desc->channel % 2) * 16;
+ unsigned int reg = BCMBCA_PMB_REG(desc->bus, desc->device, desc->reg);
+ u32 value;
+ int ret;
+
+ switch (desc->type) {
+ case PMB_PLL_CHANNEL: {
+ unsigned int regs[] = {
+ BCMBCA_PMB_REG(desc->bus, desc->device, desc->pll->status),
+ BCMBCA_PMB_REG(desc->bus, desc->device,
+ desc->pll->ch01 + desc->channel / 2),
+ };
+ u32 values[ARRAY_SIZE(regs)];
+
+ ret = regmap_multi_reg_read(clock->regmap, regs, values, ARRAY_SIZE(regs));
+ if (ret)
+ return ret;
+ /* Firmware owns PLL power and reset. */
+ if (!(values[0] & PLL_LOCK))
+ return -EAGAIN;
+ /* A held output may be undergoing a firmware rate transition. */
+ if (values[1] & (PLL_CHANNEL_HOLD << shift))
+ return -EBUSY;
+ return regmap_update_bits(clock->regmap, regs[1],
+ PLL_CHANNEL_DISABLE << shift, 0);
+ }
+ case PMB_XTAL:
+ return regmap_update_bits(clock->regmap, reg, XTAL_DRIVER_POWER_DOWN, 0);
+ case PMB_PVTMON:
+ ret = regmap_read(clock->regmap, reg, &value);
+ if (ret)
+ return ret;
+ /* Preserve the divider when firmware already enabled acquisition. */
+ if (value & PVTMON_CLOCK_ENABLE)
+ return 0;
+ return regmap_update_bits(clock->regmap, reg,
+ PVTMON_CLOCK_ENABLE | PVTMON_CLOCK_DIVIDER,
+ PVTMON_CLOCK_ENABLE |
+ FIELD_PREP(PVTMON_CLOCK_DIVIDER, 5));
+ case PMB_ZONE:
+ ret = regmap_read(clock->regmap, reg, &value);
+ if (ret)
+ return ret;
+ /* Power and isolation belong to the power-domain sequencer. */
+ if (!(value & ZONE_POWER_ON) || value & ZONE_POWER_DOWN_REQUEST)
+ return -EHOSTDOWN;
+ if (!(value & ZONE_MANUAL_CONTROL))
+ return 0;
+ return regmap_update_bits(clock->regmap, reg, ZONE_CLOCK_ENABLE,
+ ZONE_CLOCK_ENABLE);
+ case PMB_RUNNER:
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int bcmbca_pmb_clock_is_prepared(struct clk_hw *hw)
+{
+ struct bcmbca_pmb_clock *clock = to_pmb_clock(hw);
+ const struct bcmbca_pmb_clock_desc *desc = clock->desc;
+ unsigned int shift = (desc->channel % 2) * 16;
+ u32 value;
+ int ret;
+
+ if (desc->type == PMB_PLL_CHANNEL) {
+ unsigned int regs[] = {
+ BCMBCA_PMB_REG(desc->bus, desc->device, desc->pll->status),
+ BCMBCA_PMB_REG(desc->bus, desc->device,
+ desc->pll->ch01 + desc->channel / 2),
+ };
+ u32 values[ARRAY_SIZE(regs)];
+
+ ret = regmap_multi_reg_read(clock->regmap, regs, values, ARRAY_SIZE(regs));
+ if (ret || !(values[0] & PLL_LOCK))
+ return 0;
+ return !(values[1] & ((PLL_CHANNEL_DISABLE | PLL_CHANNEL_HOLD) << shift));
+ }
+
+ ret = regmap_read(clock->regmap,
+ BCMBCA_PMB_REG(desc->bus, desc->device, desc->reg), &value);
+ if (ret)
+ return 0;
+
+ switch (desc->type) {
+ case PMB_XTAL:
+ return !(value & XTAL_DRIVER_POWER_DOWN);
+ case PMB_PVTMON:
+ return !!(value & PVTMON_CLOCK_ENABLE);
+ case PMB_ZONE:
+ return (value & ZONE_POWER_ON) && !(value & ZONE_POWER_DOWN_REQUEST) &&
+ (!(value & ZONE_MANUAL_CONTROL) || (value & ZONE_CLOCK_ENABLE));
+ default:
+ return 0;
+ }
+}
+
+static unsigned long bcmbca_pmb_clock_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct bcmbca_pmb_clock *clock = to_pmb_clock(hw);
+ const struct bcmbca_pmb_clock_desc *desc = clock->desc;
+ unsigned int regs[4], count = 3;
+ u32 values[4], ndiv, pdiv, channel, mdiv;
+ unsigned int shift = (desc->channel % 2) * 16;
+ u64 multiplier, rate;
+ int ret;
+
+ if (desc->type == PMB_XTAL)
+ return parent_rate;
+ /* The parent rates of these clocks are unknown. */
+ if (desc->type != PMB_PLL_CHANNEL)
+ return 0;
+
+ regs[0] = BCMBCA_PMB_REG(desc->bus, desc->device, desc->pll->ndiv);
+ regs[1] = BCMBCA_PMB_REG(desc->bus, desc->device, desc->pll->pdiv);
+ regs[2] = BCMBCA_PMB_REG(desc->bus, desc->device,
+ desc->pll->ch01 + desc->channel / 2);
+ if (desc->channel >= 2)
+ regs[count++] = BCMBCA_PMB_REG(desc->bus, desc->device, desc->pll->ch25);
+
+ ret = regmap_multi_reg_read(clock->regmap, regs, values, count);
+ if (ret) {
+ dev_err_ratelimited(clock->dev, "cannot read %s rate: %d\n", desc->name, ret);
+ return 0;
+ }
+ ndiv = values[0];
+ pdiv = values[1];
+ channel = values[2];
+ if (channel & (PLL_MDIV_OVERRIDE << shift))
+ mdiv = (channel >> shift) & 0xff;
+ else if (desc->channel < 2)
+ mdiv = (pdiv >> (16 + desc->channel * 8)) & 0xff;
+ else
+ mdiv = (values[3] >> ((desc->channel - 2) * 8)) & 0xff;
+
+ pdiv = FIELD_GET(PLL_PDIV, pdiv);
+ /* No rate can be determined from a zero divider. */
+ if (!pdiv || !mdiv)
+ return 0;
+ multiplier = ((u64)FIELD_GET(PLL_NDIV_INT, ndiv) << 20) |
+ FIELD_GET(PLL_NDIV_FRAC, ndiv);
+ rate = div64_u64((u64)parent_rate * multiplier,
+ ((u64)pdiv * mdiv) << 20);
+
+ return rate > ULONG_MAX ? 0 : rate;
+}
+
+static const struct clk_ops bcmbca_pmb_clock_ops = {
+ .prepare = bcmbca_pmb_clock_prepare,
+ .is_prepared = bcmbca_pmb_clock_is_prepared,
+ .recalc_rate = bcmbca_pmb_clock_recalc_rate,
+ /* No unprepare: these clocks can remain in use by PMC firmware. */
+};
+
+static const struct bcmbca_pmb_pll_layout bcm6846_rdppll = {
+ .ch01 = 16,
+ .status = 19,
+ .ndiv = 21,
+ .pdiv = 22,
+ .ch25 = 23,
+};
+
+/* The BIU PLL uses the classic BPCM register layout. */
+static const struct bcmbca_pmb_pll_layout bcm6846_biupll = {
+ .ch01 = 11,
+ .status = 15,
+ .ndiv = 17,
+ .pdiv = 18,
+ .ch25 = 19,
+};
+
+#define PMB_PLL(_id, _name, _device, _channel, _pll) \
+ [_id] = { .name = _name, .type = PMB_PLL_CHANNEL, .bus = 1, \
+ .device = _device, .channel = _channel, \
+ .pll = _pll }
+#define PMB_GATE(_id, _name, _type, _bus, _device, _reg) \
+ [_id] = { .name = _name, .type = _type, .bus = _bus, \
+ .device = _device, .reg = _reg }
+#define PMB_ZONE_CLK(_id, _name, _bus, _device, _zone) \
+ PMB_GATE(_id, _name, PMB_ZONE, _bus, _device, 32 + (_zone) * 8)
+
+static const struct bcmbca_pmb_clock_desc bcm6846_clocks[] = {
+ PMB_PLL(BCM6846_CLK_RDPPLL_CH0, "rdppll-ch0", 3, 0, &bcm6846_rdppll),
+ PMB_PLL(BCM6846_CLK_RDPPLL_CH1, "rdppll-ch1", 3, 1, &bcm6846_rdppll),
+ PMB_PLL(BCM6846_CLK_RDPPLL_CH2, "rdppll-ch2", 3, 2, &bcm6846_rdppll),
+ PMB_PLL(BCM6846_CLK_RDPPLL_CH3, "rdppll-ch3", 3, 3, &bcm6846_rdppll),
+ PMB_PLL(BCM6846_CLK_RDPPLL_CH4, "rdppll-ch4", 3, 4, &bcm6846_rdppll),
+ PMB_PLL(BCM6846_CLK_RDPPLL_CH5, "rdppll-ch5", 3, 5, &bcm6846_rdppll),
+ PMB_PLL(BCM6846_CLK_BIUPLL_CH0, "biupll-ch0", 38, 0, &bcm6846_biupll),
+ PMB_PLL(BCM6846_CLK_BIUPLL_CH1, "biupll-ch1", 38, 1, &bcm6846_biupll),
+ PMB_PLL(BCM6846_CLK_BIUPLL_CH2, "biupll-ch2", 38, 2, &bcm6846_biupll),
+ PMB_PLL(BCM6846_CLK_BIUPLL_CH3, "biupll-ch3", 38, 3, &bcm6846_biupll),
+ PMB_PLL(BCM6846_CLK_BIUPLL_CH4, "biupll-ch4", 38, 4, &bcm6846_biupll),
+ PMB_PLL(BCM6846_CLK_BIUPLL_CH5, "biupll-ch5", 38, 5, &bcm6846_biupll),
+ [BCM6846_CLK_RUNNER] = { .name = "runner", .type = PMB_RUNNER },
+ PMB_GATE(BCM6846_CLK_XTAL_OUT, "xtal-out", PMB_XTAL, 1, 1, XTAL_CONTROL),
+ PMB_GATE(BCM6846_CLK_PVTMON, "pvtmon", PMB_PVTMON, 1, 6, PVTMON_CONFIG),
+ PMB_ZONE_CLK(BCM6846_CLK_PERIPH_ZONE0, "periph-zone0", 0, 0, 0),
+ PMB_ZONE_CLK(BCM6846_CLK_PERIPH_ZONE1, "periph-zone1", 0, 0, 1),
+ PMB_ZONE_CLK(BCM6846_CLK_PERIPH_ZONE2, "periph-zone2", 0, 0, 2),
+ PMB_ZONE_CLK(BCM6846_CLK_PERIPH_ZONE3, "periph-zone3", 0, 0, 3),
+ PMB_ZONE_CLK(BCM6846_CLK_MEMC, "memc", 1, 8, 0),
+ PMB_ZONE_CLK(BCM6846_CLK_USB_ZONE0, "usb-zone0", 1, 10, 0),
+ PMB_ZONE_CLK(BCM6846_CLK_USB_ZONE1, "usb-zone1", 1, 10, 1),
+ PMB_ZONE_CLK(BCM6846_CLK_USB_ZONE2, "usb-zone2", 1, 10, 2),
+ PMB_ZONE_CLK(BCM6846_CLK_USB_ZONE3, "usb-zone3", 1, 10, 3),
+ PMB_ZONE_CLK(BCM6846_CLK_WAN_ZONE0, "wan-zone0", 1, 11, 0),
+ PMB_ZONE_CLK(BCM6846_CLK_WAN_ZONE1, "wan-zone1", 1, 11, 1),
+ PMB_ZONE_CLK(BCM6846_CLK_WAN_ZONE2, "wan-zone2", 1, 11, 2),
+ PMB_ZONE_CLK(BCM6846_CLK_XRDP_ZONE0, "xrdp-zone0", 1, 12, 0),
+ PMB_ZONE_CLK(BCM6846_CLK_XRDP_ZONE1, "xrdp-zone1", 1, 12, 1),
+ PMB_ZONE_CLK(BCM6846_CLK_XRDP_ZONE2, "xrdp-zone2", 1, 12, 2),
+ PMB_ZONE_CLK(BCM6846_CLK_RUNNER0, "runner0", 1, 14, 0),
+ PMB_ZONE_CLK(BCM6846_CLK_RUNNER1, "runner1", 1, 15, 0),
+ PMB_ZONE_CLK(BCM6846_CLK_RUNNER2, "runner2", 1, 16, 0),
+ PMB_ZONE_CLK(BCM6846_CLK_PCIE0, "pcie0", 0, 18, 0),
+ PMB_ZONE_CLK(BCM6846_CLK_PCIE1, "pcie1", 0, 19, 0),
+ /* BIU uses the classic BPCM layout, with its zone at word 16. */
+ PMB_GATE(BCM6846_CLK_BIU, "biu", PMB_ZONE, 1, 39, 16),
+};
+
+static int bcmbca_pmb_clock_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap = dev_get_regmap(dev->parent, NULL);
+ struct clk_hw_onecell_data *data;
+ struct bcmbca_pmb_clock *clocks;
+ struct clk *ref;
+ unsigned int i;
+ int ret;
+
+ if (!regmap)
+ return -ENODEV;
+
+ ref = devm_clk_get(dev, "ref");
+ if (IS_ERR(ref))
+ return dev_err_probe(dev, PTR_ERR(ref), "failed to get reference clock\n");
+
+ data = devm_kzalloc(dev, struct_size(data, hws, ARRAY_SIZE(bcm6846_clocks)),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ data->num = ARRAY_SIZE(bcm6846_clocks);
+ clocks = devm_kcalloc(dev, data->num, sizeof(*clocks), GFP_KERNEL);
+ if (!clocks)
+ return -ENOMEM;
+
+ for (i = 0; i < data->num; i++) {
+ const struct bcmbca_pmb_clock_desc *desc = &bcm6846_clocks[i];
+ struct clk_parent_data parent = {};
+ struct clk_init_data init = {
+ .ops = &bcmbca_pmb_clock_ops,
+ };
+
+ init.name = devm_kasprintf(dev, GFP_KERNEL, "%s-%s", dev_name(dev), desc->name);
+ if (!init.name)
+ return -ENOMEM;
+ if (desc->type == PMB_RUNNER) {
+ struct clk_hw *parent_hw = data->hws[BCM6846_CLK_RDPPLL_CH1];
+
+ data->hws[i] =
+ devm_clk_hw_register_fixed_factor_parent_hw(dev, init.name,
+ parent_hw, 0, 1, 2);
+ if (IS_ERR(data->hws[i]))
+ return PTR_ERR(data->hws[i]);
+ continue;
+ }
+ if (desc->type == PMB_PLL_CHANNEL || desc->type == PMB_XTAL) {
+ parent.hw = __clk_get_hw(ref);
+ init.parent_data = &parent;
+ init.num_parents = 1;
+ }
+ if (desc->type == PMB_PLL_CHANNEL)
+ init.flags = CLK_GET_RATE_NOCACHE;
+ clocks[i].regmap = regmap;
+ clocks[i].dev = dev;
+ clocks[i].desc = desc;
+ clocks[i].hw.init = &init;
+ ret = devm_clk_hw_register(dev, &clocks[i].hw);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register %s\n", desc->name);
+
+ data->hws[i] = &clocks[i].hw;
+ }
+
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data);
+}
+
+static const struct of_device_id bcmbca_pmb_clock_match[] = {
+ { .compatible = "brcm,bcm6846-pmb-clock" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bcmbca_pmb_clock_match);
+
+static struct platform_driver bcmbca_pmb_clock_driver = {
+ .probe = bcmbca_pmb_clock_probe,
+ .driver = {
+ .name = "bcm6846-pmb-clock",
+ .of_match_table = bcmbca_pmb_clock_match,
+ .suppress_bind_attrs = true,
+ },
+};
+module_platform_driver(bcmbca_pmb_clock_driver);
+
+MODULE_AUTHOR("Linus Walleij <linusw@kernel.org>");
+MODULE_DESCRIPTION("Broadcom BCMBCA PMB clocks");
+MODULE_LICENSE("GPL");
--
2.56.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 7/7] hwmon: Add Broadcom PMB PVTMON monitoring
2026-11-06 8:26 [PATCH v3 0/7] BCMBCA PMB power, clock, reset and hardware monitoring support Linus Walleij
` (5 preceding siblings ...)
2026-11-06 8:26 ` [PATCH v3 6/7] clk: bcm: Add BCMBCA PMB clocks Linus Walleij
@ 2026-11-06 8:26 ` Linus Walleij
6 siblings, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-06 8:26 UTC (permalink / raw)
To: Linus Walleij, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, William Zhang, Anand Gore, Kursad Oney,
Florian Fainelli, Rafał Miłecki,
Broadcom internal kernel review list, Stephen Boyd, Brian Masney,
Jerome Brunet, Guenter Roeck, Philipp Zabel, Jonathan Corbet,
Randy Dunlap, Ulf Hansson, Benjamin Larsson
Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon,
linux-pm
Expose the BCM6846 die temperature and seven voltage inputs through
hwmon using the shared Processor Monitor Bus (PMB) regmap.
Register the temperature channel with the thermal framework so
existing zero-cell device-tree thermal sensor references work.
Poll for valid samples with a bounded timeout, releasing the PMB lock
between reads. Report temperature in millidegrees Celsius, including
negative values, and voltages in millivolts.
Acked-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Documentation/hwmon/bcm_pmb_pvtmon.rst | 53 ++++++++
Documentation/hwmon/index.rst | 1 +
MAINTAINERS | 2 +
drivers/hwmon/Kconfig | 18 +++
drivers/hwmon/Makefile | 1 +
drivers/hwmon/bcm_pmb_pvtmon.c | 231 +++++++++++++++++++++++++++++++++
6 files changed, 306 insertions(+)
diff --git a/Documentation/hwmon/bcm_pmb_pvtmon.rst b/Documentation/hwmon/bcm_pmb_pvtmon.rst
new file mode 100644
index 000000000000..7dba658bdc76
--- /dev/null
+++ b/Documentation/hwmon/bcm_pmb_pvtmon.rst
@@ -0,0 +1,53 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+Kernel driver bcm_pmb_pvtmon
+============================
+
+Supported chips:
+
+ * Broadcom BCM6846 PVTMON
+
+ Access: Processor Monitor Bus (PMB), bus 1, device 6
+
+Author: Linus Walleij <linusw@kernel.org>
+
+Description
+-----------
+
+The process, voltage and temperature monitor (PVTMON) measures die
+temperature and seven voltage inputs. The driver uses the shared PMB MFD
+transport and obtains its clock and reset from the sibling providers.
+
+With CONFIG_THERMAL_OF enabled, the temperature channel also supplies
+device-tree thermal zones. The PVTMON node uses #thermal-sensor-cells = <0>;
+voltage inputs do not have thermal sensor indices.
+
+Sysfs attributes
+----------------
+
+All attributes are read-only. Temperature is reported in millidegrees
+Celsius and voltages in millivolts, using the BCM6846 vendor conversion
+formulas and input-divider ratios.
+
+================ ================================
+Attribute Description
+================ ================================
+temp1_input Die temperature
+in0_input First 0.85 V input
+in1_input Second 0.85 V input
+in2_input VIN input
+in3_input 1.0 V input
+in4_input 1.8 V input
+in5_input 3.3 V input
+in6_input Diagnostic test input
+in0_label V0.85_1
+in1_label V0.85_2
+in2_label VIN
+in3_label V1.0
+in4_label V1.8
+in5_label V3.3
+in6_label Vtest
+================ ================================
+
+Labels follow the vendor channel names. Vtest is a diagnostic ADC input,
+not a supply rail. The driver does not change the analog test routing.
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 199ca79621e9..5a579391cf9e 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -54,6 +54,7 @@ Hardware Monitoring Kernel Drivers
axiado-pwm-fan
axiado-tsadc
bcm54140
+ bcm_pmb_pvtmon
bel-pfe
bpa-rs600
cgbc-hwmon
diff --git a/MAINTAINERS b/MAINTAINERS
index 2a280ca7d162..f38003b144c5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5453,7 +5453,9 @@ F: Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
F: Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
F: Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
F: Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
+F: Documentation/hwmon/bcm_pmb_pvtmon.rst
F: drivers/clk/bcm/clk-bcmbca-pmb.c
+F: drivers/hwmon/bcm_pmb_pvtmon.c
F: drivers/mfd/bcmbca_pmc3_pmb.c
F: drivers/pmdomain/bcm/bcmbca-pmb.c
F: drivers/reset/reset-bcmbca-pmb.c
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 18c682e1a475..7e2bc32628d4 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -334,6 +334,24 @@ config SENSORS_AXIADO_TSADC
This driver can also be built as a module. If so, the module
will be called axiado-tsadc.
+config SENSORS_BCM_PMB_PVTMON
+ tristate "Broadcom PMB PVTMON hardware monitoring"
+ depends on ARCH_BCMBCA || COMPILE_TEST
+ depends on MFD_BCMBCA_PMB
+ depends on COMMON_CLK
+ depends on RESET_CONTROLLER
+ select CLK_BCMBCA_PMB
+ select RESET_BCMBCA_PMB
+ select REGMAP
+ default MFD_BCMBCA_PMB
+ help
+ Enable temperature and voltage monitoring through the Processor
+ Monitor Bus on Broadcom BCM6846. With THERMAL_OF enabled, the
+ temperature channel also supplies the thermal zones described in
+ the device tree.
+
+ This driver can also be built as a module called bcm_pmb_pvtmon.
+
config SENSORS_K8TEMP
tristate "AMD Athlon64/FX or Opteron temperature sensor"
depends on X86 && PCI
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index d4c345ed7261..edf8e8d2f345 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_AXI_FAN_CONTROL) += axi-fan-control.o
obj-$(CONFIG_SENSORS_AXIADO_PWM_FAN) += axiado-pwm-fan.o
obj-$(CONFIG_SENSORS_AXIADO_TSADC) += axiado-tsadc.o
+obj-$(CONFIG_SENSORS_BCM_PMB_PVTMON) += bcm_pmb_pvtmon.o
obj-$(CONFIG_SENSORS_CGBC) += cgbc-hwmon.o
obj-$(CONFIG_SENSORS_CHIPCAP2) += chipcap2.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
diff --git a/drivers/hwmon/bcm_pmb_pvtmon.c b/drivers/hwmon/bcm_pmb_pvtmon.c
new file mode 100644
index 000000000000..3c58e0be3251
--- /dev/null
+++ b/drivers/hwmon/bcm_pmb_pvtmon.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Broadcom BCM6846 process, voltage and temperature monitor (PVTMON).
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/hwmon.h>
+#include <linux/mfd/bcmbca-pmb.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define PVTMON_BUS 1
+#define PVTMON_DEVICE 6
+
+/* PMB register offsets are in 32-bit words. */
+#define PVTMON_CONFIG 17
+#define PVTMON_RESET_N BIT(0)
+#define PVTMON_POWER_DOWN BIT(1)
+
+#define PVTMON_ACQ_CONFIG 20
+#define PVTMON_ACCUM_ENABLE BIT(0)
+#define PVTMON_SKIP_LENGTH GENMASK(11, 8)
+
+#define PVTMON_CHANNEL_BASE 24
+#define PVTMON_NUM_CHANNELS 8
+#define PVTMON_VALUE GENMASK(9, 0)
+#define PVTMON_VALID BIT(18)
+#define PVTMON_SAMPLES GENMASK(26, 24)
+#define PVTMON_CHANNEL_ENABLE BIT(31)
+
+/* BCM6846 voltage channel labels and input-divider ratios. */
+static const struct {
+ const char *label;
+ unsigned int divisor;
+} bcm6846_pvtmon_voltages[] = {
+ { "V0.85_1", 10 },
+ { "V0.85_2", 10 },
+ { "VIN", 7 },
+ { "V1.0", 7 },
+ { "V1.8", 4 },
+ { "V3.3", 2 },
+ { "Vtest", 10 },
+};
+
+static int bcm_pmb_pvtmon_init(struct regmap *regmap,
+ struct reset_control *reset)
+{
+ unsigned int reg = BCMBCA_PMB_REG(PVTMON_BUS, PVTMON_DEVICE, PVTMON_CONFIG);
+ u32 config, acq, channel;
+ unsigned int i;
+ int ret;
+
+ ret = regmap_read(regmap, reg, &config);
+ if (ret)
+ return ret;
+
+ /* Do not reset acquisition already running for the PMC firmware. */
+ if ((config & (PVTMON_RESET_N | PVTMON_POWER_DOWN)) != PVTMON_RESET_N) {
+ ret = regmap_update_bits(regmap, reg, PVTMON_POWER_DOWN, 0);
+ if (ret)
+ return ret;
+ ret = reset_control_reset(reset);
+ if (ret)
+ return ret;
+ }
+
+ ret = regmap_read(regmap, BCMBCA_PMB_REG(PVTMON_BUS, PVTMON_DEVICE,
+ PVTMON_ACQ_CONFIG), &acq);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < PVTMON_NUM_CHANNELS; i++) {
+ reg = BCMBCA_PMB_REG(PVTMON_BUS, PVTMON_DEVICE, PVTMON_CHANNEL_BASE + i);
+ ret = regmap_read(regmap, reg, &channel);
+ if (ret)
+ return ret;
+
+ if (channel & PVTMON_CHANNEL_ENABLE)
+ continue;
+
+ /* Average 32 samples. */
+ ret = regmap_update_bits(regmap, reg, PVTMON_CHANNEL_ENABLE | PVTMON_SAMPLES,
+ PVTMON_CHANNEL_ENABLE | FIELD_PREP(PVTMON_SAMPLES, 5));
+ if (ret)
+ return ret;
+ }
+
+ if (!(acq & PVTMON_ACCUM_ENABLE))
+ return regmap_update_bits(regmap,
+ BCMBCA_PMB_REG(PVTMON_BUS, PVTMON_DEVICE,
+ PVTMON_ACQ_CONFIG),
+ PVTMON_SKIP_LENGTH | PVTMON_ACCUM_ENABLE,
+ PVTMON_ACCUM_ENABLE | FIELD_PREP(PVTMON_SKIP_LENGTH, 8));
+
+ return 0;
+}
+
+static int bcm_pmb_pvtmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct regmap *map = dev_get_drvdata(dev);
+ unsigned int index;
+ u32 value;
+ int ret;
+
+ switch (type) {
+ case hwmon_temp:
+ if (attr != hwmon_temp_input)
+ return -EOPNOTSUPP;
+ index = 0;
+ break;
+ case hwmon_in:
+ if (attr != hwmon_in_input)
+ return -EOPNOTSUPP;
+ index = channel + 1;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* Release the PMB between samples so other clients can make progress. */
+ ret = regmap_read_poll_timeout(map,
+ BCMBCA_PMB_REG(PVTMON_BUS, PVTMON_DEVICE,
+ PVTMON_CHANNEL_BASE + index),
+ value, value & PVTMON_VALID, 1000, 100000);
+ if (ret)
+ return ret;
+
+ value = FIELD_GET(PVTMON_VALUE, value);
+ if (type == hwmon_temp) {
+ /* Signed arithmetic allows temperatures below zero Celsius. */
+ *val = (41335000 - 49055 * (int)value) / 100;
+ } else {
+ /* 880 mV ADC reference, accounting for each input divider. */
+ *val = 880 * value * 10 /
+ (bcm6846_pvtmon_voltages[channel].divisor * 1024);
+ }
+
+ return 0;
+}
+
+static int bcm_pmb_pvtmon_read_string(struct device *dev,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel, const char **str)
+{
+ if (type != hwmon_in || attr != hwmon_in_label)
+ return -EOPNOTSUPP;
+
+ *str = bcm6846_pvtmon_voltages[channel].label;
+ return 0;
+}
+
+static const struct hwmon_ops bcm_pmb_pvtmon_ops = {
+ .visible = 0444,
+ .read = bcm_pmb_pvtmon_read,
+ .read_string = bcm_pmb_pvtmon_read_string,
+};
+
+static const struct hwmon_channel_info * const bcm_pmb_pvtmon_info[] = {
+ HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL),
+ NULL
+};
+
+static const struct hwmon_chip_info bcm_pmb_pvtmon_chip_info = {
+ .ops = &bcm_pmb_pvtmon_ops,
+ .info = bcm_pmb_pvtmon_info,
+};
+
+static int bcm_pmb_pvtmon_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap = dev_get_regmap(dev->parent, NULL);
+ struct device *hwmon;
+ struct reset_control *reset;
+ struct clk *clk;
+ int ret;
+
+ if (!regmap)
+ return -ENODEV;
+
+ reset = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(reset))
+ return dev_err_probe(dev, PTR_ERR(reset), "failed to get PVTMON reset\n");
+
+ clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk), "failed to enable PVTMON clock\n");
+
+ ret = bcm_pmb_pvtmon_init(regmap, reset);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to initialize PVTMON\n");
+
+ hwmon = devm_hwmon_device_register_with_info(dev, "bcm6846_pvtmon", regmap,
+ &bcm_pmb_pvtmon_chip_info, NULL);
+ if (IS_ERR(hwmon))
+ return dev_err_probe(dev, PTR_ERR(hwmon), "failed to register hwmon device\n");
+
+ /* Acquisition remains enabled for the PMC firmware after unbinding. */
+ return 0;
+}
+
+static const struct of_device_id bcm_pmb_pvtmon_of_match[] = {
+ { .compatible = "brcm,bcm6846-pmb-pvtmon" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bcm_pmb_pvtmon_of_match);
+
+static struct platform_driver bcm_pmb_pvtmon_driver = {
+ .probe = bcm_pmb_pvtmon_probe,
+ .driver = {
+ .name = "bcm6846-pmb-pvtmon",
+ .of_match_table = bcm_pmb_pvtmon_of_match,
+ },
+};
+module_platform_driver(bcm_pmb_pvtmon_driver);
+
+MODULE_AUTHOR("Linus Walleij <linusw@kernel.org>");
+MODULE_DESCRIPTION("Broadcom PMB PVTMON hardware monitoring driver");
+MODULE_LICENSE("GPL");
--
2.56.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v3 5/7] reset: Add BCMBCA block resets through the PMB
2026-11-06 8:26 ` [PATCH v3 5/7] reset: Add BCMBCA block resets through the PMB Linus Walleij
@ 2026-11-06 8:35 ` sashiko-bot
2026-11-06 11:59 ` Philipp Zabel
1 sibling, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-06 8:35 UTC (permalink / raw)
To: Linus Walleij
Cc: mfd, devicetree, linux-clk, linux-hwmon, robh, conor+dt, lee
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Low] reset: bcmbca-pmb: redundant reset callback in
bcmbca_pmb_reset_group
--
commit cb99ec1412a9c3107e489e88034ee115dfafb214
Author: Linus Walleij <linusw@kernel.org>
reset: Add BCMBCA block resets through the PMB
This commit adds a reset controller driver for Broadcom BCMBCA blocks
controlled through the PMC3 Processor Monitor Bus regmap, implementing
the BCM6846 XRDP reset group and PVTMON acquisition reset.
> diff --git a/drivers/reset/reset-bcmbca-pmb.c b/drivers/reset/reset-bcmbca-pmb.c
> new file mode 100644
> index 0000000000000..e8e079c9ccb56
> --- /dev/null
> +++ b/drivers/reset/reset-bcmbca-pmb.c
> @@ -0,0 +1,243 @@
[ ... ]
> +struct bcmbca_pmb_reset;
> +
> +struct bcmbca_pmb_reset_group {
> + const char *name;
> + int (*reset)(struct bcmbca_pmb_reset *rst,
> + const struct bcmbca_pmb_reset_group *group);
> + const struct bcmbca_pmb_reset_block *blocks;
> + unsigned int num_blocks;
> + /* Minimum reset assertion hold time in microseconds. */
> + unsigned int assert_hold_us;
> +};
[ ... ]
> +static const struct bcmbca_pmb_reset_group bcm6846_pmb_reset_groups[] = {
> + [BCM6846_RESET_XRDP] = {
> + .name = "XRDP",
> + .reset = bcmbca_pmb_reset_sequence,
> + .blocks = bcm6846_xrdp_resets,
> + .num_blocks = ARRAY_SIZE(bcm6846_xrdp_resets),
> + .assert_hold_us = 10,
> + },
> + [BCM6846_RESET_PVTMON] = {
> + .name = "PVTMON",
> + .reset = bcmbca_pmb_reset_sequence,
> + .blocks = &bcm6846_pvtmon_reset,
> + .num_blocks = 1,
> + .assert_hold_us = 1000,
> + },
> +};
[ ... ]
> +static int bcmbca_pmb_reset(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> + struct bcmbca_pmb_reset *rst = container_of(rcdev, struct bcmbca_pmb_reset, rcdev);
> + const struct bcmbca_pmb_reset_group *group;
> +
> + if (id >= rst->variant->num_groups)
> + return -EINVAL;
> + group = &rst->variant->groups[id];
> + if (!group->reset)
> + return -EINVAL;
> +
> + guard(mutex)(&rst->lock);
> + return group->reset(rst, group);
> +}
[Severity: Low]
As reported by Philipp Zabel on RFC [1], is the reset callback pointer in
struct bcmbca_pmb_reset_group still needed now that XRDP zone power
transitions live in the PMB power domain driver?
Every entry in bcm6846_pmb_reset_groups[] sets .reset to
bcmbca_pmb_reset_sequence, so bcmbca_pmb_reset() could call
bcmbca_pmb_reset_sequence(rst, group) directly and drop the callback field
along with the forward declarations of struct bcmbca_pmb_reset and
bcmbca_pmb_reset_sequence().
[1] https://lore.kernel.org/r/90c5efa22600044657e67b9e1297bda2fb53f60c.camel@pengutronix.de
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261106-xg6846b-bcmbca-xrdp-reset-v3-0-d6adeb71afc9@kernel.org?part=5
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex
2026-11-06 8:26 ` [PATCH v3 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
@ 2026-11-06 8:36 ` sashiko-bot
2026-11-06 12:57 ` Rob Herring (Arm)
1 sibling, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-06 8:36 UTC (permalink / raw)
To: Linus Walleij
Cc: mfd, devicetree, linux-clk, linux-hwmon, robh, conor+dt, lee
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Low] dt-bindings: mfd: brcm,bcm6846-pmc references files added in
next patch
- [Low] dt-bindings: mfd: brcm,bcm6846-pmc example child nodes out of
name order
- [Low] dt-bindings: mfd: brcm,bcm6846-pmc expands PMB as Processor
Monitor Bus
--
commit 843b048574d4c45f386b5f401c61ae92d14a122f
Author: Linus Walleij <linusw@kernel.org>
dt-bindings: mfd: Describe the BCM6846 PMC complex
This commit adds a Device Tree binding schema for the Broadcom BCM6846
third generation Power Management Controller (PMC3) complex.
> diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> new file mode 100644
> index 0000000000000..d4c927cabb3f4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> @@ -0,0 +1,82 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/brcm,bcm6846-pmc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Broadcom BCM6846 Power Management Controller
> +
> +maintainers:
> + - Linus Walleij <linusw@kernel.org>
> +
> +description:
> + The third generation Power Management Controller (PMC3) contains several
> + register banks. This binding describes the Processor Monitor Bus (PMB)
> + interface within Procmon. The PMB child owns its register bank. The parent
> + provides address translation and does not own a register bank.
[Severity: Low]
As reported by William Zhang on v2 [1], should PMB be expanded as Power
Management Bus instead of Processor Monitor Bus here and in the example
comment below, matching Documentation/devicetree/bindings/power/brcm,bcm-pmb.yaml?
> +
> +properties:
> + compatible:
> + items:
> + - const: brcm,bcm6846-pmc
> + - const: simple-mfd
> +
> + ranges:
> + maxItems: 1
> +
> + "#address-cells":
> + const: 1
> +
> + "#size-cells":
> + const: 1
> +
> +patternProperties:
> + '^bus@[0-9a-f]+$':
> + $ref: /schemas/soc/bcm/brcm,bcm6846-pmb.yaml#
> + description: PMB configuration, keyhole and address mapping registers
> +
> +required:
> + - compatible
> + - ranges
> + - '#address-cells'
> + - '#size-cells'
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/brcm,bcm6846-pmb.h>
> + #include <dt-bindings/reset/brcm,bcm6846-pmb.h>
[Severity: Low]
As reported by Krzysztof Kozlowski on RFC [2], does make dt_binding_check
fail at this commit because /schemas/soc/bcm/brcm,bcm6846-pmb.yaml#, the
dt-bindings/clock/brcm,bcm6846-pmb.h and dt-bindings/reset/brcm,bcm6846-pmb.h
headers, and the child node bindings used in the example are not introduced
until the next patch in the series, commit "dt-bindings: soc: Describe the
BCM6846 Processor Monitor Bus"? Ordering that patch before this one would
keep dt_binding_check bisectable across the series.
> +
> + system-controller@ffb00000 {
> + /* Broadcom BCM6846 Power Management Controller complex */
> + compatible = "brcm,bcm6846-pmc", "simple-mfd";
> + ranges = <0x0 0xffb00000 0x21000>;
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + /* Processor Monitor Bus */
> + bus@20100 {
> + compatible = "brcm,bcm6846-pmb";
> + reg = <0x20100 0x200>;
> +
> + pmb_clk: clock-controller {
> + compatible = "brcm,bcm6846-pmb-clock";
> + clocks = <&osc50m>;
> + clock-names = "ref";
> + #clock-cells = <1>;
> + };
> +
> + pmb_reset: reset-controller {
> + compatible = "brcm,bcm6846-pmb-reset";
> + #reset-cells = <1>;
> + };
> +
> + hwmon {
> + compatible = "brcm,bcm6846-pmb-pvtmon";
> + clocks = <&pmb_clk BCM6846_CLK_PVTMON>;
> + resets = <&pmb_reset BCM6846_RESET_PVTMON>;
> + #thermal-sensor-cells = <0>;
> + };
[Severity: Low]
Should the hwmon node be placed before reset-controller so that the child
nodes without unit addresses under bus@20100 are ordered alphabetically by
node name? Otherwise scripts/dtc/dt-check-style --mode=strict warns that
child node hwmon is out of name order.
[1] https://lore.kernel.org/r/CAHi4H7GOMM9K6XG15vPyFMLOza3QQ7QPxUkCi85jA_e9D6YbKg@mail.gmail.com
[2] https://lore.kernel.org/r/ddfe83b7-d4b8-4d56-a295-fde63519bdde@kernel.org
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261106-xg6846b-bcmbca-xrdp-reset-v3-0-d6adeb71afc9@kernel.org?part=1
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 3/7] mfd: bcmbca-pmb: Add a shared BCMBCA PMC3 PMB transport
2026-11-06 8:26 ` [PATCH v3 3/7] mfd: bcmbca-pmb: Add a shared BCMBCA PMC3 PMB transport Linus Walleij
@ 2026-11-06 8:39 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-06 8:39 UTC (permalink / raw)
To: Linus Walleij
Cc: mfd, devicetree, linux-clk, linux-hwmon, robh, conor+dt, lee
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] mfd: bcmbca_pmc3_pmb: debugfs stall, WARN_ON, and HW read in
regmap init
--
commit df29cb4d33202540fcf38b25c63a3a8cd862dcfb
Author: Linus Walleij <linusw@kernel.org>
mfd: bcmbca-pmb: Add a shared BCMBCA PMC3 PMB transport
This commit adds an MFD driver for the Broadcom BCMBCA PMC3 Processor
Monitor Bus (PMB) that exposes a shared uncached regmap to child devices.
> diff --git a/drivers/mfd/bcmbca_pmc3_pmb.c b/drivers/mfd/bcmbca_pmc3_pmb.c
> new file mode 100644
> index 0000000000000..8ebcbc26a502d
> --- /dev/null
> +++ b/drivers/mfd/bcmbca_pmc3_pmb.c
[ ... ]
> +static bool bcmbca_pmb_precious_reg(struct device *dev, unsigned int reg)
> +{
> + /* Do not let debugfs probe unimplemented or firmware-owned registers. */
> + return true;
> +}
> +
> +static struct regmap *bcmbca_pmb_regmap_init(struct bcmbca_pmb *pmb)
> +{
> + const struct regmap_config config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 1,
> + .max_register = BCMBCA_PMB_REG(3, 255, 65535),
> + .cache_type = REGCACHE_NONE,
> + .precious_reg = bcmbca_pmb_precious_reg,
[Severity: Medium]
Does marking every register precious in bcmbca_pmb_precious_reg() while
setting max_register to BCMBCA_PMB_REG(3, 255, 65535) (0x03ffffff) with
reg_stride = 1 cause a 67M-iteration stall, a WARN_ON(), and an unintended
hardware read when the regmap debugfs files are read?
When the debugfs "registers" or "range" file is read,
regmap_debugfs_get_dump_start() scans all 67,108,864 addresses from 0 to
map->max_register under map->cache_lock. Because regmap_printable() is
false for every address, map->debugfs_off_cache stays empty,
WARN_ON(list_empty(&map->debugfs_off_cache)) fires on every read, and
regmap_debugfs_get_dump_start() returns base (0). regmap_read_debugfs()
then starts its loop at start_reg (0) without checking regmap_printable()
on the first iteration and calls regmap_read(map, 0, &val), issuing a
hardware PMB read to BCMBCA_PMB_REG(0, 0, 0).
In addition, because neither readable_reg nor writeable_reg is set, reading
the debugfs "access" file causes regmap_access_show() to format all
67,108,864 addresses into a single_open() seq_file buffer until a >1 GiB
allocation fails with -ENOMEM.
Omitting max_register and precious_reg from config (leaving max_register
at 0 without max_register_is_0) avoids creating the debugfs "registers",
"range", and "access" files while bcmbca_pmb_op() continues to validate
the bus and offset bounds.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261106-xg6846b-bcmbca-xrdp-reset-v3-0-d6adeb71afc9@kernel.org?part=3
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus
2026-11-06 8:26 ` [PATCH v3 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus Linus Walleij
@ 2026-11-06 8:43 ` sashiko-bot
2026-11-06 17:03 ` William Zhang
1 sibling, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-06 8:43 UTC (permalink / raw)
To: Linus Walleij
Cc: mfd, devicetree, linux-clk, linux-hwmon, robh, conor+dt, lee
Thank you for your contribution! Sashiko AI review found 5 potential
issues to consider:
- [Low] dt-bindings: hwmon: brcm,bcm6846-pmb-pvtmon uses
additionalProperties with $ref
- [Low] dt-bindings: soc: brcm,bcm6846-pmb ordered after dependent
brcm,bcm6846-pmc
- [Low] dt-bindings: soc: brcm,bcm6846-pmb examples violate
dt-check-style strict rules
- [Low] dt-bindings: soc: bcm: driver-model child nodes in
brcm,bcm6846-pmb
- [Low] dt-bindings: soc: bcm6846-pmb: expand PMB as Power Management
Bus
--
commit 6ce40c3812dd052e5e8e3945888002592aa196c2
Author: Linus Walleij <linusw@kernel.org>
dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus
This commit adds Device Tree binding schemas and header constants for the
Broadcom BCM6846 Processor Monitor Bus (PMB) and its clock, hwmon, power,
and reset child controllers.
> diff --git a/Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml b/Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
> new file mode 100644
> index 0000000000000..9bf52cf097a32
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
> @@ -0,0 +1,42 @@
[ ... ]
> +allOf:
> + - $ref: /schemas/thermal/thermal-sensor.yaml#
> +
> +properties:
> + compatible:
> + const: brcm,bcm6846-pmb-pvtmon
> +
> + clocks:
> + maxItems: 1
> + description: PVTMON acquisition clock
> +
> + resets:
> + maxItems: 1
> + description: PVTMON analog-acquisition reset
> +
> + '#thermal-sensor-cells':
> + const: 0
> +
> +required:
> + - compatible
> + - clocks
> + - resets
> + - '#thermal-sensor-cells'
> +
> +additionalProperties: false
[Severity: Low]
Should this schema use unevaluatedProperties: false instead of
additionalProperties: false? Because it references
/schemas/thermal/thermal-sensor.yaml# via allOf, additionalProperties: false
prevents properties defined only in the referenced schema from being
evaluated cleanly.
> diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> index d4c927cabb3f4..77fbf92926ab3 100644
> --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> @@ -60,6 +60,11 @@ examples:
> compatible = "brcm,bcm6846-pmb";
> reg = <0x20100 0x200>;
>
> + pmb_power: power-controller {
> + compatible = "brcm,bcm6846-pmb-power";
> + #power-domain-cells = <1>;
> + };
> +
> pmb_clk: clock-controller {
> compatible = "brcm,bcm6846-pmb-clock";
> clocks = <&osc50m>;
[Severity: Low]
Should this commit be ordered before commit "dt-bindings: mfd: Describe the
BCM6846 PMC complex"?
That earlier commit introduces brcm,bcm6846-pmc.yaml referencing
/schemas/soc/bcm/brcm,bcm6846-pmb.yaml# and including
dt-bindings/clock/brcm,bcm6846-pmb.h and
dt-bindings/reset/brcm,bcm6846-pmb.h before this commit adds them, which
breaks make dt_binding_check bisectability at the parent commit. In
addition, the commit message here still states that it describes the PMC and
only mentions the power controller child, omitting the clock, reset, and
PVTMON schemas and headers introduced in this patch.
> diff --git a/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
> new file mode 100644
> index 0000000000000..134a8a676dbd0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
> @@ -0,0 +1,90 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/soc/bcm/brcm,bcm6846-pmb.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Broadcom BCM6846 Processor Monitor Bus
> +
> +maintainers:
> + - Linus Walleij <linusw@kernel.org>
> +
> +description:
> + The Processor Monitor Bus (PMB) connects the third generation Power
> + Management Controller (PMC3) to the control registers of miscellaneous
> + independent hardware blocks.
[Severity: Low]
As reported by William Zhang on v2 [1], PMB stands for Power Management Bus
rather than Processor Monitor Bus. The commit subject, commit message, and
all five new binding schemas in this patch still expand PMB as Processor
Monitor Bus.
[ ... ]
> + power-controller:
> + type: object
> + $ref: /schemas/power/brcm,bcm6846-pmb-power.yaml#
> +
> + clock-controller:
> + type: object
> + $ref: /schemas/clock/brcm,bcm6846-pmb-clock.yaml#
> +
> + reset-controller:
> + type: object
> + $ref: /schemas/reset/brcm,bcm6846-pmb-reset.yaml#
> +
> + hwmon:
> + type: object
> + $ref: /schemas/hwmon/brcm,bcm6846-pmb-pvtmon.yaml#
[Severity: Low]
As reported by Philipp Zabel on RFC [2], should #power-domain-cells,
#clock-cells, #reset-cells, #thermal-sensor-cells, and the reference clock
live directly on the brcm,bcm6846-pmb node instead of using four addressless
child nodes?
Neither power-controller nor reset-controller has any DT resources of its
own, and the power, clock, reset, and hwmon drivers all access shared 32-bit
BPCM zone control and PVTMON_CONFIG registers over the parent PMB keyhole
interface. Folding the provider cells into the brcm,bcm6846-pmb node avoids
encoding the Linux MFD sub-driver split into the Device Tree ABI while still
allowing the MFD driver to instantiate child devices internally.
[ ... ]
> + pmb_power: power-controller {
> + compatible = "brcm,bcm6846-pmb-power";
> + #power-domain-cells = <1>;
> + };
> +
> + pmb_clk: clock-controller {
> + compatible = "brcm,bcm6846-pmb-clock";
> + clocks = <&osc50m>;
> + clock-names = "ref";
> + #clock-cells = <1>;
> + };
> +
> + pmb_reset: reset-controller {
> + compatible = "brcm,bcm6846-pmb-reset";
> + #reset-cells = <1>;
> + };
> +
> + hwmon {
> + compatible = "brcm,bcm6846-pmb-pvtmon";
> + clocks = <&pmb_clk BCM6846_CLK_PVTMON>;
> + resets = <&pmb_reset BCM6846_RESET_PVTMON>;
> + #thermal-sensor-cells = <0>;
> + };
> + };
[Severity: Low]
Does this example (and the matching example in brcm,bcm6846-pmc.yaml) trigger
unused-labels and child-name-order warnings under scripts/dtc/dt-check-style
--mode=strict? The pmb_power label is never referenced in the example, and
the unaddressed child nodes under the PMB node are not in alphabetical order
(clock-controller, hwmon, power-controller, reset-controller).
[1] https://lore.kernel.org/r/CAHi4H7GOMM9K6XG15vPyFMLOza3QQ7QPxUkCi85jA_e9D6YbKg@mail.gmail.com
[2] https://lore.kernel.org/r/f1c24a603964302ec1462b1cea790a2a7079fb3d.camel@pengutronix.de
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261106-xg6846b-bcmbca-xrdp-reset-v3-0-d6adeb71afc9@kernel.org?part=2
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 5/7] reset: Add BCMBCA block resets through the PMB
2026-11-06 8:26 ` [PATCH v3 5/7] reset: Add BCMBCA block resets through the PMB Linus Walleij
2026-11-06 8:35 ` sashiko-bot
@ 2026-11-06 11:59 ` Philipp Zabel
1 sibling, 0 replies; 15+ messages in thread
From: Philipp Zabel @ 2026-11-06 11:59 UTC (permalink / raw)
To: Linus Walleij, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, William Zhang, Anand Gore, Kursad Oney,
Florian Fainelli, Rafał Miłecki,
Broadcom internal kernel review list, Stephen Boyd, Brian Masney,
Jerome Brunet, Guenter Roeck, Jonathan Corbet, Randy Dunlap,
Ulf Hansson, Benjamin Larsson
Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon,
linux-pm
On Fr, 2026-11-06 at 09:26 +0100, Linus Walleij wrote:
> Implement the BCM6846 XRDP reset group through the shared PMB regmap.
> Assert all blocks before releasing any of them, preserving the vendor
> reset masks and ordering. Provide the independent PVTMON acquisition
> reset as well. Serialize complete sequences and hold blocks in reset
> on failure.
>
> Power domain consumers must enable their domains before requesting a
> reset.
Before requesting or before (de)asserting?
> Zone transitions belong to the PMB power domain subdriver.
Why mention it here?
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> MAINTAINERS | 1 +
> drivers/reset/Kconfig | 13 +++
> drivers/reset/Makefile | 1 +
> drivers/reset/reset-bcmbca-pmb.c | 243 +++++++++++++++++++++++++++++++++++++++
> 4 files changed, 258 insertions(+)
>
[...]
> diff --git a/drivers/reset/reset-bcmbca-pmb.c b/drivers/reset/reset-bcmbca-pmb.c
> new file mode 100644
> index 000000000000..e8e079c9ccb5
> --- /dev/null
> +++ b/drivers/reset/reset-bcmbca-pmb.c
> @@ -0,0 +1,243 @@
[...]
> +struct bcmbca_pmb_reset_group {
> + const char *name;
> + int (*reset)(struct bcmbca_pmb_reset *rst,
> + const struct bcmbca_pmb_reset_group *group);
This is again an unnecessary indirection.
[...]
> +static int bcmbca_pmb_reset_sequence(struct bcmbca_pmb_reset *rst,
> + const struct bcmbca_pmb_reset_group *group)
> +{
> + const struct bcmbca_pmb_reset_block *block;
> + enum {
> + PASS_ASSERT,
> + PASS_DEASSERT,
> + } pass;
> + unsigned int i;
> + int ret;
> +
> + if (!group->num_blocks)
> + return -EINVAL;
> +
> + /* Assert every block before releasing any of them. */
> + for (pass = PASS_ASSERT; pass <= PASS_DEASSERT; pass++) {
> + for (i = 0; i < group->num_blocks; i++) {
> + block = &group->blocks[i];
> + ret = regmap_update_bits(rst->regmap,
> + BCMBCA_PMB_REG(block->bus, block->device,
> + block->offset), block->mask,
> + pass == PASS_DEASSERT ? block->deassert_value :
> + block->assert_value);
> + if (ret)
> + goto cleanup;
> + }
> + if (pass == PASS_ASSERT && group->assert_hold_us)
> + usleep_range(group->assert_hold_us, group->assert_hold_us * 2);
> + }
> +cleanup:
> + if (ret) {
> + dev_err(rst->rcdev.dev, "%s %s failed at PMB bus %u device %u: %d\n",
> + group->name, str_assert_deassert(pass == PASS_ASSERT),
> + block->bus, block->device, ret);
> + bcmbca_pmb_reset_cleanup(rst, group);
> + }
> + return ret;
> +}
> +
> +static int bcmbca_pmb_reset(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> + struct bcmbca_pmb_reset *rst = container_of(rcdev, struct bcmbca_pmb_reset, rcdev);
> + const struct bcmbca_pmb_reset_group *group;
> +
> + if (id >= rst->variant->num_groups)
> + return -EINVAL;
Since .nr_resets is set to rst->variant->num_groups, this was already
checked by fwnode_reset_simple_xlate() before the reset controller was
created.
> + group = &rst->variant->groups[id];
> + if (!group->reset)
> + return -EINVAL;
> +
> + guard(mutex)(&rst->lock);
> + return group->reset(rst, group);
Call bcmbca_pmb_reset_sequence() directly or fold it in here.
> +}
> +
> +static const struct reset_control_ops bcmbca_pmb_reset_ops = {
> + .reset = bcmbca_pmb_reset,
> +};
> +
> +static int bcmbca_pmb_reset_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct regmap *regmap = dev_get_regmap(dev->parent, NULL);
> + struct bcmbca_pmb_reset *rst;
> +
> + if (!regmap)
> + return -ENODEV;
> +
> + rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
> + if (!rst)
> + return -ENOMEM;
> + rst->variant = device_get_match_data(dev);
> + if (!rst->variant)
> + return -ENODEV;
> + rst->regmap = regmap;
> + mutex_init(&rst->lock);
> + rst->rcdev.owner = THIS_MODULE;
> + rst->rcdev.dev = dev;
> + rst->rcdev.ops = &bcmbca_pmb_reset_ops;
> + rst->rcdev.of_node = dev->of_node;
> + rst->rcdev.of_reset_n_cells = 1;
Do not set of_reset_n_cells, .of_xlate isn't set either.
reset_controller_register() sets .fwnode_xlate =
fwnode_reset_simple_xlate() and fwnode_reset_n_cells = 1 by default,
of_reset_n_cells will be ignored in this case.
> + rst->rcdev.nr_resets = rst->variant->num_groups;
> + return devm_reset_controller_register(dev, &rst->rcdev);
> +}
> +
> +static const struct of_device_id bcmbca_pmb_reset_of_match[] = {
> + { .compatible = "brcm,bcm6846-pmb-reset", .data = &bcm6846_pmb_variant },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, bcmbca_pmb_reset_of_match);
> +
> +static struct platform_driver bcmbca_pmb_reset_driver = {
> + .probe = bcmbca_pmb_reset_probe,
> + .driver = {
> + .name = "brcm-pmb-reset",
> + .of_match_table = bcmbca_pmb_reset_of_match,
> + .suppress_bind_attrs = true,
This is new. Why?
regards
Philipp
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex
2026-11-06 8:26 ` [PATCH v3 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
2026-11-06 8:36 ` sashiko-bot
@ 2026-11-06 12:57 ` Rob Herring (Arm)
1 sibling, 0 replies; 15+ messages in thread
From: Rob Herring (Arm) @ 2026-11-06 12:57 UTC (permalink / raw)
To: Linus Walleij
Cc: linux-arm-kernel, Benjamin Larsson, Krzysztof Kozlowski,
Philipp Zabel, linux-clk, Jonathan Corbet, Anand Gore,
Florian Fainelli, devicetree,
Broadcom internal kernel review list, Stephen Boyd, Kursad Oney,
Rafał Miłecki, Randy Dunlap, linux-pm, Guenter Roeck,
Lee Jones, Ulf Hansson, William Zhang, linux-hwmon, mfd,
Brian Masney, Conor Dooley, Jerome Brunet
On Fri, 06 Nov 2026 09:26:44 +0100, Linus Walleij wrote:
> The third generation Power Management Controller (PMC3) has
> different subdevices.
>
> Identify the parent with the BCM6846-specific "brcm,bcm6846-pmc"
> compatible.
>
> Describe the complex as a simple-mfd with a PMB bus child owning its
> register resource. Include the PMB clock and reset controllers and
> PVTMON, with its acquisition clock and reset resources.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> .../devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml | 82 ++++++++++++++++++++++
> MAINTAINERS | 5 ++
> 2 files changed, 87 insertions(+)
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml: Unresolvable reference: /schemas/soc/bcm/brcm,bcm6846-pmb.yaml#
Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.example.dts:18:18: fatal error: dt-bindings/clock/brcm,bcm6846-pmb.h: No such file or directory
18 | #include <dt-bindings/clock/brcm,bcm6846-pmb.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [scripts/Makefile.dtbs:140: Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/linux-dt-review/Makefile:1726: dt_binding_check] Error 2
make: *** [Makefile:248: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.kernel.org/project/devicetree/patch/20261106-xg6846b-bcmbca-xrdp-reset-v3-1-d6adeb71afc9@kernel.org
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus
2026-11-06 8:26 ` [PATCH v3 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus Linus Walleij
2026-11-06 8:43 ` sashiko-bot
@ 2026-11-06 17:03 ` William Zhang
1 sibling, 0 replies; 15+ messages in thread
From: William Zhang @ 2026-11-06 17:03 UTC (permalink / raw)
To: Linus Walleij
Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Anand Gore, Kursad Oney, Florian Fainelli,
Rafał Miłecki, Broadcom internal kernel review list,
Stephen Boyd, Brian Masney, Jerome Brunet, Guenter Roeck,
Philipp Zabel, Jonathan Corbet, Randy Dunlap, Ulf Hansson,
Benjamin Larsson, mfd, devicetree, linux-arm-kernel, linux-clk,
linux-hwmon, linux-pm
[-- Attachment #1: Type: text/plain, Size: 15729 bytes --]
On Fri, Nov 6, 2026 at 12:27 AM Linus Walleij <linusw@kernel.org> wrote:
>
> The third generation Power Management Controller (PMC3) accesses SoC
> block control and reset registers through the Processor Monitor Bus
Power Management Bus. Need to update all the instances in this patch series.
> (PMB). Describe the BCM6846 PMC and PMB.
>
> Describe the power controller child and all supported power domain IDs,
> including the combined XRDP, Runner and WAN domain.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> I considered even just using the PMB but the PMC has more stuff and
> it seems natural to let it live in a simple-mfd node.
> ---
> .../bindings/clock/brcm,bcm6846-pmb-clock.yaml | 39 ++++++++++
> .../bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml | 42 ++++++++++
> .../devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml | 5 ++
> .../bindings/power/brcm,bcm6846-pmb-power.yaml | 44 +++++++++++
> .../bindings/reset/brcm,bcm6846-pmb-reset.yaml | 31 ++++++++
> .../bindings/soc/bcm/brcm,bcm6846-pmb.yaml | 90 ++++++++++++++++++++++
> MAINTAINERS | 8 ++
> include/dt-bindings/clock/brcm,bcm6846-pmb.h | 42 ++++++++++
> include/dt-bindings/power/brcm,bcm6846-pmb.h | 12 +++
> include/dt-bindings/reset/brcm,bcm6846-pmb.h | 11 +++
> 10 files changed, 324 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm6846-pmb-clock.yaml b/Documentation/devicetree/bindings/clock/brcm,bcm6846-pmb-clock.yaml
> new file mode 100644
> index 000000000000..519606522c8b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/brcm,bcm6846-pmb-clock.yaml
> @@ -0,0 +1,39 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/brcm,bcm6846-pmb-clock.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Broadcom BCM6846 PMB clocks
> +
> +maintainers:
> + - Linus Walleij <linusw@kernel.org>
> +
> +description:
> + The Processor Monitor Bus (PMB) provides access to the RDP and BIU PLL
> + outputs, the Runner clock, the crystal output, the PVTMON acquisition
> + clock and the clock gates in block power-control zones. Clock indices
> + are defined in dt-bindings/clock/brcm,bcm6846-pmb.h.
> + The PLLs and crystal output use a 50 MHz reference clock.
> + Zone clocks require their associated blocks to be powered.
> +
> +properties:
> + compatible:
> + const: brcm,bcm6846-pmb-clock
> +
> + clocks:
> + maxItems: 1
> +
> + clock-names:
> + const: ref
> +
> + '#clock-cells':
> + const: 1
> +
> +required:
> + - compatible
> + - clocks
> + - clock-names
> + - '#clock-cells'
> +
> +additionalProperties: false
> diff --git a/Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml b/Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
> new file mode 100644
> index 000000000000..9bf52cf097a3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
> @@ -0,0 +1,42 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/hwmon/brcm,bcm6846-pmb-pvtmon.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Broadcom BCM6846 PMB process, voltage and temperature monitor
> +
> +maintainers:
> + - Linus Walleij <linusw@kernel.org>
> +
> +description:
> + The process, voltage and temperature monitor (PVTMON) is a child of
> + the Processor Monitor Bus (PMB) controller and uses its indirect
> + register interface. It measures die temperature and seven voltages,
> + including a diagnostic test input.
> +
> +allOf:
> + - $ref: /schemas/thermal/thermal-sensor.yaml#
> +
> +properties:
> + compatible:
> + const: brcm,bcm6846-pmb-pvtmon
> +
> + clocks:
> + maxItems: 1
> + description: PVTMON acquisition clock
> +
> + resets:
> + maxItems: 1
> + description: PVTMON analog-acquisition reset
> +
> + '#thermal-sensor-cells':
> + const: 0
> +
> +required:
> + - compatible
> + - clocks
> + - resets
> + - '#thermal-sensor-cells'
> +
> +additionalProperties: false
> diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> index d4c927cabb3f..77fbf92926ab 100644
> --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> @@ -60,6 +60,11 @@ examples:
> compatible = "brcm,bcm6846-pmb";
> reg = <0x20100 0x200>;
>
> + pmb_power: power-controller {
> + compatible = "brcm,bcm6846-pmb-power";
> + #power-domain-cells = <1>;
> + };
> +
> pmb_clk: clock-controller {
> compatible = "brcm,bcm6846-pmb-clock";
> clocks = <&osc50m>;
> diff --git a/Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml b/Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
> new file mode 100644
> index 000000000000..891eb0f347e6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
> @@ -0,0 +1,44 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/power/brcm,bcm6846-pmb-power.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Broadcom BCM6846 Processor Monitor Bus power controller
> +
> +maintainers:
> + - Linus Walleij <linusw@kernel.org>
> +
> +description: |
> + The power controller is a child of the Processor Monitor Bus (PMB)
> + controller and accesses BPCM power zones through the parent regmap.
> + A domain includes all power zones of a block. The XRDP domain groups
> + XRDP, its three Runner cores and WAN, matching the vendor power sequence.
> +
> + Domain IDs are defined in dt-bindings/power/brcm,bcm6846-pmb.h:
> + BCM6846_PD_PERIPH: peripheral block (bus 0, device 0, four zones)
> + BCM6846_PD_MEMC: memory controller (bus 1, device 8, one zone)
> + BCM6846_PD_USB20: USB 2.0 (bus 1, device 10, four zones)
> + BCM6846_PD_XRDP: XRDP (bus 1, device 12, three zones), Runner cores
> + (bus 1, devices 14, 15 and 16, one zone each) and WAN
> + (bus 1, device 11, three zones)
> + BCM6846_PD_PCIE0: PCIe 0 (bus 0, device 18, one zone)
> + BCM6846_PD_PCIE1: PCIe 1 (bus 0, device 19, one zone)
> +
> + Peripheral and memory domains remain powered because they provide
> + resources required for system operation. CPU and PLL blocks use different
> + register layouts and are outside the scope of this provider.
> +
> +properties:
> + compatible:
> + const: brcm,bcm6846-pmb-power
> +
> + '#power-domain-cells':
> + const: 1
> + description: Power domain ID from dt-bindings/power/brcm,bcm6846-pmb.h
> +
> +required:
> + - compatible
> + - '#power-domain-cells'
> +
> +additionalProperties: false
> diff --git a/Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml b/Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
> new file mode 100644
> index 000000000000..d2a85266e36a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
> @@ -0,0 +1,31 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/reset/brcm,bcm6846-pmb-reset.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Broadcom BCM6846 Processor Monitor Bus reset controller
> +
> +maintainers:
> + - Linus Walleij <linusw@kernel.org>
> +
> +description:
> + The reset controller is a child of the Processor Monitor Bus (PMB)
> + controller and uses its indirect register interface.
> +
> + Each reset specifier identifies a logical reset group, which may span
> + several blocks that must be reset together.
> +
> +properties:
> + compatible:
> + const: brcm,bcm6846-pmb-reset
> +
> + '#reset-cells':
> + const: 1
> + description: Reset group ID from dt-bindings/reset/brcm,bcm6846-pmb.h
> +
> +required:
> + - compatible
> + - '#reset-cells'
> +
> +additionalProperties: false
> diff --git a/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
> new file mode 100644
> index 000000000000..134a8a676dbd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
> @@ -0,0 +1,90 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/soc/bcm/brcm,bcm6846-pmb.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Broadcom BCM6846 Processor Monitor Bus
> +
> +maintainers:
> + - Linus Walleij <linusw@kernel.org>
> +
> +description:
> + The Processor Monitor Bus (PMB) connects the third generation Power
> + Management Controller (PMC3) to the control registers of miscellaneous
> + independent hardware blocks.
> +
> + The controller provides configuration, arbitration and four keyhole
> + interfaces for indirect register access.
> +
> + Child nodes describe independent hardware blocks accessed over the PMB.
> + These provide global resources and even resources for each other.
> +
> +properties:
> + compatible:
> + const: brcm,bcm6846-pmb
> +
> + reg:
> + maxItems: 1
> + description: PMB configuration, keyhole and address mapping registers
> +
> + power-controller:
> + type: object
> + $ref: /schemas/power/brcm,bcm6846-pmb-power.yaml#
> +
> + clock-controller:
> + type: object
> + $ref: /schemas/clock/brcm,bcm6846-pmb-clock.yaml#
> +
> + reset-controller:
> + type: object
> + $ref: /schemas/reset/brcm,bcm6846-pmb-reset.yaml#
> +
> + hwmon:
> + type: object
> + $ref: /schemas/hwmon/brcm,bcm6846-pmb-pvtmon.yaml#
> +
> +required:
> + - compatible
> + - reg
> + - power-controller
> + - clock-controller
> + - reset-controller
> + - hwmon
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/brcm,bcm6846-pmb.h>
> + #include <dt-bindings/reset/brcm,bcm6846-pmb.h>
> +
> + /* Processor Monitor Bus */
> + bus@ffb20100 {
> + compatible = "brcm,bcm6846-pmb";
> + reg = <0xffb20100 0x200>;
> +
> + pmb_power: power-controller {
> + compatible = "brcm,bcm6846-pmb-power";
> + #power-domain-cells = <1>;
> + };
> +
> + pmb_clk: clock-controller {
> + compatible = "brcm,bcm6846-pmb-clock";
> + clocks = <&osc50m>;
> + clock-names = "ref";
> + #clock-cells = <1>;
> + };
> +
> + pmb_reset: reset-controller {
> + compatible = "brcm,bcm6846-pmb-reset";
> + #reset-cells = <1>;
> + };
> +
> + hwmon {
> + compatible = "brcm,bcm6846-pmb-pvtmon";
> + clocks = <&pmb_clk BCM6846_CLK_PVTMON>;
> + resets = <&pmb_reset BCM6846_RESET_PVTMON>;
> + #thermal-sensor-cells = <0>;
> + };
> + };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f14f9910911c..e11fc5064dc5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5447,7 +5447,15 @@ N: bcm[9]?6878
> BROADCOM BCMBCA PMC3 PMB DRIVER
> M: Linus Walleij <linusw@kernel.org>
> S: Maintained
> +F: Documentation/devicetree/bindings/clock/brcm,bcm6846-pmb-clock.yaml
> +F: Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
> F: Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> +F: Documentation/devicetree/bindings/power/brcm,bcm6846-pmb-power.yaml
> +F: Documentation/devicetree/bindings/reset/brcm,bcm6846-pmb-reset.yaml
> +F: Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
> +F: include/dt-bindings/clock/brcm,bcm6846-pmb.h
> +F: include/dt-bindings/power/brcm,bcm6846-pmb.h
> +F: include/dt-bindings/reset/brcm,bcm6846-pmb.h
>
> BROADCOM BDC DRIVER
> M: Justin Chen <justin.chen@broadcom.com>
> diff --git a/include/dt-bindings/clock/brcm,bcm6846-pmb.h b/include/dt-bindings/clock/brcm,bcm6846-pmb.h
> new file mode 100644
> index 000000000000..548a18ed7959
> --- /dev/null
> +++ b/include/dt-bindings/clock/brcm,bcm6846-pmb.h
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +#ifndef _DT_BINDINGS_CLOCK_BRCM_BCM6846_PMB_H
> +#define _DT_BINDINGS_CLOCK_BRCM_BCM6846_PMB_H
> +
> +#define BCM6846_CLK_RDPPLL_CH0 0
> +#define BCM6846_CLK_RDPPLL_CH1 1
> +#define BCM6846_CLK_RDPPLL_CH2 2
> +#define BCM6846_CLK_RDPPLL_CH3 3
> +#define BCM6846_CLK_RDPPLL_CH4 4
> +#define BCM6846_CLK_RDPPLL_CH5 5
> +#define BCM6846_CLK_BIUPLL_CH0 6
> +#define BCM6846_CLK_BIUPLL_CH1 7
> +#define BCM6846_CLK_BIUPLL_CH2 8
> +#define BCM6846_CLK_BIUPLL_CH3 9
> +#define BCM6846_CLK_BIUPLL_CH4 10
> +#define BCM6846_CLK_BIUPLL_CH5 11
> +#define BCM6846_CLK_RUNNER 12
> +#define BCM6846_CLK_XTAL_OUT 13
> +#define BCM6846_CLK_PVTMON 14
> +#define BCM6846_CLK_PERIPH_ZONE0 15
> +#define BCM6846_CLK_PERIPH_ZONE1 16
> +#define BCM6846_CLK_PERIPH_ZONE2 17
> +#define BCM6846_CLK_PERIPH_ZONE3 18
> +#define BCM6846_CLK_MEMC 19
> +#define BCM6846_CLK_USB_ZONE0 20
> +#define BCM6846_CLK_USB_ZONE1 21
> +#define BCM6846_CLK_USB_ZONE2 22
> +#define BCM6846_CLK_USB_ZONE3 23
> +#define BCM6846_CLK_WAN_ZONE0 24
> +#define BCM6846_CLK_WAN_ZONE1 25
> +#define BCM6846_CLK_WAN_ZONE2 26
> +#define BCM6846_CLK_XRDP_ZONE0 27
> +#define BCM6846_CLK_XRDP_ZONE1 28
> +#define BCM6846_CLK_XRDP_ZONE2 29
> +#define BCM6846_CLK_RUNNER0 30
> +#define BCM6846_CLK_RUNNER1 31
> +#define BCM6846_CLK_RUNNER2 32
> +#define BCM6846_CLK_PCIE0 33
> +#define BCM6846_CLK_PCIE1 34
> +#define BCM6846_CLK_BIU 35
> +
> +#endif
> diff --git a/include/dt-bindings/power/brcm,bcm6846-pmb.h b/include/dt-bindings/power/brcm,bcm6846-pmb.h
> new file mode 100644
> index 000000000000..abdd01c94bc5
> --- /dev/null
> +++ b/include/dt-bindings/power/brcm,bcm6846-pmb.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +#ifndef _DT_BINDINGS_POWER_BCM6846_PMB_H
> +#define _DT_BINDINGS_POWER_BCM6846_PMB_H
> +
> +#define BCM6846_PD_PERIPH 0
> +#define BCM6846_PD_MEMC 1
> +#define BCM6846_PD_USB20 2
> +#define BCM6846_PD_XRDP 3
> +#define BCM6846_PD_PCIE0 4
> +#define BCM6846_PD_PCIE1 5
> +
> +#endif
> diff --git a/include/dt-bindings/reset/brcm,bcm6846-pmb.h b/include/dt-bindings/reset/brcm,bcm6846-pmb.h
> new file mode 100644
> index 000000000000..ce68adb10108
> --- /dev/null
> +++ b/include/dt-bindings/reset/brcm,bcm6846-pmb.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +#ifndef _DT_BINDINGS_RESET_BRCM_BCM6846_PMB_H
> +#define _DT_BINDINGS_RESET_BRCM_BCM6846_PMB_H
> +
> +/* XRDP packet engine and its three Runner cores. */
> +#define BCM6846_RESET_XRDP 0
> +
> +/* Process, voltage and temperature monitor analog acquisition reset. */
> +#define BCM6846_RESET_PVTMON 1
> +
> +#endif
>
> --
> 2.56.0
>
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5473 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-11-06 17:03 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-06 8:26 [PATCH v3 0/7] BCMBCA PMB power, clock, reset and hardware monitoring support Linus Walleij
2026-11-06 8:26 ` [PATCH v3 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
2026-11-06 8:36 ` sashiko-bot
2026-11-06 12:57 ` Rob Herring (Arm)
2026-11-06 8:26 ` [PATCH v3 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus Linus Walleij
2026-11-06 8:43 ` sashiko-bot
2026-11-06 17:03 ` William Zhang
2026-11-06 8:26 ` [PATCH v3 3/7] mfd: bcmbca-pmb: Add a shared BCMBCA PMC3 PMB transport Linus Walleij
2026-11-06 8:39 ` sashiko-bot
2026-11-06 8:26 ` [PATCH v3 4/7] pmdomain: bcm: Add BCMBCA PMB power domains Linus Walleij
2026-11-06 8:26 ` [PATCH v3 5/7] reset: Add BCMBCA block resets through the PMB Linus Walleij
2026-11-06 8:35 ` sashiko-bot
2026-11-06 11:59 ` Philipp Zabel
2026-11-06 8:26 ` [PATCH v3 6/7] clk: bcm: Add BCMBCA PMB clocks Linus Walleij
2026-11-06 8:26 ` [PATCH v3 7/7] hwmon: Add Broadcom PMB PVTMON monitoring Linus Walleij
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox