Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support
@ 2026-11-01 22:14 Linus Walleij
  2026-11-01 22:14 ` [PATCH v2 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-01 22:14 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, Benjamin Larsson
  Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

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 clock, reset and hwmon
providers.

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. All patches except the last one (DTS file)
to be queued in MFD.

The patches were authored with the assistance of an LLM.

Signed-off-by: Linus Walleij <linusw@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 give PVTMON clock and reset resources.
- Add PVTMON hwmon support for temperature and all seven voltage inputs,
  retaining the zero-cell thermal sensor through the hwmon bridge.
- Add a separate BCM6846 clocks and monitoring DTS patch.
- 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: Add a shared BCMBCA PMC3 PMB transport
      reset: Add BCMBCA block resets through the PMB
      clk: bcm: Add BCMBCA PMB clocks
      hwmon: Add Broadcom PMB PVTMON monitoring
      ARM: dts: broadcom: Add BCM6846 PMB clocks and hardware monitoring

 .../bindings/clock/brcm,bcm6846-pmb-clock.yaml     |  39 +++
 .../bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml    |  42 +++
 .../devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml  |  82 +++++
 .../bindings/reset/brcm,bcm6846-pmb-reset.yaml     |  31 ++
 .../bindings/soc/bcm/brcm,bcm6846-pmb.yaml         |  80 +++++
 Documentation/hwmon/bcm_pmb_pvtmon.rst             |  53 +++
 Documentation/hwmon/index.rst                      |   1 +
 MAINTAINERS                                        |  16 +
 arch/arm/boot/dts/broadcom/bcm6846.dtsi            |  47 +++
 drivers/clk/bcm/Kconfig                            |  11 +
 drivers/clk/bcm/Makefile                           |   1 +
 drivers/clk/bcm/clk-bcmbca-pmb.c                   | 389 +++++++++++++++++++++
 drivers/hwmon/Kconfig                              |  18 +
 drivers/hwmon/Makefile                             |   1 +
 drivers/hwmon/bcm_pmb_pvtmon.c                     | 232 ++++++++++++
 drivers/mfd/Kconfig                                |  11 +
 drivers/mfd/Makefile                               |   1 +
 drivers/mfd/bcmbca_pmc3_pmb.c                      | 297 ++++++++++++++++
 drivers/reset/Kconfig                              |  13 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-bcmbca-pmb.c                   | 309 ++++++++++++++++
 include/dt-bindings/clock/brcm,bcm6846-pmb.h       |  42 +++
 include/dt-bindings/reset/brcm,bcm6846-pmb.h       |  11 +
 include/linux/mfd/bcmbca-pmb.h                     |  11 +
 24 files changed, 1739 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 v2 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex
  2026-11-01 22:14 [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support Linus Walleij
@ 2026-11-01 22:14 ` Linus Walleij
  2026-11-01 22:24   ` sashiko-bot
  2026-11-01 22:14 ` [PATCH v2 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus Linus Walleij
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Linus Walleij @ 2026-11-01 22:14 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, Benjamin Larsson
  Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

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                                        |  4 ++
 2 files changed, 86 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..78aef68bc318
--- /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>;
+
+        /* Called PMB Processor Monitor Bus in vendor tree */
+        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..eb4b3b631e82 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5444,6 +5444,10 @@ N:	bcm[9]?6856
 N:	bcm[9]?6858
 N:	bcm[9]?6878
 
+BROADCOM BCMBCA PMC3 PMB DRIVER
+M:	Linus Walleij <linusw@kernel.org>
+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 v2 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus
  2026-11-01 22:14 [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support Linus Walleij
  2026-11-01 22:14 ` [PATCH v2 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
@ 2026-11-01 22:14 ` Linus Walleij
  2026-11-01 22:32   ` sashiko-bot
  2026-11-01 22:14 ` [PATCH v2 3/7] mfd: Add a shared BCMBCA PMC3 PMB transport Linus Walleij
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Linus Walleij @ 2026-11-01 22:14 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, Benjamin Larsson
  Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

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.

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 ++++++++++++
 .../bindings/reset/brcm,bcm6846-pmb-reset.yaml     | 31 +++++++++
 .../bindings/soc/bcm/brcm,bcm6846-pmb.yaml         | 80 ++++++++++++++++++++++
 MAINTAINERS                                        |  6 ++
 include/dt-bindings/clock/brcm,bcm6846-pmb.h       | 42 ++++++++++++
 include/dt-bindings/reset/brcm,bcm6846-pmb.h       | 11 +++
 7 files changed, 251 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/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..a4a77fed94d0
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
@@ -0,0 +1,80 @@
+# 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
+
+  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
+  - clock-controller
+  - reset-controller
+  - hwmon
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/brcm,bcm6846-pmb.h>
+    #include <dt-bindings/reset/brcm,bcm6846-pmb.h>
+
+    /* Called PMB Processor Monitor Bus in vendor tree */
+    bus@ffb20100 {
+        compatible = "brcm,bcm6846-pmb";
+        reg = <0xffb20100 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 eb4b3b631e82..fa95f2dec63c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5446,7 +5446,13 @@ N:	bcm[9]?6878
 
 BROADCOM BCMBCA PMC3 PMB DRIVER
 M:	Linus Walleij <linusw@kernel.org>
+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/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/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/reset/brcm,bcm6846-pmb.h b/include/dt-bindings/reset/brcm,bcm6846-pmb.h
new file mode 100644
index 000000000000..6b1a6baac1c6
--- /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	3
+
+#endif

-- 
2.56.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/7] mfd: Add a shared BCMBCA PMC3 PMB transport
  2026-11-01 22:14 [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support Linus Walleij
  2026-11-01 22:14 ` [PATCH v2 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
  2026-11-01 22:14 ` [PATCH v2 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus Linus Walleij
@ 2026-11-01 22:14 ` Linus Walleij
  2026-11-01 22:31   ` sashiko-bot
  2026-11-01 22:14 ` [PATCH v2 4/7] reset: Add BCMBCA block resets through the PMB Linus Walleij
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Linus Walleij @ 2026-11-01 22:14 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, Benjamin Larsson
  Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

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  | 297 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/bcmbca-pmb.h |  11 ++
 5 files changed, 322 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index fa95f2dec63c..18e32cc036b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5451,8 +5451,10 @@ F:	Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
 F:	Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.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/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..837143409ce9
--- /dev/null
+++ b/drivers/mfd/bcmbca_pmc3_pmb.c
@@ -0,0 +1,297 @@
+// 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/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/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/property.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;
+	struct regmap *regmap;
+	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;
+};
+
+struct bcmbca_pmb_data {
+	const struct mfd_cell *cells;
+	unsigned int num_cells;
+};
+
+static void bcmbca_pmb_recover(struct work_struct *work)
+{
+	struct bcmbca_pmb *pmb = container_of(to_delayed_work(work),
+					   struct bcmbca_pmb, recovery);
+
+	mutex_lock(&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;
+		}
+	}
+	mutex_unlock(&pmb->lock);
+}
+
+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;
+
+	mutex_lock(&pmb->lock);
+	pmb->stopping = true;
+	mutex_unlock(&pmb->lock);
+	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 int bcmbca_pmb_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct bcmbca_pmb_data *data = device_get_match_data(dev);
+	struct bcmbca_pmb *pmb;
+	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;
+	platform_set_drvdata(pdev, pmb);
+	pmb->regmap = bcmbca_pmb_regmap_init(pmb);
+	if (IS_ERR(pmb->regmap))
+		return dev_err_probe(dev, PTR_ERR(pmb->regmap), "failed to register PMB regmap\n");
+	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, data->cells,
+				   data->num_cells, NULL, 0, NULL);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to register PMB functions\n");
+
+	return 0;
+}
+
+static const struct mfd_cell bcm6846_pmb_cells[] = {
+	{
+		.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 const struct bcmbca_pmb_data bcm6846_pmb_data = {
+	.cells = bcm6846_pmb_cells,
+	.num_cells = ARRAY_SIZE(bcm6846_pmb_cells),
+};
+
+static const struct of_device_id bcmbca_pmb_match[] = {
+	{ .compatible = "brcm,bcm6846-pmb", .data = &bcm6846_pmb_data },
+	{ }
+};
+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 v2 4/7] reset: Add BCMBCA block resets through the PMB
  2026-11-01 22:14 [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support Linus Walleij
                   ` (2 preceding siblings ...)
  2026-11-01 22:14 ` [PATCH v2 3/7] mfd: Add a shared BCMBCA PMC3 PMB transport Linus Walleij
@ 2026-11-01 22:14 ` Linus Walleij
  2026-11-01 22:14 ` [PATCH v2 5/7] clk: bcm: Add BCMBCA PMB clocks Linus Walleij
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-01 22:14 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, Benjamin Larsson
  Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

Support BCM6846 XRDP and PVTMON resets through the Processor Monitor
Bus (PMB) of the third generation Power Management Controller (PMC3).

The sequence is hardware-tested in the XG6846B OpenWrt port.

Power-cycle resets for USB2, WAN, PERIPH, MEMC, BIU and BIU PLL were
considered but left out. These belong in power-domain and platform
power-management abstractions, which can coordinate affected users.

Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 MAINTAINERS                      |   1 +
 drivers/reset/Kconfig            |  13 ++
 drivers/reset/Makefile           |   1 +
 drivers/reset/reset-bcmbca-pmb.c | 309 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 324 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 18e32cc036b5..29ec1c9d617e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5452,6 +5452,7 @@ F:	Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.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/reset/reset-bcmbca-pmb.c
 F:	include/dt-bindings/clock/brcm,bcm6846-pmb.h
 F:	include/dt-bindings/reset/brcm,bcm6846-pmb.h
 F:	include/linux/mfd/bcmbca-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..532398032fa8
--- /dev/null
+++ b/drivers/reset/reset-bcmbca-pmb.c
@@ -0,0 +1,309 @@
+// 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/delay.h>
+#include <linux/mfd/bcmbca-pmb.h>
+#include <linux/mod_devicetable.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 <dt-bindings/reset/brcm,bcm6846-pmb.h>
+
+/* BCM6846 BPCM zone control, in PMB words (6846/BPCM.h). */
+#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_ON		BIT(26)
+
+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 int bcm6846_xrdp_reset(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, matching the vendor sequence. */
+		.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 = bcm6846_xrdp_reset,
+		.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, pass == PASS_DEASSERT ? "deassert" : "assert",
+			block->bus, block->device, ret);
+		bcmbca_pmb_reset_cleanup(rst, group);
+	}
+	return ret;
+}
+
+/* The boot loader may power down the Runners before entering Linux. */
+static int bcm6846_power_on_zone(struct bcmbca_pmb_reset *rst, u8 device, u8 zone)
+{
+	unsigned int reg = BCMBCA_PMB_REG(1, device, BCM6846_ZONE_CONTROL(zone));
+	u32 value, mask;
+	int ret;
+
+	ret = regmap_read(rst->regmap, reg, &value);
+	if (ret)
+		return ret;
+	if ((value & BCM6846_ZONE_POWER_ON) && !(value & BCM6846_ZONE_POWER_DOWN))
+		return 0;
+
+	/* Match PowerOnZone() in the BCM6846 vendor PMC driver. */
+	mask = BCM6846_ZONE_POWER_DOWN | BCM6846_ZONE_DPG_EN |
+	       BCM6846_ZONE_POWER_UP | BCM6846_ZONE_MEM_POWER | BCM6846_ZONE_RESET;
+	ret = regmap_write_bits(rst->regmap, reg, mask, mask & ~BCM6846_ZONE_POWER_DOWN);
+	if (ret)
+		return ret;
+
+	return regmap_read_poll_timeout(rst->regmap, reg, value,
+					value & BCM6846_ZONE_POWER_ON, 10, 10000);
+}
+
+static int bcm6846_xrdp_reset(struct bcmbca_pmb_reset *rst,
+			      const struct bcmbca_pmb_reset_group *group)
+{
+	/* BCM6846 pmc_addr.h: XRDP, three Runners, then WAN (no WAN reset). */
+	static const struct {
+		u8 device;
+		u8 zones;
+	} power[] = {
+		{ 12, 3 }, { 14, 1 }, { 15, 1 }, { 16, 1 }, { 11, 3 },
+	};
+	unsigned int i, zone;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(power); i++) {
+		for (zone = 0; zone < power[i].zones; zone++) {
+			ret = bcm6846_power_on_zone(rst, power[i].device, zone);
+			if (ret) {
+				dev_err(rst->rcdev.dev,
+					"XRDP power-up failed at PMB bus 1 device %u zone %u: %d\n",
+					power[i].device, zone, ret);
+				bcmbca_pmb_reset_cleanup(rst, group);
+				return ret;
+			}
+		}
+	}
+
+	return bcmbca_pmb_reset_sequence(rst, group);
+}
+
+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;
+	int ret;
+
+	if (id >= rst->variant->num_groups)
+		return -EINVAL;
+	group = &rst->variant->groups[id];
+	if (!group->reset)
+		return -EINVAL;
+
+	mutex_lock(&rst->lock);
+	ret = group->reset(rst, group);
+	mutex_unlock(&rst->lock);
+	return ret;
+}
+
+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,
+	},
+};
+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 v2 5/7] clk: bcm: Add BCMBCA PMB clocks
  2026-11-01 22:14 [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support Linus Walleij
                   ` (3 preceding siblings ...)
  2026-11-01 22:14 ` [PATCH v2 4/7] reset: Add BCMBCA block resets through the PMB Linus Walleij
@ 2026-11-01 22:14 ` Linus Walleij
  2026-11-01 22:14 ` [PATCH v2 6/7] hwmon: Add Broadcom PMB PVTMON monitoring Linus Walleij
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-01 22:14 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, Benjamin Larsson
  Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

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 | 389 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 402 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 29ec1c9d617e..74f0783d512f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5451,6 +5451,7 @@ F:	Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
 F:	Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.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/reset/reset-bcmbca-pmb.c
 F:	include/dt-bindings/clock/brcm,bcm6846-pmb.h
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..41acab23688a
--- /dev/null
+++ b/drivers/clk/bcm/clk-bcmbca-pmb.c
@@ -0,0 +1,389 @@
+// 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/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.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 vendor sources do not identify these clocks' parent rates. */
+	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,
+			.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED,
+		};
+
+		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];
+			struct clk_hw *runner;
+
+			runner = devm_clk_hw_register_fixed_factor_parent_hw(dev,
+									     init.name, parent_hw,
+									     init.flags, 1, 2);
+			data->hws[i] = runner;
+			if (IS_ERR(data->hws[i]))
+				return PTR_ERR(data->hws[i]);
+			continue;
+		}
+		if (desc->type == PMB_PLL_CHANNEL || desc->type == PMB_XTAL) {
+			parent.fw_name = "ref";
+			init.parent_data = &parent;
+			init.num_parents = 1;
+		}
+		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,
+	},
+};
+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 v2 6/7] hwmon: Add Broadcom PMB PVTMON monitoring
  2026-11-01 22:14 [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support Linus Walleij
                   ` (4 preceding siblings ...)
  2026-11-01 22:14 ` [PATCH v2 5/7] clk: bcm: Add BCMBCA PMB clocks Linus Walleij
@ 2026-11-01 22:14 ` Linus Walleij
  2026-11-02  3:05   ` Guenter Roeck
  2026-11-01 22:14 ` [PATCH v2 7/7] ARM: dts: broadcom: Add BCM6846 PMB clocks and hardware monitoring Linus Walleij
  2026-11-02  4:32 ` [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support William Zhang
  7 siblings, 1 reply; 15+ messages in thread
From: Linus Walleij @ 2026-11-01 22:14 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, Benjamin Larsson
  Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

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.

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         | 232 +++++++++++++++++++++++++++++++++
 6 files changed, 307 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 74f0783d512f..124d67ea1582 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5451,7 +5451,9 @@ F:	Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
 F:	Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.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/reset/reset-bcmbca-pmb.c
 F:	include/dt-bindings/clock/brcm,bcm6846-pmb.h
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..8b95dac83994
--- /dev/null
+++ b/drivers/hwmon/bcm_pmb_pvtmon.c
@@ -0,0 +1,232 @@
+// 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/mod_devicetable.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)
+
+/* Voltage labels and divider ratios follow the BCM6846 vendor definitions. */
+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, matching the vendor acquisition setup. */
+		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

* [PATCH v2 7/7] ARM: dts: broadcom: Add BCM6846 PMB clocks and hardware monitoring
  2026-11-01 22:14 [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support Linus Walleij
                   ` (5 preceding siblings ...)
  2026-11-01 22:14 ` [PATCH v2 6/7] hwmon: Add Broadcom PMB PVTMON monitoring Linus Walleij
@ 2026-11-01 22:14 ` Linus Walleij
  2026-11-02  4:32 ` [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support William Zhang
  7 siblings, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-01 22:14 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, Benjamin Larsson
  Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

Describe the PMC complex and its PMB interface, including clock, reset
and hwmon child nodes. Supply the PMB clock controller with
its 50 MHz reference and connect PVTMON to its clock and reset
resources. Add a SoC thermal zone referencing the sensor child with a
one-second polling interval.

Leave trip points and cooling maps unspecified because the available
BCM6846 documentation does not establish suitable temperature limits.

Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 arch/arm/boot/dts/broadcom/bcm6846.dtsi | 47 +++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/arch/arm/boot/dts/broadcom/bcm6846.dtsi b/arch/arm/boot/dts/broadcom/bcm6846.dtsi
index 47f177323c18..e9775dfc5d1b 100644
--- a/arch/arm/boot/dts/broadcom/bcm6846.dtsi
+++ b/arch/arm/boot/dts/broadcom/bcm6846.dtsi
@@ -3,8 +3,10 @@
  * Copyright 2022 Broadcom Ltd.
  */
 
+#include <dt-bindings/clock/brcm,bcm6846-pmb.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/reset/brcm,bcm6846-pmb.h>
 
 / {
 	compatible = "brcm,bcm6846", "brcm,bcmbca";
@@ -57,6 +59,12 @@ pmu: pmu {
 	};
 
 	clocks: clocks {
+		osc50m: clock-50mhz {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <50000000>;
+		};
+
 		periph_clk: periph-clk {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
@@ -75,6 +83,14 @@ psci {
 		method = "smc";
 	};
 
+	thermal-zones {
+		soc_thermal: soc-thermal {
+			polling-delay-passive = <1000>;
+			polling-delay = <1000>;
+			thermal-sensors = <&pvtmon>;
+		};
+	};
+
 	axi@81000000 {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -263,5 +279,36 @@ pl081_dma: dma-controller@59000 {
 			clock-names = "apb_pclk";
 			#dma-cells = <2>;
 		};
+
+		pmc: system-controller@300000 {
+			compatible = "brcm,bcm6846-pmc", "simple-mfd";
+			ranges = <0x0 0x300000 0x21000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			pmb: 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>;
+				};
+
+				pvtmon: hwmon {
+					compatible = "brcm,bcm6846-pmb-pvtmon";
+					clocks = <&pmb_clk BCM6846_CLK_PVTMON>;
+					resets = <&pmb_reset BCM6846_RESET_PVTMON>;
+					#thermal-sensor-cells = <0>;
+				};
+			};
+		};
 	};
 };

-- 
2.56.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex
  2026-11-01 22:14 ` [PATCH v2 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
@ 2026-11-01 22:24   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-01 22:24 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 issue(s) 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] MAINTAINERS: missing S: status field in BROADCOM BCMBCA PMC3 PMB DRIVER
--

commit 39aa42d4e944629fc1763b294af564d34ce88b86
Author: Linus Walleij <linusw@kernel.org>

dt-bindings: mfd: Describe the BCM6846 PMC complex

This commit adds the Device Tree binding schema for the Broadcom BCM6846
Power Management Controller (PMC3) complex and adds a corresponding
entry in MAINTAINERS.

> 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..78aef68bc3183
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml
> @@ -0,0 +1,82 @@

[ ... ]

> +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 [1], does running
make dt_binding_check fail at this commit because patternProperties
references /schemas/soc/bcm/brcm,bcm6846-pmb.yaml# and the example
includes dt-bindings/clock/brcm,bcm6846-pmb.h and
dt-bindings/reset/brcm,bcm6846-pmb.h before they exist in the tree?

Those headers, the referenced schema, and the child compatibles
(brcm,bcm6846-pmb, brcm,bcm6846-pmb-clock, brcm,bcm6846-pmb-reset, and
brcm,bcm6846-pmb-pvtmon) are only introduced in the subsequent patch,
commit 44e16c21f8b2 ("dt-bindings: soc: Describe the BCM6846 Processor
Monitor Bus"). Should that patch be ordered before this one so that
schema validation and example compilation succeed at every commit in 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>;
> +
> +        /* Called PMB Processor Monitor Bus in vendor tree */
> +        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";

[Severity: Low]
Should the hwmon node be placed before pmb_reset: reset-controller in
the bus@20100 example node?

For child nodes without unit addresses, DTS coding style requires
alpha-numerical ordering by node name, and check_child_name_order() in
scripts/dtc/dt-check-style --mode=strict warns when hwmon appears after
reset-controller.

> diff --git a/MAINTAINERS b/MAINTAINERS
> index 93abbb315065d..eb4b3b631e82c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5444,6 +5444,10 @@ N:	bcm[9]?6856
>  N:	bcm[9]?6858
>  N:	bcm[9]?6878
>  
> +BROADCOM BCMBCA PMC3 PMB DRIVER
> +M:	Linus Walleij <linusw@kernel.org>
> +F:	Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml

[Severity: Low]
Is this new MAINTAINERS entry missing an S: status line (such as
S: Maintained)? Without it, scripts/get_maintainer.pl
--self-test=sections reports a section without status warning.

[1] https://lore.kernel.org/r/ddfe83b7-d4b8-4d56-a295-fde63519bdde@kernel.org

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261101-xg6846b-bcmbca-xrdp-reset-v2-0-455fe9eed5ee@kernel.org?part=1

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/7] mfd: Add a shared BCMBCA PMC3 PMB transport
  2026-11-01 22:14 ` [PATCH v2 3/7] mfd: Add a shared BCMBCA PMC3 PMB transport Linus Walleij
@ 2026-11-01 22:31   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-01 22:31 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 2 potential issue(s) to consider:
- [Medium] mfd: bcmbca_pmc3_pmb: debugfs stall, WARN_ON, and HW read in bcmbca_pmb_regmap_init()
- [Low] mfd: bcmbca_pmc3_pmb: mfd_cell match data and unused drvdata in bcmbca_pmb_probe()
--

commit cbd0d7381d66545c4a7f2cd3781134426406ab49
Author: Linus Walleij <linusw@kernel.org>

mfd: Add a shared BCMBCA PMC3 PMB transport

This commit adds an MFD driver for the Broadcom BCMBCA third generation Power
Management Controller (PMC3) Processor Monitor Bus (PMB) on BCM6846, exposing
a shared regmap to child devices while managing hardware keyhole semaphore
locking and recovery.

>     mfd: Add a shared BCMBCA PMC3 PMB transport
>
>     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>

> diff --git a/drivers/mfd/bcmbca_pmc3_pmb.c b/drivers/mfd/bcmbca_pmc3_pmb.c
> new file mode 100644
> index 0000000000000..837143409ce9c
> --- /dev/null
> +++ b/drivers/mfd/bcmbca_pmc3_pmb.c
[ ... ]
> +struct bcmbca_pmb_data {
> +	const struct mfd_cell *cells;
> +	unsigned int num_cells;
> +};
[ ... ]
> +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);
> +}

[Severity: Medium]
What happens when CONFIG_DEBUG_FS is enabled and a user reads the regmap
debugfs files (/sys/kernel/debug/regmap/<dev>/registers, range, or access)
with max_register set to BCMBCA_PMB_REG(3, 255, 65535) (0x03ffffff) and
bcmbca_pmb_precious_reg() returning true for all registers?

Because config.max_register is non-zero and readable_reg is unset,
regmap_debugfs_init() creates the registers, range, and access files.

When reading the registers or range file, regmap_debugfs_get_dump_start()
scans from 0 to 0x03ffffff (67,108,864 iterations) under map->cache_lock.
Because every register is marked precious, regmap_printable() returns false
for every address, leaving map->debugfs_off_cache empty and triggering a
WARN_ON on every read:

drivers/base/regmap/regmap-debugfs.c:regmap_debugfs_get_dump_start()
	WARN_ON(list_empty(&map->debugfs_off_cache));
	ret = base;

Furthermore, regmap_debugfs_get_dump_start() then returns base (0) to
regmap_read_debugfs(), which enters its loop at start_reg = 0 without checking
regmap_printable(map, start_reg) and performs a hardware PMB read of register
0 (bus 0, device 0, offset 0) on the first iteration:

drivers/base/regmap/regmap-debugfs.c:regmap_read_debugfs()
	for (i = start_reg; i >= 0 && i <= to;
	     i = regmap_next_readable_reg(map, i)) {
		...
		ret = regmap_read(map, i, &val);

Similarly, reading the access debugfs file causes regmap_access_show() to
iterate over all 67,108,864 addresses and call seq_printf() for each one,
repeatedly doubling the seq_file buffer until kvzalloc() fails with -ENOMEM.

Should max_register be left unset in bcmbca_pmb_regmap_init() (removing the
need for bcmbca_pmb_precious_reg()) so regmap_debugfs_init() does not create
the registers, range, and access debugfs files for this sparse 26-bit address
space?

[ ... ]
> +static int bcmbca_pmb_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	const struct bcmbca_pmb_data *data = device_get_match_data(dev);
[ ... ]
> +	platform_set_drvdata(pdev, pmb);
> +	pmb->regmap = bcmbca_pmb_regmap_init(pmb);
> +	if (IS_ERR(pmb->regmap))
> +		return dev_err_probe(dev, PTR_ERR(pmb->regmap), "failed to register PMB regmap\n");
> +	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, data->cells,
> +				   data->num_cells, NULL, 0, NULL);
> +	if (ret)
> +		return dev_err_probe(dev, ret,
> +				     "failed to register PMB functions\n");
> +
> +	return 0;
> +}
> +
> +static const struct mfd_cell bcm6846_pmb_cells[] = {
> +	{
> +		.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 const struct bcmbca_pmb_data bcm6846_pmb_data = {
> +	.cells = bcm6846_pmb_cells,
> +	.num_cells = ARRAY_SIZE(bcm6846_pmb_cells),
> +};
> +
> +static const struct of_device_id bcmbca_pmb_match[] = {
> +	{ .compatible = "brcm,bcm6846-pmb", .data = &bcm6846_pmb_data },
> +	{ }
> +};

[Severity: Low]
This isn't a bug, but in MFD drivers, passing mfd_cell arrays through the
.data field of struct of_device_id is discouraged in favor of either passing
bcm6846_pmb_cells and ARRAY_SIZE(bcm6846_pmb_cells) directly to
devm_mfd_add_devices() while only one compatible is matched, or storing a
device ID enum in .data and selecting the static const mfd_cell array with a
switch in bcmbca_pmb_probe().

Also, are platform_set_drvdata(pdev, pmb) and struct bcmbca_pmb::regmap needed
in bcmbca_pmb_probe(), given that struct bcmbca_pmb is private to
drivers/mfd/bcmbca_pmc3_pmb.c and child drivers look up the regmap via
dev_get_regmap(dev->parent, NULL)?

Finally, could the commit subject include the driver prefix to match MFD
conventions (for example, "mfd: bcmbca-pmb: Add a shared BCMBCA PMC3 PMB
transport")?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261101-xg6846b-bcmbca-xrdp-reset-v2-0-455fe9eed5ee@kernel.org?part=3

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus
  2026-11-01 22:14 ` [PATCH v2 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus Linus Walleij
@ 2026-11-01 22:32   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-01 22:32 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 issue(s) to consider:
- [Low] dt-bindings: soc: brcm,bcm6846-pmb ordered after dependent brcm,bcm6846-pmc
- [Low] dt-bindings: hwmon: brcm,bcm6846-pmb-pvtmon uses additionalProperties with $ref
- [Low] dt-bindings: soc: brcm,bcm6846-pmb example child nodes out of alphabetical order
- [Low] MAINTAINERS: missing S: status tag in BROADCOM BCMBCA PMC3 PMB DRIVER entry
- [Low] dt-bindings: reset: non-contiguous reset IDs in brcm,bcm6846-pmb.h
--

commit 44e16c21f8b2ce99a2b8f758565676392f84eec0
Author: Linus Walleij <linusw@kernel.org>

dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus

This commit adds Device Tree binding schemas and header files for the
Broadcom BCM6846 Processor Monitor Bus (PMB) and its child clock, reset,
and PVTMON hardware monitor controllers.

>     dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus
>     
>     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.
>     
>     Signed-off-by: Linus Walleij <linusw@kernel.org>

[Severity: Low]
Should this commit be ordered before commit 39aa42d4e944 ("dt-bindings:
mfd: Describe the BCM6846 PMC complex"), and should the commit message drop
"PMC and"?

In the parent commit 39aa42d4e944,
Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml references
/schemas/soc/bcm/brcm,bcm6846-pmb.yaml# via $ref and includes
dt-bindings/clock/brcm,bcm6846-pmb.h and
dt-bindings/reset/brcm,bcm6846-pmb.h in its example before they are added
here, which causes make dt_binding_check to fail at the parent commit
during bisection.

> 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]
Since this schema includes /schemas/thermal/thermal-sensor.yaml# via allOf,
should it use unevaluatedProperties: false instead of additionalProperties:
false so that properties from the referenced schema are evaluated properly?

> 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..a4a77fed94d05
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm6846-pmb.yaml
> @@ -0,0 +1,80 @@
[ ... ]
> +        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 unaddressed hwmon child node be placed before reset-controller
in the example so that the child nodes are in alphabetical order and pass
scripts/dtc/dt-check-style --mode=strict without a child-name-order
warning?

> diff --git a/MAINTAINERS b/MAINTAINERS
> index eb4b3b631e82c..fa95f2dec63c5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5446,7 +5446,13 @@ N:	bcm[9]?6878
>  
>  BROADCOM BCMBCA PMC3 PMB DRIVER
>  M:	Linus Walleij <linusw@kernel.org>
> +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/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/reset/brcm,bcm6846-pmb.h

[Severity: Low]
Should the BROADCOM BCMBCA PMC3 PMB DRIVER entry in MAINTAINERS include an
S: status tag (such as S: Maintained) so that scripts/get_maintainer.pl
--self-test=sections does not warn about a section without status?

> 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 0000000000000..6b1a6baac1c60
> --- /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	3
> +
> +#endif

[Severity: Low]
Since these reset constants represent abstract logical reset group IDs
rather than hardware register offsets or bit positions, should
BCM6846_RESET_PVTMON be defined as 1 instead of 3 so that the IDs in this
new binding header are contiguous starting from 0 and
bcm6846_pmb_reset_groups[] in drivers/reset/reset-bcmbca-pmb.c does not
carry two unused entries at indices 1 and 2?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261101-xg6846b-bcmbca-xrdp-reset-v2-0-455fe9eed5ee@kernel.org?part=2

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 6/7] hwmon: Add Broadcom PMB PVTMON monitoring
  2026-11-01 22:14 ` [PATCH v2 6/7] hwmon: Add Broadcom PMB PVTMON monitoring Linus Walleij
@ 2026-11-02  3:05   ` Guenter Roeck
  0 siblings, 0 replies; 15+ messages in thread
From: Guenter Roeck @ 2026-11-02  3:05 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, Philipp Zabel, Jonathan Corbet, Randy Dunlap,
	Benjamin Larsson
  Cc: mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

On 11/1/26 14:14, Linus Walleij wrote:
> 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.
> 
> Signed-off-by: Linus Walleij <linusw@kernel.org>

Acked-by: Guenter Roeck <linux@roeck-us.net>

Please let me know if you want me to take this patch through
the hwmon subsystem.

Thanks,
Guenter

> ---
>   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         | 232 +++++++++++++++++++++++++++++++++
>   6 files changed, 307 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 74f0783d512f..124d67ea1582 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5451,7 +5451,9 @@ F:	Documentation/devicetree/bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml
>   F:	Documentation/devicetree/bindings/mfd/brcm,bcm6846-pmc.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/reset/reset-bcmbca-pmb.c
>   F:	include/dt-bindings/clock/brcm,bcm6846-pmb.h
> 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..8b95dac83994
> --- /dev/null
> +++ b/drivers/hwmon/bcm_pmb_pvtmon.c
> @@ -0,0 +1,232 @@
> +// 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/mod_devicetable.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)
> +
> +/* Voltage labels and divider ratios follow the BCM6846 vendor definitions. */
> +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, matching the vendor acquisition setup. */
> +		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");
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support
  2026-11-01 22:14 [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support Linus Walleij
                   ` (6 preceding siblings ...)
  2026-11-01 22:14 ` [PATCH v2 7/7] ARM: dts: broadcom: Add BCM6846 PMB clocks and hardware monitoring Linus Walleij
@ 2026-11-02  4:32 ` William Zhang
  2026-11-02  7:50   ` Linus Walleij
  7 siblings, 1 reply; 15+ messages in thread
From: William Zhang @ 2026-11-02  4:32 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, Benjamin Larsson,
	mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

[-- Attachment #1: Type: text/plain, Size: 5109 bytes --]

On Sun, Nov 1, 2026 at 2:14 PM Linus Walleij <linusw@kernel.org> wrote:
>
> 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
Should have pointed this out last time.  PMB: Power Management Bus

> to several individual peripherals which are very clearly distinct
> devices on that bus.
>
> Handle the PMB with an MFD driver with clock, reset and hwmon
> providers.
>
> 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. All patches except the last one (DTS file)
> to be queued in MFD.
>
> The patches were authored with the assistance of an LLM.
>
> Signed-off-by: Linus Walleij <linusw@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 give PVTMON clock and reset resources.
> - Add PVTMON hwmon support for temperature and all seven voltage inputs,
>   retaining the zero-cell thermal sensor through the hwmon bridge.
> - Add a separate BCM6846 clocks and monitoring DTS patch.
> - 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: Add a shared BCMBCA PMC3 PMB transport
>       reset: Add BCMBCA block resets through the PMB
>       clk: bcm: Add BCMBCA PMB clocks
>       hwmon: Add Broadcom PMB PVTMON monitoring
>       ARM: dts: broadcom: Add BCM6846 PMB clocks and hardware monitoring
>
>  .../bindings/clock/brcm,bcm6846-pmb-clock.yaml     |  39 +++
>  .../bindings/hwmon/brcm,bcm6846-pmb-pvtmon.yaml    |  42 +++
>  .../devicetree/bindings/mfd/brcm,bcm6846-pmc.yaml  |  82 +++++
>  .../bindings/reset/brcm,bcm6846-pmb-reset.yaml     |  31 ++
>  .../bindings/soc/bcm/brcm,bcm6846-pmb.yaml         |  80 +++++
>  Documentation/hwmon/bcm_pmb_pvtmon.rst             |  53 +++
>  Documentation/hwmon/index.rst                      |   1 +
>  MAINTAINERS                                        |  16 +
>  arch/arm/boot/dts/broadcom/bcm6846.dtsi            |  47 +++
>  drivers/clk/bcm/Kconfig                            |  11 +
>  drivers/clk/bcm/Makefile                           |   1 +
>  drivers/clk/bcm/clk-bcmbca-pmb.c                   | 389 +++++++++++++++++++++
>  drivers/hwmon/Kconfig                              |  18 +
>  drivers/hwmon/Makefile                             |   1 +
>  drivers/hwmon/bcm_pmb_pvtmon.c                     | 232 ++++++++++++
>  drivers/mfd/Kconfig                                |  11 +
>  drivers/mfd/Makefile                               |   1 +
>  drivers/mfd/bcmbca_pmc3_pmb.c                      | 297 ++++++++++++++++
>  drivers/reset/Kconfig                              |  13 +
>  drivers/reset/Makefile                             |   1 +
>  drivers/reset/reset-bcmbca-pmb.c                   | 309 ++++++++++++++++
>  include/dt-bindings/clock/brcm,bcm6846-pmb.h       |  42 +++
>  include/dt-bindings/reset/brcm,bcm6846-pmb.h       |  11 +
>  include/linux/mfd/bcmbca-pmb.h                     |  11 +
>  24 files changed, 1739 insertions(+)
> ---
> base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
> change-id: 20261013-xg6846b-bcmbca-xrdp-reset-de71b80c25a4
>
> Best regards,
> --
> Linus Walleij <linusw@kernel.org>
>

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5473 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support
  2026-11-02  4:32 ` [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support William Zhang
@ 2026-11-02  7:50   ` Linus Walleij
  2026-11-02  8:35     ` Linus Walleij
  0 siblings, 1 reply; 15+ messages in thread
From: Linus Walleij @ 2026-11-02  7:50 UTC (permalink / raw)
  To: William Zhang
  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, Benjamin Larsson,
	mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

On Mon, Nov 2, 2026 at 5:33 AM William Zhang <william.zhang@broadcom.com> wrote:

> > Inside the PMC is the PMB, the processor monitor bus. This bridges

> Should have pointed this out last time.  PMB: Power Management Bus

I think you did point it out, I just didn't manage to change it everywhere,
hopefully I only missed this one...

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support
  2026-11-02  7:50   ` Linus Walleij
@ 2026-11-02  8:35     ` Linus Walleij
  0 siblings, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-11-02  8:35 UTC (permalink / raw)
  To: William Zhang
  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, Benjamin Larsson,
	mfd, devicetree, linux-arm-kernel, linux-clk, linux-hwmon

On Mon, Nov 2, 2026 at 8:50 AM Linus Walleij <linusw@kernel.org> wrote:
> On Mon, Nov 2, 2026 at 5:33 AM William Zhang <william.zhang@broadcom.com> wrote:
>
> > > Inside the PMC is the PMB, the processor monitor bus. This bridges
>
> > Should have pointed this out last time.  PMB: Power Management Bus
>
> I think you did point it out, I just didn't manage to change it everywhere,
> hopefully I only missed this one...

Ah no, it was the PMC3 I corrected. OK fixed this everywhere now
for v3, thanks William!

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2026-11-02  8:36 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-01 22:14 [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support Linus Walleij
2026-11-01 22:14 ` [PATCH v2 1/7] dt-bindings: mfd: Describe the BCM6846 PMC complex Linus Walleij
2026-11-01 22:24   ` sashiko-bot
2026-11-01 22:14 ` [PATCH v2 2/7] dt-bindings: soc: Describe the BCM6846 Processor Monitor Bus Linus Walleij
2026-11-01 22:32   ` sashiko-bot
2026-11-01 22:14 ` [PATCH v2 3/7] mfd: Add a shared BCMBCA PMC3 PMB transport Linus Walleij
2026-11-01 22:31   ` sashiko-bot
2026-11-01 22:14 ` [PATCH v2 4/7] reset: Add BCMBCA block resets through the PMB Linus Walleij
2026-11-01 22:14 ` [PATCH v2 5/7] clk: bcm: Add BCMBCA PMB clocks Linus Walleij
2026-11-01 22:14 ` [PATCH v2 6/7] hwmon: Add Broadcom PMB PVTMON monitoring Linus Walleij
2026-11-02  3:05   ` Guenter Roeck
2026-11-01 22:14 ` [PATCH v2 7/7] ARM: dts: broadcom: Add BCM6846 PMB clocks and hardware monitoring Linus Walleij
2026-11-02  4:32 ` [PATCH v2 0/7] BCMBCA PMB clock, reset and hardware monitoring support William Zhang
2026-11-02  7:50   ` Linus Walleij
2026-11-02  8:35     ` Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox